From 7317e7ca3a46f34ea8eac349c4bf04f3c7789b78 Mon Sep 17 00:00:00 2001
From: Kowalski
Date: Tue, 4 Mar 2025 16:10:15 +0100
Subject: [PATCH] Base commit.
---
.gitignore | 15 +
.htaccess | 1 +
app/Bootstrap.php | 50 +
app/Core/RouterFactory.php | 21 +
app/Presentation/@layout.latte | 19 +
app/Presentation/Accessory/LatteExtension.php | 22 +
app/Presentation/Error/Error4xx/403.latte | 7 +
app/Presentation/Error/Error4xx/404.latte | 8 +
app/Presentation/Error/Error4xx/410.latte | 6 +
app/Presentation/Error/Error4xx/4xx.latte | 6 +
.../Error/Error4xx/Error4xxPresenter.php | 27 +
app/Presentation/Error/Error5xx/500.phtml | 27 +
app/Presentation/Error/Error5xx/503.phtml | 24 +
.../Error/Error5xx/Error5xxPresenter.php | 39 +
app/Presentation/Home/HomePresenter.php | 12 +
app/Presentation/Home/default.latte | 38 +
composer.json | 38 +
composer.lock | 1489 ++++++++++++++++
config/common.neon | 27 +
config/services.neon | 11 +
readme.md | 52 +
vendor/autoload.php | 25 +
vendor/bin/latte-lint | 119 ++
vendor/bin/latte-lint.bat | 5 +
vendor/bin/neon-lint | 119 ++
vendor/bin/neon-lint.bat | 5 +
vendor/bin/tester | 119 ++
vendor/bin/tester.bat | 5 +
vendor/composer/ClassLoader.php | 579 +++++++
vendor/composer/InstalledVersions.php | 359 ++++
vendor/composer/LICENSE | 21 +
vendor/composer/autoload_classmap.php | 673 ++++++++
vendor/composer/autoload_files.php | 10 +
vendor/composer/autoload_namespaces.php | 9 +
vendor/composer/autoload_psr4.php | 11 +
vendor/composer/autoload_real.php | 50 +
vendor/composer/autoload_static.php | 711 ++++++++
vendor/composer/installed.json | 1536 +++++++++++++++++
vendor/composer/installed.php | 203 +++
vendor/composer/platform_check.php | 26 +
vendor/latte/latte/bin/latte-lint | 35 +
vendor/latte/latte/composer.json | 55 +
vendor/latte/latte/license.md | 60 +
vendor/latte/latte/readme.md | 39 +
.../src/Bridges/Tracy/BlueScreenPanel.php | 123 ++
.../latte/src/Bridges/Tracy/LattePanel.php | 122 ++
.../src/Bridges/Tracy/TracyExtension.php | 37 +
.../Tracy/templates/LattePanel.panel.phtml | 101 ++
.../Tracy/templates/LattePanel.tab.phtml | 15 +
.../latte/latte/src/Latte/Compiler/Block.php | 41 +
.../latte/src/Latte/Compiler/Escaper.php | 268 +++
.../src/Latte/Compiler/ExpressionBuilder.php | 129 ++
.../latte/latte/src/Latte/Compiler/Node.php | 21 +
.../latte/src/Latte/Compiler/NodeHelpers.php | 128 ++
.../src/Latte/Compiler/NodeTraverser.php | 73 +
.../src/Latte/Compiler/Nodes/AreaNode.php | 17 +
.../Latte/Compiler/Nodes/AuxiliaryNode.php | 41 +
.../src/Latte/Compiler/Nodes/FragmentNode.php | 69 +
.../Compiler/Nodes/Html/AttributeNode.php | 66 +
.../Compiler/Nodes/Html/BogusTagNode.php | 46 +
.../Latte/Compiler/Nodes/Html/CommentNode.php | 39 +
.../Latte/Compiler/Nodes/Html/ElementNode.php | 152 ++
.../src/Latte/Compiler/Nodes/NopNode.php | 27 +
.../Latte/Compiler/Nodes/Php/ArgumentNode.php | 51 +
.../Compiler/Nodes/Php/ArrayItemNode.php | 74 +
.../Compiler/Nodes/Php/ClosureUseNode.php | 38 +
.../Compiler/Nodes/Php/ComplexTypeNode.php | 17 +
.../Nodes/Php/Expression/ArrayAccessNode.php | 41 +
.../Nodes/Php/Expression/ArrayNode.php | 68 +
.../Nodes/Php/Expression/AssignNode.php | 53 +
.../Nodes/Php/Expression/AssignOpNode.php | 56 +
.../Nodes/Php/Expression/AuxiliaryNode.php | 42 +
.../Nodes/Php/Expression/BinaryOpNode.php | 65 +
.../Nodes/Php/Expression/CastNode.php | 43 +
.../Php/Expression/ClassConstantFetchNode.php | 42 +
.../Nodes/Php/Expression/CloneNode.php | 36 +
.../Nodes/Php/Expression/ClosureNode.php | 74 +
.../Php/Expression/ConstantFetchNode.php | 45 +
.../Nodes/Php/Expression/EmptyNode.php | 36 +
.../Php/Expression/ErrorSuppressNode.php | 36 +
.../Nodes/Php/Expression/FilterCallNode.php | 39 +
.../Nodes/Php/Expression/FunctionCallNode.php | 45 +
.../Php/Expression/FunctionCallableNode.php | 39 +
.../Compiler/Nodes/Php/Expression/InNode.php | 42 +
.../Nodes/Php/Expression/InstanceofNode.php | 40 +
.../Nodes/Php/Expression/IssetNode.php | 54 +
.../Nodes/Php/Expression/MatchNode.php | 49 +
.../Nodes/Php/Expression/MethodCallNode.php | 50 +
.../Php/Expression/MethodCallableNode.php | 42 +
.../Compiler/Nodes/Php/Expression/NewNode.php | 45 +
.../Compiler/Nodes/Php/Expression/NotNode.php | 36 +
.../Nodes/Php/Expression/PostOpNode.php | 54 +
.../Nodes/Php/Expression/PreOpNode.php | 54 +
.../Php/Expression/PropertyFetchNode.php | 42 +
.../Php/Expression/StaticMethodCallNode.php | 65 +
.../Expression/StaticMethodCallableNode.php | 57 +
.../Expression/StaticPropertyFetchNode.php | 42 +
.../Nodes/Php/Expression/TemporaryNode.php | 38 +
.../Nodes/Php/Expression/TernaryNode.php | 50 +
.../Nodes/Php/Expression/UnaryOpNode.php | 45 +
.../Nodes/Php/Expression/VariableNode.php | 40 +
.../Compiler/Nodes/Php/ExpressionNode.php | 41 +
.../Latte/Compiler/Nodes/Php/FilterNode.php | 62 +
.../Compiler/Nodes/Php/IdentifierNode.php | 42 +
.../Nodes/Php/InterpolatedStringPartNode.php | 36 +
.../Nodes/Php/IntersectionTypeNode.php | 39 +
.../Latte/Compiler/Nodes/Php/ListItemNode.php | 48 +
.../src/Latte/Compiler/Nodes/Php/ListNode.php | 56 +
.../Latte/Compiler/Nodes/Php/MatchArmNode.php | 45 +
.../Latte/Compiler/Nodes/Php/ModifierNode.php | 107 ++
.../src/Latte/Compiler/Nodes/Php/NameNode.php | 85 +
.../Compiler/Nodes/Php/NullableTypeNode.php | 35 +
.../Compiler/Nodes/Php/ParameterNode.php | 54 +
.../Compiler/Nodes/Php/Scalar/BooleanNode.php | 30 +
.../Compiler/Nodes/Php/Scalar/FloatNode.php | 63 +
.../Compiler/Nodes/Php/Scalar/IntegerNode.php | 70 +
.../Php/Scalar/InterpolatedStringNode.php | 74 +
.../Compiler/Nodes/Php/Scalar/NullNode.php | 29 +
.../Compiler/Nodes/Php/Scalar/StringNode.php | 40 +
.../Latte/Compiler/Nodes/Php/ScalarNode.php | 19 +
.../Compiler/Nodes/Php/SuperiorTypeNode.php | 35 +
.../Compiler/Nodes/Php/UnionTypeNode.php | 39 +
.../Nodes/Php/VarLikeIdentifierNode.php | 21 +
.../Latte/Compiler/Nodes/StatementNode.php | 15 +
.../src/Latte/Compiler/Nodes/TemplateNode.php | 34 +
.../src/Latte/Compiler/Nodes/TextNode.php | 43 +
.../latte/src/Latte/Compiler/PhpHelpers.php | 257 +++
.../latte/src/Latte/Compiler/Position.php | 45 +
.../latte/src/Latte/Compiler/PrintContext.php | 341 ++++
vendor/latte/latte/src/Latte/Compiler/Tag.php | 116 ++
.../latte/src/Latte/Compiler/TagLexer.php | 396 +++++
.../latte/src/Latte/Compiler/TagParser.php | 473 +++++
.../src/Latte/Compiler/TagParserData.php | 607 +++++++
.../src/Latte/Compiler/TemplateGenerator.php | 209 +++
.../src/Latte/Compiler/TemplateLexer.php | 318 ++++
.../src/Latte/Compiler/TemplateParser.php | 455 +++++
.../src/Latte/Compiler/TemplateParserHtml.php | 574 ++++++
.../latte/latte/src/Latte/Compiler/Token.php | 255 +++
.../latte/src/Latte/Compiler/TokenStream.php | 135 ++
vendor/latte/latte/src/Latte/ContentType.php | 22 +
vendor/latte/latte/src/Latte/Engine.php | 653 +++++++
.../src/Latte/Essential/AuxiliaryIterator.php | 46 +
.../latte/src/Latte/Essential/Blueprint.php | 183 ++
.../src/Latte/Essential/CachingIterator.php | 227 +++
.../src/Latte/Essential/CoreExtension.php | 257 +++
.../latte/src/Latte/Essential/Filters.php | 753 ++++++++
.../src/Latte/Essential/Nodes/BlockNode.php | 160 ++
.../src/Latte/Essential/Nodes/CaptureNode.php | 87 +
.../Latte/Essential/Nodes/ContentTypeNode.php | 87 +
.../Latte/Essential/Nodes/DebugbreakNode.php | 53 +
.../src/Latte/Essential/Nodes/DefineNode.php | 133 ++
.../src/Latte/Essential/Nodes/DoNode.php | 61 +
.../src/Latte/Essential/Nodes/DumpNode.php | 58 +
.../src/Latte/Essential/Nodes/EmbedNode.php | 125 ++
.../src/Latte/Essential/Nodes/ExtendsNode.php | 57 +
.../Essential/Nodes/FirstLastSepNode.php | 81 +
.../src/Latte/Essential/Nodes/ForNode.php | 91 +
.../src/Latte/Essential/Nodes/ForeachNode.php | 182 ++
.../Latte/Essential/Nodes/IfChangedNode.php | 141 ++
.../Latte/Essential/Nodes/IfContentNode.php | 85 +
.../src/Latte/Essential/Nodes/IfNode.php | 182 ++
.../src/Latte/Essential/Nodes/ImportNode.php | 55 +
.../Essential/Nodes/IncludeBlockNode.php | 143 ++
.../Latte/Essential/Nodes/IncludeFileNode.php | 81 +
.../Essential/Nodes/IterateWhileNode.php | 96 ++
.../src/Latte/Essential/Nodes/JumpNode.php | 88 +
.../src/Latte/Essential/Nodes/NAttrNode.php | 105 ++
.../src/Latte/Essential/Nodes/NClassNode.php | 54 +
.../src/Latte/Essential/Nodes/NElseNode.php | 88 +
.../src/Latte/Essential/Nodes/NTagNode.php | 71 +
.../Latte/Essential/Nodes/ParametersNode.php | 84 +
.../src/Latte/Essential/Nodes/PrintNode.php | 65 +
.../src/Latte/Essential/Nodes/RawPhpNode.php | 52 +
.../Latte/Essential/Nodes/RollbackNode.php | 43 +
.../Latte/Essential/Nodes/SpacelessNode.php | 62 +
.../src/Latte/Essential/Nodes/SwitchNode.php | 118 ++
.../Essential/Nodes/TemplatePrintNode.php | 67 +
.../Essential/Nodes/TemplateTypeNode.php | 44 +
.../src/Latte/Essential/Nodes/TraceNode.php | 41 +
.../Latte/Essential/Nodes/TranslateNode.php | 104 ++
.../src/Latte/Essential/Nodes/TryNode.php | 74 +
.../src/Latte/Essential/Nodes/VarNode.php | 102 ++
.../Latte/Essential/Nodes/VarPrintNode.php | 53 +
.../src/Latte/Essential/Nodes/VarTypeNode.php | 42 +
.../src/Latte/Essential/Nodes/WhileNode.php | 81 +
.../latte/src/Latte/Essential/Passes.php | 73 +
.../src/Latte/Essential/RawPhpExtension.php | 26 +
.../src/Latte/Essential/RollbackException.php | 16 +
.../latte/src/Latte/Essential/Tracer.php | 117 ++
.../Latte/Essential/TranslatorExtension.php | 106 ++
vendor/latte/latte/src/Latte/Extension.php | 97 ++
vendor/latte/latte/src/Latte/Helpers.php | 98 ++
vendor/latte/latte/src/Latte/Loader.php | 38 +
.../latte/src/Latte/Loaders/FileLoader.php | 93 +
.../latte/src/Latte/Loaders/StringLoader.php | 74 +
vendor/latte/latte/src/Latte/Policy.php | 24 +
.../src/Latte/PositionAwareException.php | 47 +
.../latte/latte/src/Latte/Runtime/Block.php | 20 +
.../src/Latte/Runtime/FilterExecutor.php | 144 ++
.../latte/src/Latte/Runtime/FilterInfo.php | 37 +
.../latte/latte/src/Latte/Runtime/Filters.php | 283 +++
.../src/Latte/Runtime/FunctionExecutor.php | 68 +
vendor/latte/latte/src/Latte/Runtime/Html.php | 31 +
.../src/Latte/Runtime/HtmlStringable.php | 17 +
.../latte/src/Latte/Runtime/Template.php | 383 ++++
.../Latte/Sandbox/Nodes/FunctionCallNode.php | 30 +
.../Sandbox/Nodes/FunctionCallableNode.php | 29 +
.../Latte/Sandbox/Nodes/MethodCallNode.php | 32 +
.../Sandbox/Nodes/MethodCallableNode.php | 30 +
.../Latte/Sandbox/Nodes/PropertyFetchNode.php | 32 +
.../src/Latte/Sandbox/Nodes/SandboxNode.php | 73 +
.../Sandbox/Nodes/StaticMethodCallNode.php | 31 +
.../Nodes/StaticMethodCallableNode.php | 30 +
.../Sandbox/Nodes/StaticPropertyFetchNode.php | 32 +
.../src/Latte/Sandbox/RuntimeChecker.php | 114 ++
.../src/Latte/Sandbox/SandboxExtension.php | 136 ++
.../src/Latte/Sandbox/SecurityPolicy.php | 183 ++
vendor/latte/latte/src/Latte/attributes.php | 24 +
vendor/latte/latte/src/Latte/exceptions.php | 60 +
vendor/latte/latte/src/Tools/Linter.php | 153 ++
vendor/nette/application/.phpstorm.meta.php | 66 +
vendor/nette/application/composer.json | 61 +
vendor/nette/application/license.md | 60 +
vendor/nette/application/readme.md | 13 +
.../src/Application/Application.php | 235 +++
.../Application/Attributes/CrossOrigin.php | 25 +
.../src/Application/Attributes/Deprecated.php | 13 +
.../src/Application/Attributes/Parameter.php | 18 +
.../src/Application/Attributes/Persistent.php | 21 +
.../src/Application/Attributes/Requires.php | 27 +
.../src/Application/ErrorPresenter.php | 44 +
.../application/src/Application/Helpers.php | 53 +
.../src/Application/IPresenter.php | 19 +
.../src/Application/IPresenterFactory.php | 28 +
.../src/Application/LinkGenerator.php | 297 ++++
.../src/Application/MicroPresenter.php | 158 ++
.../src/Application/PresenterFactory.php | 137 ++
.../application/src/Application/Request.php | 190 ++
.../application/src/Application/Response.php | 27 +
.../Responses/CallbackResponse.php | 40 +
.../Application/Responses/FileResponse.php | 125 ++
.../Application/Responses/ForwardResponse.php | 41 +
.../Application/Responses/JsonResponse.php | 54 +
.../Responses/RedirectResponse.php | 51 +
.../Application/Responses/TextResponse.php | 47 +
.../Application/Responses/VoidResponse.php | 23 +
.../src/Application/Routers/CliRouter.php | 108 ++
.../src/Application/Routers/Route.php | 192 +++
.../src/Application/Routers/RouteList.php | 144 ++
.../src/Application/Routers/SimpleRouter.php | 43 +
.../src/Application/UI/AccessPolicy.php | 125 ++
.../src/Application/UI/BadSignalException.php | 22 +
.../src/Application/UI/Component.php | 383 ++++
.../Application/UI/ComponentReflection.php | 219 +++
.../src/Application/UI/Control.php | 166 ++
.../application/src/Application/UI/Form.php | 158 ++
.../Application/UI/InvalidLinkException.php | 18 +
.../application/src/Application/UI/Link.php | 89 +
.../src/Application/UI/MethodReflection.php | 35 +
.../src/Application/UI/Multiplier.php | 34 +
.../src/Application/UI/ParameterConverter.php | 190 ++
.../src/Application/UI/Presenter.php | 1175 +++++++++++++
.../src/Application/UI/Renderable.php | 30 +
.../src/Application/UI/SignalReceiver.php | 22 +
.../src/Application/UI/StatePersistent.php | 30 +
.../src/Application/UI/Template.php | 35 +
.../src/Application/UI/TemplateFactory.php | 22 +
.../src/Application/exceptions.php | 74 +
.../src/Application/templates/error.phtml | 49 +
.../ApplicationDI/ApplicationExtension.php | 291 ++++
.../Bridges/ApplicationDI/LatteExtension.php | 177 ++
.../PresenterFactoryCallback.php | 64 +
.../ApplicationDI/RoutingExtension.php | 104 ++
.../ApplicationLatte/DefaultTemplate.php | 55 +
.../Bridges/ApplicationLatte/LatteFactory.php | 21 +
.../ApplicationLatte/Nodes/ControlNode.php | 142 ++
.../ApplicationLatte/Nodes/IfCurrentNode.php | 70 +
.../ApplicationLatte/Nodes/LinkNode.php | 92 +
.../ApplicationLatte/Nodes/NNonceNode.php | 37 +
.../Nodes/SnippetAreaNode.php | 88 +
.../ApplicationLatte/Nodes/SnippetNode.php | 169 ++
.../Nodes/TemplatePrintNode.php | 61 +
.../ApplicationLatte/SnippetBridge.php | 95 +
.../ApplicationLatte/SnippetRuntime.php | 141 ++
.../src/Bridges/ApplicationLatte/Template.php | 159 ++
.../ApplicationLatte/TemplateFactory.php | 138 ++
.../Bridges/ApplicationLatte/UIExtension.php | 133 ++
.../src/Bridges/ApplicationLatte/UIMacros.php | 187 ++
.../Bridges/ApplicationLatte/UIRuntime.php | 84 +
.../Bridges/ApplicationTracy/RoutingPanel.php | 145 ++
.../templates/RoutingPanel.panel.phtml | 182 ++
.../templates/RoutingPanel.tab.phtml | 15 +
.../application/src/compatibility-intf.php | 88 +
.../nette/application/src/compatibility.php | 28 +
vendor/nette/bootstrap/composer.json | 57 +
vendor/nette/bootstrap/config.stub.neon | 10 +
vendor/nette/bootstrap/license.md | 60 +
vendor/nette/bootstrap/readme.md | 30 +
.../bootstrap/src/Bootstrap/Configurator.php | 367 ++++
.../Extensions/ConstantsExtension.php | 36 +
.../src/Bootstrap/Extensions/PhpExtension.php | 42 +
vendor/nette/bootstrap/src/Configurator.php | 19 +
vendor/nette/caching/composer.json | 48 +
vendor/nette/caching/license.md | 60 +
vendor/nette/caching/readme.md | 398 +++++
.../src/Bridges/CacheDI/CacheExtension.php | 57 +
.../src/Bridges/CacheLatte/CacheExtension.php | 75 +
.../src/Bridges/CacheLatte/CacheMacro.php | 168 ++
.../Bridges/CacheLatte/Nodes/CacheNode.php | 70 +
.../src/Bridges/CacheLatte/Runtime.php | 98 ++
.../src/Bridges/Psr/PsrCacheAdapter.php | 116 ++
.../nette/caching/src/Caching/BulkReader.php | 26 +
.../nette/caching/src/Caching/BulkWriter.php | 28 +
vendor/nette/caching/src/Caching/Cache.php | 435 +++++
.../caching/src/Caching/OutputHelper.php | 55 +
vendor/nette/caching/src/Caching/Storage.php | 46 +
.../src/Caching/Storages/DevNullStorage.php | 44 +
.../src/Caching/Storages/FileStorage.php | 374 ++++
.../caching/src/Caching/Storages/Journal.php | 31 +
.../src/Caching/Storages/MemcachedStorage.php | 230 +++
.../src/Caching/Storages/MemoryStorage.php | 52 +
.../src/Caching/Storages/SQLiteJournal.php | 145 ++
.../src/Caching/Storages/SQLiteStorage.php | 148 ++
vendor/nette/caching/src/compatibility.php | 39 +
.../nette/component-model/.phpstorm.meta.php | 7 +
vendor/nette/component-model/composer.json | 39 +
vendor/nette/component-model/license.md | 60 +
vendor/nette/component-model/readme.md | 31 +
.../src/ComponentModel/ArrayAccess.php | 66 +
.../src/ComponentModel/Component.php | 313 ++++
.../src/ComponentModel/Container.php | 260 +++
.../src/ComponentModel/IComponent.php | 35 +
.../src/ComponentModel/IContainer.php | 42 +
.../RecursiveComponentIterator.php | 44 +
vendor/nette/database/composer.json | 44 +
vendor/nette/database/license.md | 60 +
vendor/nette/database/readme.md | 141 ++
.../Bridges/DatabaseDI/DatabaseExtension.php | 139 ++
.../Bridges/DatabaseTracy/ConnectionPanel.php | 162 ++
.../Bridges/DatabaseTracy/dist/panel.phtml | 83 +
.../src/Bridges/DatabaseTracy/dist/tab.phtml | 13 +
.../src/Bridges/DatabaseTracy/panel.latte | 71 +
.../src/Bridges/DatabaseTracy/tab.latte | 6 +
.../database/src/Database/Connection.php | 367 ++++
.../database/src/Database/Conventions.php | 47 +
.../AmbiguousReferenceKeyException.php | 18 +
.../Conventions/DiscoveredConventions.php | 99 ++
.../Conventions/StaticConventions.php | 71 +
.../nette/database/src/Database/DateTime.php | 34 +
vendor/nette/database/src/Database/Driver.php | 102 ++
.../database/src/Database/DriverException.php | 63 +
.../src/Database/Drivers/MsSqlDriver.php | 225 +++
.../src/Database/Drivers/MySqlDriver.php | 224 +++
.../src/Database/Drivers/OciDriver.php | 142 ++
.../src/Database/Drivers/OdbcDriver.php | 113 ++
.../src/Database/Drivers/PgSqlDriver.php | 260 +++
.../src/Database/Drivers/SqliteDriver.php | 252 +++
.../src/Database/Drivers/SqlsrvDriver.php | 243 +++
.../nette/database/src/Database/Explorer.php | 209 +++
.../nette/database/src/Database/Helpers.php | 403 +++++
vendor/nette/database/src/Database/IRow.php | 16 +
.../database/src/Database/IRowContainer.php | 16 +
.../database/src/Database/IStructure.php | 78 +
.../database/src/Database/Reflection.php | 101 ++
.../src/Database/Reflection/Column.php | 37 +
.../src/Database/Reflection/ForeignKey.php | 34 +
.../src/Database/Reflection/Index.php | 33 +
.../src/Database/Reflection/Table.php | 118 ++
.../nette/database/src/Database/ResultSet.php | 270 +++
vendor/nette/database/src/Database/Row.php | 64 +
.../database/src/Database/SqlLiteral.php | 41 +
.../database/src/Database/SqlPreprocessor.php | 354 ++++
.../nette/database/src/Database/Structure.php | 284 +++
.../database/src/Database/Table/ActiveRow.php | 295 ++++
.../src/Database/Table/GroupedSelection.php | 277 +++
.../database/src/Database/Table/IRow.php | 18 +
.../src/Database/Table/IRowContainer.php | 18 +
.../database/src/Database/Table/Selection.php | 1070 ++++++++++++
.../src/Database/Table/SqlBuilder.php | 861 +++++++++
.../database/src/Database/exceptions.php | 50 +
.../nette/database/src/compatibility-intf.php | 28 +
vendor/nette/database/src/compatibility.php | 19 +
vendor/nette/di/.phpstorm.meta.php | 8 +
vendor/nette/di/composer.json | 45 +
vendor/nette/di/license.md | 60 +
vendor/nette/di/readme.md | 364 ++++
.../di/src/Bridges/DITracy/ContainerPanel.php | 82 +
.../templates/ContainerPanel.panel.phtml | 81 +
.../templates/ContainerPanel.tab.phtml | 11 +
vendor/nette/di/src/DI/Attributes/Inject.php | 18 +
vendor/nette/di/src/DI/Autowiring.php | 162 ++
vendor/nette/di/src/DI/Compiler.php | 315 ++++
vendor/nette/di/src/DI/CompilerExtension.php | 170 ++
vendor/nette/di/src/DI/Config/Adapter.php | 25 +
.../di/src/DI/Config/Adapters/NeonAdapter.php | 243 +++
.../di/src/DI/Config/Adapters/PhpAdapter.php | 36 +
vendor/nette/di/src/DI/Config/Helpers.php | 43 +
vendor/nette/di/src/DI/Config/Loader.php | 120 ++
vendor/nette/di/src/DI/Container.php | 383 ++++
vendor/nette/di/src/DI/ContainerBuilder.php | 406 +++++
vendor/nette/di/src/DI/ContainerLoader.php | 112 ++
.../src/DI/Definitions/AccessorDefinition.php | 128 ++
.../di/src/DI/Definitions/Definition.php | 181 ++
.../src/DI/Definitions/FactoryDefinition.php | 230 +++
.../src/DI/Definitions/ImportedDefinition.php | 44 +
.../src/DI/Definitions/LocatorDefinition.php | 176 ++
.../nette/di/src/DI/Definitions/Reference.php | 64 +
.../src/DI/Definitions/ServiceDefinition.php | 228 +++
.../nette/di/src/DI/Definitions/Statement.php | 68 +
vendor/nette/di/src/DI/DependencyChecker.php | 189 ++
vendor/nette/di/src/DI/DynamicParameter.php | 20 +
.../di/src/DI/Extensions/DIExtension.php | 139 ++
.../src/DI/Extensions/DecoratorExtension.php | 87 +
.../di/src/DI/Extensions/DefinitionSchema.php | 232 +++
.../src/DI/Extensions/ExtensionsExtension.php | 48 +
.../di/src/DI/Extensions/InjectExtension.php | 172 ++
.../src/DI/Extensions/ParametersExtension.php | 102 ++
.../di/src/DI/Extensions/SearchExtension.php | 159 ++
.../src/DI/Extensions/ServicesExtension.php | 260 +++
vendor/nette/di/src/DI/Helpers.php | 285 +++
vendor/nette/di/src/DI/PhpGenerator.php | 202 +++
vendor/nette/di/src/DI/Resolver.php | 663 +++++++
vendor/nette/di/src/DI/exceptions.php | 49 +
vendor/nette/di/src/compatibility.php | 39 +
vendor/nette/forms/.phpstorm.meta.php | 8 +
vendor/nette/forms/composer.json | 50 +
vendor/nette/forms/eslint.config.js | 53 +
vendor/nette/forms/examples/assets/logo.png | Bin 0 -> 1346 bytes
vendor/nette/forms/examples/assets/style.css | 72 +
vendor/nette/forms/examples/basic-example.php | 132 ++
.../forms/examples/bootstrap4-rendering.php | 107 ++
.../forms/examples/bootstrap5-rendering.php | 112 ++
vendor/nette/forms/examples/containers.php | 64 +
.../nette/forms/examples/custom-control.php | 137 ++
.../nette/forms/examples/custom-rendering.php | 127 ++
.../nette/forms/examples/custom-validator.php | 64 +
vendor/nette/forms/examples/html5.php | 63 +
vendor/nette/forms/examples/latte.php | 62 +
.../examples/latte/form-bootstrap5.latte | 66 +
vendor/nette/forms/examples/latte/form.latte | 37 +
vendor/nette/forms/examples/latte/page.latte | 19 +
.../nette/forms/examples/live-validation.php | 106 ++
vendor/nette/forms/examples/localization.ini | 12 +
vendor/nette/forms/examples/localization.php | 89 +
.../nette/forms/examples/manual-rendering.php | 95 +
vendor/nette/forms/license.md | 60 +
vendor/nette/forms/package.json | 31 +
vendor/nette/forms/readme.md | 93 +
vendor/nette/forms/rollup.config.js | 78 +
.../src/Bridges/FormsDI/FormsExtension.php | 43 +
.../src/Bridges/FormsLatte/FormMacros.php | 330 ++++
.../src/Bridges/FormsLatte/FormsExtension.php | 50 +
.../FormsLatte/Nodes/FieldNNameNode.php | 125 ++
.../FormsLatte/Nodes/FormContainerNode.php | 60 +
.../FormsLatte/Nodes/FormNNameNode.php | 85 +
.../src/Bridges/FormsLatte/Nodes/FormNode.php | 93 +
.../FormsLatte/Nodes/FormPrintNode.php | 60 +
.../FormsLatte/Nodes/InputErrorNode.php | 51 +
.../Bridges/FormsLatte/Nodes/InputNode.php | 71 +
.../Bridges/FormsLatte/Nodes/LabelNode.php | 90 +
.../forms/src/Bridges/FormsLatte/Runtime.php | 86 +
vendor/nette/forms/src/Forms/Blueprint.php | 233 +++
vendor/nette/forms/src/Forms/Container.php | 607 +++++++
vendor/nette/forms/src/Forms/Control.php | 45 +
vendor/nette/forms/src/Forms/ControlGroup.php | 122 ++
.../forms/src/Forms/Controls/BaseControl.php | 583 +++++++
.../nette/forms/src/Forms/Controls/Button.php | 75 +
.../forms/src/Forms/Controls/Checkbox.php | 97 ++
.../forms/src/Forms/Controls/CheckboxList.php | 126 ++
.../src/Forms/Controls/ChoiceControl.php | 146 ++
.../forms/src/Forms/Controls/ColorPicker.php | 60 +
.../src/Forms/Controls/CsrfProtection.php | 102 ++
.../src/Forms/Controls/DateTimeControl.php | 193 +++
.../forms/src/Forms/Controls/HiddenField.php | 113 ++
.../forms/src/Forms/Controls/ImageButton.php | 44 +
.../src/Forms/Controls/MultiChoiceControl.php | 157 ++
.../src/Forms/Controls/MultiSelectBox.php | 95 +
.../forms/src/Forms/Controls/RadioList.php | 122 ++
.../forms/src/Forms/Controls/SelectBox.php | 148 ++
.../forms/src/Forms/Controls/SubmitButton.php | 116 ++
.../forms/src/Forms/Controls/TextArea.php | 34 +
.../forms/src/Forms/Controls/TextBase.php | 151 ++
.../forms/src/Forms/Controls/TextInput.php | 114 ++
.../src/Forms/Controls/UploadControl.php | 151 ++
vendor/nette/forms/src/Forms/Form.php | 794 +++++++++
vendor/nette/forms/src/Forms/FormRenderer.php | 25 +
vendor/nette/forms/src/Forms/Helpers.php | 322 ++++
.../Forms/Rendering/DataClassGenerator.php | 33 +
.../Forms/Rendering/DefaultFormRenderer.php | 527 ++++++
.../src/Forms/Rendering/LatteRenderer.php | 28 +
vendor/nette/forms/src/Forms/Rule.php | 35 +
vendor/nette/forms/src/Forms/Rules.php | 345 ++++
.../forms/src/Forms/SubmitterControl.php | 25 +
vendor/nette/forms/src/Forms/Validator.php | 408 +++++
.../nette/forms/src/assets/formValidator.ts | 458 +++++
vendor/nette/forms/src/assets/index.umd.ts | 10 +
vendor/nette/forms/src/assets/netteForms.js | 563 ++++++
.../nette/forms/src/assets/netteForms.min.js | 7 +
vendor/nette/forms/src/assets/package.json | 24 +
vendor/nette/forms/src/assets/types.ts | 32 +
vendor/nette/forms/src/assets/validators.ts | 192 +++
vendor/nette/forms/src/assets/webalize.ts | 16 +
vendor/nette/forms/src/compatibility.php | 37 +
vendor/nette/forms/tsconfig.json | 19 +
vendor/nette/http/.phpstorm.meta.php | 79 +
vendor/nette/http/composer.json | 51 +
vendor/nette/http/license.md | 60 +
vendor/nette/http/readme.md | 791 +++++++++
.../http/src/Bridges/HttpDI/HttpExtension.php | 171 ++
.../src/Bridges/HttpDI/SessionExtension.php | 100 ++
.../src/Bridges/HttpTracy/SessionPanel.php | 41 +
.../src/Bridges/HttpTracy/dist/panel.phtml | 32 +
.../http/src/Bridges/HttpTracy/dist/tab.phtml | 9 +
.../http/src/Bridges/HttpTracy/panel.latte | 32 +
.../http/src/Bridges/HttpTracy/tab.latte | 5 +
vendor/nette/http/src/Http/Context.php | 83 +
vendor/nette/http/src/Http/FileUpload.php | 280 +++
vendor/nette/http/src/Http/Helpers.php | 62 +
vendor/nette/http/src/Http/IRequest.php | 141 ++
vendor/nette/http/src/Http/IResponse.php | 411 +++++
vendor/nette/http/src/Http/Request.php | 323 ++++
vendor/nette/http/src/Http/RequestFactory.php | 382 ++++
vendor/nette/http/src/Http/Response.php | 282 +++
vendor/nette/http/src/Http/Session.php | 560 ++++++
vendor/nette/http/src/Http/SessionSection.php | 229 +++
vendor/nette/http/src/Http/Url.php | 448 +++++
vendor/nette/http/src/Http/UrlImmutable.php | 338 ++++
vendor/nette/http/src/Http/UrlScript.php | 114 ++
vendor/nette/http/src/Http/UserStorage.php | 179 ++
vendor/nette/mail/.phpstorm.meta.php | 8 +
vendor/nette/mail/composer.json | 45 +
vendor/nette/mail/license.md | 60 +
vendor/nette/mail/readme.md | 239 +++
.../mail/src/Bridges/MailDI/MailExtension.php | 88 +
vendor/nette/mail/src/Mail/DkimSigner.php | 156 ++
vendor/nette/mail/src/Mail/FallbackMailer.php | 79 +
vendor/nette/mail/src/Mail/Mailer.php | 32 +
vendor/nette/mail/src/Mail/Message.php | 411 +++++
vendor/nette/mail/src/Mail/MimePart.php | 326 ++++
vendor/nette/mail/src/Mail/SendmailMailer.php | 81 +
vendor/nette/mail/src/Mail/Signer.php | 20 +
vendor/nette/mail/src/Mail/SmtpMailer.php | 238 +++
vendor/nette/mail/src/Mail/exceptions.php | 40 +
vendor/nette/neon/bin/neon-lint | 92 +
vendor/nette/neon/composer.json | 40 +
vendor/nette/neon/license.md | 60 +
vendor/nette/neon/readme.md | 521 ++++++
vendor/nette/neon/src/Neon/Decoder.php | 36 +
vendor/nette/neon/src/Neon/Encoder.php | 97 ++
vendor/nette/neon/src/Neon/Entity.php | 31 +
vendor/nette/neon/src/Neon/Exception.php | 18 +
vendor/nette/neon/src/Neon/Lexer.php | 83 +
vendor/nette/neon/src/Neon/Neon.php | 67 +
vendor/nette/neon/src/Neon/Node.php | 35 +
.../neon/src/Neon/Node/ArrayItemNode.php | 90 +
vendor/nette/neon/src/Neon/Node/ArrayNode.php | 35 +
.../neon/src/Neon/Node/BlockArrayNode.php | 31 +
.../neon/src/Neon/Node/EntityChainNode.php | 49 +
.../nette/neon/src/Neon/Node/EntityNode.php | 53 +
.../neon/src/Neon/Node/InlineArrayNode.php | 28 +
.../nette/neon/src/Neon/Node/LiteralNode.php | 116 ++
.../nette/neon/src/Neon/Node/StringNode.php | 95 +
vendor/nette/neon/src/Neon/Parser.php | 264 +++
vendor/nette/neon/src/Neon/Token.php | 29 +
vendor/nette/neon/src/Neon/TokenStream.php | 95 +
vendor/nette/neon/src/Neon/Traverser.php | 79 +
vendor/nette/php-generator/composer.json | 44 +
vendor/nette/php-generator/license.md | 60 +
vendor/nette/php-generator/readme.md | 1008 +++++++++++
.../src/PhpGenerator/Attribute.php | 49 +
.../src/PhpGenerator/ClassLike.php | 147 ++
.../src/PhpGenerator/ClassManipulator.php | 131 ++
.../src/PhpGenerator/ClassType.php | 237 +++
.../src/PhpGenerator/Closure.php | 66 +
.../src/PhpGenerator/Constant.php | 66 +
.../php-generator/src/PhpGenerator/Dumper.php | 288 ++++
.../src/PhpGenerator/EnumCase.php | 36 +
.../src/PhpGenerator/EnumType.php | 148 ++
.../src/PhpGenerator/Extractor.php | 561 ++++++
.../src/PhpGenerator/Factory.php | 365 ++++
.../src/PhpGenerator/GlobalFunction.php | 41 +
.../src/PhpGenerator/Helpers.php | 159 ++
.../src/PhpGenerator/InterfaceType.php | 95 +
.../src/PhpGenerator/Literal.php | 48 +
.../php-generator/src/PhpGenerator/Method.php | 111 ++
.../src/PhpGenerator/Parameter.php | 96 ++
.../src/PhpGenerator/PhpFile.php | 191 ++
.../src/PhpGenerator/PhpLiteral.php | 16 +
.../src/PhpGenerator/PhpNamespace.php | 410 +++++
.../src/PhpGenerator/Printer.php | 539 ++++++
.../src/PhpGenerator/PromotedParameter.php | 35 +
.../src/PhpGenerator/Property.php | 152 ++
.../src/PhpGenerator/PropertyAccessMode.php | 33 +
.../src/PhpGenerator/PropertyHook.php | 123 ++
.../src/PhpGenerator/PropertyHookType.php | 33 +
.../src/PhpGenerator/PsrPrinter.php | 27 +
.../src/PhpGenerator/TraitType.php | 54 +
.../src/PhpGenerator/TraitUse.php | 49 +
.../PhpGenerator/Traits/AttributeAware.php | 49 +
.../src/PhpGenerator/Traits/CommentAware.php | 49 +
.../PhpGenerator/Traits/ConstantsAware.php | 79 +
.../src/PhpGenerator/Traits/FunctionLike.php | 178 ++
.../src/PhpGenerator/Traits/MethodsAware.php | 88 +
.../src/PhpGenerator/Traits/NameAware.php | 48 +
.../PhpGenerator/Traits/PropertiesAware.php | 81 +
.../src/PhpGenerator/Traits/PropertyLike.php | 149 ++
.../src/PhpGenerator/Traits/TraitsAware.php | 76 +
.../PhpGenerator/Traits/VisibilityAware.php | 75 +
.../php-generator/src/PhpGenerator/Type.php | 122 ++
.../src/PhpGenerator/Visibility.php | 34 +
vendor/nette/robot-loader/composer.json | 40 +
vendor/nette/robot-loader/license.md | 60 +
vendor/nette/robot-loader/readme.md | 149 ++
.../src/RobotLoader/RobotLoader.php | 514 ++++++
vendor/nette/routing/.phpstorm.meta.php | 8 +
vendor/nette/routing/composer.json | 40 +
vendor/nette/routing/license.md | 60 +
vendor/nette/routing/readme.md | 530 ++++++
vendor/nette/routing/src/Routing/Route.php | 638 +++++++
.../nette/routing/src/Routing/RouteList.php | 305 ++++
vendor/nette/routing/src/Routing/Router.php | 32 +
.../routing/src/Routing/SimpleRouter.php | 72 +
vendor/nette/schema/composer.json | 39 +
vendor/nette/schema/license.md | 60 +
vendor/nette/schema/readme.md | 537 ++++++
vendor/nette/schema/src/Schema/Context.php | 51 +
.../schema/src/Schema/DynamicParameter.php | 15 +
.../schema/src/Schema/Elements/AnyOf.php | 147 ++
.../nette/schema/src/Schema/Elements/Base.php | 162 ++
.../schema/src/Schema/Elements/Structure.php | 210 +++
.../nette/schema/src/Schema/Elements/Type.php | 208 +++
vendor/nette/schema/src/Schema/Expect.php | 118 ++
vendor/nette/schema/src/Schema/Helpers.php | 183 ++
vendor/nette/schema/src/Schema/Message.php | 98 ++
vendor/nette/schema/src/Schema/Processor.php | 96 ++
vendor/nette/schema/src/Schema/Schema.php | 37 +
.../schema/src/Schema/ValidationException.php | 55 +
vendor/nette/security/composer.json | 46 +
vendor/nette/security/license.md | 60 +
vendor/nette/security/readme.md | 436 +++++
.../Bridges/SecurityDI/SecurityExtension.php | 146 ++
.../Bridges/SecurityHttp/CookieStorage.php | 100 ++
.../Bridges/SecurityHttp/SessionStorage.php | 157 ++
.../src/Bridges/SecurityTracy/UserPanel.php | 62 +
.../templates/UserPanel.panel.phtml | 13 +
.../templates/UserPanel.tab.phtml | 11 +
.../src/Security/AuthenticationException.php | 18 +
.../security/src/Security/Authenticator.php | 42 +
.../security/src/Security/Authorizator.php | 44 +
.../security/src/Security/IAuthenticator.php | 37 +
.../nette/security/src/Security/IIdentity.php | 34 +
.../nette/security/src/Security/Identity.php | 116 ++
.../security/src/Security/IdentityHandler.php | 21 +
.../nette/security/src/Security/Passwords.php | 72 +
.../security/src/Security/Permission.php | 755 ++++++++
.../nette/security/src/Security/Resource.php | 25 +
vendor/nette/security/src/Security/Role.php | 25 +
.../src/Security/SimpleAuthenticator.php | 61 +
.../security/src/Security/SimpleIdentity.php | 18 +
vendor/nette/security/src/Security/User.php | 331 ++++
.../security/src/Security/UserStorage.php | 44 +
vendor/nette/security/src/compatibility.php | 37 +
vendor/nette/tester/composer.json | 39 +
vendor/nette/tester/license.md | 49 +
vendor/nette/tester/readme.md | 237 +++
.../tester/src/CodeCoverage/Collector.php | 197 +++
.../Generators/AbstractGenerator.php | 123 ++
.../Generators/CloverXMLGenerator.php | 225 +++
.../CodeCoverage/Generators/HtmlGenerator.php | 108 ++
.../CodeCoverage/Generators/template.phtml | 587 +++++++
.../tester/src/CodeCoverage/PhpParser.php | 187 ++
vendor/nette/tester/src/Framework/Assert.php | 676 ++++++++
.../tester/src/Framework/AssertException.php | 42 +
.../tester/src/Framework/DataProvider.php | 104 ++
.../nette/tester/src/Framework/DomQuery.php | 159 ++
vendor/nette/tester/src/Framework/Dumper.php | 429 +++++
.../tester/src/Framework/Environment.php | 270 +++
vendor/nette/tester/src/Framework/Expect.php | 126 ++
.../nette/tester/src/Framework/FileMock.php | 217 +++
.../tester/src/Framework/FileMutator.php | 235 +++
vendor/nette/tester/src/Framework/Helpers.php | 152 ++
.../nette/tester/src/Framework/TestCase.php | 294 ++++
.../nette/tester/src/Framework/functions.php | 85 +
vendor/nette/tester/src/Runner/CliTester.php | 394 +++++
.../nette/tester/src/Runner/CommandLine.php | 189 ++
vendor/nette/tester/src/Runner/Job.php | 213 +++
.../src/Runner/Output/ConsolePrinter.php | 169 ++
.../tester/src/Runner/Output/JUnitPrinter.php | 74 +
.../nette/tester/src/Runner/Output/Logger.php | 82 +
.../tester/src/Runner/Output/TapPrinter.php | 65 +
.../nette/tester/src/Runner/OutputHandler.php | 25 +
.../tester/src/Runner/PhpInterpreter.php | 131 ++
vendor/nette/tester/src/Runner/Runner.php | 236 +++
vendor/nette/tester/src/Runner/Test.php | 152 ++
.../nette/tester/src/Runner/TestHandler.php | 307 ++++
vendor/nette/tester/src/Runner/exceptions.php | 15 +
vendor/nette/tester/src/Runner/info.php | 46 +
vendor/nette/tester/src/bootstrap.php | 32 +
vendor/nette/tester/src/tester | 6 +
vendor/nette/tester/src/tester.php | 37 +
vendor/nette/utils/.phpstorm.meta.php | 13 +
vendor/nette/utils/composer.json | 51 +
vendor/nette/utils/license.md | 60 +
vendor/nette/utils/readme.md | 55 +
vendor/nette/utils/src/HtmlStringable.php | 22 +
.../utils/src/Iterators/CachingIterator.php | 150 ++
vendor/nette/utils/src/Iterators/Mapper.php | 33 +
vendor/nette/utils/src/SmartObject.php | 140 ++
vendor/nette/utils/src/StaticClass.php | 34 +
vendor/nette/utils/src/Translator.php | 25 +
vendor/nette/utils/src/Utils/ArrayHash.php | 106 ++
vendor/nette/utils/src/Utils/ArrayList.php | 136 ++
vendor/nette/utils/src/Utils/Arrays.php | 553 ++++++
vendor/nette/utils/src/Utils/Callback.php | 137 ++
vendor/nette/utils/src/Utils/DateTime.php | 140 ++
vendor/nette/utils/src/Utils/FileInfo.php | 69 +
vendor/nette/utils/src/Utils/FileSystem.php | 326 ++++
vendor/nette/utils/src/Utils/Finder.php | 510 ++++++
vendor/nette/utils/src/Utils/Floats.php | 107 ++
vendor/nette/utils/src/Utils/Helpers.php | 104 ++
vendor/nette/utils/src/Utils/Html.php | 839 +++++++++
vendor/nette/utils/src/Utils/Image.php | 831 +++++++++
vendor/nette/utils/src/Utils/ImageColor.php | 75 +
vendor/nette/utils/src/Utils/ImageType.php | 25 +
vendor/nette/utils/src/Utils/Iterables.php | 238 +++
vendor/nette/utils/src/Utils/Json.php | 84 +
.../nette/utils/src/Utils/ObjectHelpers.php | 229 +++
vendor/nette/utils/src/Utils/Paginator.php | 245 +++
vendor/nette/utils/src/Utils/Random.php | 52 +
vendor/nette/utils/src/Utils/Reflection.php | 322 ++++
.../utils/src/Utils/ReflectionMethod.php | 36 +
vendor/nette/utils/src/Utils/Strings.php | 728 ++++++++
vendor/nette/utils/src/Utils/Type.php | 267 +++
vendor/nette/utils/src/Utils/Validators.php | 416 +++++
vendor/nette/utils/src/Utils/exceptions.php | 50 +
vendor/nette/utils/src/compatibility.php | 32 +
vendor/nette/utils/src/exceptions.php | 109 ++
vendor/symfony/thanks/LICENSE | 19 +
vendor/symfony/thanks/README.md | 53 +
vendor/symfony/thanks/composer.json | 27 +
.../thanks/src/Command/FundCommand.php | 92 +
.../thanks/src/Command/ThanksCommand.php | 95 +
vendor/symfony/thanks/src/GitHubClient.php | 234 +++
vendor/symfony/thanks/src/Thanks.php | 132 ++
vendor/tracy/tracy/.phpstorm.meta.php | 10 +
vendor/tracy/tracy/composer.json | 49 +
vendor/tracy/tracy/eslint.config.js | 40 +
vendor/tracy/tracy/examples/ajax-fetch.php | 79 +
vendor/tracy/tracy/examples/ajax-jquery.php | 79 +
.../tracy/examples/assets/E_COMPILE_ERROR.php | 5 +
vendor/tracy/tracy/examples/assets/arrow.png | Bin 0 -> 817 bytes
vendor/tracy/tracy/examples/assets/style.css | 33 +
vendor/tracy/tracy/examples/barDump.php | 32 +
vendor/tracy/tracy/examples/dump-snapshot.php | 56 +
vendor/tracy/tracy/examples/dump.php | 100 ++
vendor/tracy/tracy/examples/exception.php | 52 +
vendor/tracy/tracy/examples/fatal-error.php | 24 +
vendor/tracy/tracy/examples/notice.php | 33 +
.../tracy/tracy/examples/output-debugger.php | 17 +
vendor/tracy/tracy/examples/preloading.php | 34 +
vendor/tracy/tracy/examples/redirect.php | 33 +
vendor/tracy/tracy/examples/warning.php | 26 +
vendor/tracy/tracy/license.md | 55 +
vendor/tracy/tracy/package.json | 13 +
vendor/tracy/tracy/readme.md | 460 +++++
.../tracy/tracy/src/Bridges/Nette/Bridge.php | 158 ++
.../tracy/src/Bridges/Nette/MailSender.php | 57 +
.../src/Bridges/Nette/TracyExtension.php | 184 ++
.../Bridges/Psr/PsrToTracyLoggerAdapter.php | 59 +
.../Bridges/Psr/TracyToPsrLoggerAdapter.php | 58 +
vendor/tracy/tracy/src/Tracy/Bar/Bar.php | 162 ++
.../tracy/src/Tracy/Bar/DefaultBarPanel.php | 55 +
.../tracy/tracy/src/Tracy/Bar/IBarPanel.php | 29 +
.../tracy/tracy/src/Tracy/Bar/assets/bar.css | 304 ++++
.../tracy/tracy/src/Tracy/Bar/assets/bar.js | 680 ++++++++
.../tracy/src/Tracy/Bar/assets/bar.phtml | 31 +
.../tracy/src/Tracy/Bar/assets/loader.phtml | 29 +
.../tracy/src/Tracy/Bar/assets/panels.phtml | 30 +
.../src/Tracy/Bar/panels/dumps.panel.phtml | 29 +
.../src/Tracy/Bar/panels/dumps.tab.phtml | 13 +
.../src/Tracy/Bar/panels/errors.panel.phtml | 20 +
.../src/Tracy/Bar/panels/errors.tab.phtml | 25 +
.../src/Tracy/Bar/panels/info.panel.phtml | 125 ++
.../tracy/src/Tracy/Bar/panels/info.tab.phtml | 15 +
.../tracy/src/Tracy/BlueScreen/BlueScreen.php | 502 ++++++
.../src/Tracy/BlueScreen/CodeHighlighter.php | 139 ++
.../Tracy/BlueScreen/assets/bluescreen.css | 422 +++++
.../src/Tracy/BlueScreen/assets/bluescreen.js | 76 +
.../src/Tracy/BlueScreen/assets/content.phtml | 73 +
.../src/Tracy/BlueScreen/assets/page.phtml | 57 +
.../Tracy/BlueScreen/assets/section-cli.phtml | 36 +
.../assets/section-environment.phtml | 103 ++
.../assets/section-exception-causedBy.phtml | 29 +
.../assets/section-exception-exception.phtml | 21 +
.../BlueScreen/assets/section-exception.phtml | 72 +
.../BlueScreen/assets/section-header.phtml | 35 +
.../BlueScreen/assets/section-http.phtml | 124 ++
.../assets/section-lastMutedError.phtml | 29 +
.../assets/section-stack-callStack.phtml | 92 +
.../assets/section-stack-exception.phtml | 38 +
.../assets/section-stack-fiber.phtml | 16 +
.../assets/section-stack-generator.phtml | 21 +
.../assets/section-stack-sourceFile.phtml | 46 +
.../tracy/src/Tracy/Debugger/Debugger.php | 616 +++++++
.../src/Tracy/Debugger/DeferredContent.php | 155 ++
.../Tracy/Debugger/DevelopmentStrategy.php | 125 ++
.../src/Tracy/Debugger/ProductionStrategy.php | 84 +
.../src/Tracy/Debugger/assets/error.500.phtml | 44 +
.../tracy/src/Tracy/Dumper/Describer.php | 360 ++++
.../tracy/tracy/src/Tracy/Dumper/Dumper.php | 254 +++
.../tracy/tracy/src/Tracy/Dumper/Exposer.php | 277 +++
.../tracy/tracy/src/Tracy/Dumper/Renderer.php | 424 +++++
vendor/tracy/tracy/src/Tracy/Dumper/Value.php | 65 +
.../src/Tracy/Dumper/assets/dumper-dark.css | 145 ++
.../src/Tracy/Dumper/assets/dumper-light.css | 145 ++
.../tracy/src/Tracy/Dumper/assets/dumper.js | 392 +++++
vendor/tracy/tracy/src/Tracy/Helpers.php | 646 +++++++
.../tracy/tracy/src/Tracy/Logger/ILogger.php | 27 +
.../tracy/tracy/src/Tracy/Logger/Logger.php | 195 +++
.../Tracy/OutputDebugger/OutputDebugger.php | 83 +
.../tracy/src/Tracy/Session/FileSession.php | 105 ++
.../tracy/src/Tracy/Session/NativeSession.php | 26 +
.../src/Tracy/Session/SessionStorage.php | 18 +
.../tracy/tracy/src/Tracy/assets/helpers.js | 30 +
vendor/tracy/tracy/src/Tracy/assets/reset.css | 386 +++++
.../tracy/src/Tracy/assets/table-sort.css | 15 +
.../tracy/src/Tracy/assets/table-sort.js | 39 +
vendor/tracy/tracy/src/Tracy/assets/tabs.css | 11 +
vendor/tracy/tracy/src/Tracy/assets/tabs.js | 40 +
.../tracy/tracy/src/Tracy/assets/toggle.css | 35 +
vendor/tracy/tracy/src/Tracy/assets/toggle.js | 116 ++
vendor/tracy/tracy/src/Tracy/functions.php | 46 +
vendor/tracy/tracy/src/tracy.php | 31 +
.../tracy/tools/create-phar/create-phar.php | 87 +
.../tools/open-in-editor/linux/install.sh | 38 +
.../tools/open-in-editor/linux/open-editor.sh | 109 ++
.../tools/open-in-editor/windows/install.cmd | 9 +
.../open-in-editor/windows/open-editor.js | 84 +
www/.htaccess | 41 +
www/favicon.ico | Bin 0 -> 2550 bytes
www/index.php | 10 +
www/robots.txt | 0
842 files changed, 108417 insertions(+)
create mode 100644 .gitignore
create mode 100644 .htaccess
create mode 100644 app/Bootstrap.php
create mode 100644 app/Core/RouterFactory.php
create mode 100644 app/Presentation/@layout.latte
create mode 100644 app/Presentation/Accessory/LatteExtension.php
create mode 100644 app/Presentation/Error/Error4xx/403.latte
create mode 100644 app/Presentation/Error/Error4xx/404.latte
create mode 100644 app/Presentation/Error/Error4xx/410.latte
create mode 100644 app/Presentation/Error/Error4xx/4xx.latte
create mode 100644 app/Presentation/Error/Error4xx/Error4xxPresenter.php
create mode 100644 app/Presentation/Error/Error5xx/500.phtml
create mode 100644 app/Presentation/Error/Error5xx/503.phtml
create mode 100644 app/Presentation/Error/Error5xx/Error5xxPresenter.php
create mode 100644 app/Presentation/Home/HomePresenter.php
create mode 100644 app/Presentation/Home/default.latte
create mode 100644 composer.json
create mode 100644 composer.lock
create mode 100644 config/common.neon
create mode 100644 config/services.neon
create mode 100644 readme.md
create mode 100644 vendor/autoload.php
create mode 100644 vendor/bin/latte-lint
create mode 100644 vendor/bin/latte-lint.bat
create mode 100644 vendor/bin/neon-lint
create mode 100644 vendor/bin/neon-lint.bat
create mode 100644 vendor/bin/tester
create mode 100644 vendor/bin/tester.bat
create mode 100644 vendor/composer/ClassLoader.php
create mode 100644 vendor/composer/InstalledVersions.php
create mode 100644 vendor/composer/LICENSE
create mode 100644 vendor/composer/autoload_classmap.php
create mode 100644 vendor/composer/autoload_files.php
create mode 100644 vendor/composer/autoload_namespaces.php
create mode 100644 vendor/composer/autoload_psr4.php
create mode 100644 vendor/composer/autoload_real.php
create mode 100644 vendor/composer/autoload_static.php
create mode 100644 vendor/composer/installed.json
create mode 100644 vendor/composer/installed.php
create mode 100644 vendor/composer/platform_check.php
create mode 100644 vendor/latte/latte/bin/latte-lint
create mode 100644 vendor/latte/latte/composer.json
create mode 100644 vendor/latte/latte/license.md
create mode 100644 vendor/latte/latte/readme.md
create mode 100644 vendor/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php
create mode 100644 vendor/latte/latte/src/Bridges/Tracy/LattePanel.php
create mode 100644 vendor/latte/latte/src/Bridges/Tracy/TracyExtension.php
create mode 100644 vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.panel.phtml
create mode 100644 vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.tab.phtml
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Block.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Escaper.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/ExpressionBuilder.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Node.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/NodeHelpers.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/NodeTraverser.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/AreaNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/AuxiliaryNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Html/BogusTagNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Html/CommentNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/NopNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArgumentNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ClosureUseNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ComplexTypeNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayAccessNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AuxiliaryNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/BinaryOpNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CastNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClassConstantFetchNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CloneNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ConstantFetchNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/EmptyNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ErrorSuppressNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallableNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InstanceofNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MatchNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallableNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NotNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PropertyFetchNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallableNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticPropertyFetchNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TemporaryNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/TernaryNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/UnaryOpNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/VariableNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ExpressionNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/IdentifierNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/InterpolatedStringPartNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/IntersectionTypeNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListItemNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ListNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/MatchArmNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NullableTypeNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ParameterNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/BooleanNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/FloatNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/IntegerNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/InterpolatedStringNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/NullNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/StringNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ScalarNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/SuperiorTypeNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/UnionTypeNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/Php/VarLikeIdentifierNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/StatementNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/TemplateNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Nodes/TextNode.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/PhpHelpers.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Position.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/PrintContext.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Tag.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/TagLexer.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/TagParser.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/TagParserData.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/TemplateGenerator.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/TemplateLexer.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/TemplateParser.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/TemplateParserHtml.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/Token.php
create mode 100644 vendor/latte/latte/src/Latte/Compiler/TokenStream.php
create mode 100644 vendor/latte/latte/src/Latte/ContentType.php
create mode 100644 vendor/latte/latte/src/Latte/Engine.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/AuxiliaryIterator.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Blueprint.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/CachingIterator.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/CoreExtension.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Filters.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/BlockNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/DebugbreakNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/DefineNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/DoNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/DumpNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/ForNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/IfNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/ImportNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/IncludeFileNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/JumpNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/NAttrNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/NClassNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/NElseNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/NTagNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/ParametersNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/PrintNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/RawPhpNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/RollbackNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/SpacelessNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/SwitchNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/TemplatePrintNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/TemplateTypeNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/TraceNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/TranslateNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/TryNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/VarNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/VarPrintNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/VarTypeNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Nodes/WhileNode.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Passes.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/RawPhpExtension.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/RollbackException.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/Tracer.php
create mode 100644 vendor/latte/latte/src/Latte/Essential/TranslatorExtension.php
create mode 100644 vendor/latte/latte/src/Latte/Extension.php
create mode 100644 vendor/latte/latte/src/Latte/Helpers.php
create mode 100644 vendor/latte/latte/src/Latte/Loader.php
create mode 100644 vendor/latte/latte/src/Latte/Loaders/FileLoader.php
create mode 100644 vendor/latte/latte/src/Latte/Loaders/StringLoader.php
create mode 100644 vendor/latte/latte/src/Latte/Policy.php
create mode 100644 vendor/latte/latte/src/Latte/PositionAwareException.php
create mode 100644 vendor/latte/latte/src/Latte/Runtime/Block.php
create mode 100644 vendor/latte/latte/src/Latte/Runtime/FilterExecutor.php
create mode 100644 vendor/latte/latte/src/Latte/Runtime/FilterInfo.php
create mode 100644 vendor/latte/latte/src/Latte/Runtime/Filters.php
create mode 100644 vendor/latte/latte/src/Latte/Runtime/FunctionExecutor.php
create mode 100644 vendor/latte/latte/src/Latte/Runtime/Html.php
create mode 100644 vendor/latte/latte/src/Latte/Runtime/HtmlStringable.php
create mode 100644 vendor/latte/latte/src/Latte/Runtime/Template.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallableNode.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/Nodes/MethodCallNode.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/Nodes/MethodCallableNode.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/Nodes/PropertyFetchNode.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/Nodes/SandboxNode.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/Nodes/StaticMethodCallNode.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/Nodes/StaticMethodCallableNode.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/Nodes/StaticPropertyFetchNode.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/RuntimeChecker.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/SandboxExtension.php
create mode 100644 vendor/latte/latte/src/Latte/Sandbox/SecurityPolicy.php
create mode 100644 vendor/latte/latte/src/Latte/attributes.php
create mode 100644 vendor/latte/latte/src/Latte/exceptions.php
create mode 100644 vendor/latte/latte/src/Tools/Linter.php
create mode 100644 vendor/nette/application/.phpstorm.meta.php
create mode 100644 vendor/nette/application/composer.json
create mode 100644 vendor/nette/application/license.md
create mode 100644 vendor/nette/application/readme.md
create mode 100644 vendor/nette/application/src/Application/Application.php
create mode 100644 vendor/nette/application/src/Application/Attributes/CrossOrigin.php
create mode 100644 vendor/nette/application/src/Application/Attributes/Deprecated.php
create mode 100644 vendor/nette/application/src/Application/Attributes/Parameter.php
create mode 100644 vendor/nette/application/src/Application/Attributes/Persistent.php
create mode 100644 vendor/nette/application/src/Application/Attributes/Requires.php
create mode 100644 vendor/nette/application/src/Application/ErrorPresenter.php
create mode 100644 vendor/nette/application/src/Application/Helpers.php
create mode 100644 vendor/nette/application/src/Application/IPresenter.php
create mode 100644 vendor/nette/application/src/Application/IPresenterFactory.php
create mode 100644 vendor/nette/application/src/Application/LinkGenerator.php
create mode 100644 vendor/nette/application/src/Application/MicroPresenter.php
create mode 100644 vendor/nette/application/src/Application/PresenterFactory.php
create mode 100644 vendor/nette/application/src/Application/Request.php
create mode 100644 vendor/nette/application/src/Application/Response.php
create mode 100644 vendor/nette/application/src/Application/Responses/CallbackResponse.php
create mode 100644 vendor/nette/application/src/Application/Responses/FileResponse.php
create mode 100644 vendor/nette/application/src/Application/Responses/ForwardResponse.php
create mode 100644 vendor/nette/application/src/Application/Responses/JsonResponse.php
create mode 100644 vendor/nette/application/src/Application/Responses/RedirectResponse.php
create mode 100644 vendor/nette/application/src/Application/Responses/TextResponse.php
create mode 100644 vendor/nette/application/src/Application/Responses/VoidResponse.php
create mode 100644 vendor/nette/application/src/Application/Routers/CliRouter.php
create mode 100644 vendor/nette/application/src/Application/Routers/Route.php
create mode 100644 vendor/nette/application/src/Application/Routers/RouteList.php
create mode 100644 vendor/nette/application/src/Application/Routers/SimpleRouter.php
create mode 100644 vendor/nette/application/src/Application/UI/AccessPolicy.php
create mode 100644 vendor/nette/application/src/Application/UI/BadSignalException.php
create mode 100644 vendor/nette/application/src/Application/UI/Component.php
create mode 100644 vendor/nette/application/src/Application/UI/ComponentReflection.php
create mode 100644 vendor/nette/application/src/Application/UI/Control.php
create mode 100644 vendor/nette/application/src/Application/UI/Form.php
create mode 100644 vendor/nette/application/src/Application/UI/InvalidLinkException.php
create mode 100644 vendor/nette/application/src/Application/UI/Link.php
create mode 100644 vendor/nette/application/src/Application/UI/MethodReflection.php
create mode 100644 vendor/nette/application/src/Application/UI/Multiplier.php
create mode 100644 vendor/nette/application/src/Application/UI/ParameterConverter.php
create mode 100644 vendor/nette/application/src/Application/UI/Presenter.php
create mode 100644 vendor/nette/application/src/Application/UI/Renderable.php
create mode 100644 vendor/nette/application/src/Application/UI/SignalReceiver.php
create mode 100644 vendor/nette/application/src/Application/UI/StatePersistent.php
create mode 100644 vendor/nette/application/src/Application/UI/Template.php
create mode 100644 vendor/nette/application/src/Application/UI/TemplateFactory.php
create mode 100644 vendor/nette/application/src/Application/exceptions.php
create mode 100644 vendor/nette/application/src/Application/templates/error.phtml
create mode 100644 vendor/nette/application/src/Bridges/ApplicationDI/ApplicationExtension.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationDI/LatteExtension.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationDI/PresenterFactoryCallback.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationDI/RoutingExtension.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/DefaultTemplate.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/LatteFactory.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/ControlNode.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/IfCurrentNode.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/LinkNode.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/NNonceNode.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetAreaNode.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetNode.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/TemplatePrintNode.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/SnippetBridge.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/SnippetRuntime.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/Template.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/TemplateFactory.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/UIExtension.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/UIMacros.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationLatte/UIRuntime.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationTracy/RoutingPanel.php
create mode 100644 vendor/nette/application/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml
create mode 100644 vendor/nette/application/src/Bridges/ApplicationTracy/templates/RoutingPanel.tab.phtml
create mode 100644 vendor/nette/application/src/compatibility-intf.php
create mode 100644 vendor/nette/application/src/compatibility.php
create mode 100644 vendor/nette/bootstrap/composer.json
create mode 100644 vendor/nette/bootstrap/config.stub.neon
create mode 100644 vendor/nette/bootstrap/license.md
create mode 100644 vendor/nette/bootstrap/readme.md
create mode 100644 vendor/nette/bootstrap/src/Bootstrap/Configurator.php
create mode 100644 vendor/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php
create mode 100644 vendor/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.php
create mode 100644 vendor/nette/bootstrap/src/Configurator.php
create mode 100644 vendor/nette/caching/composer.json
create mode 100644 vendor/nette/caching/license.md
create mode 100644 vendor/nette/caching/readme.md
create mode 100644 vendor/nette/caching/src/Bridges/CacheDI/CacheExtension.php
create mode 100644 vendor/nette/caching/src/Bridges/CacheLatte/CacheExtension.php
create mode 100644 vendor/nette/caching/src/Bridges/CacheLatte/CacheMacro.php
create mode 100644 vendor/nette/caching/src/Bridges/CacheLatte/Nodes/CacheNode.php
create mode 100644 vendor/nette/caching/src/Bridges/CacheLatte/Runtime.php
create mode 100644 vendor/nette/caching/src/Bridges/Psr/PsrCacheAdapter.php
create mode 100644 vendor/nette/caching/src/Caching/BulkReader.php
create mode 100644 vendor/nette/caching/src/Caching/BulkWriter.php
create mode 100644 vendor/nette/caching/src/Caching/Cache.php
create mode 100644 vendor/nette/caching/src/Caching/OutputHelper.php
create mode 100644 vendor/nette/caching/src/Caching/Storage.php
create mode 100644 vendor/nette/caching/src/Caching/Storages/DevNullStorage.php
create mode 100644 vendor/nette/caching/src/Caching/Storages/FileStorage.php
create mode 100644 vendor/nette/caching/src/Caching/Storages/Journal.php
create mode 100644 vendor/nette/caching/src/Caching/Storages/MemcachedStorage.php
create mode 100644 vendor/nette/caching/src/Caching/Storages/MemoryStorage.php
create mode 100644 vendor/nette/caching/src/Caching/Storages/SQLiteJournal.php
create mode 100644 vendor/nette/caching/src/Caching/Storages/SQLiteStorage.php
create mode 100644 vendor/nette/caching/src/compatibility.php
create mode 100644 vendor/nette/component-model/.phpstorm.meta.php
create mode 100644 vendor/nette/component-model/composer.json
create mode 100644 vendor/nette/component-model/license.md
create mode 100644 vendor/nette/component-model/readme.md
create mode 100644 vendor/nette/component-model/src/ComponentModel/ArrayAccess.php
create mode 100644 vendor/nette/component-model/src/ComponentModel/Component.php
create mode 100644 vendor/nette/component-model/src/ComponentModel/Container.php
create mode 100644 vendor/nette/component-model/src/ComponentModel/IComponent.php
create mode 100644 vendor/nette/component-model/src/ComponentModel/IContainer.php
create mode 100644 vendor/nette/component-model/src/ComponentModel/RecursiveComponentIterator.php
create mode 100644 vendor/nette/database/composer.json
create mode 100644 vendor/nette/database/license.md
create mode 100644 vendor/nette/database/readme.md
create mode 100644 vendor/nette/database/src/Bridges/DatabaseDI/DatabaseExtension.php
create mode 100644 vendor/nette/database/src/Bridges/DatabaseTracy/ConnectionPanel.php
create mode 100644 vendor/nette/database/src/Bridges/DatabaseTracy/dist/panel.phtml
create mode 100644 vendor/nette/database/src/Bridges/DatabaseTracy/dist/tab.phtml
create mode 100644 vendor/nette/database/src/Bridges/DatabaseTracy/panel.latte
create mode 100644 vendor/nette/database/src/Bridges/DatabaseTracy/tab.latte
create mode 100644 vendor/nette/database/src/Database/Connection.php
create mode 100644 vendor/nette/database/src/Database/Conventions.php
create mode 100644 vendor/nette/database/src/Database/Conventions/AmbiguousReferenceKeyException.php
create mode 100644 vendor/nette/database/src/Database/Conventions/DiscoveredConventions.php
create mode 100644 vendor/nette/database/src/Database/Conventions/StaticConventions.php
create mode 100644 vendor/nette/database/src/Database/DateTime.php
create mode 100644 vendor/nette/database/src/Database/Driver.php
create mode 100644 vendor/nette/database/src/Database/DriverException.php
create mode 100644 vendor/nette/database/src/Database/Drivers/MsSqlDriver.php
create mode 100644 vendor/nette/database/src/Database/Drivers/MySqlDriver.php
create mode 100644 vendor/nette/database/src/Database/Drivers/OciDriver.php
create mode 100644 vendor/nette/database/src/Database/Drivers/OdbcDriver.php
create mode 100644 vendor/nette/database/src/Database/Drivers/PgSqlDriver.php
create mode 100644 vendor/nette/database/src/Database/Drivers/SqliteDriver.php
create mode 100644 vendor/nette/database/src/Database/Drivers/SqlsrvDriver.php
create mode 100644 vendor/nette/database/src/Database/Explorer.php
create mode 100644 vendor/nette/database/src/Database/Helpers.php
create mode 100644 vendor/nette/database/src/Database/IRow.php
create mode 100644 vendor/nette/database/src/Database/IRowContainer.php
create mode 100644 vendor/nette/database/src/Database/IStructure.php
create mode 100644 vendor/nette/database/src/Database/Reflection.php
create mode 100644 vendor/nette/database/src/Database/Reflection/Column.php
create mode 100644 vendor/nette/database/src/Database/Reflection/ForeignKey.php
create mode 100644 vendor/nette/database/src/Database/Reflection/Index.php
create mode 100644 vendor/nette/database/src/Database/Reflection/Table.php
create mode 100644 vendor/nette/database/src/Database/ResultSet.php
create mode 100644 vendor/nette/database/src/Database/Row.php
create mode 100644 vendor/nette/database/src/Database/SqlLiteral.php
create mode 100644 vendor/nette/database/src/Database/SqlPreprocessor.php
create mode 100644 vendor/nette/database/src/Database/Structure.php
create mode 100644 vendor/nette/database/src/Database/Table/ActiveRow.php
create mode 100644 vendor/nette/database/src/Database/Table/GroupedSelection.php
create mode 100644 vendor/nette/database/src/Database/Table/IRow.php
create mode 100644 vendor/nette/database/src/Database/Table/IRowContainer.php
create mode 100644 vendor/nette/database/src/Database/Table/Selection.php
create mode 100644 vendor/nette/database/src/Database/Table/SqlBuilder.php
create mode 100644 vendor/nette/database/src/Database/exceptions.php
create mode 100644 vendor/nette/database/src/compatibility-intf.php
create mode 100644 vendor/nette/database/src/compatibility.php
create mode 100644 vendor/nette/di/.phpstorm.meta.php
create mode 100644 vendor/nette/di/composer.json
create mode 100644 vendor/nette/di/license.md
create mode 100644 vendor/nette/di/readme.md
create mode 100644 vendor/nette/di/src/Bridges/DITracy/ContainerPanel.php
create mode 100644 vendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.panel.phtml
create mode 100644 vendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.tab.phtml
create mode 100644 vendor/nette/di/src/DI/Attributes/Inject.php
create mode 100644 vendor/nette/di/src/DI/Autowiring.php
create mode 100644 vendor/nette/di/src/DI/Compiler.php
create mode 100644 vendor/nette/di/src/DI/CompilerExtension.php
create mode 100644 vendor/nette/di/src/DI/Config/Adapter.php
create mode 100644 vendor/nette/di/src/DI/Config/Adapters/NeonAdapter.php
create mode 100644 vendor/nette/di/src/DI/Config/Adapters/PhpAdapter.php
create mode 100644 vendor/nette/di/src/DI/Config/Helpers.php
create mode 100644 vendor/nette/di/src/DI/Config/Loader.php
create mode 100644 vendor/nette/di/src/DI/Container.php
create mode 100644 vendor/nette/di/src/DI/ContainerBuilder.php
create mode 100644 vendor/nette/di/src/DI/ContainerLoader.php
create mode 100644 vendor/nette/di/src/DI/Definitions/AccessorDefinition.php
create mode 100644 vendor/nette/di/src/DI/Definitions/Definition.php
create mode 100644 vendor/nette/di/src/DI/Definitions/FactoryDefinition.php
create mode 100644 vendor/nette/di/src/DI/Definitions/ImportedDefinition.php
create mode 100644 vendor/nette/di/src/DI/Definitions/LocatorDefinition.php
create mode 100644 vendor/nette/di/src/DI/Definitions/Reference.php
create mode 100644 vendor/nette/di/src/DI/Definitions/ServiceDefinition.php
create mode 100644 vendor/nette/di/src/DI/Definitions/Statement.php
create mode 100644 vendor/nette/di/src/DI/DependencyChecker.php
create mode 100644 vendor/nette/di/src/DI/DynamicParameter.php
create mode 100644 vendor/nette/di/src/DI/Extensions/DIExtension.php
create mode 100644 vendor/nette/di/src/DI/Extensions/DecoratorExtension.php
create mode 100644 vendor/nette/di/src/DI/Extensions/DefinitionSchema.php
create mode 100644 vendor/nette/di/src/DI/Extensions/ExtensionsExtension.php
create mode 100644 vendor/nette/di/src/DI/Extensions/InjectExtension.php
create mode 100644 vendor/nette/di/src/DI/Extensions/ParametersExtension.php
create mode 100644 vendor/nette/di/src/DI/Extensions/SearchExtension.php
create mode 100644 vendor/nette/di/src/DI/Extensions/ServicesExtension.php
create mode 100644 vendor/nette/di/src/DI/Helpers.php
create mode 100644 vendor/nette/di/src/DI/PhpGenerator.php
create mode 100644 vendor/nette/di/src/DI/Resolver.php
create mode 100644 vendor/nette/di/src/DI/exceptions.php
create mode 100644 vendor/nette/di/src/compatibility.php
create mode 100644 vendor/nette/forms/.phpstorm.meta.php
create mode 100644 vendor/nette/forms/composer.json
create mode 100644 vendor/nette/forms/eslint.config.js
create mode 100644 vendor/nette/forms/examples/assets/logo.png
create mode 100644 vendor/nette/forms/examples/assets/style.css
create mode 100644 vendor/nette/forms/examples/basic-example.php
create mode 100644 vendor/nette/forms/examples/bootstrap4-rendering.php
create mode 100644 vendor/nette/forms/examples/bootstrap5-rendering.php
create mode 100644 vendor/nette/forms/examples/containers.php
create mode 100644 vendor/nette/forms/examples/custom-control.php
create mode 100644 vendor/nette/forms/examples/custom-rendering.php
create mode 100644 vendor/nette/forms/examples/custom-validator.php
create mode 100644 vendor/nette/forms/examples/html5.php
create mode 100644 vendor/nette/forms/examples/latte.php
create mode 100644 vendor/nette/forms/examples/latte/form-bootstrap5.latte
create mode 100644 vendor/nette/forms/examples/latte/form.latte
create mode 100644 vendor/nette/forms/examples/latte/page.latte
create mode 100644 vendor/nette/forms/examples/live-validation.php
create mode 100644 vendor/nette/forms/examples/localization.ini
create mode 100644 vendor/nette/forms/examples/localization.php
create mode 100644 vendor/nette/forms/examples/manual-rendering.php
create mode 100644 vendor/nette/forms/license.md
create mode 100644 vendor/nette/forms/package.json
create mode 100644 vendor/nette/forms/readme.md
create mode 100644 vendor/nette/forms/rollup.config.js
create mode 100644 vendor/nette/forms/src/Bridges/FormsDI/FormsExtension.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/FormMacros.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/FormsExtension.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FieldNNameNode.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FormContainerNode.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FormNNameNode.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FormNode.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/Nodes/FormPrintNode.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/Nodes/InputErrorNode.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/Nodes/InputNode.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/Nodes/LabelNode.php
create mode 100644 vendor/nette/forms/src/Bridges/FormsLatte/Runtime.php
create mode 100644 vendor/nette/forms/src/Forms/Blueprint.php
create mode 100644 vendor/nette/forms/src/Forms/Container.php
create mode 100644 vendor/nette/forms/src/Forms/Control.php
create mode 100644 vendor/nette/forms/src/Forms/ControlGroup.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/BaseControl.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/Button.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/Checkbox.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/CheckboxList.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/ChoiceControl.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/ColorPicker.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/CsrfProtection.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/DateTimeControl.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/HiddenField.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/ImageButton.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/MultiChoiceControl.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/MultiSelectBox.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/RadioList.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/SelectBox.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/SubmitButton.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/TextArea.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/TextBase.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/TextInput.php
create mode 100644 vendor/nette/forms/src/Forms/Controls/UploadControl.php
create mode 100644 vendor/nette/forms/src/Forms/Form.php
create mode 100644 vendor/nette/forms/src/Forms/FormRenderer.php
create mode 100644 vendor/nette/forms/src/Forms/Helpers.php
create mode 100644 vendor/nette/forms/src/Forms/Rendering/DataClassGenerator.php
create mode 100644 vendor/nette/forms/src/Forms/Rendering/DefaultFormRenderer.php
create mode 100644 vendor/nette/forms/src/Forms/Rendering/LatteRenderer.php
create mode 100644 vendor/nette/forms/src/Forms/Rule.php
create mode 100644 vendor/nette/forms/src/Forms/Rules.php
create mode 100644 vendor/nette/forms/src/Forms/SubmitterControl.php
create mode 100644 vendor/nette/forms/src/Forms/Validator.php
create mode 100644 vendor/nette/forms/src/assets/formValidator.ts
create mode 100644 vendor/nette/forms/src/assets/index.umd.ts
create mode 100644 vendor/nette/forms/src/assets/netteForms.js
create mode 100644 vendor/nette/forms/src/assets/netteForms.min.js
create mode 100644 vendor/nette/forms/src/assets/package.json
create mode 100644 vendor/nette/forms/src/assets/types.ts
create mode 100644 vendor/nette/forms/src/assets/validators.ts
create mode 100644 vendor/nette/forms/src/assets/webalize.ts
create mode 100644 vendor/nette/forms/src/compatibility.php
create mode 100644 vendor/nette/forms/tsconfig.json
create mode 100644 vendor/nette/http/.phpstorm.meta.php
create mode 100644 vendor/nette/http/composer.json
create mode 100644 vendor/nette/http/license.md
create mode 100644 vendor/nette/http/readme.md
create mode 100644 vendor/nette/http/src/Bridges/HttpDI/HttpExtension.php
create mode 100644 vendor/nette/http/src/Bridges/HttpDI/SessionExtension.php
create mode 100644 vendor/nette/http/src/Bridges/HttpTracy/SessionPanel.php
create mode 100644 vendor/nette/http/src/Bridges/HttpTracy/dist/panel.phtml
create mode 100644 vendor/nette/http/src/Bridges/HttpTracy/dist/tab.phtml
create mode 100644 vendor/nette/http/src/Bridges/HttpTracy/panel.latte
create mode 100644 vendor/nette/http/src/Bridges/HttpTracy/tab.latte
create mode 100644 vendor/nette/http/src/Http/Context.php
create mode 100644 vendor/nette/http/src/Http/FileUpload.php
create mode 100644 vendor/nette/http/src/Http/Helpers.php
create mode 100644 vendor/nette/http/src/Http/IRequest.php
create mode 100644 vendor/nette/http/src/Http/IResponse.php
create mode 100644 vendor/nette/http/src/Http/Request.php
create mode 100644 vendor/nette/http/src/Http/RequestFactory.php
create mode 100644 vendor/nette/http/src/Http/Response.php
create mode 100644 vendor/nette/http/src/Http/Session.php
create mode 100644 vendor/nette/http/src/Http/SessionSection.php
create mode 100644 vendor/nette/http/src/Http/Url.php
create mode 100644 vendor/nette/http/src/Http/UrlImmutable.php
create mode 100644 vendor/nette/http/src/Http/UrlScript.php
create mode 100644 vendor/nette/http/src/Http/UserStorage.php
create mode 100644 vendor/nette/mail/.phpstorm.meta.php
create mode 100644 vendor/nette/mail/composer.json
create mode 100644 vendor/nette/mail/license.md
create mode 100644 vendor/nette/mail/readme.md
create mode 100644 vendor/nette/mail/src/Bridges/MailDI/MailExtension.php
create mode 100644 vendor/nette/mail/src/Mail/DkimSigner.php
create mode 100644 vendor/nette/mail/src/Mail/FallbackMailer.php
create mode 100644 vendor/nette/mail/src/Mail/Mailer.php
create mode 100644 vendor/nette/mail/src/Mail/Message.php
create mode 100644 vendor/nette/mail/src/Mail/MimePart.php
create mode 100644 vendor/nette/mail/src/Mail/SendmailMailer.php
create mode 100644 vendor/nette/mail/src/Mail/Signer.php
create mode 100644 vendor/nette/mail/src/Mail/SmtpMailer.php
create mode 100644 vendor/nette/mail/src/Mail/exceptions.php
create mode 100644 vendor/nette/neon/bin/neon-lint
create mode 100644 vendor/nette/neon/composer.json
create mode 100644 vendor/nette/neon/license.md
create mode 100644 vendor/nette/neon/readme.md
create mode 100644 vendor/nette/neon/src/Neon/Decoder.php
create mode 100644 vendor/nette/neon/src/Neon/Encoder.php
create mode 100644 vendor/nette/neon/src/Neon/Entity.php
create mode 100644 vendor/nette/neon/src/Neon/Exception.php
create mode 100644 vendor/nette/neon/src/Neon/Lexer.php
create mode 100644 vendor/nette/neon/src/Neon/Neon.php
create mode 100644 vendor/nette/neon/src/Neon/Node.php
create mode 100644 vendor/nette/neon/src/Neon/Node/ArrayItemNode.php
create mode 100644 vendor/nette/neon/src/Neon/Node/ArrayNode.php
create mode 100644 vendor/nette/neon/src/Neon/Node/BlockArrayNode.php
create mode 100644 vendor/nette/neon/src/Neon/Node/EntityChainNode.php
create mode 100644 vendor/nette/neon/src/Neon/Node/EntityNode.php
create mode 100644 vendor/nette/neon/src/Neon/Node/InlineArrayNode.php
create mode 100644 vendor/nette/neon/src/Neon/Node/LiteralNode.php
create mode 100644 vendor/nette/neon/src/Neon/Node/StringNode.php
create mode 100644 vendor/nette/neon/src/Neon/Parser.php
create mode 100644 vendor/nette/neon/src/Neon/Token.php
create mode 100644 vendor/nette/neon/src/Neon/TokenStream.php
create mode 100644 vendor/nette/neon/src/Neon/Traverser.php
create mode 100644 vendor/nette/php-generator/composer.json
create mode 100644 vendor/nette/php-generator/license.md
create mode 100644 vendor/nette/php-generator/readme.md
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Attribute.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/ClassLike.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/ClassManipulator.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/ClassType.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Closure.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Constant.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Dumper.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/EnumCase.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/EnumType.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Extractor.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Factory.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/GlobalFunction.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Helpers.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/InterfaceType.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Literal.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Method.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Parameter.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/PhpFile.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/PhpLiteral.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/PhpNamespace.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Printer.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/PromotedParameter.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Property.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/PropertyAccessMode.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/PropertyHook.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/PropertyHookType.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/PsrPrinter.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/TraitType.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/TraitUse.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/AttributeAware.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/CommentAware.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/ConstantsAware.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/FunctionLike.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/MethodsAware.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/NameAware.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/PropertiesAware.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/PropertyLike.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/TraitsAware.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Traits/VisibilityAware.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Type.php
create mode 100644 vendor/nette/php-generator/src/PhpGenerator/Visibility.php
create mode 100644 vendor/nette/robot-loader/composer.json
create mode 100644 vendor/nette/robot-loader/license.md
create mode 100644 vendor/nette/robot-loader/readme.md
create mode 100644 vendor/nette/robot-loader/src/RobotLoader/RobotLoader.php
create mode 100644 vendor/nette/routing/.phpstorm.meta.php
create mode 100644 vendor/nette/routing/composer.json
create mode 100644 vendor/nette/routing/license.md
create mode 100644 vendor/nette/routing/readme.md
create mode 100644 vendor/nette/routing/src/Routing/Route.php
create mode 100644 vendor/nette/routing/src/Routing/RouteList.php
create mode 100644 vendor/nette/routing/src/Routing/Router.php
create mode 100644 vendor/nette/routing/src/Routing/SimpleRouter.php
create mode 100644 vendor/nette/schema/composer.json
create mode 100644 vendor/nette/schema/license.md
create mode 100644 vendor/nette/schema/readme.md
create mode 100644 vendor/nette/schema/src/Schema/Context.php
create mode 100644 vendor/nette/schema/src/Schema/DynamicParameter.php
create mode 100644 vendor/nette/schema/src/Schema/Elements/AnyOf.php
create mode 100644 vendor/nette/schema/src/Schema/Elements/Base.php
create mode 100644 vendor/nette/schema/src/Schema/Elements/Structure.php
create mode 100644 vendor/nette/schema/src/Schema/Elements/Type.php
create mode 100644 vendor/nette/schema/src/Schema/Expect.php
create mode 100644 vendor/nette/schema/src/Schema/Helpers.php
create mode 100644 vendor/nette/schema/src/Schema/Message.php
create mode 100644 vendor/nette/schema/src/Schema/Processor.php
create mode 100644 vendor/nette/schema/src/Schema/Schema.php
create mode 100644 vendor/nette/schema/src/Schema/ValidationException.php
create mode 100644 vendor/nette/security/composer.json
create mode 100644 vendor/nette/security/license.md
create mode 100644 vendor/nette/security/readme.md
create mode 100644 vendor/nette/security/src/Bridges/SecurityDI/SecurityExtension.php
create mode 100644 vendor/nette/security/src/Bridges/SecurityHttp/CookieStorage.php
create mode 100644 vendor/nette/security/src/Bridges/SecurityHttp/SessionStorage.php
create mode 100644 vendor/nette/security/src/Bridges/SecurityTracy/UserPanel.php
create mode 100644 vendor/nette/security/src/Bridges/SecurityTracy/templates/UserPanel.panel.phtml
create mode 100644 vendor/nette/security/src/Bridges/SecurityTracy/templates/UserPanel.tab.phtml
create mode 100644 vendor/nette/security/src/Security/AuthenticationException.php
create mode 100644 vendor/nette/security/src/Security/Authenticator.php
create mode 100644 vendor/nette/security/src/Security/Authorizator.php
create mode 100644 vendor/nette/security/src/Security/IAuthenticator.php
create mode 100644 vendor/nette/security/src/Security/IIdentity.php
create mode 100644 vendor/nette/security/src/Security/Identity.php
create mode 100644 vendor/nette/security/src/Security/IdentityHandler.php
create mode 100644 vendor/nette/security/src/Security/Passwords.php
create mode 100644 vendor/nette/security/src/Security/Permission.php
create mode 100644 vendor/nette/security/src/Security/Resource.php
create mode 100644 vendor/nette/security/src/Security/Role.php
create mode 100644 vendor/nette/security/src/Security/SimpleAuthenticator.php
create mode 100644 vendor/nette/security/src/Security/SimpleIdentity.php
create mode 100644 vendor/nette/security/src/Security/User.php
create mode 100644 vendor/nette/security/src/Security/UserStorage.php
create mode 100644 vendor/nette/security/src/compatibility.php
create mode 100644 vendor/nette/tester/composer.json
create mode 100644 vendor/nette/tester/license.md
create mode 100644 vendor/nette/tester/readme.md
create mode 100644 vendor/nette/tester/src/CodeCoverage/Collector.php
create mode 100644 vendor/nette/tester/src/CodeCoverage/Generators/AbstractGenerator.php
create mode 100644 vendor/nette/tester/src/CodeCoverage/Generators/CloverXMLGenerator.php
create mode 100644 vendor/nette/tester/src/CodeCoverage/Generators/HtmlGenerator.php
create mode 100644 vendor/nette/tester/src/CodeCoverage/Generators/template.phtml
create mode 100644 vendor/nette/tester/src/CodeCoverage/PhpParser.php
create mode 100644 vendor/nette/tester/src/Framework/Assert.php
create mode 100644 vendor/nette/tester/src/Framework/AssertException.php
create mode 100644 vendor/nette/tester/src/Framework/DataProvider.php
create mode 100644 vendor/nette/tester/src/Framework/DomQuery.php
create mode 100644 vendor/nette/tester/src/Framework/Dumper.php
create mode 100644 vendor/nette/tester/src/Framework/Environment.php
create mode 100644 vendor/nette/tester/src/Framework/Expect.php
create mode 100644 vendor/nette/tester/src/Framework/FileMock.php
create mode 100644 vendor/nette/tester/src/Framework/FileMutator.php
create mode 100644 vendor/nette/tester/src/Framework/Helpers.php
create mode 100644 vendor/nette/tester/src/Framework/TestCase.php
create mode 100644 vendor/nette/tester/src/Framework/functions.php
create mode 100644 vendor/nette/tester/src/Runner/CliTester.php
create mode 100644 vendor/nette/tester/src/Runner/CommandLine.php
create mode 100644 vendor/nette/tester/src/Runner/Job.php
create mode 100644 vendor/nette/tester/src/Runner/Output/ConsolePrinter.php
create mode 100644 vendor/nette/tester/src/Runner/Output/JUnitPrinter.php
create mode 100644 vendor/nette/tester/src/Runner/Output/Logger.php
create mode 100644 vendor/nette/tester/src/Runner/Output/TapPrinter.php
create mode 100644 vendor/nette/tester/src/Runner/OutputHandler.php
create mode 100644 vendor/nette/tester/src/Runner/PhpInterpreter.php
create mode 100644 vendor/nette/tester/src/Runner/Runner.php
create mode 100644 vendor/nette/tester/src/Runner/Test.php
create mode 100644 vendor/nette/tester/src/Runner/TestHandler.php
create mode 100644 vendor/nette/tester/src/Runner/exceptions.php
create mode 100644 vendor/nette/tester/src/Runner/info.php
create mode 100644 vendor/nette/tester/src/bootstrap.php
create mode 100644 vendor/nette/tester/src/tester
create mode 100644 vendor/nette/tester/src/tester.php
create mode 100644 vendor/nette/utils/.phpstorm.meta.php
create mode 100644 vendor/nette/utils/composer.json
create mode 100644 vendor/nette/utils/license.md
create mode 100644 vendor/nette/utils/readme.md
create mode 100644 vendor/nette/utils/src/HtmlStringable.php
create mode 100644 vendor/nette/utils/src/Iterators/CachingIterator.php
create mode 100644 vendor/nette/utils/src/Iterators/Mapper.php
create mode 100644 vendor/nette/utils/src/SmartObject.php
create mode 100644 vendor/nette/utils/src/StaticClass.php
create mode 100644 vendor/nette/utils/src/Translator.php
create mode 100644 vendor/nette/utils/src/Utils/ArrayHash.php
create mode 100644 vendor/nette/utils/src/Utils/ArrayList.php
create mode 100644 vendor/nette/utils/src/Utils/Arrays.php
create mode 100644 vendor/nette/utils/src/Utils/Callback.php
create mode 100644 vendor/nette/utils/src/Utils/DateTime.php
create mode 100644 vendor/nette/utils/src/Utils/FileInfo.php
create mode 100644 vendor/nette/utils/src/Utils/FileSystem.php
create mode 100644 vendor/nette/utils/src/Utils/Finder.php
create mode 100644 vendor/nette/utils/src/Utils/Floats.php
create mode 100644 vendor/nette/utils/src/Utils/Helpers.php
create mode 100644 vendor/nette/utils/src/Utils/Html.php
create mode 100644 vendor/nette/utils/src/Utils/Image.php
create mode 100644 vendor/nette/utils/src/Utils/ImageColor.php
create mode 100644 vendor/nette/utils/src/Utils/ImageType.php
create mode 100644 vendor/nette/utils/src/Utils/Iterables.php
create mode 100644 vendor/nette/utils/src/Utils/Json.php
create mode 100644 vendor/nette/utils/src/Utils/ObjectHelpers.php
create mode 100644 vendor/nette/utils/src/Utils/Paginator.php
create mode 100644 vendor/nette/utils/src/Utils/Random.php
create mode 100644 vendor/nette/utils/src/Utils/Reflection.php
create mode 100644 vendor/nette/utils/src/Utils/ReflectionMethod.php
create mode 100644 vendor/nette/utils/src/Utils/Strings.php
create mode 100644 vendor/nette/utils/src/Utils/Type.php
create mode 100644 vendor/nette/utils/src/Utils/Validators.php
create mode 100644 vendor/nette/utils/src/Utils/exceptions.php
create mode 100644 vendor/nette/utils/src/compatibility.php
create mode 100644 vendor/nette/utils/src/exceptions.php
create mode 100644 vendor/symfony/thanks/LICENSE
create mode 100644 vendor/symfony/thanks/README.md
create mode 100644 vendor/symfony/thanks/composer.json
create mode 100644 vendor/symfony/thanks/src/Command/FundCommand.php
create mode 100644 vendor/symfony/thanks/src/Command/ThanksCommand.php
create mode 100644 vendor/symfony/thanks/src/GitHubClient.php
create mode 100644 vendor/symfony/thanks/src/Thanks.php
create mode 100644 vendor/tracy/tracy/.phpstorm.meta.php
create mode 100644 vendor/tracy/tracy/composer.json
create mode 100644 vendor/tracy/tracy/eslint.config.js
create mode 100644 vendor/tracy/tracy/examples/ajax-fetch.php
create mode 100644 vendor/tracy/tracy/examples/ajax-jquery.php
create mode 100644 vendor/tracy/tracy/examples/assets/E_COMPILE_ERROR.php
create mode 100644 vendor/tracy/tracy/examples/assets/arrow.png
create mode 100644 vendor/tracy/tracy/examples/assets/style.css
create mode 100644 vendor/tracy/tracy/examples/barDump.php
create mode 100644 vendor/tracy/tracy/examples/dump-snapshot.php
create mode 100644 vendor/tracy/tracy/examples/dump.php
create mode 100644 vendor/tracy/tracy/examples/exception.php
create mode 100644 vendor/tracy/tracy/examples/fatal-error.php
create mode 100644 vendor/tracy/tracy/examples/notice.php
create mode 100644 vendor/tracy/tracy/examples/output-debugger.php
create mode 100644 vendor/tracy/tracy/examples/preloading.php
create mode 100644 vendor/tracy/tracy/examples/redirect.php
create mode 100644 vendor/tracy/tracy/examples/warning.php
create mode 100644 vendor/tracy/tracy/license.md
create mode 100644 vendor/tracy/tracy/package.json
create mode 100644 vendor/tracy/tracy/readme.md
create mode 100644 vendor/tracy/tracy/src/Bridges/Nette/Bridge.php
create mode 100644 vendor/tracy/tracy/src/Bridges/Nette/MailSender.php
create mode 100644 vendor/tracy/tracy/src/Bridges/Nette/TracyExtension.php
create mode 100644 vendor/tracy/tracy/src/Bridges/Psr/PsrToTracyLoggerAdapter.php
create mode 100644 vendor/tracy/tracy/src/Bridges/Psr/TracyToPsrLoggerAdapter.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/Bar.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/DefaultBarPanel.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/IBarPanel.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/assets/bar.css
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/assets/bar.js
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/assets/bar.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/assets/loader.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/assets/panels.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/panels/dumps.panel.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/panels/dumps.tab.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/panels/errors.panel.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/panels/errors.tab.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/panels/info.panel.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Bar/panels/info.tab.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/CodeHighlighter.php
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.css
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.js
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/content.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/page.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-cli.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-environment.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-causedBy.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-exception.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-header.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-http.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-lastMutedError.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-exception.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-fiber.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-generator.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Debugger/Debugger.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Debugger/DeferredContent.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Debugger/DevelopmentStrategy.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Debugger/ProductionStrategy.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Debugger/assets/error.500.phtml
create mode 100644 vendor/tracy/tracy/src/Tracy/Dumper/Describer.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Dumper/Dumper.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Dumper/Exposer.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Dumper/Renderer.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Dumper/Value.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-dark.css
create mode 100644 vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-light.css
create mode 100644 vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper.js
create mode 100644 vendor/tracy/tracy/src/Tracy/Helpers.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Logger/ILogger.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Logger/Logger.php
create mode 100644 vendor/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Session/FileSession.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Session/NativeSession.php
create mode 100644 vendor/tracy/tracy/src/Tracy/Session/SessionStorage.php
create mode 100644 vendor/tracy/tracy/src/Tracy/assets/helpers.js
create mode 100644 vendor/tracy/tracy/src/Tracy/assets/reset.css
create mode 100644 vendor/tracy/tracy/src/Tracy/assets/table-sort.css
create mode 100644 vendor/tracy/tracy/src/Tracy/assets/table-sort.js
create mode 100644 vendor/tracy/tracy/src/Tracy/assets/tabs.css
create mode 100644 vendor/tracy/tracy/src/Tracy/assets/tabs.js
create mode 100644 vendor/tracy/tracy/src/Tracy/assets/toggle.css
create mode 100644 vendor/tracy/tracy/src/Tracy/assets/toggle.js
create mode 100644 vendor/tracy/tracy/src/Tracy/functions.php
create mode 100644 vendor/tracy/tracy/src/tracy.php
create mode 100644 vendor/tracy/tracy/tools/create-phar/create-phar.php
create mode 100644 vendor/tracy/tracy/tools/open-in-editor/linux/install.sh
create mode 100644 vendor/tracy/tracy/tools/open-in-editor/linux/open-editor.sh
create mode 100644 vendor/tracy/tracy/tools/open-in-editor/windows/install.cmd
create mode 100644 vendor/tracy/tracy/tools/open-in-editor/windows/open-editor.js
create mode 100644 www/.htaccess
create mode 100644 www/favicon.ico
create mode 100644 www/index.php
create mode 100644 www/robots.txt
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7f126b3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+## 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
+.vscode/
+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/app/Bootstrap.php b/app/Bootstrap.php
new file mode 100644
index 0000000..1724498
--- /dev/null
+++ b/app/Bootstrap.php
@@ -0,0 +1,50 @@
+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->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/RouterFactory.php b/app/Core/RouterFactory.php
new file mode 100644
index 0000000..3b1a285
--- /dev/null
+++ b/app/Core/RouterFactory.php
@@ -0,0 +1,21 @@
+addRoute('/[/]', 'Home:default');
+ return $router;
+ }
+}
diff --git a/app/Presentation/@layout.latte b/app/Presentation/@layout.latte
new file mode 100644
index 0000000..d3b9933
--- /dev/null
+++ b/app/Presentation/@layout.latte
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ {ifset title}{include title|stripHtml} | {/ifset}Nette Web
+
+
+
+ {$flash->message}
+
+ {include content}
+
+ {block scripts}
+
+ {/block}
+
+
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 @@
+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..dc678e6
--- /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..3b212c9
--- /dev/null
+++ b/app/Presentation/Home/HomePresenter.php
@@ -0,0 +1,12 @@
+
+ Congratulations!
+
+
+
+
You have successfully created your Nette Web project.
+
+
+ If you are exploring Nette for the first time, you should read the
+ Quick Start , documentation ,
+ blog and forum .
+
+
We hope you enjoy Nette!
+
+
+
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..00513be
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,38 @@
+{
+ "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.1",
+ "nette/application": "^3.2.3",
+ "nette/bootstrap": "^3.2",
+ "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.0",
+ "tracy/tracy": "^2.10"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5",
+ "symfony/thanks": "^1"
+ },
+ "autoload": {
+ "psr-4": {
+ "App\\": "app"
+ }
+ },
+ "minimum-stability": "stable",
+ "config": {
+ "allow-plugins": {
+ "symfony/thanks": true
+ }
+ }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..50e123b
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,1489 @@
+{
+ "_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": "9c49a418f02ffb235919088891200a26",
+ "packages": [
+ {
+ "name": "latte/latte",
+ "version": "v3.0.20",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/latte.git",
+ "reference": "4db7a5502f8cef02fffa84fc9c34a635d9c79d4d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/latte/zipball/4db7a5502f8cef02fffa84fc9c34a635d9c79d4d",
+ "reference": "4db7a5502f8cef02fffa84fc9c34a635d9c79d4d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": "8.0 - 8.4"
+ },
+ "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": "^1",
+ "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.0-dev"
+ }
+ },
+ "autoload": {
+ "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.0.20"
+ },
+ "time": "2024-10-08T00:58:27+00:00"
+ },
+ {
+ "name": "nette/application",
+ "version": "v3.2.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/application.git",
+ "reference": "9c288cc45df467dc012504f4ad64791279720af8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/application/zipball/9c288cc45df467dc012504f4ad64791279720af8",
+ "reference": "9c288cc45df467dc012504f4ad64791279720af8",
+ "shasum": ""
+ },
+ "require": {
+ "nette/component-model": "^3.1",
+ "nette/http": "^3.3",
+ "nette/routing": "^3.1",
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "conflict": {
+ "latte/latte": "<2.7.1 || >=3.0.0 <3.0.18 || >=3.1",
+ "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": "dev-master",
+ "latte/latte": "^2.10.2 || ^3.0.18",
+ "mockery/mockery": "^2.0",
+ "nette/di": "^3.2",
+ "nette/forms": "^3.2",
+ "nette/robot-loader": "^4.0",
+ "nette/security": "^3.2",
+ "nette/tester": "^2.5",
+ "phpstan/phpstan-nette": "^1.0",
+ "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": {
+ "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.6"
+ },
+ "time": "2024-09-10T10:08:04+00:00"
+ },
+ {
+ "name": "nette/bootstrap",
+ "version": "v3.2.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/bootstrap.git",
+ "reference": "91d08432cb33d6c08d58b215c769d04f20580624"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/bootstrap/zipball/91d08432cb33d6c08d58b215c769d04f20580624",
+ "reference": "91d08432cb33d6c08d58b215c769d04f20580624",
+ "shasum": ""
+ },
+ "require": {
+ "nette/di": "^3.1",
+ "nette/utils": "^3.2.1 || ^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "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": "^1.0",
+ "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": {
+ "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.5"
+ },
+ "time": "2024-11-14T00:49:46+00:00"
+ },
+ {
+ "name": "nette/caching",
+ "version": "v3.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/caching.git",
+ "reference": "b37d2c9647b41a9d04f099f10300dc5496c4eb77"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/caching/zipball/b37d2c9647b41a9d04f099f10300dc5496c4eb77",
+ "reference": "b37d2c9647b41a9d04f099f10300dc5496c4eb77",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "conflict": {
+ "latte/latte": ">=3.0.0 <3.0.12"
+ },
+ "require-dev": {
+ "latte/latte": "^2.11 || ^3.0.12",
+ "nette/di": "^3.1 || ^4.0",
+ "nette/tester": "^2.4",
+ "phpstan/phpstan": "^1.0",
+ "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.3-dev"
+ }
+ },
+ "autoload": {
+ "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.3.1"
+ },
+ "time": "2024-08-07T00:01:58+00:00"
+ },
+ {
+ "name": "nette/component-model",
+ "version": "v3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/component-model.git",
+ "reference": "fb7608fd5f1c378ef9ef8ddc459c6ef0b63e9d77"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/component-model/zipball/fb7608fd5f1c378ef9ef8ddc459c6ef0b63e9d77",
+ "reference": "fb7608fd5f1c378ef9ef8ddc459c6ef0b63e9d77",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "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.1"
+ },
+ "time": "2024-08-07T00:35:59+00:00"
+ },
+ {
+ "name": "nette/database",
+ "version": "v3.2.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/database.git",
+ "reference": "cb825ac1cffe1ede98388a9c4e6c4445c26b961d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/database/zipball/cb825ac1cffe1ede98388a9c4e6c4445c26b961d",
+ "reference": "cb825ac1cffe1ede98388a9c4e6c4445c26b961d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-pdo": "*",
+ "nette/caching": "^3.2",
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "jetbrains/phpstorm-attributes": "^1.0",
+ "mockery/mockery": "^1.6",
+ "nette/di": "^3.1",
+ "nette/tester": "^2.5",
+ "phpstan/phpstan-nette": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "autoload": {
+ "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.6"
+ },
+ "time": "2025-01-12T15:33:57+00:00"
+ },
+ {
+ "name": "nette/di",
+ "version": "v3.2.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/di.git",
+ "reference": "57f923a7af32435b6e4921c0adbc70c619625a17"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/di/zipball/57f923a7af32435b6e4921c0adbc70c619625a17",
+ "reference": "57f923a7af32435b6e4921c0adbc70c619625a17",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-tokenizer": "*",
+ "nette/neon": "^3.3 || ^4.0",
+ "nette/php-generator": "^4.1.6",
+ "nette/robot-loader": "^4.0",
+ "nette/schema": "^1.2.5",
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5.2",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "autoload": {
+ "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.4"
+ },
+ "time": "2025-01-10T04:57:37+00:00"
+ },
+ {
+ "name": "nette/forms",
+ "version": "v3.2.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/forms.git",
+ "reference": "7e59cee3a16e0382f83680c94babb85a0a167dd0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/forms/zipball/7e59cee3a16e0382f83680c94babb85a0a167dd0",
+ "reference": "7e59cee3a16e0382f83680c94babb85a0a167dd0",
+ "shasum": ""
+ },
+ "require": {
+ "nette/component-model": "^3.1",
+ "nette/http": "^3.3",
+ "nette/utils": "^4.0.4",
+ "php": "8.1 - 8.4"
+ },
+ "conflict": {
+ "latte/latte": ">=3.0.0 <3.0.12 || >=3.1"
+ },
+ "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": "^1",
+ "tracy/tracy": "^2.9"
+ },
+ "suggest": {
+ "ext-intl": "to use date/time controls"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "autoload": {
+ "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.5"
+ },
+ "time": "2024-10-22T18:42:14+00:00"
+ },
+ {
+ "name": "nette/http",
+ "version": "v3.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/http.git",
+ "reference": "3e2587b34beb66f238f119b12fbb4f0b9ab2d6d1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/http/zipball/3e2587b34beb66f238f119b12fbb4f0b9ab2d6d1",
+ "reference": "3e2587b34beb66f238f119b12fbb4f0b9ab2d6d1",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0.4",
+ "php": "8.1 - 8.4"
+ },
+ "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": "^1.0",
+ "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": {
+ "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.2"
+ },
+ "time": "2025-01-12T16:27:57+00:00"
+ },
+ {
+ "name": "nette/mail",
+ "version": "v4.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/mail.git",
+ "reference": "d99839701c48031d6f35e3be95bdd9418f66ad2d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/mail/zipball/d99839701c48031d6f35e3be95bdd9418f66ad2d",
+ "reference": "d99839701c48031d6f35e3be95bdd9418f66ad2d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "nette/utils": "^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "nette/di": "^3.1 || ^4.0",
+ "nette/tester": "^2.4",
+ "phpstan/phpstan-nette": "^1.0",
+ "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": {
+ "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.3"
+ },
+ "time": "2024-10-05T03:15:12+00:00"
+ },
+ {
+ "name": "nette/neon",
+ "version": "v3.4.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/neon.git",
+ "reference": "3411aa86b104e2d5b7e760da4600865ead963c3c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/neon/zipball/3411aa86b104e2d5b7e760da4600865ead963c3c",
+ "reference": "3411aa86b104e2d5b7e760da4600865ead963c3c",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.4",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.7"
+ },
+ "bin": [
+ "bin/neon-lint"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "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://ne-on.org",
+ "keywords": [
+ "export",
+ "import",
+ "neon",
+ "nette",
+ "yaml"
+ ],
+ "support": {
+ "issues": "https://github.com/nette/neon/issues",
+ "source": "https://github.com/nette/neon/tree/v3.4.4"
+ },
+ "time": "2024-10-04T22:00:08+00:00"
+ },
+ {
+ "name": "nette/php-generator",
+ "version": "v4.1.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/php-generator.git",
+ "reference": "d201c9bc217e0969d1b678d286be49302972fb56"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/php-generator/zipball/d201c9bc217e0969d1b678d286be49302972fb56",
+ "reference": "d201c9bc217e0969d1b678d286be49302972fb56",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^3.2.9 || ^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "jetbrains/phpstorm-attributes": "dev-master",
+ "nette/tester": "^2.4",
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.8"
+ },
+ "suggest": {
+ "nikic/php-parser": "to use ClassType::from(withBodies: true) & ClassType::fromCode()"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.1-dev"
+ }
+ },
+ "autoload": {
+ "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.4 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.1.7"
+ },
+ "time": "2024-11-29T01:41:18+00:00"
+ },
+ {
+ "name": "nette/robot-loader",
+ "version": "v4.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/robot-loader.git",
+ "reference": "45d67753fb4865bb718e9a6c9be69cc9470137b7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/robot-loader/zipball/45d67753fb4865bb718e9a6c9be69cc9470137b7",
+ "reference": "45d67753fb4865bb718e9a6c9be69cc9470137b7",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "nette/utils": "^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.4",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "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.0.3"
+ },
+ "time": "2024-06-18T20:26:39+00:00"
+ },
+ {
+ "name": "nette/routing",
+ "version": "v3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/routing.git",
+ "reference": "5b0782d3b50af68614253a373fa663ed03206a3f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/routing/zipball/5b0782d3b50af68614253a373fa663ed03206a3f",
+ "reference": "5b0782d3b50af68614253a373fa663ed03206a3f",
+ "shasum": ""
+ },
+ "require": {
+ "nette/http": "^3.2 || ~4.0.0",
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5",
+ "phpstan/phpstan": "^1",
+ "tracy/tracy": "^2.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "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.1"
+ },
+ "time": "2024-11-04T11:59:47+00:00"
+ },
+ {
+ "name": "nette/schema",
+ "version": "v1.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/schema.git",
+ "reference": "da801d52f0354f70a638673c4a0f04e16529431d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d",
+ "reference": "da801d52f0354f70a638673c4a0f04e16529431d",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5.2",
+ "phpstan/phpstan-nette": "^1.0",
+ "tracy/tracy": "^2.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "autoload": {
+ "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.2"
+ },
+ "time": "2024-10-06T23:10:23+00:00"
+ },
+ {
+ "name": "nette/security",
+ "version": "v3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/security.git",
+ "reference": "6e19bf604934aec0cd3343a307e28fd997e40e96"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/security/zipball/6e19bf604934aec0cd3343a307e28fd997e40e96",
+ "reference": "6e19bf604934aec0cd3343a307e28fd997e40e96",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "conflict": {
+ "nette/di": "<3.0-stable",
+ "nette/http": "<3.1.3"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.5",
+ "nette/di": "^3.1",
+ "nette/http": "^3.2",
+ "nette/tester": "^2.5",
+ "phpstan/phpstan-nette": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "autoload": {
+ "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.1"
+ },
+ "time": "2024-11-04T12:25:05+00:00"
+ },
+ {
+ "name": "nette/utils",
+ "version": "v4.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/utils.git",
+ "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/utils/zipball/736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
+ "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
+ "shasum": ""
+ },
+ "require": {
+ "php": "8.0 - 8.4"
+ },
+ "conflict": {
+ "nette/finder": "<3",
+ "nette/schema": "<1.2.2"
+ },
+ "require-dev": {
+ "jetbrains/phpstorm-attributes": "dev-master",
+ "nette/tester": "^2.5",
+ "phpstan/phpstan": "^1.0",
+ "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.0-dev"
+ }
+ },
+ "autoload": {
+ "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.0.5"
+ },
+ "time": "2024-08-07T15:39:19+00:00"
+ },
+ {
+ "name": "tracy/tracy",
+ "version": "v2.10.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/tracy.git",
+ "reference": "e7af75205b184ca8895bc57fafd331f8d5022d26"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/tracy/zipball/e7af75205b184ca8895bc57fafd331f8d5022d26",
+ "reference": "e7af75205b184ca8895bc57fafd331f8d5022d26",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-session": "*",
+ "php": "8.0 - 8.4"
+ },
+ "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": "^1.0",
+ "psr/log": "^1.0 || ^2.0 || ^3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.10-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Tracy/functions.php"
+ ],
+ "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.10.9"
+ },
+ "time": "2024-11-07T14:48:00+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "nette/tester",
+ "version": "v2.5.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/tester.git",
+ "reference": "c11863785779e87b40adebf150364f2e5938c111"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/tester/zipball/c11863785779e87b40adebf150364f2e5938c111",
+ "reference": "c11863785779e87b40adebf150364f2e5938c111",
+ "shasum": ""
+ },
+ "require": {
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "ext-simplexml": "*",
+ "phpstan/phpstan": "^1.0"
+ },
+ "bin": [
+ "src/tester"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.5-dev"
+ }
+ },
+ "autoload": {
+ "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.4"
+ },
+ "time": "2024-10-23T23:57:10+00:00"
+ },
+ {
+ "name": "symfony/thanks",
+ "version": "v1.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/thanks.git",
+ "reference": "ad3f07af819f058666f0cac3f0737f18d31e3d05"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/thanks/zipball/ad3f07af819f058666f0cac3f0737f18d31e3d05",
+ "reference": "ad3f07af819f058666f0cac3f0737f18d31e3d05",
+ "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.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-10-01T09:47:21+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {
+ "php": ">= 8.1"
+ },
+ "platform-dev": [],
+ "plugin-api-version": "2.6.0"
+}
diff --git a/config/common.neon b/config/common.neon
new file mode 100644
index 0000000..02cee12
--- /dev/null
+++ b/config/common.neon
@@ -0,0 +1,27 @@
+parameters:
+
+
+application:
+ errorPresenter:
+ 4xx: Error:Error4xx
+ 5xx: Error:Error5xx
+ mapping: App\Presentation\*\**Presenter
+
+
+database:
+ dsn: 'sqlite::memory:'
+ user:
+ password:
+
+
+latte:
+ strictTypes: yes
+ strictParsing: yes
+ extensions:
+ - App\Presentation\Accessory\LatteExtension
+
+
+di:
+ export:
+ parameters: no
+ tags: no
diff --git a/config/services.neon b/config/services.neon
new file mode 100644
index 0000000..67302ee
--- /dev/null
+++ b/config/services.neon
@@ -0,0 +1,11 @@
+services:
+ - App\Core\RouterFactory::createRouter
+
+
+search:
+ - in: %appDir%
+ classes:
+ - *Facade
+ - *Factory
+ - *Repository
+ - *Service
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..7a891dc
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,52 @@
+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.1.
+
+
+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.
+
+
+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
+this [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..8ea5db6
--- /dev/null
+++ b/vendor/autoload.php
@@ -0,0 +1,25 @@
+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/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..7395a23
--- /dev/null
+++ b/vendor/composer/autoload_classmap.php
@@ -0,0 +1,673 @@
+ $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\\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\\ExpressionBuilder' => $vendorDir . '/latte/latte/src/Latte/Compiler/ExpressionBuilder.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\\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\\ArrayItemNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.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\\ErrorSuppressNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ErrorSuppressNode.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\\FunctionCallableNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallableNode.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\\MethodCallableNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallableNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\NewNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\NotNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NotNode.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\\StaticCallNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticCallableNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallableNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticMethodCallNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticMethodCallableNode' => $vendorDir . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallableNode.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\\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\\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\\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\\PrintNode' => $vendorDir . '/latte/latte/src/Latte/Essential/Nodes/PrintNode.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\\Filters' => $vendorDir . '/latte/latte/src/Latte/Runtime/Filters.php',
+ 'Latte\\Runtime\\FunctionExecutor' => $vendorDir . '/latte/latte/src/Latte/Runtime/FunctionExecutor.php',
+ 'Latte\\Runtime\\Html' => $vendorDir . '/latte/latte/src/Latte/Runtime/Html.php',
+ 'Latte\\Runtime\\HtmlStringable' => $vendorDir . '/latte/latte/src/Latte/Runtime/HtmlStringable.php',
+ 'Latte\\Runtime\\Template' => $vendorDir . '/latte/latte/src/Latte/Runtime/Template.php',
+ 'Latte\\Sandbox\\Nodes\\FunctionCallNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php',
+ 'Latte\\Sandbox\\Nodes\\FunctionCallableNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallableNode.php',
+ 'Latte\\Sandbox\\Nodes\\MethodCallNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/MethodCallNode.php',
+ 'Latte\\Sandbox\\Nodes\\MethodCallableNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/MethodCallableNode.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\\StaticMethodCallableNode' => $vendorDir . '/latte/latte/src/Latte/Sandbox/Nodes/StaticMethodCallableNode.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\\Tools\\Linter' => $vendorDir . '/latte/latte/src/Tools/Linter.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\\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\\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\\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\\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\\CacheMacro' => $vendorDir . '/nette/caching/src/Bridges/CacheLatte/CacheMacro.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\\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\\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..99e0930
--- /dev/null
+++ b/vendor/composer/autoload_files.php
@@ -0,0 +1,10 @@
+ $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 . '/symfony/thanks/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..32e005a
--- /dev/null
+++ b/vendor/composer/autoload_real.php
@@ -0,0 +1,50 @@
+register(true);
+
+ $filesToLoad = \Composer\Autoload\ComposerStaticInit9c49a418f02ffb235919088891200a26::$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..95eb247
--- /dev/null
+++ b/vendor/composer/autoload_static.php
@@ -0,0 +1,711 @@
+ __DIR__ . '/..' . '/tracy/tracy/src/Tracy/functions.php',
+ );
+
+ public static $prefixLengthsPsr4 = array (
+ 'S' =>
+ array (
+ 'Symfony\\Thanks\\' => 15,
+ ),
+ 'A' =>
+ array (
+ 'App\\' => 4,
+ ),
+ );
+
+ public static $prefixDirsPsr4 = array (
+ 'Symfony\\Thanks\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/thanks/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\\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\\ExpressionBuilder' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/ExpressionBuilder.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\\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\\ArrayItemNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.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\\ErrorSuppressNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ErrorSuppressNode.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\\FunctionCallableNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallableNode.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\\MethodCallableNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallableNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\NewNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\NotNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NotNode.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\\StaticCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticCallableNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallableNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticMethodCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php',
+ 'Latte\\Compiler\\Nodes\\Php\\Expression\\StaticMethodCallableNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallableNode.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\\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\\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\\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\\PrintNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Essential/Nodes/PrintNode.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\\Filters' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/Filters.php',
+ 'Latte\\Runtime\\FunctionExecutor' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/FunctionExecutor.php',
+ 'Latte\\Runtime\\Html' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/Html.php',
+ 'Latte\\Runtime\\HtmlStringable' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/HtmlStringable.php',
+ 'Latte\\Runtime\\Template' => __DIR__ . '/..' . '/latte/latte/src/Latte/Runtime/Template.php',
+ 'Latte\\Sandbox\\Nodes\\FunctionCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallNode.php',
+ 'Latte\\Sandbox\\Nodes\\FunctionCallableNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/FunctionCallableNode.php',
+ 'Latte\\Sandbox\\Nodes\\MethodCallNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/MethodCallNode.php',
+ 'Latte\\Sandbox\\Nodes\\MethodCallableNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/MethodCallableNode.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\\StaticMethodCallableNode' => __DIR__ . '/..' . '/latte/latte/src/Latte/Sandbox/Nodes/StaticMethodCallableNode.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\\Tools\\Linter' => __DIR__ . '/..' . '/latte/latte/src/Tools/Linter.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\\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\\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\\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\\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\\CacheMacro' => __DIR__ . '/..' . '/nette/caching/src/Bridges/CacheLatte/CacheMacro.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\\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\\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 = ComposerStaticInit9c49a418f02ffb235919088891200a26::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit9c49a418f02ffb235919088891200a26::$prefixDirsPsr4;
+ $loader->classMap = ComposerStaticInit9c49a418f02ffb235919088891200a26::$classMap;
+
+ }, null, ClassLoader::class);
+ }
+}
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
new file mode 100644
index 0000000..c82957f
--- /dev/null
+++ b/vendor/composer/installed.json
@@ -0,0 +1,1536 @@
+{
+ "packages": [
+ {
+ "name": "latte/latte",
+ "version": "v3.0.20",
+ "version_normalized": "3.0.20.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/latte.git",
+ "reference": "4db7a5502f8cef02fffa84fc9c34a635d9c79d4d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/latte/zipball/4db7a5502f8cef02fffa84fc9c34a635d9c79d4d",
+ "reference": "4db7a5502f8cef02fffa84fc9c34a635d9c79d4d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": "8.0 - 8.4"
+ },
+ "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": "^1",
+ "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": "2024-10-08T00:58:27+00:00",
+ "bin": [
+ "bin/latte-lint"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "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.0.20"
+ },
+ "install-path": "../latte/latte"
+ },
+ {
+ "name": "nette/application",
+ "version": "v3.2.6",
+ "version_normalized": "3.2.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/application.git",
+ "reference": "9c288cc45df467dc012504f4ad64791279720af8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/application/zipball/9c288cc45df467dc012504f4ad64791279720af8",
+ "reference": "9c288cc45df467dc012504f4ad64791279720af8",
+ "shasum": ""
+ },
+ "require": {
+ "nette/component-model": "^3.1",
+ "nette/http": "^3.3",
+ "nette/routing": "^3.1",
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "conflict": {
+ "latte/latte": "<2.7.1 || >=3.0.0 <3.0.18 || >=3.1",
+ "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": "dev-master",
+ "latte/latte": "^2.10.2 || ^3.0.18",
+ "mockery/mockery": "^2.0",
+ "nette/di": "^3.2",
+ "nette/forms": "^3.2",
+ "nette/robot-loader": "^4.0",
+ "nette/security": "^3.2",
+ "nette/tester": "^2.5",
+ "phpstan/phpstan-nette": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "suggest": {
+ "latte/latte": "Allows using Latte in templates",
+ "nette/forms": "Allows to use Nette\\Application\\UI\\Form"
+ },
+ "time": "2024-09-10T10:08:04+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.6"
+ },
+ "install-path": "../nette/application"
+ },
+ {
+ "name": "nette/bootstrap",
+ "version": "v3.2.5",
+ "version_normalized": "3.2.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/bootstrap.git",
+ "reference": "91d08432cb33d6c08d58b215c769d04f20580624"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/bootstrap/zipball/91d08432cb33d6c08d58b215c769d04f20580624",
+ "reference": "91d08432cb33d6c08d58b215c769d04f20580624",
+ "shasum": ""
+ },
+ "require": {
+ "nette/di": "^3.1",
+ "nette/utils": "^3.2.1 || ^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "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": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "suggest": {
+ "nette/robot-loader": "to use Configurator::createRobotLoader()",
+ "tracy/tracy": "to use Configurator::enableTracy()"
+ },
+ "time": "2024-11-14T00:49:46+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.5"
+ },
+ "install-path": "../nette/bootstrap"
+ },
+ {
+ "name": "nette/caching",
+ "version": "v3.3.1",
+ "version_normalized": "3.3.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/caching.git",
+ "reference": "b37d2c9647b41a9d04f099f10300dc5496c4eb77"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/caching/zipball/b37d2c9647b41a9d04f099f10300dc5496c4eb77",
+ "reference": "b37d2c9647b41a9d04f099f10300dc5496c4eb77",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "conflict": {
+ "latte/latte": ">=3.0.0 <3.0.12"
+ },
+ "require-dev": {
+ "latte/latte": "^2.11 || ^3.0.12",
+ "nette/di": "^3.1 || ^4.0",
+ "nette/tester": "^2.4",
+ "phpstan/phpstan": "^1.0",
+ "psr/simple-cache": "^2.0 || ^3.0",
+ "tracy/tracy": "^2.9"
+ },
+ "suggest": {
+ "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal"
+ },
+ "time": "2024-08-07T00:01:58+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.3.1"
+ },
+ "install-path": "../nette/caching"
+ },
+ {
+ "name": "nette/component-model",
+ "version": "v3.1.1",
+ "version_normalized": "3.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/component-model.git",
+ "reference": "fb7608fd5f1c378ef9ef8ddc459c6ef0b63e9d77"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/component-model/zipball/fb7608fd5f1c378ef9ef8ddc459c6ef0b63e9d77",
+ "reference": "fb7608fd5f1c378ef9ef8ddc459c6ef0b63e9d77",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "time": "2024-08-07T00:35:59+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "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.1"
+ },
+ "install-path": "../nette/component-model"
+ },
+ {
+ "name": "nette/database",
+ "version": "v3.2.6",
+ "version_normalized": "3.2.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/database.git",
+ "reference": "cb825ac1cffe1ede98388a9c4e6c4445c26b961d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/database/zipball/cb825ac1cffe1ede98388a9c4e6c4445c26b961d",
+ "reference": "cb825ac1cffe1ede98388a9c4e6c4445c26b961d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-pdo": "*",
+ "nette/caching": "^3.2",
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "jetbrains/phpstorm-attributes": "^1.0",
+ "mockery/mockery": "^1.6",
+ "nette/di": "^3.1",
+ "nette/tester": "^2.5",
+ "phpstan/phpstan-nette": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "time": "2025-01-12T15:33:57+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.6"
+ },
+ "install-path": "../nette/database"
+ },
+ {
+ "name": "nette/di",
+ "version": "v3.2.4",
+ "version_normalized": "3.2.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/di.git",
+ "reference": "57f923a7af32435b6e4921c0adbc70c619625a17"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/di/zipball/57f923a7af32435b6e4921c0adbc70c619625a17",
+ "reference": "57f923a7af32435b6e4921c0adbc70c619625a17",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-tokenizer": "*",
+ "nette/neon": "^3.3 || ^4.0",
+ "nette/php-generator": "^4.1.6",
+ "nette/robot-loader": "^4.0",
+ "nette/schema": "^1.2.5",
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5.2",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "time": "2025-01-10T04:57:37+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.4"
+ },
+ "install-path": "../nette/di"
+ },
+ {
+ "name": "nette/forms",
+ "version": "v3.2.5",
+ "version_normalized": "3.2.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/forms.git",
+ "reference": "7e59cee3a16e0382f83680c94babb85a0a167dd0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/forms/zipball/7e59cee3a16e0382f83680c94babb85a0a167dd0",
+ "reference": "7e59cee3a16e0382f83680c94babb85a0a167dd0",
+ "shasum": ""
+ },
+ "require": {
+ "nette/component-model": "^3.1",
+ "nette/http": "^3.3",
+ "nette/utils": "^4.0.4",
+ "php": "8.1 - 8.4"
+ },
+ "conflict": {
+ "latte/latte": ">=3.0.0 <3.0.12 || >=3.1"
+ },
+ "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": "^1",
+ "tracy/tracy": "^2.9"
+ },
+ "suggest": {
+ "ext-intl": "to use date/time controls"
+ },
+ "time": "2024-10-22T18:42:14+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.5"
+ },
+ "install-path": "../nette/forms"
+ },
+ {
+ "name": "nette/http",
+ "version": "v3.3.2",
+ "version_normalized": "3.3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/http.git",
+ "reference": "3e2587b34beb66f238f119b12fbb4f0b9ab2d6d1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/http/zipball/3e2587b34beb66f238f119b12fbb4f0b9ab2d6d1",
+ "reference": "3e2587b34beb66f238f119b12fbb4f0b9ab2d6d1",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0.4",
+ "php": "8.1 - 8.4"
+ },
+ "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": "^1.0",
+ "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-01-12T16:27:57+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.2"
+ },
+ "install-path": "../nette/http"
+ },
+ {
+ "name": "nette/mail",
+ "version": "v4.0.3",
+ "version_normalized": "4.0.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/mail.git",
+ "reference": "d99839701c48031d6f35e3be95bdd9418f66ad2d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/mail/zipball/d99839701c48031d6f35e3be95bdd9418f66ad2d",
+ "reference": "d99839701c48031d6f35e3be95bdd9418f66ad2d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "nette/utils": "^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "nette/di": "^3.1 || ^4.0",
+ "nette/tester": "^2.4",
+ "phpstan/phpstan-nette": "^1.0",
+ "tracy/tracy": "^2.8"
+ },
+ "suggest": {
+ "ext-fileinfo": "to detect type of attached files",
+ "ext-openssl": "to use Nette\\Mail\\DkimSigner"
+ },
+ "time": "2024-10-05T03:15:12+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "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.3"
+ },
+ "install-path": "../nette/mail"
+ },
+ {
+ "name": "nette/neon",
+ "version": "v3.4.4",
+ "version_normalized": "3.4.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/neon.git",
+ "reference": "3411aa86b104e2d5b7e760da4600865ead963c3c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/neon/zipball/3411aa86b104e2d5b7e760da4600865ead963c3c",
+ "reference": "3411aa86b104e2d5b7e760da4600865ead963c3c",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.4",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.7"
+ },
+ "time": "2024-10-04T22:00:08+00:00",
+ "bin": [
+ "bin/neon-lint"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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://ne-on.org",
+ "keywords": [
+ "export",
+ "import",
+ "neon",
+ "nette",
+ "yaml"
+ ],
+ "support": {
+ "issues": "https://github.com/nette/neon/issues",
+ "source": "https://github.com/nette/neon/tree/v3.4.4"
+ },
+ "install-path": "../nette/neon"
+ },
+ {
+ "name": "nette/php-generator",
+ "version": "v4.1.7",
+ "version_normalized": "4.1.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/php-generator.git",
+ "reference": "d201c9bc217e0969d1b678d286be49302972fb56"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/php-generator/zipball/d201c9bc217e0969d1b678d286be49302972fb56",
+ "reference": "d201c9bc217e0969d1b678d286be49302972fb56",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^3.2.9 || ^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "jetbrains/phpstorm-attributes": "dev-master",
+ "nette/tester": "^2.4",
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.8"
+ },
+ "suggest": {
+ "nikic/php-parser": "to use ClassType::from(withBodies: true) & ClassType::fromCode()"
+ },
+ "time": "2024-11-29T01:41:18+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.1-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.4 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.1.7"
+ },
+ "install-path": "../nette/php-generator"
+ },
+ {
+ "name": "nette/robot-loader",
+ "version": "v4.0.3",
+ "version_normalized": "4.0.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/robot-loader.git",
+ "reference": "45d67753fb4865bb718e9a6c9be69cc9470137b7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/robot-loader/zipball/45d67753fb4865bb718e9a6c9be69cc9470137b7",
+ "reference": "45d67753fb4865bb718e9a6c9be69cc9470137b7",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "nette/utils": "^4.0",
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.4",
+ "phpstan/phpstan": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "time": "2024-06-18T20:26:39+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "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.0.3"
+ },
+ "install-path": "../nette/robot-loader"
+ },
+ {
+ "name": "nette/routing",
+ "version": "v3.1.1",
+ "version_normalized": "3.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/routing.git",
+ "reference": "5b0782d3b50af68614253a373fa663ed03206a3f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/routing/zipball/5b0782d3b50af68614253a373fa663ed03206a3f",
+ "reference": "5b0782d3b50af68614253a373fa663ed03206a3f",
+ "shasum": ""
+ },
+ "require": {
+ "nette/http": "^3.2 || ~4.0.0",
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5",
+ "phpstan/phpstan": "^1",
+ "tracy/tracy": "^2.9"
+ },
+ "time": "2024-11-04T11:59:47+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "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.1"
+ },
+ "install-path": "../nette/routing"
+ },
+ {
+ "name": "nette/schema",
+ "version": "v1.3.2",
+ "version_normalized": "1.3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/schema.git",
+ "reference": "da801d52f0354f70a638673c4a0f04e16529431d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d",
+ "reference": "da801d52f0354f70a638673c4a0f04e16529431d",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5.2",
+ "phpstan/phpstan-nette": "^1.0",
+ "tracy/tracy": "^2.8"
+ },
+ "time": "2024-10-06T23:10:23+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.2"
+ },
+ "install-path": "../nette/schema"
+ },
+ {
+ "name": "nette/security",
+ "version": "v3.2.1",
+ "version_normalized": "3.2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/security.git",
+ "reference": "6e19bf604934aec0cd3343a307e28fd997e40e96"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/security/zipball/6e19bf604934aec0cd3343a307e28fd997e40e96",
+ "reference": "6e19bf604934aec0cd3343a307e28fd997e40e96",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^4.0",
+ "php": "8.1 - 8.4"
+ },
+ "conflict": {
+ "nette/di": "<3.0-stable",
+ "nette/http": "<3.1.3"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.5",
+ "nette/di": "^3.1",
+ "nette/http": "^3.2",
+ "nette/tester": "^2.5",
+ "phpstan/phpstan-nette": "^1.0",
+ "tracy/tracy": "^2.9"
+ },
+ "time": "2024-11-04T12:25:05+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.1"
+ },
+ "install-path": "../nette/security"
+ },
+ {
+ "name": "nette/tester",
+ "version": "v2.5.4",
+ "version_normalized": "2.5.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/tester.git",
+ "reference": "c11863785779e87b40adebf150364f2e5938c111"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/tester/zipball/c11863785779e87b40adebf150364f2e5938c111",
+ "reference": "c11863785779e87b40adebf150364f2e5938c111",
+ "shasum": ""
+ },
+ "require": {
+ "php": "8.0 - 8.4"
+ },
+ "require-dev": {
+ "ext-simplexml": "*",
+ "phpstan/phpstan": "^1.0"
+ },
+ "time": "2024-10-23T23:57:10+00:00",
+ "bin": [
+ "src/tester"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.5-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "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.4"
+ },
+ "install-path": "../nette/tester"
+ },
+ {
+ "name": "nette/utils",
+ "version": "v4.0.5",
+ "version_normalized": "4.0.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/utils.git",
+ "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/utils/zipball/736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
+ "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96",
+ "shasum": ""
+ },
+ "require": {
+ "php": "8.0 - 8.4"
+ },
+ "conflict": {
+ "nette/finder": "<3",
+ "nette/schema": "<1.2.2"
+ },
+ "require-dev": {
+ "jetbrains/phpstorm-attributes": "dev-master",
+ "nette/tester": "^2.5",
+ "phpstan/phpstan": "^1.0",
+ "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": "2024-08-07T15:39:19+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "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.0.5"
+ },
+ "install-path": "../nette/utils"
+ },
+ {
+ "name": "symfony/thanks",
+ "version": "v1.4.0",
+ "version_normalized": "1.4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/thanks.git",
+ "reference": "ad3f07af819f058666f0cac3f0737f18d31e3d05"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/thanks/zipball/ad3f07af819f058666f0cac3f0737f18d31e3d05",
+ "reference": "ad3f07af819f058666f0cac3f0737f18d31e3d05",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^1.0|^2.0",
+ "php": ">=8.1"
+ },
+ "time": "2024-10-01T09:47:21+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.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/thanks"
+ },
+ {
+ "name": "tracy/tracy",
+ "version": "v2.10.9",
+ "version_normalized": "2.10.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/tracy.git",
+ "reference": "e7af75205b184ca8895bc57fafd331f8d5022d26"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/tracy/zipball/e7af75205b184ca8895bc57fafd331f8d5022d26",
+ "reference": "e7af75205b184ca8895bc57fafd331f8d5022d26",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-session": "*",
+ "php": "8.0 - 8.4"
+ },
+ "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": "^1.0",
+ "psr/log": "^1.0 || ^2.0 || ^3.0"
+ },
+ "time": "2024-11-07T14:48:00+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.10-dev"
+ }
+ },
+ "installation-source": "dist",
+ "autoload": {
+ "files": [
+ "src/Tracy/functions.php"
+ ],
+ "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.10.9"
+ },
+ "install-path": "../tracy/tracy"
+ }
+ ],
+ "dev": true,
+ "dev-package-names": [
+ "nette/tester",
+ "symfony/thanks"
+ ]
+}
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
new file mode 100644
index 0000000..cc02e32
--- /dev/null
+++ b/vendor/composer/installed.php
@@ -0,0 +1,203 @@
+ 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(
+ 'latte/latte' => array(
+ 'pretty_version' => 'v3.0.20',
+ 'version' => '3.0.20.0',
+ 'reference' => '4db7a5502f8cef02fffa84fc9c34a635d9c79d4d',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../latte/latte',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/application' => array(
+ 'pretty_version' => 'v3.2.6',
+ 'version' => '3.2.6.0',
+ 'reference' => '9c288cc45df467dc012504f4ad64791279720af8',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/application',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/bootstrap' => array(
+ 'pretty_version' => 'v3.2.5',
+ 'version' => '3.2.5.0',
+ 'reference' => '91d08432cb33d6c08d58b215c769d04f20580624',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/bootstrap',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/caching' => array(
+ 'pretty_version' => 'v3.3.1',
+ 'version' => '3.3.1.0',
+ 'reference' => 'b37d2c9647b41a9d04f099f10300dc5496c4eb77',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/caching',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/component-model' => array(
+ 'pretty_version' => 'v3.1.1',
+ 'version' => '3.1.1.0',
+ 'reference' => 'fb7608fd5f1c378ef9ef8ddc459c6ef0b63e9d77',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/component-model',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/database' => array(
+ 'pretty_version' => 'v3.2.6',
+ 'version' => '3.2.6.0',
+ 'reference' => 'cb825ac1cffe1ede98388a9c4e6c4445c26b961d',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/database',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/di' => array(
+ 'pretty_version' => 'v3.2.4',
+ 'version' => '3.2.4.0',
+ 'reference' => '57f923a7af32435b6e4921c0adbc70c619625a17',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/di',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/forms' => array(
+ 'pretty_version' => 'v3.2.5',
+ 'version' => '3.2.5.0',
+ 'reference' => '7e59cee3a16e0382f83680c94babb85a0a167dd0',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/forms',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/http' => array(
+ 'pretty_version' => 'v3.3.2',
+ 'version' => '3.3.2.0',
+ 'reference' => '3e2587b34beb66f238f119b12fbb4f0b9ab2d6d1',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/http',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/mail' => array(
+ 'pretty_version' => 'v4.0.3',
+ 'version' => '4.0.3.0',
+ 'reference' => 'd99839701c48031d6f35e3be95bdd9418f66ad2d',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/mail',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/neon' => array(
+ 'pretty_version' => 'v3.4.4',
+ 'version' => '3.4.4.0',
+ 'reference' => '3411aa86b104e2d5b7e760da4600865ead963c3c',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/neon',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/php-generator' => array(
+ 'pretty_version' => 'v4.1.7',
+ 'version' => '4.1.7.0',
+ 'reference' => 'd201c9bc217e0969d1b678d286be49302972fb56',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/php-generator',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/robot-loader' => array(
+ 'pretty_version' => 'v4.0.3',
+ 'version' => '4.0.3.0',
+ 'reference' => '45d67753fb4865bb718e9a6c9be69cc9470137b7',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/robot-loader',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/routing' => array(
+ 'pretty_version' => 'v3.1.1',
+ 'version' => '3.1.1.0',
+ 'reference' => '5b0782d3b50af68614253a373fa663ed03206a3f',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/routing',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/schema' => array(
+ 'pretty_version' => 'v1.3.2',
+ 'version' => '1.3.2.0',
+ 'reference' => 'da801d52f0354f70a638673c4a0f04e16529431d',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/schema',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/security' => array(
+ 'pretty_version' => 'v3.2.1',
+ 'version' => '3.2.1.0',
+ 'reference' => '6e19bf604934aec0cd3343a307e28fd997e40e96',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/security',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'nette/tester' => array(
+ 'pretty_version' => 'v2.5.4',
+ 'version' => '2.5.4.0',
+ 'reference' => 'c11863785779e87b40adebf150364f2e5938c111',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../nette/tester',
+ 'aliases' => array(),
+ 'dev_requirement' => true,
+ ),
+ 'nette/utils' => array(
+ 'pretty_version' => 'v4.0.5',
+ 'version' => '4.0.5.0',
+ 'reference' => '736c567e257dbe0fcf6ce81b4d6dbe05c6899f96',
+ '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,
+ ),
+ 'symfony/thanks' => array(
+ 'pretty_version' => 'v1.4.0',
+ 'version' => '1.4.0.0',
+ 'reference' => 'ad3f07af819f058666f0cac3f0737f18d31e3d05',
+ 'type' => 'composer-plugin',
+ 'install_path' => __DIR__ . '/../symfony/thanks',
+ 'aliases' => array(),
+ 'dev_requirement' => true,
+ ),
+ 'tracy/tracy' => array(
+ 'pretty_version' => 'v2.10.9',
+ 'version' => '2.10.9.0',
+ 'reference' => 'e7af75205b184ca8895bc57fafd331f8d5022d26',
+ '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..4c3a5d6
--- /dev/null
+++ b/vendor/composer/platform_check.php
@@ -0,0 +1,26 @@
+= 80100)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.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/latte/latte/bin/latte-lint b/vendor/latte/latte/bin/latte-lint
new file mode 100644
index 0000000..eecb1c3
--- /dev/null
+++ b/vendor/latte/latte/bin/latte-lint
@@ -0,0 +1,35 @@
+#!/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];
+$linter = new Latte\Tools\Linter(debug: $debug, strict: $strict);
+$ok = $linter->scanDirectory($path);
+exit($ok ? 0 : 1);
diff --git a/vendor/latte/latte/composer.json b/vendor/latte/latte/composer.json
new file mode 100644
index 0000000..40946a0
--- /dev/null
+++ b/vendor/latte/latte/composer.json
@@ -0,0 +1,55 @@
+{
+ "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.0 - 8.4",
+ "ext-json": "*",
+ "ext-tokenizer": "*"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5",
+ "tracy/tracy": "^2.10",
+ "nette/utils": "^4.0",
+ "phpstan/phpstan": "^1",
+ "nette/php-generator": "^4.0"
+ },
+ "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/"]
+ },
+ "minimum-stability": "dev",
+ "bin": ["bin/latte-lint"],
+ "scripts": {
+ "phpstan": "phpstan analyse",
+ "tester": "tester tests -s"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-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 @@
+[](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?
+
+[](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..969bd20
--- /dev/null
+++ b/vendor/latte/latte/src/Bridges/Tracy/BlueScreenPanel.php
@@ -0,0 +1,123 @@
+addPanel([self::class, 'renderError']);
+ $blueScreen->addAction([self::class, 'renderUnknownMacro']);
+ if (
+ version_compare(Tracy\Debugger::VERSION, '2.9.0', '>=')
+ && version_compare(Tracy\Debugger::VERSION, '3.0', '<')
+ ) {
+ Tracy\Debugger::addSourceMapper([self::class, '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)
+ . '
',
+ ];
+
+ } elseif (
+ $e
+ && ($file = $e->getFile())
+ && (version_compare(Tracy\Debugger::VERSION, '2.9.0', '<'))
+ && ($mapped = self::mapLatteSourceCode($file, $e->getLine()))
+ ) {
+ return [
+ 'tab' => 'Template',
+ 'panel' => 'File: ' . Helpers::editorLink($mapped['file'], $mapped['line']) . '
'
+ . ($mapped['line']
+ ? BlueScreen::highlightFile($mapped['file'], $mapped['line'])
+ : ''),
+ ];
+ }
+
+ 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
+ {
+ if (!strpos($file, '.latte--')) {
+ return null;
+ }
+
+ $lines = file($file);
+ if (
+ !preg_match('#^/\*\* source: (\S+\.latte)#m', implode('', array_slice($lines, 0, 10)), $m)
+ || !@is_file($m[1]) // @ - may trigger error
+ ) {
+ return null;
+ }
+
+ $file = $m[1];
+ $line = $line && preg_match('#/\* line (\d+) \*/#', $lines[$line - 1], $m) ? (int) $m[1] : 0;
+ return ['file' => $file, 'line' => $line, 'label' => 'Latte', 'active' => true];
+ }
+}
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..b23e5a0
--- /dev/null
+++ b/vendor/latte/latte/src/Bridges/Tracy/LattePanel.php
@@ -0,0 +1,122 @@
+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) {
+ $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__ . '/templates/LattePanel.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__ . '/templates/LattePanel.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/templates/LattePanel.panel.phtml b/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.panel.phtml
new file mode 100644
index 0000000..7e9a659
--- /dev/null
+++ b/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.panel.phtml
@@ -0,0 +1,101 @@
+ '#00000052',
+ 'extends' => '#cd1c1c7d',
+ 'import' => '#17c35b8f',
+ 'includeblock' => '#17c35b8f',
+ 'embed' => '#4f1ccd7d',
+ 'sandbox' => 'black',
+];
+
+?>
+
+
+
+Rendered Templates
+
+
+
+
+
+
+ template->getReferenceType()): ?>
+ └
+ = Helpers::escapeHtml($item->template->getReferenceType()) ?>
+
+
+ = Helpers::editorLink($item->template->getName()) ?>
+
+ php
+
+
+ = $item->count > 1 ? $item->count . '×' : '' ?>
+
+
+
+
+
+
Parameters
+
+
+
+template->getParameters() as $k => $v): ?>
+ = Helpers::escapeHtml($k) ?> = Dumper::toHtml($v, [Dumper::LIVE => true]) ?>
+
+
+
+
diff --git a/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.tab.phtml b/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.tab.phtml
new file mode 100644
index 0000000..375425c
--- /dev/null
+++ b/vendor/latte/latte/src/Bridges/Tracy/templates/LattePanel.tab.phtml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+ = Helpers::escapeHtml($name) ?>
+
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..a98526a
--- /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..cd690dd
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Escaper.php
@@ -0,0 +1,268 @@
+ [
+ self::HtmlText => 'escapeHtmlText',
+ self::HtmlAttribute => 'escapeHtmlAttr',
+ self::HtmlAttribute . '/' . self::JavaScript => 'escapeHtmlAttr',
+ self::HtmlAttribute . '/' . self::Css => 'escapeHtmlAttr',
+ self::HtmlAttribute . '/' . self::Url => 'escapeHtmlAttr',
+ self::HtmlComment => 'escapeHtmlComment',
+ 'xml' => 'escapeXml',
+ 'xml/attr' => 'escapeXml',
+ ],
+ self::JavaScript => [
+ self::HtmlText => 'escapeHtmlText',
+ self::HtmlAttribute => 'escapeHtmlAttr',
+ self::HtmlAttribute . '/' . self::JavaScript => 'escapeHtmlAttr',
+ self::HtmlRawText . '/' . self::JavaScript => 'convertJSToHtmlRawText',
+ self::HtmlComment => 'escapeHtmlComment',
+ ],
+ self::Css => [
+ self::HtmlText => 'escapeHtmlText',
+ self::HtmlAttribute => 'escapeHtmlAttr',
+ self::HtmlAttribute . '/' . self::Css => 'escapeHtmlAttr',
+ self::HtmlRawText . '/' . self::Css => 'convertJSToHtmlRawText',
+ self::HtmlComment => 'escapeHtmlComment',
+ ],
+ self::HtmlText => [
+ self::HtmlAttribute => 'convertHtmlToHtmlAttr',
+ self::HtmlAttribute . '/' . self::JavaScript => 'convertHtmlToHtmlAttr',
+ self::HtmlAttribute . '/' . self::Css => 'convertHtmlToHtmlAttr',
+ self::HtmlAttribute . '/' . self::Url => 'convertHtmlToHtmlAttr',
+ self::HtmlComment => 'escapeHtmlComment',
+ self::HtmlRawText . '/' . self::HtmlText => 'convertHtmlToHtmlRawText',
+ ],
+ self::HtmlAttribute => [
+ self::HtmlText => 'convertHtmlToHtmlAttr',
+ ],
+ self::HtmlAttribute . '/' . self::Url => [
+ self::HtmlText => 'convertHtmlToHtmlAttr',
+ self::HtmlAttribute => 'nop',
+ ],
+ ];
+
+ 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;
+ $this->subType = self::Text;
+ if ($el->is('script')) {
+ $type = $el->getAttribute('type');
+ if ($type === true || $type === null
+ || is_string($type) && preg_match('#((application|text)/(((x-)?java|ecma|j|live)script|json)|application/.+\+json|text/plain|module|importmap|)$#Ai', $type)
+ ) {
+ $this->subType = self::JavaScript;
+
+ } elseif (is_string($type) && preg_match('#text/((x-)?template|html)$#Ai', $type)) {
+ $this->subType = self::HtmlText;
+ }
+
+ } 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 = strtolower($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;
+ } elseif ((in_array($name, ['href', 'src', 'action', 'formaction'], true)
+ || ($name === 'data' && $this->tag === 'object'))
+ ) {
+ $this->subType = self::Url;
+ }
+ }
+ }
+
+
+ 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\Filters::escapeHtmlText(' . $str . ')',
+ self::HtmlTag => 'LR\Filters::escapeHtmlTag(' . $str . ')',
+ self::HtmlAttribute => match ($this->subType) {
+ '',
+ self::Url => 'LR\Filters::escapeHtmlAttr(' . $str . ')',
+ self::JavaScript => 'LR\Filters::escapeHtmlAttr(LR\Filters::escapeJs(' . $str . '))',
+ self::Css => 'LR\Filters::escapeHtmlAttr(LR\Filters::escapeCss(' . $str . '))',
+ },
+ self::HtmlComment => 'LR\Filters::escapeHtmlComment(' . $str . ')',
+ self::HtmlBogusTag => 'LR\Filters::escapeHtml(' . $str . ')',
+ self::HtmlRawText => match ($this->subType) {
+ self::Text => 'LR\Filters::convertJSToHtmlRawText(' . $str . ')', // sanitization, escaping is not possible
+ self::HtmlText => 'LR\Filters::escapeHtmlRawTextHtml(' . $str . ')',
+ self::JavaScript => 'LR\Filters::escapeJs(' . $str . ')',
+ self::Css => 'LR\Filters::escapeCss(' . $str . ')',
+ },
+ default => throw new \LogicException("Unknown context $this->contentType, $this->state."),
+ },
+ ContentType::Xml => match ($this->state) {
+ self::HtmlText,
+ self::HtmlBogusTag => 'LR\Filters::escapeXml(' . $str . ')',
+ self::HtmlAttribute => 'LR\Filters::escapeXml(' . $str . ')',
+ self::HtmlComment => 'LR\Filters::escapeHtmlComment(' . $str . ')',
+ self::HtmlTag => 'LR\Filters::escapeXmlTag(' . $str . ')',
+ default => throw new \LogicException("Unknown context $this->contentType, $this->state."),
+ },
+ ContentType::JavaScript => 'LR\Filters::escapeJs(' . $str . ')',
+ ContentType::Css => 'LR\Filters::escapeCss(' . $str . ')',
+ ContentType::ICal => 'LR\Filters::escapeIcal(' . $str . ')',
+ ContentType::Text => '($this->filters->escape)(' . $str . ')',
+ default => throw new \LogicException("Unknown content-type $this->contentType."),
+ };
+ }
+
+
+ public function escapeMandatory(string $str): string
+ {
+ return match ($this->contentType) {
+ ContentType::Html => match ($this->state) {
+ self::HtmlAttribute => "LR\\Filters::escapeHtmlQuotes($str)",
+ self::HtmlRawText => match ($this->subType) {
+ self::HtmlText => 'LR\Filters::convertHtmlToHtmlRawText(' . $str . ')',
+ default => "LR\\Filters::convertJSToHtmlRawText($str)",
+ },
+ self::HtmlComment => 'LR\Filters::escapeHtmlComment(' . $str . ')',
+ default => $str,
+ },
+ ContentType::Xml => match ($this->state) {
+ self::HtmlAttribute => "LR\\Filters::escapeHtmlQuotes($str)",
+ self::HtmlComment => 'LR\Filters::escapeHtmlComment(' . $str . ')',
+ default => $str,
+ },
+ default => $str,
+ };
+ }
+
+
+ public function check(string $str): string
+ {
+ if ($this->state === self::HtmlAttribute && $this->subType === self::Url) {
+ $str = 'LR\Filters::safeUrl(' . $str . ')';
+ }
+ return $str;
+ }
+
+
+ public static function getConvertor(string $source, string $dest): ?callable
+ {
+ return match (true) {
+ $source === $dest => [Filters::class, 'nop'],
+ isset(self::Convertors[$source][$dest]) => [Filters::class, self::Convertors[$source][$dest]],
+ default => null,
+ };
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/ExpressionBuilder.php b/vendor/latte/latte/src/Latte/Compiler/ExpressionBuilder.php
new file mode 100644
index 0000000..be20e3f
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/ExpressionBuilder.php
@@ -0,0 +1,129 @@
+expr : $name);
+ return new self(new Expression\FunctionCallNode($name, self::arrayToArgs($args)));
+ }
+
+
+ public function property(ExpressionNode|self|string $name): self
+ {
+ $name = is_string($name)
+ ? new IdentifierNode($name)
+ : ($name instanceof self ? $name->expr : $name);
+ return new self(new Expression\PropertyFetchNode($this->expr, $name));
+ }
+
+
+ public function method(ExpressionNode|self|string $name, array $args = []): self
+ {
+ $name = is_string($name)
+ ? new IdentifierNode($name)
+ : ($name instanceof self ? $name->expr : $name);
+ return new self(new Expression\MethodCallNode($this->expr, $name, self::arrayToArgs($args)));
+ }
+
+
+ public function staticMethod(ExpressionNode|self|string $name, array $args = []): self
+ {
+ $name = is_string($name)
+ ? new IdentifierNode($name)
+ : ($name instanceof self ? $name->expr : $name);
+ return new self(new Expression\StaticMethodCallNode($this->expr, $name, self::arrayToArgs($args)));
+ }
+
+
+ public function build(): ExpressionNode|NameNode
+ {
+ return $this->expr;
+ }
+
+
+ public static function valueToNode(bool|int|float|string|array|null|ExpressionNode $value): ExpressionNode
+ {
+ return match (true) {
+ $value === null => new Scalar\NullNode,
+ is_bool($value) => new Scalar\BooleanNode($value),
+ is_int($value) => new Scalar\IntegerNode($value),
+ is_float($value) => new Scalar\FloatNode($value),
+ is_string($value) => new Scalar\StringNode($value),
+ is_array($value) => self::arrayToNode($value),
+ default => $value, // ExpressionNode
+ };
+ }
+
+
+ private static function arrayToNode(array $arr): Expression\ArrayNode
+ {
+ $node = new Expression\ArrayNode;
+ $lastKey = -1;
+ foreach ($arr as $key => $val) {
+ if ($lastKey !== null && ++$lastKey === $key) {
+ $node->items[] = new Nodes\Php\ArrayItemNode(self::valueToNode($val));
+ } else {
+ $lastKey = null;
+ $node->items[] = new Nodes\Php\ArrayItemNode(self::valueToNode($val), self::valueToNode($key));
+ }
+ }
+
+ return $node;
+ }
+
+
+ /** @return ArgumentNode[] */
+ private static function arrayToArgs(array $arr): array
+ {
+ $args = [];
+ foreach ($arr as $key => $arg) {
+ $args[] = $arg instanceof ArgumentNode
+ ? $arg
+ : new ArgumentNode(
+ self::valueToNode($arg),
+ name: is_string($key) ? new IdentifierNode($key) : null,
+ );
+ }
+
+ return $args;
+ }
+}
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..a740ea7
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/NodeHelpers.php
@@ -0,0 +1,128 @@
+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..d79a6c5
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/NodeTraverser.php
@@ -0,0 +1,73 @@
+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;
+ $children = false;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ 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..9e3e693
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/FragmentNode.php
@@ -0,0 +1,69 @@
+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;
+ }
+ }
+}
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..22dd7f9
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/AttributeNode.php
@@ -0,0 +1,66 @@
+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));
+ if ($this->value instanceof FragmentNode && $escaper->export() === 'html/attr/url') {
+ foreach ($this->value->children as $child) {
+ $res .= $child->print($context);
+ $escaper->enterHtmlAttribute(null);
+ }
+ } else {
+ $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..9ad6d84
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Html/ElementNode.php
@@ -0,0 +1,152 @@
+data ??= new \stdClass;
+ $this->tagNode = new AuxiliaryNode(\Closure::fromCallable([$this, 'printStartTag']));
+ }
+
+
+ public function getAttribute(string $name): string|Node|bool|null
+ {
+ foreach ($this->attributes?->children as $child) {
+ if ($child instanceof AttributeNode
+ && $child->name instanceof Nodes\TextNode
+ && strcasecmp($name, $child->name->content) === 0
+ ) {
+ return NodeHelpers::toText($child->value) ?? $child->value ?? true;
+ }
+ }
+
+ return null;
+ }
+
+
+ public function is(string $name): bool
+ {
+ return $this->contentType === ContentType::Html
+ ? strcasecmp($this->name, $name) === 0
+ : $this->name === $name;
+ }
+
+
+ public function isRawText(): bool
+ {
+ return $this->contentType === ContentType::Html
+ && ($this->is('script') || $this->is('style'));
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $res = $this->endTagVar = null;
+ if ($this->captureTagName || $this->variableName) {
+ $endTag = $this->endTagVar = '$ʟ_tag[' . $context->generateId() . ']';
+ $res = "$this->endTagVar = '';";
+ } else {
+ $endTag = var_export('' . $this->name . '>', true);
+ }
+
+ $res .= $this->tagNode->print($context); // calls $this->printStartTag()
+
+ if ($this->content) {
+ $context->beginEscape()->enterHtmlText($this);
+ $content = $this->content->print($context);
+ $context->restoreEscape();
+ $res .= $this->breakable
+ ? 'try { ' . $content . ' } finally { echo ' . $endTag . '; } '
+ : $content . 'echo ' . $endTag . ';';
+ }
+
+ return $res;
+ }
+
+
+ private function printStartTag(PrintContext $context): string
+ {
+ $context->beginEscape()->enterHtmlTag($this->name);
+ $res = "echo '<';";
+
+ if ($this->endTagVar) {
+ $expr = $this->variableName
+ ? 'LR\Filters::safeTag('
+ . $this->variableName->print($context)
+ . ($this->contentType === ContentType::Xml ? ', true' : '')
+ . ')'
+ : var_export($this->name, true);
+ $res .= "echo \$ʟ_tmp = $expr /* line {$this->position->line} */;"
+ . "{$this->endTagVar} = '' . \$ʟ_tmp . '>' . {$this->endTagVar};";
+ } else {
+ $res .= 'echo ' . var_export($this->name, true) . ';';
+ }
+
+ foreach ($this->attributes?->children ?? [] as $attr) {
+ $res .= $attr->print($context);
+ }
+
+ $res .= "echo '" . ($this->selfClosing ? '/>' : '>') . "';";
+ $context->restoreEscape();
+ return $res;
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->tagNode;
+ if ($this->variableName) {
+ yield $this->variableName;
+ }
+ if ($this->attributes) {
+ yield $this->attributes;
+ }
+ if ($this->content) {
+ yield $this->content;
+ }
+ }
+}
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..771f6e3
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ArrayItemNode.php
@@ -0,0 +1,74 @@
+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;
+ }
+}
+
+
+class_alias(ArrayItemNode::class, Expression\ArrayItemNode::class);
+
+namespace Latte\Compiler\Nodes\Php\Expression;
+
+if (false) {
+ /** @deprecated use Latte\Compiler\Nodes\Php\ArrayItemNode */
+ class ArrayItemNode
+ {
+ }
+}
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..6c8a042
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ArrayNode.php
@@ -0,0 +1,68 @@
+ */
+ 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
+ {
+ // Converts [...$var] -> $var, because PHP 8.0 doesn't support unpacking with string keys
+ if (PHP_VERSION_ID < 80100) {
+ $res = '[';
+ $merge = false;
+ foreach ($this->items as $item) {
+ if ($item === null) {
+ $res .= ', ';
+ } elseif ($item->unpack) {
+ $res .= '], ' . $item->value->print($context) . ', [';
+ $merge = true;
+ } else {
+ $res .= $item->print($context) . ', ';
+ }
+ }
+
+ $res = str_ends_with($res, ', ') ? substr($res, 0, -2) : $res;
+ return $merge ? "array_merge($res])" : $res . ']';
+ }
+
+ return '[' . $context->implode($this->items) . ']';
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ foreach ($this->items as &$item) {
+ yield $item;
+ }
+ }
+}
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..37dae2b
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignNode.php
@@ -0,0 +1,53 @@
+validate();
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $this->validate();
+ return $context->infixOp($this, $this->var, $this->byRef ? ' = &' : ' = ', $this->expr);
+ }
+
+
+ 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..6f9f008
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/AssignOpNode.php
@@ -0,0 +1,56 @@
+>', '**', '??'];
+
+
+ public function __construct(
+ public ExpressionNode $var,
+ public /*readonly*/ 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->infixOp($this, $this->var, ' ' . $this->operator . '= ', $this->expr);
+ }
+
+
+ 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..2fce771
--- /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..529fb73
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/BinaryOpNode.php
@@ -0,0 +1,65 @@
+>', '**',
+ '==', '!=', '===', '!==', '<=>', '<', '<=', '>', '>=', '??', ];
+
+
+ public function __construct(
+ public ExpressionNode $left,
+ public /*readonly*/ 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->infixOp($this, $this->left, ' ' . $this->operator . ' ', $this->right);
+ }
+
+
+ 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..df4c3fe
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CastNode.php
@@ -0,0 +1,43 @@
+ 1, 'float' => 1, 'string' => 1, 'array' => 1, 'object' => 1, 'bool' => 1];
+
+
+ public function __construct(
+ public /*readonly*/ 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 $context->prefixOp($this, '(' . $this->type . ') ', $this->expr);
+ }
+
+
+ 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..5930e95
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/CloneNode.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/ClosureNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php
new file mode 100644
index 0000000..f6abf8e
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ClosureNode.php
@@ -0,0 +1,74 @@
+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;
+ }
+
+ foreach ($this->uses as &$item) {
+ yield $item;
+ }
+
+ 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..2c919f1
--- /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(self::Source) ? self::Source : null)',
+ '__DIR__' => '(is_file(self::Source) ? dirname(self::Source) : 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/ErrorSuppressNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ErrorSuppressNode.php
new file mode 100644
index 0000000..5d93cab
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/ErrorSuppressNode.php
@@ -0,0 +1,36 @@
+prefixOp($this, '@', $this->expr);
+ }
+
+
+ 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..966a9fe
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FilterCallNode.php
@@ -0,0 +1,39 @@
+filter->printSimple($context, $this->expr->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..defebda
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallNode.php
@@ -0,0 +1,45 @@
+ */
+ public array $args = [],
+ public ?Position $position = null,
+ ) {
+ (function (Php\ArgumentNode ...$args) {})(...$args);
+ }
+
+
+ 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;
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallableNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallableNode.php
new file mode 100644
index 0000000..8f5fb80
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/FunctionCallableNode.php
@@ -0,0 +1,39 @@
+memberAsString($this->name)
+ : $context->callExpr($this->name) . '(...)';
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->name;
+ }
+}
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..649a586
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/InstanceofNode.php
@@ -0,0 +1,40 @@
+postfixOp($this, $this->expr, ' instanceof ')
+ . $context->dereferenceExpr($this->class);
+ }
+
+
+ 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..a0496dd
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/IssetNode.php
@@ -0,0 +1,54 @@
+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;
+ }
+ }
+}
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..da40030
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MatchNode.php
@@ -0,0 +1,49 @@
+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;
+ }
+ }
+}
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..ddd1146
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallNode.php
@@ -0,0 +1,50 @@
+ */
+ public array $args = [],
+ public bool $nullsafe = false,
+ public ?Position $position = null,
+ ) {
+ (function (Php\ArgumentNode ...$args) {})(...$args);
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ 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;
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallableNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallableNode.php
new file mode 100644
index 0000000..d653946
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/MethodCallableNode.php
@@ -0,0 +1,42 @@
+object->print($context) . ', ' . $context->memberAsString($this->name) . ']'
+ : $context->dereferenceExpr($this->object)
+ . '->' . $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/NewNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php
new file mode 100644
index 0000000..25d5a02
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NewNode.php
@@ -0,0 +1,45 @@
+dereferenceExpr($this->class)
+ . ($this->args ? '(' . $context->implode($this->args) . ')' : '');
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->class;
+ foreach ($this->args as &$item) {
+ yield $item;
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NotNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NotNode.php
new file mode 100644
index 0000000..cb9a30f
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/NotNode.php
@@ -0,0 +1,36 @@
+prefixOp($this, '!', $this->expr);
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->expr;
+ }
+}
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..ae87000
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PostOpNode.php
@@ -0,0 +1,54 @@
+ 1, '--' => 1];
+
+
+ public function __construct(
+ public ExpressionNode $var,
+ public /*readonly*/ 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->postfixOp($this, $this->var, $this->operator);
+ }
+
+
+ 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..865dd46
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/PreOpNode.php
@@ -0,0 +1,54 @@
+ 1, '--' => 1];
+
+
+ public function __construct(
+ public ExpressionNode $var,
+ public /*readonly*/ 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->prefixOp($this, $this->operator, $this->var);
+ }
+
+
+ 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..c288e90
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallNode.php
@@ -0,0 +1,65 @@
+ */
+ public array $args = [],
+ public ?Position $position = null,
+ ) {
+ (function (Php\ArgumentNode ...$args) {})(...$args);
+ }
+
+
+ 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;
+ }
+ }
+}
+
+
+class_alias(StaticMethodCallNode::class, StaticCallNode::class);
+
+if (false) {
+ /** @deprecated use Latte\Compiler\Nodes\Php\Expression\StaticMethodCallNode */
+ class StaticCallNode
+ {
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallableNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallableNode.php
new file mode 100644
index 0000000..4c51393
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/StaticMethodCallableNode.php
@@ -0,0 +1,57 @@
+name instanceof VariableNode => $this->name->print($context),
+ $this->name instanceof ExpressionNode => '{' . $this->name->print($context) . '}',
+ default => $this->name,
+ };
+ return PHP_VERSION_ID < 80100
+ ? '[' . $this->class->print($context) . ', ' . $context->memberAsString($this->name) . ']'
+ : $context->dereferenceExpr($this->class) . '::' . $name . '(...)';
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->class;
+ yield $this->name;
+ }
+}
+
+
+class_alias(StaticMethodCallableNode::class, StaticCallableNode::class);
+
+if (false) {
+ /** @deprecated use Latte\Compiler\Nodes\Php\Expression\StaticMethodCallableNode */
+ class StaticCallableNode
+ {
+ }
+}
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 @@
+infixOp(
+ $this,
+ $this->cond,
+ ' ?' . ($this->if !== null ? ' ' . $this->if->print($context) . ' ' : '') . ': ',
+ $this->else ?? new NameNode('null'),
+ );
+ }
+
+
+ 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..e8978c0
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Expression/UnaryOpNode.php
@@ -0,0 +1,45 @@
+ 1, '-' => 1, '~' => 1];
+
+
+ public function __construct(
+ public ExpressionNode $expr,
+ public /*readonly*/ 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
+ {
+ return $this->expr instanceof self || $this->expr instanceof PreOpNode
+ ? $this->operator . '(' . $this->expr->print($context) . ')' // Enforce -(-$expr) instead of --$expr
+ : $context->prefixOp($this, $this->operator, $this->expr);
+ }
+
+
+ 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..666f67c
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/FilterNode.php
@@ -0,0 +1,62 @@
+filters->' . $context->objectProperty($this->name) . ')('
+ . $expr
+ . ($this->args ? ', ' . $context->implode($this->args) : '')
+ . ')';
+ }
+
+
+ public function printContentAware(PrintContext $context, string $expr): string
+ {
+ 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;
+ }
+ }
+}
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;
+ }
+ }
+}
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..4242624
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/MatchArmNode.php
@@ -0,0 +1,45 @@
+conds ? $context->implode($this->conds) : 'default')
+ . ' => '
+ . $this->body->print($context);
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ if ($this->conds) {
+ foreach ($this->conds as &$item) {
+ yield $item;
+ }
+ }
+ 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..a1a05e3
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ModifierNode.php
@@ -0,0 +1,107 @@
+filters as $filter) {
+ if ($filter->name->name === $name) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ throw new \LogicException('Cannot directly print ModifierNode');
+ }
+
+
+ public function printSimple(PrintContext $context, string $expr): string
+ {
+ $escape = $this->escape;
+ $check = $this->check;
+ foreach ($this->filters as $filter) {
+ $name = $filter->name->name;
+ if ($name === 'nocheck' || $name === 'noCheck') {
+ $check = false;
+ } elseif ($name === 'noescape') {
+ $escape = false;
+ } else {
+ if ($name === 'datastream' || $name === 'dataStream') {
+ $check = false;
+ }
+ $expr = $filter->printSimple($context, $expr);
+ }
+ }
+
+ $escaper = $context->getEscaper();
+ if ($check) {
+ $expr = $escaper->check($expr);
+ }
+
+ $expr = $escape
+ ? $escaper->escape($expr)
+ : $escaper->escapeMandatory($expr);
+
+ return $expr;
+ }
+
+
+ public function printContentAware(PrintContext $context, string $expr): string
+ {
+ foreach ($this->filters as $filter) {
+ $name = $filter->name->name;
+ if ($name === 'noescape') {
+ $noescape = true;
+ } else {
+ $expr = $filter->printContentAware($context, $expr);
+ }
+ }
+
+ if ($this->escape && empty($noescape)) {
+ $expr = 'LR\Filters::convertTo($ʟ_fi, '
+ . var_export($context->getEscaper()->export(), true) . ', '
+ . $expr
+ . ')';
+ }
+
+ return $expr;
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ foreach ($this->filters as &$filter) {
+ yield $filter;
+ }
+ }
+}
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..9b6e258
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/NameNode.php
@@ -0,0 +1,85 @@
+kind = self::KindFullyQualified;
+ $this->name = substr($name, 1);
+ } else {
+ $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', 'clone', '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/ParameterNode.php b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ParameterNode.php
new file mode 100644
index 0000000..54d02d4
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/ParameterNode.php
@@ -0,0 +1,54 @@
+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..ee1646c
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/FloatNode.php
@@ -0,0 +1,63 @@
+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..36fac32
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/IntegerNode.php
@@ -0,0 +1,70 @@
+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..4ac9370
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/Php/Scalar/InterpolatedStringNode.php
@@ -0,0 +1,74 @@
+ */
+ 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;
+ }
+ }
+}
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;
+ }
+ }
+}
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/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..2b6f4f2
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Nodes/TextNode.php
@@ -0,0 +1,43 @@
+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..920763b
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/PhpHelpers.php
@@ -0,0 +1,257 @@
+ $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 {
+ return chr(octdec($ch));
+ }
+ },
+ $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..daa8428
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Position.php
@@ -0,0 +1,45 @@
+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..8dd4630
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/PrintContext.php
@@ -0,0 +1,341 @@
+ [10, 1],
+ Expression\PostOpNode::class => [10, -1],
+ Expression\UnaryOpNode::class => [10, 1],
+ Expression\CastNode::class => [10, 1],
+ Expression\ErrorSuppressNode::class => [10, 1],
+ Expression\InstanceofNode::class => [20, 0],
+ Expression\NotNode::class => [30, 1],
+ Expression\TernaryNode::class => [150, 0],
+ // parser uses %left for assignments, but they really behave as %right
+ Expression\AssignNode::class => [160, 1],
+ Expression\AssignOpNode::class => [160, 1],
+ ];
+
+ private array $binaryPrecedenceMap = [
+ // [precedence, associativity] (-1 is %left, 0 is %nonassoc and 1 is %right)
+ '**' => [0, 1],
+ '*' => [40, -1],
+ '/' => [40, -1],
+ '%' => [40, -1],
+ '+' => [50, -1],
+ '-' => [50, -1],
+ '.' => [50, -1],
+ '<<' => [60, -1],
+ '>>' => [60, -1],
+ '<' => [70, 0],
+ '<=' => [70, 0],
+ '>' => [70, 0],
+ '>=' => [70, 0],
+ '==' => [80, 0],
+ '!=' => [80, 0],
+ '===' => [80, 0],
+ '!==' => [80, 0],
+ '<=>' => [80, 0],
+ '&' => [90, -1],
+ '^' => [100, -1],
+ '|' => [110, -1],
+ '&&' => [120, -1],
+ '||' => [130, -1],
+ '??' => [140, 1],
+ 'and' => [170, -1],
+ 'xor' => [180, -1],
+ 'or' => [190, -1],
+ ];
+ private int $counter = 0;
+
+ /** @var Escaper[] */
+ private array $escaperStack = [];
+
+
+ public function __construct(string $contentType = ContentType::Html)
+ {
+ $this->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) {
+ [, $l, $pos, $format, $cond, $r] = $m;
+ $arg = $args[$pos];
+
+ $code = match ($format) {
+ 'dump' => PhpHelpers::dump($arg),
+ 'node' => $arg ? $arg->print($this) : '',
+ 'raw' => (string) $arg,
+ 'args' => $this->implode($arg instanceof Expression\ArrayNode ? $arg->toArguments() : $arg),
+ 'line' => $arg?->line ? "/* line $arg->line */" : '',
+ };
+
+ if ($cond && ($code === '[]' || $code === '')) {
+ return $r ? $l : $r;
+ }
+
+ return $code === ''
+ ? trim($l) . $r
+ : $l . $code . $r;
+ },
+ $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$\"\\") . '"';
+ }
+
+
+ /**
+ * Prints an infix operation while taking precedence into account.
+ */
+ public function infixOp(Node $node, Node $leftNode, string $operatorString, Node $rightNode): string
+ {
+ [$precedence, $associativity] = $this->getPrecedence($node);
+ return $this->prec($leftNode, $precedence, $associativity, -1)
+ . $operatorString
+ . $this->prec($rightNode, $precedence, $associativity, 1);
+ }
+
+
+ /**
+ * Prints a prefix operation while taking precedence into account.
+ */
+ public function prefixOp(Node $node, string $operatorString, Node $expr): string
+ {
+ [$precedence, $associativity] = $this->getPrecedence($node);
+ return $operatorString . $this->prec($expr, $precedence, $associativity, 1);
+ }
+
+
+ /**
+ * Prints a postfix operation while taking precedence into account.
+ */
+ public function postfixOp(Node $node, Node $var, string $operatorString): string
+ {
+ [$precedence, $associativity] = $this->getPrecedence($node);
+ return $this->prec($var, $precedence, $associativity, -1) . $operatorString;
+ }
+
+
+ /**
+ * Prints an expression node with the least amount of parentheses necessary to preserve the meaning.
+ */
+ private function prec(Node $node, int $parentPrecedence, int $parentAssociativity, int $childPosition): string
+ {
+ $precedence = $this->getPrecedence($node);
+ if ($precedence) {
+ $childPrecedence = $precedence[0];
+ if ($childPrecedence > $parentPrecedence
+ || ($parentPrecedence === $childPrecedence && $parentAssociativity !== $childPosition)
+ ) {
+ return '(' . $node->print($this) . ')';
+ }
+ }
+
+ return $node->print($this);
+ }
+
+
+ private function getPrecedence(Node $node): ?array
+ {
+ return $node instanceof Expression\BinaryOpNode
+ ? $this->binaryPrecedenceMap[$node->operator]
+ : $this->exprPrecedenceMap[$node::class] ?? null;
+ }
+
+
+ /**
+ * 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\FunctionCallableNode
+ || $expr instanceof Expression\MethodCallNode
+ || $expr instanceof Expression\MethodCallableNode
+ || $expr instanceof Expression\StaticMethodCallNode
+ || $expr instanceof Expression\StaticMethodCallableNode
+ || $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\FunctionCallableNode
+ || $expr instanceof Expression\MethodCallNode
+ || $expr instanceof Expression\MethodCallableNode
+ || $expr instanceof Expression\StaticMethodCallNode
+ || $expr instanceof Expression\StaticMethodCallableNode
+ || $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) . ']';
+ }
+}
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..270c7d9
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Tag.php
@@ -0,0 +1,116 @@
+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) && !in_array($tag->name, $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->nAttributeNode, $this->htmlElement->attributes->children, true);
+ $this->htmlElement->attributes->children[$index] = $this->nAttributeNode = $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..710b603
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/TagLexer.php
@@ -0,0 +1,396 @@
+ 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) (? [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]* ) )
+
+ (? [ \t\r\n]+ )|
+ ( (? ' ) (? ( \\. | [^'\\] )* ' )? )|
+ ( (? " ) .* )|
+ ( (? <<< [ \t]* (?: (?&label) | ' (?&label) ' | " (?&label) " ) \r?\n ) .* )|
+ ( (? /\* ) (? .*?\*/ )? )|
+ (? \$ (?&label) )|
+ (?
+ ((?&lnum) | (?&dnum)) [eE][+-]? (?&lnum)|
+ (? (?&lnum)? \. (?&lnum) | (?&lnum) \. (?&lnum)? )
+ )|
+ (?
+ 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*|
+ 0[bB][01]+(_[01]+)*|
+ 0[oO][0-7]+(_[0-7]+)*|
+ (? [0-9]+(_[0-9]+)* )
+ )|
+ (? \\ (?&label) ( \\ (?&label) )* )|
+ (? (?&label) ( \\ (?&label) )+ )|
+ (? (?&label) (?= [ \t\r\n]* [(&=] ) )|
+ (? (?&label)((--?|\.)[a-zA-Z0-9_\x80-\xff]+)* )|
+ (
+ (
+ (? -> )|
+ (? \?-> )|
+ (? \?\?-> )
+ )
+ (? [ \t\r\n]+ )?
+ (? (?&label) )?
+ )|
+ (? => )|
+ (? \+= )|
+ (? -= )|
+ (? \*= )|
+ (? /= )|
+ (? \.= )|
+ (? %= )|
+ (? &= )|
+ (? \|= )|
+ (? \^= )|
+ (? <<= )|
+ (? >>= )|
+ (? \*\*= )|
+ (? \?\?= )|
+ (? \?\? )|
+ (? \|\| )|
+ (? && )|
+ (? & (?= [ \t\r\n]* (\$|\.\.\.) ) )|
+ (? & )|
+ (? === )|
+ (? !== )|
+ (? == )|
+ (? != | <> )|
+ (? <=> )|
+ (? <= )|
+ (? >= )|
+ (? << )|
+ (? >> )|
+ (? \+\+ )|
+ (? -- )|
+ (? \*\* )|
+ (? :: )|
+ (? \\ )|
+ (? \.\.\. )|
+ (? \( [ \t]* int [ \t]* \) )|
+ (? \( [ \t]* float [ \t]* \) )|
+ (? \( [ \t]* string [ \t]* \) )|
+ (? \( [ \t]* array [ \t]* \) )|
+ (? \( [ \t]* object [ \t]* \) )|
+ (? \( [ \t]* bool [ \t]* \) )|
+ (? \( [ \t]* expand [ \t]* \) )|
+ ( (? /?} ) .* )|
+ (? [;:,.|^&+/*=%!\~$<>?@#(){[\]-] )|
+ (? . )
+ ~xsA
+ XX;
+
+ $depth = 0;
+ matchRE:
+ preg_match_all($re, $this->input, $matches, PREG_SET_ORDER | PREG_UNMATCHED_AS_NULL, $this->offset);
+ if (preg_last_error()) {
+ throw new CompileException(preg_last_error_msg());
+ }
+
+ foreach ($matches as $m) {
+ if (isset($m['char'])) {
+ if ($m['char'] === '{') {
+ $depth++;
+ }
+ $this->addToken(null, $m['char']);
+
+ } elseif (isset($m['end'])) {
+ $depth--;
+ if ($depth < 0) {
+ return;
+ }
+ foreach (str_split($m['end']) as $ch) {
+ $this->addToken(null, $ch);
+ }
+
+ goto matchRE;
+
+ } elseif (isset($m[$type = 'Php_ObjectOperator'])
+ || isset($m[$type = 'Php_NullsafeObjectOperator'])
+ || isset($m[$type = 'Php_UndefinedsafeObjectOperator'])
+ ) {
+ $this->addToken(constant(Token::class . '::' . $type), $m[$type]);
+ if (isset($m['Php_Whitespace'])) {
+ $this->addToken(Token::Php_Whitespace, $m['Php_Whitespace']);
+ }
+ if (isset($m['Php_Identifier'])) {
+ $this->addToken(Token::Php_Identifier, $m['Php_Identifier']);
+ }
+
+ } elseif (isset($m['Php_Identifier'])) {
+ $lower = strtolower($m['Php_Identifier']);
+ $this->addToken(
+ self::Keywords[$lower] ?? (preg_match('~[A-Z_][A-Z0-9_]{2,}$~DA', $m['Php_Identifier']) ? Token::Php_Constant : Token::Php_Identifier),
+ $m['Php_Identifier'],
+ );
+
+ } elseif (isset($m['Php_IdentifierFollowed'])) {
+ $lower = strtolower($m['Php_IdentifierFollowed']);
+ $this->addToken(self::KeywordsFollowed[$lower] ?? self::Keywords[$lower] ?? Token::Php_Identifier, $m['Php_IdentifierFollowed']);
+
+ } elseif (isset($m['Php_ConstantEncapsedString'])) {
+ isset($m['rest'])
+ ? $this->addToken(Token::Php_ConstantEncapsedString, "'" . $m['rest'])
+ : throw new CompileException('Unterminated string.', $this->position);
+
+ } elseif (isset($m['string'])) {
+ $pos = $this->position;
+ $this->addToken(null, '"');
+ $count = count($this->tokens);
+ $this->tokenizeString('"');
+ $token = $this->tokens[$count] ?? null;
+ $this->addToken(null, '"');
+ if (
+ count($this->tokens) <= $count + 2
+ && (!$token || $token->type === Token::Php_EncapsedAndWhitespace)
+ ) {
+ array_splice($this->tokens, $count - 1, null, [new Token(Token::Php_ConstantEncapsedString, '"' . $token?->text . '"', $pos)]);
+ }
+ goto matchRE;
+
+ } elseif (isset($m['Php_Integer'])) {
+ $num = PhpHelpers::decodeNumber($m['Php_Integer']);
+ $this->addToken(is_float($num) ? Token::Php_Float : Token::Php_Integer, $m['Php_Integer']);
+
+ } elseif (isset($m['Php_StartHeredoc'])) {
+ $this->addToken(Token::Php_StartHeredoc, $m['Php_StartHeredoc']);
+ $endRe = '(?<=\n)[ \t]*' . trim($m['Php_StartHeredoc'], "< \t\r\n'\"") . '\b';
+ if (str_contains($m['Php_StartHeredoc'], "'")) { // nowdoc
+ if (!preg_match('~(.*?)(' . $endRe . ')~sA', $this->input, $m, 0, $this->offset)) {
+ throw new CompileException('Unterminated NOWDOC.', $this->position);
+ } elseif ($m[1] !== '') {
+ $this->addToken(Token::Php_EncapsedAndWhitespace, $m[1]);
+ }
+ $this->addToken(Token::Php_EndHeredoc, $m[2]);
+ } else {
+ $end = $this->tokenizeString($endRe);
+ $this->addToken(Token::Php_EndHeredoc, $end);
+ }
+ goto matchRE;
+
+ } elseif (isset($m['Php_Comment'])) {
+ isset($m['rest'])
+ ? $this->addToken(Token::Php_Comment, '/*' . $m['rest'])
+ : throw new CompileException('Unterminated comment.', $this->position);
+
+ } elseif (isset($m['badchar'])) {
+ throw new CompileException("Unexpected '$m[badchar]'", $this->position);
+
+ } else {
+ foreach ($m as $type => $text) {
+ if ($text !== null && !is_int($type)) {
+ $this->addToken(constant(Token::class . '::' . $type), $text);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+
+ private function tokenizeString(string $endRe): string
+ {
+ $re = <<<'XX'
+ ~(?J)(?n) # allow duplicate named groups, no auto capture
+ (?(DEFINE) (? [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]* ) )
+
+ ( (? \{\$ ) .* )|
+ (? \$\{ )|
+ ( (? \$ (?&label) )
+ (
+ (
+ (? -> )|
+ (? \?-> )|
+ (? \?\?-> )
+ )
+ (? (?&label) )
+ |
+ (? \[ )
+ (
+ (? \$ (?&label) )|
+ (? (?&label) )|
+ (? - )?
+ (?
+ 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)*|
+ 0[bB][01]+(_[01]+)*|
+ 0[oO][0-7]+(_[0-7]+)*|
+ [0-9]+(_[0-9]+)*
+ )
+ )?
+ (? ] )?
+ |
+ )
+ )|
+ XX . "
+ ((? $endRe ) .* )|
+ (? ( \\\\. | [^\\\\] ) )
+ ~xsA";
+
+ matchRE:
+ preg_match_all($re, $this->input, $matches, PREG_SET_ORDER | PREG_UNMATCHED_AS_NULL, $this->offset);
+ if (preg_last_error()) {
+ throw new CompileException(preg_last_error_msg());
+ }
+
+ $buffer = '';
+ foreach ($matches as $m) {
+ if (isset($m['char'])) {
+ $buffer .= $m['char'];
+ continue;
+ } elseif ($buffer !== '') {
+ $this->addToken(Token::Php_EncapsedAndWhitespace, $buffer);
+ $buffer = '';
+ }
+
+ if (isset($m['Php_CurlyOpen'])) {
+ $this->addToken(Token::Php_CurlyOpen, '{');
+ $this->tokenizeCode();
+ if (($this->input[$this->offset] ?? null) === '}') {
+ $this->addToken(null, '}');
+ }
+ goto matchRE;
+
+ } elseif (isset($m['Php_DollarOpenCurlyBraces'])) {
+ throw new CompileException('Syntax ${...} is not supported.', $this->position);
+
+ } elseif (isset($m['Php_Variable'])) {
+ $this->addToken(Token::Php_Variable, $m['Php_Variable']);
+ if (isset($m[$type = 'Php_ObjectOperator'])
+ || isset($m[$type = 'Php_NullsafeObjectOperator'])
+ || isset($m[$type = 'Php_UndefinedsafeObjectOperator'])
+ ) {
+ $this->addToken(constant(Token::class . '::' . $type), $m[$type]);
+ $this->addToken(Token::Php_Identifier, $m['Php_Identifier']);
+
+ } elseif (isset($m['offset'])) {
+ $this->addToken(null, '[');
+ if (!isset($m['offsetEnd'])) {
+ throw new CompileException("Missing ']'", $this->position);
+ } elseif (isset($m['offsetVar'])) {
+ $this->addToken(Token::Php_Variable, $m['offsetVar']);
+ } elseif (isset($m['offsetString'])) {
+ $this->addToken(Token::Php_Identifier, $m['offsetString']);
+ } elseif (isset($m['Php_NumString'])) {
+ if (isset($m['offsetMinus'])) {
+ $this->addToken(null, '-');
+ }
+ $this->addToken(Token::Php_NumString, $m['Php_NumString']);
+ } else {
+ throw new CompileException("Unexpected '" . substr($this->input, $this->offset - 1, 5) . "'", $this->position);
+ }
+ $this->addToken(null, ']');
+ }
+
+ } elseif (isset($m['end'])) {
+ return $m['end'];
+ }
+ }
+
+ throw new CompileException('Unterminated string.', $this->position->advance($buffer));
+ }
+
+
+ private function addToken(?int $type, string $text): void
+ {
+ $this->tokens[] = new Token($type ?? ord($text), $text, $this->position);
+ $this->position = $this->position->advance($text);
+ $this->offset += strlen($text);
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/TagParser.php b/vendor/latte/latte/src/Latte/Compiler/TagParser.php
new file mode 100644
index 0000000..55019ca
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/TagParser.php
@@ -0,0 +1,473 @@
+ */
+ protected \SplObjectStorage $shortArrays;
+ private int /*readonly*/ $offsetDelta;
+
+
+ public function __construct(array $tokens)
+ {
+ $this->offsetDelta = $tokens[0]->position->offset ?? 0;
+ $tokens = $this->filterTokens($tokens);
+ $this->stream = new TokenStream(new \ArrayIterator($tokens));
+ }
+
+
+ /**
+ * Parses PHP-like expression.
+ */
+ public function parseExpression(): ExpressionNode
+ {
+ return $this->parse(self::SchemaExpression, recovery: true);
+ }
+
+
+ /**
+ * Parses optional list of arguments. Named and variadic arguments are also supported.
+ */
+ public function parseArguments(): Expression\ArrayNode
+ {
+ return $this->parse(self::SchemaArguments, recovery: true);
+ }
+
+
+ /**
+ * Parses optional list of filters.
+ */
+ public function parseModifier(): Node\ModifierNode
+ {
+ return $this->isEnd()
+ ? new Node\ModifierNode([])
+ : $this->parse(self::SchemaFilters);
+ }
+
+
+ /**
+ * Parses unquoted string or PHP-like expression.
+ */
+ public function parseUnquotedStringOrExpression(bool $colon = true): ExpressionNode
+ {
+ $position = $this->stream->peek()->position;
+ $lexer = new TagLexer;
+ $tokens = $lexer->tokenizeUnquotedString($this->text, $position, $colon, $this->offsetDelta);
+
+ if (!$tokens) {
+ return $this->parseExpression();
+ }
+
+ $parser = new self($tokens);
+ $end = $position->offset + strlen($parser->text) - 2; // 2 quotes
+ do {
+ $this->stream->consume();
+ } while ($this->stream->peek()->position->offset < $end);
+
+ return $parser->parseExpression();
+ }
+
+
+ /**
+ * Parses optional type declaration.
+ */
+ public function parseType(): ?Node\SuperiorTypeNode
+ {
+ $kind = [
+ Token::Php_Identifier, Token::Php_Constant, Token::Php_Ellipsis, Token::Php_Array, Token::Php_Integer,
+ Token::Php_NameFullyQualified, Token::Php_NameQualified, Token::Php_Null, Token::Php_False,
+ '(', ')', '<', '>', '[', ']', '|', '&', '{', '}', ':', ',', '=', '?',
+ ];
+ $res = null;
+ while ($token = $this->stream->tryConsume(...$kind)) {
+ $res .= $token->text;
+ }
+
+ return $res ? new Node\SuperiorTypeNode($res) : null;
+ }
+
+
+ /**
+ * Parses variables used in foreach.
+ * @internal
+ */
+ public function parseForeach(): array
+ {
+ return $this->parse(self::SchemaForeach);
+ }
+
+
+ /**
+ * Consumes optional token followed by whitespace. Suitable before parseUnquotedStringOrExpression().
+ */
+ public function tryConsumeTokenBeforeUnquotedString(string ...$kind): ?Token
+ {
+ $token = $this->stream->peek();
+ return $token->is(...$kind) // is followed by whitespace
+ && $this->stream->peek(1)->position->offset > $token->position->offset + strlen($token->text)
+ ? $this->stream->consume()
+ : null;
+ }
+
+
+ /** @deprecated use tryConsumeTokenBeforeUnquotedString() */
+ public function tryConsumeModifier(string ...$kind): ?Token
+ {
+ return $this->tryConsumeTokenBeforeUnquotedString(...$kind);
+ }
+
+
+ public function isEnd(): bool
+ {
+ return $this->stream->peek()->isEnd();
+ }
+
+
+ /** @throws Latte\CompileException */
+ private function parse(string $schema, bool $recovery = false): mixed
+ {
+ $symbol = self::SymbolNone; // We start off with no lookahead-token
+ $this->startTokenStack = []; // Keep stack of start token
+ $token = null;
+ $state = 0; // Start off in the initial state and keep a stack of previous states
+ $stateStack = [$state];
+ $this->semStack = []; // Semantic value stack (contains values of tokens and semantic action results)
+ $stackPos = 0; // Current position in the stack(s)
+ $this->shortArrays = new \SplObjectStorage;
+
+ do {
+ if (self::ActionBase[$state] === 0) {
+ $rule = self::ActionDefault[$state];
+ } else {
+ if ($symbol === self::SymbolNone) {
+ $recovery = $recovery
+ ? [$this->stream->getIndex(), $state, $stateStack, $stackPos, $this->semValue, $this->semStack, $this->startTokenStack]
+ : null;
+
+
+ $token = $token
+ ? $this->stream->consume()
+ : new Token(ord($schema), $schema);
+
+ recovery:
+ $symbol = self::TokenToSymbol[$token->type];
+ }
+
+ $idx = self::ActionBase[$state] + $symbol;
+ if ((($idx >= 0 && $idx < count(self::Action) && self::ActionCheck[$idx] === $symbol)
+ || ($state < self::Yy2Tblstate
+ && ($idx = self::ActionBase[$state + self::NumNonLeafStates] + $symbol) >= 0
+ && $idx < count(self::Action) && self::ActionCheck[$idx] === $symbol))
+ && ($action = self::Action[$idx]) !== self::DefaultAction
+ ) {
+ /*
+ >= numNonLeafStates: shift and reduce
+ > 0: shift
+ = 0: accept
+ < 0: reduce
+ = -YYUNEXPECTED: error
+ */
+ if ($action > 0) { // shift
+ ++$stackPos;
+ $stateStack[$stackPos] = $state = $action;
+ $this->semStack[$stackPos] = $token->text;
+ $this->startTokenStack[$stackPos] = $token;
+ $symbol = self::SymbolNone;
+ if ($action < self::NumNonLeafStates) {
+ continue;
+ }
+
+ $rule = $action - self::NumNonLeafStates; // shift-and-reduce
+ } else {
+ $rule = -$action;
+ }
+ } else {
+ $rule = self::ActionDefault[$state];
+ }
+ }
+
+ do {
+ if ($rule === 0) { // accept
+ $this->finalizeShortArrays();
+ return $this->semValue;
+
+ } elseif ($rule !== self::UnexpectedTokenRule) { // reduce
+ $this->reduce($rule, $stackPos);
+
+ // Goto - shift nonterminal
+ $ruleLength = self::RuleToLength[$rule];
+ $stackPos -= $ruleLength;
+ $nonTerminal = self::RuleToNonTerminal[$rule];
+ $idx = self::GotoBase[$nonTerminal] + $stateStack[$stackPos];
+ if ($idx >= 0 && $idx < count(self::Goto) && self::GotoCheck[$idx] === $nonTerminal) {
+ $state = self::Goto[$idx];
+ } else {
+ $state = self::GotoDefault[$nonTerminal];
+ }
+
+ ++$stackPos;
+ $stateStack[$stackPos] = $state;
+ $this->semStack[$stackPos] = $this->semValue;
+ if ($ruleLength === 0) {
+ $this->startTokenStack[$stackPos] = $token;
+ }
+
+ } elseif ($recovery && $this->isExpectedEof($state)) { // recoverable error
+ [, $state, $stateStack, $stackPos, $this->semValue, $this->semStack, $this->startTokenStack] = $recovery;
+ $this->stream->seek($recovery[0]);
+ $token = new Token(Token::End, '');
+ goto recovery;
+
+ } else { // error
+ throw new Latte\CompileException('Unexpected ' . ($token->text ? "'$token->text'" : 'end'), $token->position);
+ }
+
+ if ($state < self::NumNonLeafStates) {
+ break;
+ }
+
+ $rule = $state - self::NumNonLeafStates; // shift-and-reduce
+ } while (true);
+ } while (true);
+ }
+
+
+ /**
+ * Can EOF be the next token?
+ */
+ private function isExpectedEof(int $state): bool
+ {
+ foreach (self::SymbolToName as $symbol => $name) {
+ $idx = self::ActionBase[$state] + $symbol;
+ if (($idx >= 0 && $idx < count(self::Action) && self::ActionCheck[$idx] === $symbol
+ || $state < self::Yy2Tblstate
+ && ($idx = self::ActionBase[$state + self::NumNonLeafStates] + $symbol) >= 0
+ && $idx < count(self::Action) && self::ActionCheck[$idx] === $symbol)
+ && self::Action[$idx] !== self::UnexpectedTokenRule
+ && self::Action[$idx] !== self::DefaultAction
+ && $symbol === 0
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ public function throwReservedKeywordException(Token $token)
+ {
+ throw new Latte\CompileException("Keyword '$token->text' cannot be used in Latte.", $token->position);
+ }
+
+
+ protected function checkFunctionName(
+ Expression\FunctionCallNode|Expression\FunctionCallableNode $func,
+ ): ExpressionNode
+ {
+ if ($func->name instanceof NameNode && $func->name->isKeyword()) {
+ $this->throwReservedKeywordException(new Token(0, (string) $func->name, $func->name->position));
+ }
+ return $func;
+ }
+
+
+ protected static function handleBuiltinTypes(NameNode $name): NameNode|Node\IdentifierNode
+ {
+ $builtinTypes = [
+ 'bool' => true, 'int' => true, 'float' => true, 'string' => true, 'iterable' => true, 'void' => true,
+ 'object' => true, 'null' => true, 'false' => true, 'mixed' => true, 'never' => true,
+ ];
+
+ $lowerName = strtolower($name->toCodeString());
+ return isset($builtinTypes[$lowerName])
+ ? new Node\IdentifierNode($lowerName, $name->position)
+ : $name;
+ }
+
+
+ protected static function parseOffset(string $str, Position $position): Scalar\StringNode|Scalar\IntegerNode
+ {
+ if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) {
+ return new Scalar\StringNode($str, $position);
+ }
+
+ $num = +$str;
+ if (!is_int($num)) {
+ return new Scalar\StringNode($str, $position);
+ }
+
+ return new Scalar\IntegerNode($num, Scalar\IntegerNode::KindDecimal, $position);
+ }
+
+
+ /** @param ExpressionNode[] $parts */
+ protected function parseDocString(
+ string $startToken,
+ array $parts,
+ string $endToken,
+ Position $startPos,
+ Position $endPos,
+ ): Scalar\StringNode|Scalar\InterpolatedStringNode
+ {
+ $hereDoc = !str_contains($startToken, "'");
+ preg_match('/\A[ \t]*/', $endToken, $matches);
+ $indentation = $matches[0];
+ if (str_contains($indentation, ' ') && str_contains($indentation, "\t")) {
+ throw new CompileException('Invalid indentation - tabs and spaces cannot be mixed', $endPos);
+
+ } elseif (!$parts) {
+ return new Scalar\StringNode('', $startPos);
+
+ } elseif (!$parts[0] instanceof Node\InterpolatedStringPartNode) {
+ // If there is no leading encapsed string part, pretend there is an empty one
+ $this->stripIndentation('', $indentation, true, false, $parts[0]->position);
+ }
+
+ $newParts = [];
+ foreach ($parts as $i => $part) {
+ if ($part instanceof Node\InterpolatedStringPartNode) {
+ $isLast = $i === \count($parts) - 1;
+ $part->value = $this->stripIndentation(
+ $part->value,
+ $indentation,
+ $i === 0,
+ $isLast,
+ $part->position,
+ );
+ if ($isLast) {
+ $part->value = preg_replace('~(\r\n|\n|\r)\z~', '', $part->value);
+ }
+ if ($hereDoc) {
+ $part->value = PhpHelpers::decodeEscapeSequences($part->value, null);
+ }
+ if ($i === 0 && $isLast) {
+ return new Scalar\StringNode($part->value, $startPos);
+ }
+ if ($part->value === '') {
+ continue;
+ }
+ }
+ $newParts[] = $part;
+ }
+
+ return new Scalar\InterpolatedStringNode($newParts, $startPos);
+ }
+
+
+ private function stripIndentation(
+ string $str,
+ string $indentation,
+ bool $atStart,
+ bool $atEnd,
+ Position $position,
+ ): string
+ {
+ if ($indentation === '') {
+ return $str;
+ }
+ $start = $atStart ? '(?:(?<=\n)|\A)' : '(?<=\n)';
+ $end = $atEnd ? '(?:(?=[\r\n])|\z)' : '(?=[\r\n])';
+ $regex = '/' . $start . '([ \t]*)(' . $end . ')?/D';
+ return preg_replace_callback(
+ $regex,
+ function ($matches) use ($indentation, $position) {
+ $indentLen = \strlen($indentation);
+ $prefix = substr($matches[1], 0, $indentLen);
+ if (str_contains($prefix, $indentation[0] === ' ' ? "\t" : ' ')) {
+ throw new CompileException('Invalid indentation - tabs and spaces cannot be mixed', $position);
+ } elseif (strlen($prefix) < $indentLen && !isset($matches[2])) {
+ throw new CompileException(
+ 'Invalid body indentation level ' .
+ '(expecting an indentation level of at least ' . $indentLen . ')',
+ $position,
+ );
+ }
+ return substr($matches[0], strlen($prefix));
+ },
+ $str,
+ );
+ }
+
+
+ public function convertArrayToList(Expression\ArrayNode $array): Node\ListNode
+ {
+ $this->shortArrays->detach($array);
+ $items = [];
+ foreach ($array->items as $item) {
+ $value = $item->value;
+ if ($item->unpack) {
+ throw new CompileException('Spread operator is not supported in assignments.', $value->position);
+ }
+ $value = match (true) {
+ $value instanceof Expression\TemporaryNode => $value->value,
+ $value instanceof Expression\ArrayNode && $this->shortArrays->contains($value) => $this->convertArrayToList($value),
+ default => $value,
+ };
+ $items[] = $value
+ ? new Node\ListItemNode($value, $item->key, $item->byRef, $item->position)
+ : null;
+ }
+ return new Node\ListNode($items, $array->position);
+ }
+
+
+ private function finalizeShortArrays(): void
+ {
+ foreach ($this->shortArrays as $node) {
+ foreach ($node->items as $item) {
+ if ($item->value instanceof Expression\TemporaryNode) {
+ throw new CompileException('Cannot use empty array elements or list() in arrays.', $item->position);
+ }
+ }
+ }
+ }
+
+
+ /** @param Token[] $tokens */
+ private function filterTokens(array $tokens): array
+ {
+ $this->text = '';
+ $res = [];
+ foreach ($tokens as $token) {
+ $this->text .= $token->text;
+ if (!$token->is(Token::Php_Whitespace, Token::Php_Comment)) {
+ $res[] = $token;
+ }
+ }
+
+ return $res;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/TagParserData.php b/vendor/latte/latte/src/Latte/Compiler/TagParserData.php
new file mode 100644
index 0000000..a754133
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/TagParserData.php
@@ -0,0 +1,607 @@
+'",
+ "'='",
+ "'+='",
+ "'-='",
+ "'*='",
+ "'/='",
+ "'.='",
+ "'%='",
+ "'&='",
+ "'|='",
+ "'^='",
+ "'<<='",
+ "'>>='",
+ "'**='",
+ "'??='",
+ "'?'",
+ "':'",
+ "'??'",
+ "'||'",
+ "'&&'",
+ "'|'",
+ "'^'",
+ "'&'",
+ "'&'",
+ "'=='",
+ "'!='",
+ "'==='",
+ "'!=='",
+ "'<=>'",
+ "'<'",
+ "'<='",
+ "'>'",
+ "'>='",
+ "'.'",
+ "'<<'",
+ "'>>'",
+ "'in'",
+ "'+'",
+ "'-'",
+ "'*'",
+ "'/'",
+ "'%'",
+ "'!'",
+ "'instanceof'",
+ "'~'",
+ "'++'",
+ "'--'",
+ "'(int)'",
+ "'(float'",
+ "'(string)'",
+ "'(array)'",
+ "'(object)'",
+ "'(bool)'",
+ "'@'",
+ "'**'",
+ "'['",
+ "'new'",
+ "'clone'",
+ 'integer',
+ 'floating-point number',
+ 'identifier',
+ 'variable name',
+ 'constant',
+ 'variable',
+ 'number',
+ 'string content',
+ 'quoted string',
+ "'match'",
+ "'default'",
+ "'function'",
+ "'fn'",
+ "'return'",
+ "'use'",
+ "'isset'",
+ "'empty'",
+ "'->'",
+ "'?->'",
+ "'??->'",
+ "'list'",
+ "'array'",
+ "'heredoc start'",
+ "'heredoc end'",
+ "'\${'",
+ "'{\$'",
+ "'::'",
+ "'...'",
+ "'(expand)'",
+ 'fully qualified name',
+ 'namespaced name',
+ "'null'",
+ "'true'",
+ "'false'",
+ "'e'",
+ "'m'",
+ "'a'",
+ "'f'",
+ "'('",
+ "')'",
+ "'{'",
+ "'}'",
+ "';'",
+ "']'",
+ "'\"'",
+ "'$'",
+ "'\\\\'",
+ 'whitespace',
+ 'comment',
+ ];
+
+ /** Temporary value containing the result of last semantic action (reduction) */
+ protected mixed $semValue = null;
+
+ /** Semantic value stack (contains values of tokens and semantic action results) */
+ protected array $semStack;
+
+ /** @var Token[] Start attribute stack */
+ protected array $startTokenStack;
+
+
+ protected function reduce(int $rule, int $pos): void
+ {
+ (match ($rule) {
+ 0, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 28, 29, 57, 70, 72, 93, 98, 99, 165, 182, 184, 188, 189, 191, 192, 194, 205, 210, 211, 216, 217, 219, 220, 221, 222, 224, 226, 227, 229, 234, 235, 239, 243, 250, 252, 253, 255, 260, 278, 290 => fn() => $this->semValue = $this->semStack[$pos],
+ 2 => fn() => $this->semValue = new Node\ModifierNode($this->semStack[$pos], position: $this->startTokenStack[$pos]->position),
+ 3 => fn() => $this->semValue = new Expression\ArrayNode($this->semStack[$pos], position: $this->startTokenStack[$pos]->position),
+ 22, 23, 24, 25, 26, 62, 63, 64 => fn() => $this->semValue = new Node\IdentifierNode($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 27 => fn() => $this->semValue = new Expression\VariableNode(substr($this->semStack[$pos], 1), $this->startTokenStack[$pos]->position),
+ 30, 40, 51, 81, 90, 91, 150, 151, 171, 172, 190, 218, 225, 251, 254, 286 => fn() => $this->semValue = $this->semStack[$pos - 1],
+ 31, 39, 52, 73, 89, 170, 193 => fn() => $this->semValue = [],
+ 32, 41, 53, 75, 83, 86, 173, 259, 274 => fn() => $this->semValue = [$this->semStack[$pos]],
+ 33, 42, 54, 66, 68, 76, 82, 174, 258 => function () use ($pos) {
+ $this->semStack[$pos - 2][] = $this->semStack[$pos];
+ $this->semValue = $this->semStack[$pos - 2];
+ },
+ 34, 36 => fn() => $this->semValue = false,
+ 35, 37 => fn() => $this->semValue = true,
+ 38 => fn() => $this->semValue = new Expression\MatchNode($this->semStack[$pos - 4], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 6]->position),
+ 43 => fn() => $this->semValue = new Node\MatchArmNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 44 => fn() => $this->semValue = new Node\MatchArmNode(null, $this->semStack[$pos], $this->startTokenStack[$pos - 3]->position),
+ 45 => fn() => $this->semValue = [null, ...$this->semStack[$pos]],
+ 46 => fn() => $this->semValue = [$this->semStack[$pos - 2], ...$this->semStack[$pos]],
+ 47, 49 => fn() => $this->semValue = [$this->semStack[$pos], false],
+ 48 => fn() => $this->semValue = [$this->semStack[$pos], true],
+ 50 => fn() => $this->semValue = [$this->convertArrayToList($this->semStack[$pos]), false],
+ 55 => fn() => $this->semValue = new Node\ParameterNode($this->semStack[$pos], null, $this->semStack[$pos - 3], $this->semStack[$pos - 2], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position),
+ 56 => fn() => $this->semValue = new Node\ParameterNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->semStack[$pos - 5], $this->semStack[$pos - 4], $this->semStack[$pos - 3], $this->startTokenStack[$pos - 5]->position),
+ 58 => fn() => $this->semValue = new Node\NullableTypeNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 59 => fn() => $this->semValue = new Node\UnionTypeNode($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 60 => fn() => $this->semValue = new Node\IntersectionTypeNode($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 61 => fn() => $this->semValue = TagParser::handleBuiltinTypes($this->semStack[$pos]),
+ 65, 67 => fn() => $this->semValue = [$this->semStack[$pos - 2], $this->semStack[$pos]],
+ 69, 71, 215 => fn() => $this->semValue = null,
+ 74, 92 => fn() => $this->semValue = $this->semStack[$pos - 2],
+ 77 => fn() => $this->semValue = new Node\ArgumentNode($this->semStack[$pos], false, false, null, $this->startTokenStack[$pos]->position),
+ 78 => fn() => $this->semValue = new Node\ArgumentNode($this->semStack[$pos], true, false, null, $this->startTokenStack[$pos - 1]->position),
+ 79 => fn() => $this->semValue = new Node\ArgumentNode($this->semStack[$pos], false, true, null, $this->startTokenStack[$pos - 1]->position),
+ 80 => fn() => $this->semValue = new Node\ArgumentNode($this->semStack[$pos], false, false, $this->semStack[$pos - 2], $this->startTokenStack[$pos - 2]->position),
+ 84, 85 => fn() => $this->semValue = new Expression\FilterCallNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 87, 272, 273 => function () use ($pos) {
+ $this->semStack[$pos - 1][] = $this->semStack[$pos];
+ $this->semValue = $this->semStack[$pos - 1];
+ },
+ 88 => fn() => $this->semValue = new Node\FilterNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 94, 96 => fn() => $this->semValue = new Expression\AssignNode($this->semStack[$pos - 2], $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position),
+ 95 => fn() => $this->semValue = new Expression\AssignNode($this->convertArrayToList($this->semStack[$pos - 2]), $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position),
+ 97 => fn() => $this->semValue = new Expression\AssignNode($this->semStack[$pos - 3], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position),
+ 100 => fn() => $this->semValue = new Expression\CloneNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 101 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '+', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 102 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '-', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 103 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '*', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 104 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '/', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 105 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '.', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 106 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '%', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 107 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '&', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 108 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '|', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 109 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '^', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 110 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '<<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 111 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '>>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 112 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '**', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 113 => fn() => $this->semValue = new Expression\AssignOpNode($this->semStack[$pos - 2], '??', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 114 => fn() => $this->semValue = new Expression\PostOpNode($this->semStack[$pos - 1], '++', $this->startTokenStack[$pos - 1]->position),
+ 115 => fn() => $this->semValue = new Expression\PreOpNode($this->semStack[$pos], '++', $this->startTokenStack[$pos - 1]->position),
+ 116 => fn() => $this->semValue = new Expression\PostOpNode($this->semStack[$pos - 1], '--', $this->startTokenStack[$pos - 1]->position),
+ 117 => fn() => $this->semValue = new Expression\PreOpNode($this->semStack[$pos], '--', $this->startTokenStack[$pos - 1]->position),
+ 118 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '||', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 119 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '&&', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 120 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], 'or', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 121 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], 'and', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 122 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], 'xor', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 123, 124 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '&', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 125 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '^', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 126 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '.', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 127 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '+', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 128 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '-', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 129 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '*', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 130 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '/', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 131 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '%', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 132 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 133 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 134 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '**', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 135 => fn() => $this->semValue = new Expression\InNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 136 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '+', $this->startTokenStack[$pos - 1]->position),
+ 137 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '-', $this->startTokenStack[$pos - 1]->position),
+ 138 => fn() => $this->semValue = new Expression\NotNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 139 => fn() => $this->semValue = new Expression\UnaryOpNode($this->semStack[$pos], '~', $this->startTokenStack[$pos - 1]->position),
+ 140 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '===', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 141 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '!==', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 142 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '==', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 143 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '!=', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 144 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<=>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 145 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 146 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '<=', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 147 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 148 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '>=', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 149 => fn() => $this->semValue = new Expression\InstanceofNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 152 => fn() => $this->semValue = new Expression\TernaryNode($this->semStack[$pos - 4], $this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 4]->position),
+ 153 => fn() => $this->semValue = new Expression\TernaryNode($this->semStack[$pos - 3], null, $this->semStack[$pos], $this->startTokenStack[$pos - 3]->position),
+ 154 => fn() => $this->semValue = new Expression\TernaryNode($this->semStack[$pos - 2], $this->semStack[$pos], null, $this->startTokenStack[$pos - 2]->position),
+ 155 => fn() => $this->semValue = new Expression\BinaryOpNode($this->semStack[$pos - 2], '??', $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 156 => fn() => $this->semValue = new Expression\IssetNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position),
+ 157 => fn() => $this->semValue = new Expression\EmptyNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position),
+ 158 => fn() => $this->semValue = new Expression\CastNode('int', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 159 => fn() => $this->semValue = new Expression\CastNode('float', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 160 => fn() => $this->semValue = new Expression\CastNode('string', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 161 => fn() => $this->semValue = new Expression\CastNode('array', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 162 => fn() => $this->semValue = new Expression\CastNode('object', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 163 => fn() => $this->semValue = new Expression\CastNode('bool', $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 164 => fn() => $this->semValue = new Expression\ErrorSuppressNode($this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ 166 => fn() => $this->semValue = new Expression\ClosureNode((bool) $this->semStack[$pos - 6], $this->semStack[$pos - 4], [], $this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 7]->position),
+ 167 => fn() => $this->semValue = new Expression\ClosureNode((bool) $this->semStack[$pos - 10], $this->semStack[$pos - 8], $this->semStack[$pos - 6], $this->semStack[$pos - 5], $this->semStack[$pos - 2], $this->startTokenStack[$pos - 11]->position),
+ 168 => fn() => $this->semValue = new Expression\ClosureNode((bool) $this->semStack[$pos - 7], $this->semStack[$pos - 5], $this->semStack[$pos - 3], $this->semStack[$pos - 2], null, $this->startTokenStack[$pos - 8]->position),
+ 169 => fn() => $this->semValue = new Expression\NewNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 175 => fn() => $this->semValue = new Node\ClosureUseNode($this->semStack[$pos], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 1]->position),
+ 176, 178 => fn() => $this->semValue = $this->checkFunctionName(new Expression\FunctionCallNode($this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position)),
+ 177, 179 => fn() => $this->semValue = $this->checkFunctionName(new Expression\FunctionCallableNode($this->semStack[$pos - 3], $this->startTokenStack[$pos - 3]->position)),
+ 180 => fn() => $this->semValue = new Expression\StaticMethodCallNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 3]->position),
+ 181 => fn() => $this->semValue = new Expression\StaticMethodCallableNode($this->semStack[$pos - 5], $this->semStack[$pos - 3], $this->startTokenStack[$pos - 5]->position),
+ 183, 185, 186 => fn() => $this->semValue = new Node\NameNode($this->semStack[$pos], Node\NameNode::KindNormal, $this->startTokenStack[$pos]->position),
+ 187 => fn() => $this->semValue = new Node\NameNode($this->semStack[$pos], Node\NameNode::KindFullyQualified, $this->startTokenStack[$pos]->position),
+ 195 => fn() => $this->semValue = new Expression\ConstantFetchNode($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 196 => fn() => $this->semValue = new Expression\ClassConstantFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 197 => fn() => $this->semValue = new Expression\ClassConstantFetchNode($this->semStack[$pos - 4], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 4]->position),
+ 198 => fn() => $this->semValue = new Expression\ArrayNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 2]->position),
+ 199 => fn() => $this->semValue = new Expression\ArrayNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position),
+ 200 => function () use ($pos) {
+ $this->semValue = $this->semStack[$pos];
+ $this->shortArrays->attach($this->semValue);
+ },
+ 201 => fn() => $this->semValue = Scalar\StringNode::parse($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 202 => fn() => $this->semValue = Scalar\InterpolatedStringNode::parse($this->semStack[$pos - 1], $this->startTokenStack[$pos - 2]->position),
+ 203 => fn() => $this->semValue = Scalar\IntegerNode::parse($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 204 => fn() => $this->semValue = Scalar\FloatNode::parse($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 206, 287 => fn() => $this->semValue = new Scalar\StringNode($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 207 => fn() => $this->semValue = new Scalar\BooleanNode(true, $this->startTokenStack[$pos]->position),
+ 208 => fn() => $this->semValue = new Scalar\BooleanNode(false, $this->startTokenStack[$pos]->position),
+ 209 => fn() => $this->semValue = new Scalar\NullNode($this->startTokenStack[$pos]->position),
+ 212 => fn() => $this->semValue = $this->parseDocString($this->semStack[$pos - 2], [$this->semStack[$pos - 1]], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position, $this->startTokenStack[$pos]->position),
+ 213 => fn() => $this->semValue = $this->parseDocString($this->semStack[$pos - 1], [], $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position, $this->startTokenStack[$pos]->position),
+ 214 => fn() => $this->semValue = $this->parseDocString($this->semStack[$pos - 2], $this->semStack[$pos - 1], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position, $this->startTokenStack[$pos]->position),
+ 223 => fn() => $this->semValue = new Expression\ConstantFetchNode(new Node\NameNode($this->semStack[$pos], Node\NameNode::KindNormal, $this->startTokenStack[$pos]->position), $this->startTokenStack[$pos]->position),
+ 228, 244, 279 => fn() => $this->semValue = new Expression\ArrayAccessNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position),
+ 230 => fn() => $this->semValue = new Expression\MethodCallNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->semStack[$pos], false, $this->startTokenStack[$pos - 3]->position),
+ 231 => fn() => $this->semValue = new Expression\MethodCallableNode($this->semStack[$pos - 5], $this->semStack[$pos - 3], $this->startTokenStack[$pos - 5]->position),
+ 232 => fn() => $this->semValue = new Expression\MethodCallNode($this->semStack[$pos - 3], $this->semStack[$pos - 1], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position),
+ 233 => fn() => $this->semValue = new Expression\MethodCallNode(new Expression\BinaryOpNode($this->semStack[$pos - 3], '??', new Scalar\NullNode($this->startTokenStack[$pos - 3]->position), $this->startTokenStack[$pos - 3]->position), $this->semStack[$pos - 1], $this->semStack[$pos], true, $this->startTokenStack[$pos - 3]->position),
+ 236, 245, 280 => fn() => $this->semValue = new Expression\PropertyFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], false, $this->startTokenStack[$pos - 2]->position),
+ 237, 246, 281 => fn() => $this->semValue = new Expression\PropertyFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], true, $this->startTokenStack[$pos - 2]->position),
+ 238, 247, 282 => fn() => $this->semValue = new Expression\PropertyFetchNode(new Expression\BinaryOpNode($this->semStack[$pos - 2], '??', new Scalar\NullNode($this->startTokenStack[$pos - 2]->position), $this->startTokenStack[$pos - 2]->position), $this->semStack[$pos], true, $this->startTokenStack[$pos - 2]->position),
+ 240 => fn() => $this->semValue = new Expression\VariableNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position),
+ 241 => function () use ($pos) {
+ $var = $this->semStack[$pos]->name;
+ $this->semValue = \is_string($var)
+ ? new Node\VarLikeIdentifierNode($var, $this->startTokenStack[$pos]->position)
+ : $var;
+ },
+ 242, 248, 249 => fn() => $this->semValue = new Expression\StaticPropertyFetchNode($this->semStack[$pos - 2], $this->semStack[$pos], $this->startTokenStack[$pos - 2]->position),
+ 256 => fn() => $this->semValue = $this->convertArrayToList(new Expression\ArrayNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 3]->position)),
+ 257 => function () use ($pos) {
+ $this->semValue = $this->semStack[$pos];
+ $end = count($this->semValue) - 1;
+ if (
+ $this->semValue[$end]->value instanceof Expression\TemporaryNode
+ && !$this->semValue[$end]->value->value
+ ) {
+ array_pop($this->semValue);
+ }
+ },
+ 261 => fn() => $this->semValue = new Node\ArrayItemNode(new Expression\TemporaryNode($this->semStack[$pos], $this->startTokenStack[$pos]->position), null, false, false, $this->startTokenStack[$pos]->position),
+ 262 => fn() => $this->semValue = new Node\ArrayItemNode(new Expression\TemporaryNode($this->semStack[$pos], $this->startTokenStack[$pos - 2]->position), $this->semStack[$pos - 2], false, false, $this->startTokenStack[$pos - 2]->position),
+ 263 => fn() => $this->semValue = new Node\ArrayItemNode(new Expression\TemporaryNode(null), null, false, false, $this->startTokenStack[$pos]->position),
+ 264 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], null, false, false, $this->startTokenStack[$pos]->position),
+ 265 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], null, true, false, $this->startTokenStack[$pos - 1]->position),
+ 266, 268 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], $this->semStack[$pos - 2], false, false, $this->startTokenStack[$pos - 2]->position),
+ 267, 269 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], $this->semStack[$pos - 3], true, false, $this->startTokenStack[$pos - 3]->position),
+ 270, 271 => fn() => $this->semValue = new Node\ArrayItemNode($this->semStack[$pos], null, false, true, $this->startTokenStack[$pos - 1]->position),
+ 275 => fn() => $this->semValue = [$this->semStack[$pos - 1], $this->semStack[$pos]],
+ 276 => fn() => $this->semValue = new Node\InterpolatedStringPartNode($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 277 => fn() => $this->semValue = new Expression\VariableNode($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 283, 284 => fn() => $this->semValue = new Expression\VariableNode($this->semStack[$pos - 1], $this->startTokenStack[$pos - 2]->position),
+ 285 => fn() => $this->semValue = new Expression\ArrayAccessNode($this->semStack[$pos - 4], $this->semStack[$pos - 2], $this->startTokenStack[$pos - 5]->position),
+ 288 => fn() => $this->semValue = TagParser::parseOffset($this->semStack[$pos], $this->startTokenStack[$pos]->position),
+ 289 => fn() => $this->semValue = TagParser::parseOffset('-' . $this->semStack[$pos], $this->startTokenStack[$pos - 1]->position),
+ })();
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/TemplateGenerator.php b/vendor/latte/latte/src/Latte/Compiler/TemplateGenerator.php
new file mode 100644
index 0000000..34d961f
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/TemplateGenerator.php
@@ -0,0 +1,209 @@
+ */
+ private array $methods = [];
+
+ /** @var array */
+ private array $properties = [];
+
+ /** @var array */
+ private array $constants = [];
+
+
+ /**
+ * Compiles nodes to PHP file
+ */
+ public function generate(
+ Nodes\TemplateNode $node,
+ string $className,
+ ?string $templateName = null,
+ bool $strictMode = false,
+ ): string
+ {
+ $context = new PrintContext($node->contentType);
+ $code = $node->main->print($context);
+ $code = self::buildParams($code, [], '$ʟ_args', $context);
+ $this->addMethod('main', $code, 'array $ʟ_args');
+
+ $head = (new NodeTraverser)->traverse($node->head, fn(Node $node) => $node instanceof Nodes\TextNode ? new Nodes\NopNode : $node);
+ $code = $head->print($context);
+ if ($code || $context->paramsExtraction) {
+ $code .= 'return get_defined_vars();';
+ $code = self::buildParams($code, $context->paramsExtraction, '$this->params', $context);
+ $this->addMethod('prepare', $code, '', 'array');
+ }
+
+ if ($node->contentType !== ContentType::Html) {
+ $this->addConstant('ContentType', $node->contentType);
+ }
+
+ if ($templateName !== null && !preg_match('#\n|\?#', $templateName)) {
+ $this->addConstant('Source', $templateName);
+ }
+
+ $this->generateBlocks($context->blocks, $context);
+
+ $members = [];
+ foreach ($this->constants as $name => $value) {
+ $members[] = "\tpublic const $name = " . PhpHelpers::dump($value, true) . ';';
+ }
+
+ foreach ($this->properties as $name => $value) {
+ $members[] = "\tpublic $$name = " . PhpHelpers::dump($value, true) . ';';
+ }
+
+ foreach (array_filter($this->methods) as $name => $method) {
+ $members[] = ($method['comment'] === null ? '' : "\n\t/** " . str_replace('*/', '* /', $method['comment']) . ' */')
+ . "\n\tpublic function $name($method[arguments])"
+ . ($method['returns'] ? ': ' . $method['returns'] : '')
+ . "\n\t{\n"
+ . ($method['body'] ? "\t\t$method[body]\n" : '') . "\t}";
+ }
+
+ $code = "getEscaper()->getContentType();
+ foreach ($blocks as $block) {
+ if (!$block->isDynamic()) {
+ $meta[$block->layer][$block->name->value] = $contentType === $block->escaping
+ ? $block->method
+ : [$block->method, $block->escaping];
+ }
+
+ $body = $this->buildParams($block->content, $block->parameters, '$ʟ_args', $context);
+ if (!$block->isDynamic() && str_contains($body, '$')) {
+ $embedded = $block->tag->name === 'block' && is_int($block->layer) && $block->layer;
+ $body = 'extract(' . ($embedded ? 'end($this->varStack)' : '$this->params') . ');' . $body;
+ }
+
+ $this->addMethod(
+ $block->method,
+ $body,
+ 'array $ʟ_args',
+ 'void',
+ $block->tag->getNotation(true) . ' on line ' . $block->tag->position->line,
+ );
+ }
+
+ if (isset($meta)) {
+ $this->addConstant('Blocks', $meta);
+ }
+ }
+
+
+ private function buildParams(string $body, array $params, string $cont, PrintContext $context): string
+ {
+ if (!str_contains($body, '$') && !str_contains($body, 'get_defined_vars()')) {
+ return $body;
+ }
+
+ $res = [];
+ foreach ($params as $i => $param) {
+ $res[] = $context->format(
+ '%node = %raw[%dump] ?? %raw[%dump] ?? %node;',
+ $param->var,
+ $cont,
+ $i,
+ $cont,
+ $param->var->name,
+ $param->default,
+ );
+ }
+
+ $extract = $params
+ ? implode('', $res) . 'unset($ʟ_args);'
+ : "extract($cont);" . (str_contains($cont, '$this') ? '' : "unset($cont);");
+ return $extract . "\n\n" . $body;
+ }
+
+
+ /**
+ * Adds custom method to template.
+ * @internal
+ */
+ public function addMethod(
+ string $name,
+ string $body,
+ string $arguments = '',
+ string $returns = 'void',
+ ?string $comment = null,
+ ): void
+ {
+ $body = trim($body);
+ $this->methods[$name] = compact('body', 'arguments', 'returns', 'comment');
+ }
+
+
+ /**
+ * Returns custom methods.
+ * @return array
+ * @internal
+ */
+ public function getMethods(): array
+ {
+ return $this->methods;
+ }
+
+
+ /**
+ * Adds custom property to template.
+ * @internal
+ */
+ public function addProperty(string $name, mixed $value): void
+ {
+ $this->properties[$name] = $value;
+ }
+
+
+ /**
+ * Returns custom properties.
+ * @return array
+ * @internal
+ */
+ public function getProperties(): array
+ {
+ return $this->properties;
+ }
+
+
+ /**
+ * Adds custom constant to template.
+ * @internal
+ */
+ public function addConstant(string $name, mixed $value): void
+ {
+ $this->constants[$name] = $value;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/TemplateLexer.php b/vendor/latte/latte/src/Latte/Compiler/TemplateLexer.php
new file mode 100644
index 0000000..acc0b32
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/TemplateLexer.php
@@ -0,0 +1,318 @@
+]*) */
+ public const ReTagName = '[a-zA-Z][a-zA-Z0-9:_.-]*';
+
+ /** special HTML attribute prefix */
+ public const NPrefix = 'n:';
+
+ /** HTML attribute name/value (\p{C} means \x00-\x1F except space) */
+ private const ReAttrName = '[^\p{C} "\'<>=`/]';
+
+ private string $openDelimiter = '';
+ private string $closeDelimiter = '';
+ private array $delimiters = [];
+ private TagLexer $tagLexer;
+
+ /** @var array */
+ private array $states = [];
+ private string $input;
+ private Position $position;
+
+
+ public function __construct()
+ {
+ $this->position = new Position;
+ $this->setState(self::StatePlain);
+ $this->setSyntax(null);
+ $this->tagLexer = new TagLexer;
+ }
+
+
+ /** @return \Generator */
+ public function tokenize(string $template): \Generator
+ {
+ $this->input = $this->normalize($template);
+
+ do {
+ $offset = $this->position->offset;
+ $state = $this->states[0];
+ $tokens = $this->{"state$state[name]"}(...$state['args']);
+ yield from $tokens;
+
+ } while ($offset !== $this->position->offset);
+
+ if ($offset < strlen($this->input)) {
+ throw new CompileException("Unexpected '" . substr($this->input, $offset, 10) . "'", $this->position);
+ }
+
+ yield new Token(Token::End, '', $this->position);
+ }
+
+
+ private function statePlain(): array
+ {
+ return $this->match('~
+ (?.+?)??
+ (?(?<=\n|^)[ \t]+)?
+ (
+ (?' . $this->openDelimiter . '(?!\*))| # {tag
+ (?' . $this->openDelimiter . '\*)| # {* comment
+ $
+ )
+ ~xsiAuD');
+ }
+
+
+ private function stateLatteTag(): array
+ {
+ $tokens[] = $this->match('~
+ (?/)?
+ (? = | _(?!_) | [a-z]\w*+(?:[.:-]\w+)*+(?!::|\(|\\\\))? # name, /name, but not function( or class:: or namespace\
+ ~xsiAu');
+
+ $tokens[] = $this->tagLexer->tokenizePartially($this->input, $this->position);
+
+ $tokens[] = $this->match('~
+ (?/)?
+ (?' . $this->closeDelimiter . ')
+ (?[ \t]*\R)?
+ ~xsiAu');
+
+ return array_merge(...$tokens);
+ }
+
+
+ private function stateLatteComment(): array
+ {
+ return $this->match('~
+ (?.+?)??
+ (
+ (?\*' . $this->closeDelimiter . ')(?[ \t]*\R{1,2})?|
+ $
+ )
+ ~xsiAu');
+ }
+
+
+ private function stateHtmlText(): array
+ {
+ return $this->match('~(?J)
+ (?.+?)??
+ (
+ (?(?<=\n|^)[ \t]+)?(?<)(?/)?(?=[a-z]|' . $this->openDelimiter . ')| # < tag
+ (?)| # -->
+ (?(?<=\n|^)[ \t]+)?(?' . $this->openDelimiter . '(?!\*))| # {tag
+ (?(?<=\n|^)[ \t]+)?(?' . $this->openDelimiter . '\*)| # {* comment
+ $
+ )
+ ~xsiAu');
+ }
+
+
+ private function stateHtmlBogus(): array
+ {
+ return $this->match('~
+ (?.+?)??
+ (
+ (?>)| # >
+ (?' . $this->openDelimiter . '(?!\*))| # {tag
+ (?' . $this->openDelimiter . '\*)| # {* comment
+ $
+ )
+ ~xsiAu');
+ }
+
+
+ /**
+ * Matches next token.
+ * @return Token[]
+ */
+ private function match(string $re): array
+ {
+ preg_match($re, $this->input, $matches, PREG_UNMATCHED_AS_NULL, $this->position->offset);
+ if (preg_last_error()) {
+ throw new CompileException(preg_last_error_msg());
+ }
+
+ $tokens = [];
+ foreach ($matches as $k => $v) {
+ if ($v !== null && !\is_int($k)) {
+ $tokens[] = new Token(\constant(Token::class . '::' . $k), $v, $this->position);
+ $this->position = $this->position->advance($v);
+ }
+ }
+
+ return $tokens;
+ }
+
+
+ public function setState(string $state, ...$args): void
+ {
+ $this->states[0] = ['name' => $state, 'args' => $args];
+ }
+
+
+ public function pushState(string $state, ...$args): void
+ {
+ array_unshift($this->states, null);
+ $this->setState($state, ...$args);
+ }
+
+
+ public function popState(): void
+ {
+ array_shift($this->states);
+ }
+
+
+ public function getState(): string
+ {
+ return $this->states[0]['name'];
+ }
+
+
+ /**
+ * Changes tag delimiters.
+ */
+ public function setSyntax(?string $type, ?string $endTag = null): static
+ {
+ $left = '\{(?![\s\'"{}])';
+ $end = $endTag ? '\{/' . preg_quote($endTag, '~') . '\}' : null;
+
+ $this->delimiters[] = [$this->openDelimiter, $this->closeDelimiter];
+ [$this->openDelimiter, $this->closeDelimiter] = match ($type) {
+ null => [$left, '\}'], // {...}
+ 'off' => [$endTag ? '(?=' . $end . ')\{' : '(?!x)x', '\}'],
+ 'double' => $endTag // {{...}}
+ ? ['(?:\{' . $left . '|(?=' . $end . ')\{)', '\}(?:\}|(?<=' . $end . '))']
+ : ['\{' . $left, '\}\}'],
+ default => throw new \InvalidArgumentException("Unknown syntax '$type'"),
+ };
+ return $this;
+ }
+
+
+ public function popSyntax(): void
+ {
+ [$this->openDelimiter, $this->closeDelimiter] = array_pop($this->delimiters);
+ }
+
+
+ private function normalize(string $str): string
+ {
+ if (str_starts_with($str, "\u{FEFF}")) { // BOM
+ $str = substr($str, 3);
+ }
+
+ $str = str_replace("\r\n", "\n", $str);
+
+ if (!preg_match('##u', $str)) {
+ preg_match('#(?:[\x00-\x7F]|[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3})*+#A', $str, $m);
+ throw new CompileException('Template is not valid UTF-8 stream.', $this->position->advance($m[0]));
+
+ } elseif (preg_match('#(.*?)([\x00-\x08\x0B\x0C\x0E-\x1F\x7F])#s', $str, $m)) {
+ throw new CompileException('Template contains control character \x' . dechex(ord($m[2])), $this->position->advance($m[1]));
+ }
+ return $str;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/TemplateParser.php b/vendor/latte/latte/src/Latte/Compiler/TemplateParser.php
new file mode 100644
index 0000000..279ee64
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/TemplateParser.php
@@ -0,0 +1,455 @@
+ */
+ private array $tagParsers = [];
+
+ /** @var array */
+ private array $attrParsersInfo = [];
+
+ private TemplateParserHtml $html;
+ private ?TokenStream $stream = null;
+ private TemplateLexer $lexer;
+ private ?Policy $policy = null;
+ private string $contentType;
+ private int $counter = 0;
+ private ?Tag $tag = null;
+ private $lastResolver;
+ private \WeakMap $lookFor;
+
+
+ public function __construct()
+ {
+ $this->lexer = new TemplateLexer;
+ $this->setContentType(ContentType::Html);
+ }
+
+
+ /**
+ * Parses tokens to nodes.
+ * @throws CompileException
+ */
+ public function parse(string $template): Nodes\TemplateNode
+ {
+ $this->html = new TemplateParserHtml($this, $this->completeAttrParsers());
+ $this->stream = new TokenStream($this->lexer->tokenize($template));
+ $this->lookFor = new \WeakMap;
+
+ $headLength = 0;
+ $findLength = function (FragmentNode $fragment) use (&$headLength) {
+ if ($this->inHead && !end($fragment->children) instanceof Nodes\TextNode) {
+ $headLength = count($fragment->children);
+ }
+ };
+
+ $node = new Nodes\TemplateNode;
+ $node->main = $this->parseFragment([$this->html, 'inTextResolve'], $findLength);
+ $node->head = new FragmentNode(array_splice($node->main->children, 0, $headLength));
+ $node->contentType = $this->contentType;
+
+ if (!$this->stream->peek()->isEnd()) {
+ $this->stream->throwUnexpectedException();
+ }
+
+ return $node;
+ }
+
+
+ public function parseFragment(callable $resolver, ?callable $after = null): FragmentNode
+ {
+ $res = new FragmentNode;
+ $save = [$this->lastResolver, $this->tag];
+ $this->lastResolver = $resolver;
+ try {
+ while (!$this->stream->peek()->isEnd()) {
+ if ($node = $resolver($res)) {
+ $res->append($node);
+ $after && $after($res);
+ } else {
+ break;
+ }
+ }
+
+ return $res;
+ } finally {
+ [$this->lastResolver, $this->tag] = $save;
+ }
+ }
+
+
+ public function inTextResolve(): ?Node
+ {
+ $token = $this->stream->peek();
+ return match ($token->type) {
+ Token::Text => $this->parseText(),
+ Token::Indentation => $this->parseIndentation(),
+ Token::Newline => $this->parseNewline(),
+ Token::Latte_TagOpen => $this->parseLatteStatement(),
+ Token::Latte_CommentOpen => $this->parseLatteComment(),
+ default => null,
+ };
+ }
+
+
+ public function parseText(): Nodes\TextNode
+ {
+ $token = $this->stream->consume(Token::Text, Token::Html_Name);
+ $this->inHead = $this->inHead && trim($token->text) === '';
+ $this->lastIndentation = null;
+ return new Nodes\TextNode($token->text, $token->position);
+ }
+
+
+ private function parseIndentation(): Nodes\TextNode
+ {
+ $token = $this->stream->consume(Token::Indentation);
+ return $this->lastIndentation = new Nodes\TextNode($token->text, $token->position);
+ }
+
+
+ private function parseNewline(): Nodes\AreaNode
+ {
+ $token = $this->stream->consume(Token::Newline);
+ if ($this->lastIndentation) { // drop indentation & newline
+ $this->lastIndentation->content = '';
+ $this->lastIndentation = null;
+ return new Nodes\NopNode;
+ } else {
+ return new Nodes\TextNode($token->text, $token->position);
+ }
+ }
+
+
+ public function parseLatteComment(): Nodes\NopNode
+ {
+ if (str_ends_with($this->stream->peek(-1)?->text ?? "\n", "\n")) {
+ $this->lastIndentation ??= new Nodes\TextNode('');
+ }
+ $openToken = $this->stream->consume(Token::Latte_CommentOpen);
+ $this->lexer->pushState(TemplateLexer::StateLatteComment);
+ $this->stream->consume(Token::Text);
+ $this->stream->tryConsume(Token::Latte_CommentClose) || $this->stream->throwUnexpectedException([Token::Latte_CommentClose], addendum: " started $openToken->position");
+ $this->lexer->popState();
+ return new Nodes\NopNode;
+ }
+
+
+ public function parseLatteStatement(?callable $resolver = null): ?Node
+ {
+ $this->lexer->pushState(TemplateLexer::StateLatteTag);
+ if ($this->stream->peek(1)->is(Token::Slash)
+ || (isset($this->tag, $this->lookFor[$this->tag]) && in_array($this->stream->peek(1)->text, $this->lookFor[$this->tag], true))
+ ) {
+ $this->lexer->popState();
+ return null; // go back to previous parseLatteStatement()
+ }
+ $this->lexer->popState();
+
+ $token = $this->stream->peek();
+ $startTag = $this->pushTag($this->parseLatteTag());
+
+ $parser = $this->getTagParser($startTag->name, $token->position);
+ $res = $parser($startTag, $this);
+ if ($res instanceof \Generator) {
+ if (!$res->valid() && !$startTag->void) {
+ throw new \LogicException("Incorrect behavior of {{$startTag->name}} parser, yield call is expected (on line {$startTag->position->line})");
+ }
+
+ $this->ensureIsConsumed($startTag);
+ if ($startTag->outputMode === $startTag::OutputKeepIndentation) {
+ $this->lastIndentation = null;
+ }
+
+ if ($startTag->void) {
+ $res->send([new FragmentNode, $startTag]);
+ } else {
+ while ($res->valid()) {
+ $this->lookFor[$startTag] = $res->current() ?: null;
+ $content = $this->parseFragment($resolver ?? $this->lastResolver);
+
+ if (!$this->stream->is(Token::Latte_TagOpen)) {
+ $this->checkEndTag($startTag, null);
+ $res->send([$content, null]);
+ break;
+ }
+
+ $tag = $this->parseLatteTag();
+
+ if ($startTag->outputMode === $startTag::OutputKeepIndentation) {
+ $this->lastIndentation = null;
+ }
+
+ if ($tag->closing) {
+ $this->checkEndTag($startTag, $tag);
+ $res->send([$content, $tag]);
+ $this->ensureIsConsumed($tag);
+ break;
+ } elseif (in_array($tag->name, $this->lookFor[$startTag] ?? [], true)) {
+ $this->pushTag($tag);
+ $res->send([$content, $tag]);
+ $this->ensureIsConsumed($tag);
+ $this->popTag();
+ } else {
+ throw new CompileException('Unexpected tag ' . substr($tag->getNotation(true), 0, -1) . '}', $tag->position);
+ }
+ }
+ }
+
+ if ($res->valid()) {
+ throw new \LogicException("Incorrect behavior of {{$startTag->name}} parser, more yield calls than expected (on line {$startTag->position->line})");
+ }
+
+ $node = $res->getReturn();
+
+ } elseif ($startTag->void) {
+ throw new CompileException('Unexpected /} in tag ' . substr($startTag->getNotation(true), 0, -1) . '/}', $startTag->position);
+
+ } else {
+ $this->ensureIsConsumed($startTag);
+ $node = $res;
+ if ($startTag->outputMode === $startTag::OutputKeepIndentation) {
+ $this->lastIndentation = null;
+ }
+ }
+
+ if (!$node instanceof Node) {
+ throw new \LogicException("Incorrect behavior of {{$startTag->name}} parser, unexpected returned value (on line {$startTag->position->line})");
+ }
+
+ $this->inHead = $this->inHead && $startTag->outputMode === $startTag::OutputNone;
+
+ $this->popTag();
+
+ $node->position = $startTag->position;
+ return $node;
+ }
+
+
+ private function parseLatteTag(): Tag
+ {
+ $stream = $this->stream;
+ if (str_ends_with($stream->peek(-1)?->text ?? "\n", "\n")) {
+ $this->lastIndentation ??= new Nodes\TextNode('');
+ }
+
+ $inTag = in_array($this->lexer->getState(), [TemplateLexer::StateHtmlTag, TemplateLexer::StateHtmlQuotedValue, TemplateLexer::StateHtmlComment, TemplateLexer::StateHtmlBogus], true);
+ $openToken = $stream->consume(Token::Latte_TagOpen);
+ $this->lexer->pushState(TemplateLexer::StateLatteTag);
+ $tag = new Tag(
+ position: $openToken->position,
+ closing: $closing = (bool) $stream->tryConsume(Token::Slash),
+ name: $stream->tryConsume(Token::Latte_Name)?->text ?? ($closing ? '' : '='),
+ tokens: $this->consumeTag(),
+ void: (bool) $stream->tryConsume(Token::Slash),
+ inHead: $this->inHead,
+ inTag: $inTag,
+ htmlElement: $this->html->getElement(),
+ );
+ $stream->tryConsume(Token::Latte_TagClose) || $stream->throwUnexpectedException([Token::Latte_TagClose], addendum: " started $openToken->position");
+ $this->lexer->popState();
+ return $tag;
+ }
+
+
+ private function consumeTag(): array
+ {
+ $res = [];
+ while ($this->stream->peek()->isPhpKind()) {
+ $res[] = $this->stream->consume();
+ }
+
+ $res[] = new Token(Token::End, '', $this->stream->peek()->position);
+ return $res;
+ }
+
+
+ /** @param array $parsers */
+ public function addTags(array $parsers): static
+ {
+ foreach ($parsers as $name => $info) {
+ $info = $info instanceof \stdClass ? $info : Latte\Extension::order($info);
+ if (str_starts_with($name, TemplateLexer::NPrefix)) {
+ $this->attrParsersInfo[substr($name, 2)] = $info;
+ } else {
+ $this->tagParsers[$name] = $info->subject;
+ if ($info->generator = Helpers::toReflection($info->subject)->isGenerator()) {
+ $this->attrParsersInfo[$name] = $info;
+ }
+ }
+ }
+
+ return $this;
+ }
+
+
+ /** @return callable(Tag, self): (Node|\Generator|void) */
+ private function getTagParser(string $name, Position $pos): callable
+ {
+ if (!isset($this->tagParsers[$name])) {
+ $hint = ($t = Helpers::getSuggestion(array_keys($this->tagParsers), $name))
+ ? ", did you mean {{$t}}?"
+ : '';
+ if ($this->html->getElement()?->isRawText()) {
+ $hint .= ' (in JavaScript or CSS, try to put a space after bracket or use n:syntax=off)';
+ }
+ throw new CompileException("Unexpected tag {{$name}}$hint", $pos);
+ } elseif (!$this->isTagAllowed($name)) {
+ throw new SecurityViolationException("Tag {{$name}} is not allowed", $pos);
+ }
+
+ return $this->tagParsers[$name];
+ }
+
+
+ private function completeAttrParsers(): array
+ {
+ $list = Helpers::sortBeforeAfter($this->attrParsersInfo);
+ $parsers = [];
+ foreach ($list as $name => $info) {
+ $parsers[$name] = $info->subject;
+ if ($info->generator ?? false) {
+ $parsers[Tag::PrefixInner . '-' . $name] = $parsers[Tag::PrefixTag . '-' . $name] = $parsers[$name];
+ }
+ }
+
+ return $parsers;
+ }
+
+
+ private function checkEndTag(Tag $start, ?Tag $end): void
+ {
+ if (!$end) {
+ if ($start->name !== 'syntax' && ($start->name !== 'block' || $this->tag->parent)) { // TODO: hardcoded
+ $this->stream->throwUnexpectedException(expected: ["{/$start->name}"]);
+ }
+
+ } elseif (
+ ($end->name !== $start->name && $end->name !== '')
+ || !$end->closing
+ || $end->void
+ ) {
+ throw new CompileException("Unexpected {$end->getNotation()}, expecting {/$start->name}", $end->position);
+ }
+ }
+
+
+ public function ensureIsConsumed(Tag $tag): void
+ {
+ if (!$tag->parser->isEnd()) {
+ $end = $tag->isNAttribute() ? ['end of attribute'] : ['end of tag'];
+ $tag->parser->stream->throwUnexpectedException($end, addendum: ' in ' . $tag->getNotation());
+ }
+ }
+
+
+ public function checkBlockIsUnique(Block $block): void
+ {
+ if ($block->isDynamic() || !preg_match('#^[a-z]#iD', $name = (string) $block->name->value)) {
+ throw new CompileException(ucfirst($block->tag->name) . " name must start with letter a-z, '$name' given.", $block->tag->position);
+ }
+
+ if ($block->layer === Template::LayerSnippet
+ ? isset($this->blocks[$block->layer][$name])
+ : (isset($this->blocks[Template::LayerLocal][$name]) || isset($this->blocks[$this->blockLayer][$name]))
+ ) {
+ throw new CompileException("Cannot redeclare {$block->tag->name} '{$name}'", $block->tag->position);
+ }
+
+ $this->blocks[$block->layer][$name] = $block;
+ }
+
+
+ public function setPolicy(?Policy $policy): static
+ {
+ $this->policy = $policy;
+ return $this;
+ }
+
+
+ public function setContentType(string $type): static
+ {
+ $this->contentType = $type;
+ $this->lexer->setState($type === ContentType::Html || $type === ContentType::Xml
+ ? TemplateLexer::StateHtmlText
+ : TemplateLexer::StatePlain);
+ return $this;
+ }
+
+
+ public function getContentType(): string
+ {
+ return $this->contentType;
+ }
+
+
+ /** @internal */
+ public function getStream(): TokenStream
+ {
+ return $this->stream;
+ }
+
+
+ public function getLexer(): TemplateLexer
+ {
+ return $this->lexer;
+ }
+
+
+ public function peekTag(): ?Tag
+ {
+ return $this->tag;
+ }
+
+
+ public function pushTag(Tag $tag): Tag
+ {
+ $tag->parent = $this->tag;
+ $this->tag = $tag;
+ return $tag;
+ }
+
+
+ public function popTag(): void
+ {
+ $this->tag = $this->tag->parent;
+ }
+
+
+ public function generateId(): int
+ {
+ return $this->counter++;
+ }
+
+
+ public function isTagAllowed(string $name): bool
+ {
+ return !$this->policy || $this->policy->isTagAllowed($name);
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/TemplateParserHtml.php b/vendor/latte/latte/src/Latte/Compiler/TemplateParserHtml.php
new file mode 100644
index 0000000..ec0b438
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/TemplateParserHtml.php
@@ -0,0 +1,574 @@
+ */
+ private array /*readonly*/ $attrParsers;
+ private ?Html\ElementNode $element = null;
+ private TemplateParser /*readonly*/ $parser;
+
+ /** @var array{string, ?Nodes\Php\ExpressionNode} */
+ private ?array $endName = null;
+
+
+ public function __construct(TemplateParser $parser, array $attrParsers)
+ {
+ $this->parser = $parser;
+ $this->attrParsers = $attrParsers;
+ }
+
+
+ public function getElement(): ?Html\ElementNode
+ {
+ return $this->element;
+ }
+
+
+ public function inTextResolve(): ?Node
+ {
+ $stream = $this->parser->getStream();
+ $token = $stream->peek();
+ return match ($token->type) {
+ Token::Html_TagOpen => $this->parseTag(),
+ Token::Html_CommentOpen => $this->parseComment(),
+ Token::Html_BogusOpen => $this->parseBogusTag(),
+ default => $this->parser->inTextResolve(),
+ };
+ }
+
+
+ public function inTagResolve(): ?Node
+ {
+ $stream = $this->parser->getStream();
+ $token = $stream->peek();
+ return match ($token->type) {
+ Token::Html_Name => str_starts_with($token->text, TemplateLexer::NPrefix)
+ ? $this->parseNAttribute()
+ : $this->parseAttribute(),
+ Token::Latte_TagOpen => $this->parseAttribute(),
+ Token::Whitespace => $this->parseAttributeWhitespace(),
+ Token::Html_TagClose => null,
+ default => $this->parser->inTextResolve(),
+ };
+ }
+
+
+ private function parseTag(): ?Node
+ {
+ $stream = $this->parser->getStream();
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlTag);
+ if (!$stream->peek(1)?->is(Token::Slash)) {
+ return $this->parseElement();
+ }
+
+ if ($this->element
+ && $this->parser->peekTag() === $this->element->data->tag // is directly in the element
+ ) {
+ $save = $stream->getIndex();
+ $this->endName = [$endText] = $this->parseEndTag();
+ if ($this->element->is($endText) || $this->element->data->textualName === $endText) {
+ return null; // go to parseElement() one level up to close the element
+ }
+ $stream->seek($save);
+ if (!in_array($endText, $this->element->data->unclosedTags ?? [], true)) {
+ return null; // go to parseElement() one level up to collapse
+ }
+ }
+
+ if ($this->parser->strict) {
+ $stream->throwUnexpectedException(excerpt: '/');
+ }
+ return $this->parseBogusEndTag();
+ }
+
+
+ private function parseElement(): Node
+ {
+ $res = new FragmentNode;
+ $res->append($this->extractIndentation());
+ $res->append($this->parseStartTag($this->element));
+ $elem = $this->element;
+
+ $stream = $this->parser->getStream();
+ $void = $this->resolveVoidness($elem);
+ $attrs = $this->prepareNAttrs($elem->nAttributes, $void);
+ $outerNodes = $this->openNAttrNodes($attrs[Tag::PrefixNone] ?? []);
+ $tagNodes = $this->openNAttrNodes($attrs[Tag::PrefixTag] ?? []);
+ $elem->tagNode = $this->finishNAttrNodes($elem->tagNode, $tagNodes);
+ $elem->captureTagName = (bool) $tagNodes;
+
+ if (!$void) {
+ $content = new FragmentNode;
+ if ($token = $stream->tryConsume(Token::Newline)) {
+ $content->append(new Nodes\TextNode($token->text, $token->position));
+ }
+
+ $innerNodes = $this->openNAttrNodes($attrs[Tag::PrefixInner] ?? []);
+ $elem->data->tag = $this->parser->peekTag();
+ $frag = $this->parser->parseFragment([$this, 'inTextResolve']);
+ $content->append($this->finishNAttrNodes($frag, $innerNodes));
+
+ [$endText, $endVariable] = $this->endName;
+ $this->endName = null;
+ if ($endText && ($this->element->is($endText) || $this->element->data->textualName === $endText)) {
+ $elem->content = $content;
+ $elem->content->append($this->extractIndentation());
+
+ } elseif ($outerNodes || $innerNodes || $tagNodes
+ || $this->parser->strict
+ || $elem->variableName
+ || $endVariable
+ || $elem->isRawText()
+ ) {
+ $stream->throwUnexpectedException(
+ addendum: ", expecting {$elem->data->textualName}> for element started $elem->position",
+ excerpt: $endText ? "/{$endText}>" : $stream->peek(1)?->text . $stream->peek(2)?->text,
+ );
+ } else { // element collapsed to tags
+ $res->append($content);
+ $this->element = $elem->parent;
+ if ($this->element && !$stream->is(Token::Html_TagOpen)) {
+ $this->element->data->unclosedTags[] = $elem->name;
+ }
+ return $res;
+ }
+ }
+
+ if ($token = $stream->tryConsume(Token::Newline)) {
+ $res->append(new Nodes\TextNode($token->text, $token->position));
+ }
+
+ $res = $this->finishNAttrNodes($res, $outerNodes);
+ $this->element = $elem->parent;
+ return $res;
+ }
+
+
+ private function extractIndentation(): AreaNode
+ {
+ if ($this->parser->lastIndentation) {
+ $dolly = clone $this->parser->lastIndentation;
+ $this->parser->lastIndentation->content = '';
+ return $dolly;
+ } else {
+ return new Nodes\NopNode;
+ }
+ }
+
+
+ private function parseStartTag(&$elem = null): Html\ElementNode
+ {
+ $stream = $this->parser->getStream();
+ $openToken = $stream->consume(Token::Html_TagOpen);
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlTag);
+
+ [$textual, $variable] = $this->parseTagName($this->parser->strict);
+ if (($this->parser->strict || $variable)
+ && !$stream->is(Token::Whitespace, Token::Slash, Token::Html_TagClose)
+ ) {
+ throw $stream->throwUnexpectedException();
+ }
+
+ $this->parser->lastIndentation = null;
+ $this->parser->inHead = false;
+ $elem = new Html\ElementNode(
+ name: $variable ? '' : $textual,
+ position: $openToken->position,
+ parent: $this->element,
+ data: (object) ['tag' => $this->parser->peekTag()],
+ contentType: $this->parser->getContentType(),
+ );
+ $elem->attributes = $this->parser->parseFragment([$this, 'inTagResolve']);
+ $elem->selfClosing = (bool) $stream->tryConsume(Token::Slash);
+ $elem->variableName = $variable;
+ $elem->data->textualName = $textual;
+ $stream->consume(Token::Html_TagClose);
+ $state = !$elem->selfClosing && $elem->isRawText()
+ ? TemplateLexer::StateHtmlRawText
+ : TemplateLexer::StateHtmlText;
+ $this->parser->getLexer()->setState($state, $elem->name);
+ return $elem;
+ }
+
+
+ /** @return array{string, ?Nodes\Php\ExpressionNode} */
+ private function parseEndTag(): array
+ {
+ $stream = $this->parser->getStream();
+ $lexer = $this->parser->getLexer();
+ $stream->consume(Token::Html_TagOpen);
+ $lexer->setState(TemplateLexer::StateHtmlTag);
+ $stream->consume(Token::Slash);
+ if (isset($this->element->nAttributes['syntax'])) { // hardcoded
+ $lexer->popSyntax();
+ }
+ $name = $this->parseTagName();
+ $stream->tryConsume(Token::Whitespace);
+ $stream->consume(Token::Html_TagClose);
+ $lexer->setState(TemplateLexer::StateHtmlText);
+ return $name;
+ }
+
+
+ /** @return array{string, ?Nodes\Php\ExpressionNode} */
+ private function parseTagName(bool $strict = true): array
+ {
+ $variable = $text = null;
+ $parts = [];
+ $stream = $this->parser->getStream();
+ do {
+ if ($stream->is(Token::Latte_TagOpen)) {
+ $save = $stream->getIndex();
+ $statement = $this->parser->parseLatteStatement([$this, 'inTagResolve']);
+ if (!$statement instanceof Latte\Essential\Nodes\PrintNode) {
+ if (!$parts || $strict) {
+ throw new CompileException('Only expression can be used as a HTML tag name.', $statement->position);
+ }
+ $stream->seek($save);
+ break;
+ }
+ $parts[] = $statement->expression;
+ $save -= $stream->getIndex();
+ while ($save < 0) {
+ $text .= $stream->peek($save++)->text;
+ }
+ $variable = true;
+
+ } elseif ($token = $stream->tryConsume(Token::Html_Name)) {
+ $parts[] = new Latte\Compiler\Nodes\Php\Scalar\StringNode($token->text, $token->position);
+ $text .= $token->text;
+
+ } elseif (!$parts) {
+ throw $stream->throwUnexpectedException([Token::Html_Name, Token::Latte_TagOpen]);
+ } else {
+ break;
+ }
+ } while (true);
+
+ $variable = $variable
+ ? Latte\Compiler\Nodes\Php\Expression\BinaryOpNode::nest('.', ...$parts)
+ : null;
+ return [$text, $variable];
+ }
+
+
+ private function parseBogusEndTag(): ?Html\BogusTagNode
+ {
+ $stream = $this->parser->getStream();
+ $openToken = $stream->consume(Token::Html_TagOpen);
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlTag);
+ $this->parser->lastIndentation = null;
+ $this->parser->inHead = false;
+ $node = new Html\BogusTagNode(
+ openDelimiter: $openToken->text . $stream->consume(Token::Slash)->text . $stream->consume(Token::Html_Name)->text,
+ content: new Nodes\TextNode($stream->tryConsume(Token::Whitespace)->text ?? ''),
+ endDelimiter: $stream->consume(Token::Html_TagClose)->text,
+ position: $openToken->position,
+ );
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlText);
+ return $node;
+ }
+
+
+ private function parseBogusTag(): Html\BogusTagNode
+ {
+ $stream = $this->parser->getStream();
+ $openToken = $stream->consume(Token::Html_BogusOpen);
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlBogus);
+ $this->parser->lastIndentation = null;
+ $this->parser->inHead = false;
+ $content = $this->parser->parseFragment([$this->parser, 'inTextResolve']);
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlText);
+ return new Html\BogusTagNode(
+ openDelimiter: $openToken->text,
+ content: $content,
+ endDelimiter: $stream->consume(Token::Html_TagClose)->text,
+ position: $openToken->position,
+ );
+ }
+
+
+ private function resolveVoidness(Html\ElementNode $elem): bool
+ {
+ if ($elem->contentType !== ContentType::Html) {
+ return $elem->selfClosing;
+ } elseif (isset(Helpers::$emptyElements[strtolower($elem->name)])) {
+ return true;
+ } elseif ($elem->selfClosing) { // auto-correct
+ $elem->content = new Nodes\NopNode;
+ $elem->selfClosing = false;
+ $last = end($elem->attributes->children);
+ if ($last instanceof Nodes\TextNode && $last->isWhitespace()) {
+ array_pop($elem->attributes->children);
+ }
+ return true;
+ }
+
+ return $elem->selfClosing;
+ }
+
+
+ private function parseAttributeWhitespace(): Node
+ {
+ $stream = $this->parser->getStream();
+ $token = $stream->consume(Token::Whitespace);
+ return $stream->is(Token::Html_Name) && str_starts_with($stream->peek()->text, TemplateLexer::NPrefix)
+ ? new Nodes\NopNode
+ : new Nodes\TextNode($token->text, $token->position);
+ }
+
+
+ private function parseAttribute(): ?Node
+ {
+ $stream = $this->parser->getStream();
+ if ($stream->is(Token::Latte_TagOpen)) {
+ $name = $this->parser->parseLatteStatement();
+ if (!$name instanceof Latte\Essential\Nodes\PrintNode) {
+ return $name; // value like ''
+ }
+ } else {
+ $name = $this->parser->parseText();
+ }
+
+ [$value, $quote] = $this->parseAttributeValue();
+ return new Html\AttributeNode(
+ name: $name,
+ value: $value,
+ quote: $quote,
+ position: $name->position,
+ );
+ }
+
+
+ private function parseAttributeValue(): ?array
+ {
+ $stream = $this->parser->getStream();
+ $save = $stream->getIndex();
+ $this->consumeIgnored();
+ if (!$stream->tryConsume(Token::Equals)) {
+ $stream->seek($save);
+ return null;
+ }
+
+ $this->consumeIgnored();
+ if ($quoteToken = $stream->tryConsume(Token::Quote)) {
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlQuotedValue, $quoteToken->text);
+ $value = $this->parser->parseFragment([$this->parser, 'inTextResolve']);
+ $stream->tryConsume(Token::Quote) || $stream->throwUnexpectedException([$quoteToken->text], addendum: ", end of HTML attribute started $quoteToken->position");
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlTag);
+ return [$value, $quoteToken->text];
+ }
+
+ $value = $this->parser->parseFragment(
+ fn() => match ($stream->peek()->type) {
+ Token::Html_Name => $this->parser->parseText(),
+ Token::Latte_TagOpen => $this->parser->parseLatteStatement(),
+ Token::Latte_CommentOpen => $this->parser->parseLatteComment(),
+ default => null,
+ },
+ )->simplify() ?? $stream->throwUnexpectedException();
+ return [$value, null];
+ }
+
+
+ private function parseNAttribute(): Nodes\TextNode
+ {
+ $stream = $this->parser->getStream();
+ $nameToken = $stream->consume(Token::Html_Name);
+ $save = $stream->getIndex();
+ $pos = $stream->peek()->position;
+ $name = substr($nameToken->text, strlen(TemplateLexer::NPrefix));
+ if ($this->parser->peekTag() !== $this->element->data->tag) {
+ throw new CompileException("Attribute n:$name must not appear inside {tags}", $nameToken->position);
+
+ } elseif (isset($this->element->nAttributes[$name])) {
+ throw new CompileException("Found multiple attributes n:$name.", $nameToken->position);
+ }
+
+ $this->consumeIgnored();
+ if ($stream->tryConsume(Token::Equals)) {
+ $this->consumeIgnored();
+ if ($quoteToken = $stream->tryConsume(Token::Quote)) {
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlQuotedNAttrValue, $quoteToken->text);
+ $valueToken = $stream->tryConsume(Token::Text);
+ $pos = $stream->peek()->position;
+ $stream->tryConsume(Token::Quote) || $stream->throwUnexpectedException([$quoteToken->text], addendum: ", end of n:attribute started $quoteToken->position");
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlTag);
+ } else {
+ $valueToken = $stream->consume(Token::Html_Name);
+ }
+ if ($valueToken) {
+ $tokens = (new TagLexer)->tokenize($valueToken->text, $valueToken->position);
+ }
+ } else {
+ $stream->seek($save);
+ }
+ $tokens ??= [new Token(Token::End, '', $pos)];
+
+ $this->element->nAttributes[$name] = new Tag(
+ name: preg_replace('~(inner-|tag-|)~', '', $name),
+ tokens: $tokens,
+ position: $nameToken->position,
+ prefix: $this->getPrefix($name),
+ inTag: true,
+ htmlElement: $this->element,
+ nAttributeNode: $node = new Nodes\TextNode(''),
+ );
+ return $node;
+ }
+
+
+ private function parseComment(): Html\CommentNode
+ {
+ $this->parser->lastIndentation = null;
+ $this->parser->inHead = false;
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlComment);
+ $stream = $this->parser->getStream();
+ $openToken = $stream->consume(Token::Html_CommentOpen);
+ $node = new Html\CommentNode(
+ position: $openToken->position,
+ content: $this->parser->parseFragment([$this->parser, 'inTextResolve']),
+ );
+ $stream->tryConsume(Token::Html_CommentClose) || $stream->throwUnexpectedException([Token::Html_CommentClose], addendum: " started $openToken->position");
+ $this->parser->getLexer()->setState(TemplateLexer::StateHtmlText);
+ return $node;
+ }
+
+
+ private function consumeIgnored(): void
+ {
+ $stream = $this->parser->getStream();
+ do {
+ if ($stream->tryConsume(Token::Whitespace)) {
+ continue;
+ }
+ if ($stream->tryConsume(Token::Latte_CommentOpen)) {
+ $this->parser->getLexer()->pushState(TemplateLexer::StateLatteComment);
+ $stream->consume(Token::Text);
+ $stream->consume(Token::Latte_CommentClose);
+ $this->parser->getLexer()->popState();
+ $stream->tryConsume(Token::Newline);
+ continue;
+ }
+ return;
+ } while (true);
+ }
+
+
+ private function prepareNAttrs(array $attrs, bool $void): array
+ {
+ $res = [];
+ foreach ($this->attrParsers as $name => $foo) {
+ if ($tag = $attrs[$name] ?? null) {
+ $prefix = $this->getPrefix($name);
+ if (!$prefix || !$void) {
+ $res[$prefix][] = $tag;
+ unset($attrs[$name]);
+ }
+ }
+ }
+
+ if ($attrs) {
+ $hint = Helpers::getSuggestion(array_keys($this->attrParsers), $k = key($attrs));
+ throw new CompileException('Unexpected attribute n:'
+ . ($hint ? "$k, did you mean n:$hint?" : implode(' and n:', array_keys($attrs))), $attrs[$k]->position);
+ }
+
+ return $res;
+ }
+
+
+ /**
+ * @param array $toOpen
+ * @return array
+ */
+ private function openNAttrNodes(array $toOpen): array
+ {
+ $toClose = [];
+ foreach ($toOpen as $tag) {
+ $parser = $this->getAttrParser($tag->name, $tag->position);
+ $this->parser->pushTag($tag);
+ $res = $parser($tag, $this->parser);
+ if ($res instanceof \Generator && $res->valid()) {
+ $toClose[] = [$res, $tag];
+
+ } elseif ($res instanceof AreaNode) {
+ $this->parser->ensureIsConsumed($tag);
+ $res->position = $tag->position;
+ $tag->replaceNAttribute($res);
+ $this->parser->popTag();
+
+ } elseif (!$res) {
+ $this->parser->ensureIsConsumed($tag);
+ $this->parser->popTag();
+
+ } else {
+ throw new CompileException("Unexpected value returned by {$tag->getNotation()} parser.", $tag->position);
+ }
+ }
+
+ return $toClose;
+ }
+
+
+ /** @param array $toClose */
+ private function finishNAttrNodes(AreaNode $node, array $toClose): AreaNode
+ {
+ while ([$gen, $tag] = array_pop($toClose)) {
+ $gen->send([$node, null]);
+ $node = $gen->getReturn();
+ $node->position = $tag->position;
+ $this->parser->popTag();
+ $this->parser->ensureIsConsumed($tag);
+ }
+
+ return $node;
+ }
+
+
+ /** @return callable(Tag, TemplateParser): (Node|\Generator|void) */
+ private function getAttrParser(string $name, Position $pos): callable
+ {
+ if (!isset($this->attrParsers[$name])) {
+ $hint = ($t = Helpers::getSuggestion(array_keys($this->attrParsers), $name))
+ ? ", did you mean n:$t?"
+ : '';
+ throw new CompileException("Unknown n:{$name}{$hint}", $pos);
+ } elseif (!$this->parser->isTagAllowed($name)) {
+ throw new SecurityViolationException("Attribute n:$name is not allowed", $pos);
+ }
+ return $this->attrParsers[$name];
+ }
+
+
+ private function getPrefix(string $name): string
+ {
+ return match (true) {
+ str_starts_with($name, 'inner-') => Tag::PrefixInner,
+ str_starts_with($name, 'tag-') => Tag::PrefixTag,
+ default => Tag::PrefixNone,
+ };
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/Token.php b/vendor/latte/latte/src/Latte/Compiler/Token.php
new file mode 100644
index 0000000..da1562a
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/Token.php
@@ -0,0 +1,255 @@
+ '[EOF]',
+ self::Text => 'text',
+ self::Whitespace => 'whitespace',
+ self::Newline => 'newline',
+ self::Indentation => 'indentation',
+ self::Slash => "'/'",
+ self::Equals => "'='",
+ self::Quote => 'quote',
+
+ self::Latte_TagOpen => 'Latte tag',
+ self::Latte_TagClose => 'end of Latte tag',
+ self::Latte_Name => 'tag name',
+ self::Latte_CommentOpen => 'Latte comment',
+ self::Latte_CommentClose => 'end of Latte comment',
+
+ self::Html_TagOpen => 'HTML tag',
+ self::Html_TagClose => 'end of HTML tag',
+ self::Html_CommentOpen => 'HTML comment',
+ self::Html_CommentClose => 'end of HTML comment',
+ self::Html_BogusOpen => 'HTML bogus tag',
+ self::Html_Name => 'HTML name',
+
+ self::Php_LogicalOr => "'or'",
+ self::Php_LogicalXor => "'xor'",
+ self::Php_LogicalAnd => "'and'",
+ self::Php_DoubleArrow => "'=>'",
+ self::Php_PlusEqual => "'+='",
+ self::Php_MinusEqual => "'-='",
+ self::Php_MulEqual => "'*='",
+ self::Php_DivEqual => "'/='",
+ self::Php_ConcatEqual => "'.='",
+ self::Php_ModEqual => "'%='",
+ self::Php_AndEqual => "'&='",
+ self::Php_OrEqual => "'|='",
+ self::Php_XorEqual => "'^='",
+ self::Php_SlEqual => "'<<='",
+ self::Php_SrEqual => "'>>='",
+ self::Php_PowEqual => "'**='",
+ self::Php_CoalesceEqual => "'??='",
+ self::Php_Coalesce => "'??'",
+ self::Php_BooleanOr => "'||'",
+ self::Php_BooleanAnd => "'&&'",
+ self::Php_AmpersandNotFollowed => "'&'",
+ self::Php_AmpersandFollowed => "'&'",
+ self::Php_IsEqual => "'=='",
+ self::Php_IsNotEqual => "'!='",
+ self::Php_IsIdentical => "'==='",
+ self::Php_IsNotIdentical => "'!=='",
+ self::Php_Spaceship => "'<=>'",
+ self::Php_IsSmallerOrEqual => "'<='",
+ self::Php_IsGreaterOrEqual => "'>='",
+ self::Php_Sl => "'<<'",
+ self::Php_Sr => "'>>'",
+ self::Php_In => "'in'",
+ self::Php_Instanceof => "'instanceof'",
+ self::Php_Inc => "'++'",
+ self::Php_Dec => "'--'",
+ self::Php_IntCast => "'(int)'",
+ self::Php_FloatCast => "'(float)'",
+ self::Php_StringCast => "'(string)'",
+ self::Php_ArrayCast => "'(array)'",
+ self::Php_ObjectCast => "'(object)'",
+ self::Php_BoolCast => "'(bool)'",
+ self::Php_Pow => "'**'",
+ self::Php_New => "'new'",
+ self::Php_Clone => "'clone'",
+ self::Php_Integer => 'integer',
+ self::Php_Float => 'floating-point number',
+ self::Php_Identifier => 'identifier',
+ self::Php_StringVarname => 'variable name',
+ self::Php_Constant => 'constant',
+ self::Php_Variable => 'variable',
+ self::Php_NumString => 'number',
+ self::Php_EncapsedAndWhitespace => 'string content',
+ self::Php_ConstantEncapsedString => 'quoted string',
+ self::Php_Match => "'match'",
+ self::Php_Default => "'default'",
+ self::Php_Function => "'function'",
+ self::Php_Fn => "'fn'",
+ self::Php_Return => "'return'",
+ self::Php_Use => "'use'",
+ self::Php_Isset => "'isset'",
+ self::Php_Empty => "'empty'",
+ self::Php_ObjectOperator => "'->'",
+ self::Php_NullsafeObjectOperator => "'?->'",
+ self::Php_UndefinedsafeObjectOperator => "'??->'",
+ self::Php_List => "'list'",
+ self::Php_Array => "'array'",
+ self::Php_StartHeredoc => 'heredoc start',
+ self::Php_EndHeredoc => 'heredoc end',
+ self::Php_DollarOpenCurlyBraces => "'\${'",
+ self::Php_CurlyOpen => "'{\$'",
+ self::Php_PaamayimNekudotayim => "'::'",
+ self::Php_NsSeparator => "'\\'",
+ self::Php_Ellipsis => "'...'",
+ self::Php_ExpandCast => "'(expand)'",
+ self::Php_NameFullyQualified => 'fully qualified name',
+ self::Php_NameQualified => 'namespaced name',
+ self::Php_Whitespace => 'whitespace',
+ self::Php_Comment => 'comment',
+ self::Php_Null => "'null'",
+ self::Php_True => "'true'",
+ self::Php_False => "'false'",
+ ];
+
+
+ public function __construct(
+ public /*readonly*/ int $type,
+ public /*readonly*/ string $text,
+ public /*readonly*/ ?Position $position = null,
+ ) {
+ }
+
+
+ public function is(int|string ...$kind): bool
+ {
+ return in_array($this->type, $kind, true)
+ || in_array($this->text, $kind, true);
+ }
+
+
+ public function isEnd(): bool
+ {
+ return $this->type === self::End;
+ }
+
+
+ public function isPhpKind(): bool
+ {
+ return $this->type > 0 && $this->type < 10000;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Compiler/TokenStream.php b/vendor/latte/latte/src/Latte/Compiler/TokenStream.php
new file mode 100644
index 0000000..a0f6550
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Compiler/TokenStream.php
@@ -0,0 +1,135 @@
+source = $source;
+ }
+
+
+ /**
+ * Tells whether the token at current position is of given kind.
+ */
+ public function is(int|string ...$kind): bool
+ {
+ return $this->peek()->is(...$kind);
+ }
+
+
+ /**
+ * Gets the token at $offset from the current position.
+ */
+ public function peek(int $offset = 0): ?Token
+ {
+ $pos = $this->index + $offset;
+ while ($pos >= 0 && !isset($this->tokens[$pos]) && $this->source->valid()) {
+ if ($this->tokens) {
+ $this->source->next();
+ }
+
+ if ($this->source->valid()) {
+ $this->tokens[] = $this->source->current();
+ }
+ }
+
+ return $this->tokens[$pos] ?? null;
+ }
+
+
+ /**
+ * Consumes the current token (if is of given kind) or throws exception on end.
+ * @throws CompileException
+ */
+ public function consume(int|string ...$kind): Token
+ {
+ $token = $this->peek();
+ if ($kind && !$token->is(...$kind)) {
+ $kind = array_map(fn($item) => is_string($item) ? "'$item'" : Token::Names[$item], $kind);
+ $this->throwUnexpectedException($kind);
+ } elseif (!$token->isEnd()) {
+ $this->index++;
+ }
+ return $token;
+ }
+
+
+ /**
+ * Consumes the current token of given kind or returns null.
+ */
+ public function tryConsume(int|string ...$kind): ?Token
+ {
+ $token = $this->peek();
+ if (!$token->is(...$kind)) {
+ return null;
+ } elseif (!$token->isEnd()) {
+ $this->index++;
+ }
+ return $token;
+ }
+
+
+ /**
+ * Sets the input cursor to the position.
+ */
+ public function seek(int $index): void
+ {
+ if ($index >= count($this->tokens) || $index < 0) {
+ throw new \InvalidArgumentException('The position is out of range.');
+ }
+ $this->index = $index;
+ }
+
+
+ /**
+ * Returns the cursor position.
+ */
+ public function getIndex(): int
+ {
+ return $this->index;
+ }
+
+
+ /**
+ * @throws CompileException
+ * @return never
+ */
+ public function throwUnexpectedException(array $expected = [], string $addendum = '', string $excerpt = ''): void
+ {
+ $token = $this->peek()->text . $excerpt;
+ $expected = array_map(fn($item) => is_int($item) ? Token::Names[$item] : $item, $expected);
+ throw new CompileException(
+ 'Unexpected '
+ . ($token === ''
+ ? 'end'
+ : "'" . trim($token, "\n") . "'")
+ . ($expected && count($expected) < 5
+ ? ', expecting ' . implode(', ', $expected)
+ : '')
+ . $addendum,
+ $this->peek()->position,
+ );
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/ContentType.php b/vendor/latte/latte/src/Latte/ContentType.php
new file mode 100644
index 0000000..0b4595a
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/ContentType.php
@@ -0,0 +1,22 @@
+filters = new Runtime\FilterExecutor;
+ $this->functions = new Runtime\FunctionExecutor;
+ $this->providers = new \stdClass;
+ $this->addExtension(new Essential\CoreExtension);
+ $this->addExtension(new Sandbox\SandboxExtension);
+ }
+
+
+ /**
+ * Renders template to output.
+ * @param object|mixed[] $params
+ */
+ public function render(string $name, object|array $params = [], ?string $block = null): void
+ {
+ $template = $this->createTemplate($name, $this->processParams($params));
+ $template->global->coreCaptured = false;
+ $template->render($block);
+ }
+
+
+ /**
+ * Renders template to string.
+ * @param object|mixed[] $params
+ */
+ public function renderToString(string $name, object|array $params = [], ?string $block = null): string
+ {
+ $template = $this->createTemplate($name, $this->processParams($params));
+ $template->global->coreCaptured = true;
+ return $template->capture(fn() => $template->render($block));
+ }
+
+
+ /**
+ * Creates template object.
+ * @param mixed[] $params
+ */
+ public function createTemplate(string $name, array $params = [], $clearCache = true): Runtime\Template
+ {
+ $this->cacheKey = $clearCache ? null : $this->cacheKey;
+ $class = $this->getTemplateClass($name);
+ if (!class_exists($class, false)) {
+ $this->loadTemplate($name);
+ }
+
+ $this->providers->fn = $this->functions;
+ return new $class(
+ $this,
+ $params,
+ $this->filters,
+ $this->providers,
+ $name,
+ );
+ }
+
+
+ /**
+ * Compiles template to PHP code.
+ */
+ public function compile(string $name): string
+ {
+ if ($this->sandboxed && !$this->policy) {
+ throw new \LogicException('In sandboxed mode you need to set a security policy.');
+ }
+
+ $template = $this->getLoader()->getContent($name);
+
+ try {
+ $node = $this->parse($template);
+ $this->applyPasses($node);
+ $compiled = $this->generate($node, $name);
+
+ } catch (\Throwable $e) {
+ if (!$e instanceof CompileException && !$e instanceof SecurityViolationException) {
+ $e = new CompileException("Thrown exception '{$e->getMessage()}'", previous: $e);
+ }
+
+ throw $e->setSource($template, $name);
+ }
+
+ if ($this->phpBinary) {
+ Compiler\PhpHelpers::checkCode($this->phpBinary, $compiled, "(compiled $name)");
+ }
+
+ return $compiled;
+ }
+
+
+ /**
+ * Parses template to AST node.
+ */
+ public function parse(string $template): TemplateNode
+ {
+ $parser = new Compiler\TemplateParser;
+ $parser->strict = $this->strictParsing;
+
+ foreach ($this->extensions as $extension) {
+ $extension->beforeCompile($this);
+ $parser->addTags($extension->getTags());
+ }
+
+ return $parser
+ ->setContentType($this->contentType)
+ ->setPolicy($this->getPolicy(effective: true))
+ ->parse($template);
+ }
+
+
+ /**
+ * Calls node visitors.
+ */
+ public function applyPasses(TemplateNode &$node): void
+ {
+ $passes = [];
+ foreach ($this->extensions as $extension) {
+ $passes = array_merge($passes, $extension->getPasses());
+ }
+
+ $passes = Helpers::sortBeforeAfter($passes);
+ foreach ($passes as $pass) {
+ $pass = $pass instanceof \stdClass ? $pass->subject : $pass;
+ ($pass)($node);
+ }
+ }
+
+
+ /**
+ * Generates compiled PHP code.
+ */
+ public function generate(TemplateNode $node, string $name): string
+ {
+ $generator = new Compiler\TemplateGenerator;
+ return $generator->generate(
+ $node,
+ $this->getTemplateClass($name),
+ $name,
+ $this->strictTypes,
+ );
+ }
+
+
+ /**
+ * Compiles template to cache.
+ * @throws \LogicException
+ */
+ public function warmupCache(string $name): void
+ {
+ if (!$this->tempDirectory) {
+ throw new \LogicException('Path to temporary directory is not set.');
+ }
+
+ $class = $this->getTemplateClass($name);
+ if (!class_exists($class, false)) {
+ $this->loadTemplate($name);
+ }
+ }
+
+
+ private function loadTemplate(string $name): void
+ {
+ if (!$this->tempDirectory) {
+ $compiled = $this->compile($name);
+ if (@eval(substr($compiled, 5)) === false) { // @ is escalated to exception, substr removes setSource($compiled, "$name (compiled)");
+ }
+
+ return;
+ }
+
+ // Solving atomicity to work everywhere is really pain in the ass.
+ // 1) We want to do as little as possible IO calls on production and also directory and file can be not writable
+ // so on Linux we include the file directly without shared lock, therefore, the file must be created atomically by renaming.
+ // 2) On Windows file cannot be renamed-to while is open (ie by include), so we have to acquire a lock.
+ $cacheFile = $this->getCacheFile($name);
+ $cacheKey = $this->autoRefresh
+ ? md5(serialize($this->getCacheSignature($name)))
+ : null;
+ $lock = defined('PHP_WINDOWS_VERSION_BUILD') || $this->autoRefresh
+ ? $this->acquireLock("$cacheFile.lock", LOCK_SH)
+ : null;
+
+ if (
+ !($this->autoRefresh && $cacheKey !== stream_get_contents($lock))
+ && (@include $cacheFile) !== 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("$cacheFile.lock", LOCK_EX);
+
+ // while waiting for exclusive lock, someone might have already created the cache
+ if (!is_file($cacheFile) || ($this->autoRefresh && $cacheKey !== stream_get_contents($lock))) {
+ $compiled = $this->compile($name);
+ if (
+ file_put_contents("$cacheFile.tmp", $compiled) !== strlen($compiled)
+ || !rename("$cacheFile.tmp", $cacheFile)
+ ) {
+ @unlink("$cacheFile.tmp"); // @ - file may not exist
+ throw new RuntimeException("Unable to create '$cacheFile'.");
+ }
+
+ fseek($lock, 0);
+ fwrite($lock, $cacheKey ?? md5(serialize($this->getCacheSignature($name))));
+ ftruncate($lock, ftell($lock));
+
+ if (function_exists('opcache_invalidate')) {
+ @opcache_invalidate($cacheFile, true); // @ can be restricted
+ }
+ }
+
+ if ((include $cacheFile) === false) {
+ throw new RuntimeException("Unable to load '$cacheFile'.");
+ }
+
+ 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;
+ }
+
+
+ public function getCacheFile(string $name): string
+ {
+ $base = preg_match('#([/\\\\][\w@.-]{3,35}){1,3}$#D', '/' . $name, $m)
+ ? preg_replace('#[^\w@.-]+#', '-', substr($m[0], 1)) . '--'
+ : '';
+ return $this->tempDirectory . '/' . $base . $this->generateCacheHash($name) . '.php';
+ }
+
+
+ public function getTemplateClass(string $name): string
+ {
+ return 'Template_' . $this->generateCacheHash($name);
+ }
+
+
+ private function generateCacheHash(string $name): string
+ {
+ $this->cacheKey ??= md5(serialize($this->getCacheKey()));
+ $hash = $this->cacheKey . $this->getLoader()->getUniqueId($name);
+ return substr(md5($hash), 0, 10);
+ }
+
+
+ /**
+ * Values that affect the results of compilation and the name of the cache file.
+ */
+ protected function getCacheKey(): array
+ {
+ return [
+ $this->contentType,
+ array_keys($this->getFunctions()),
+ array_map(
+ fn($extension) => [
+ get_debug_type($extension),
+ $extension->getCacheKey($this),
+ filemtime((new \ReflectionObject($extension))->getFileName()),
+ ],
+ $this->extensions,
+ ),
+ ];
+ }
+
+
+ /**
+ * Values that check the expiration of the compiled template.
+ */
+ protected function getCacheSignature(string $name): array
+ {
+ return [
+ self::Version,
+ $this->getLoader()->getContent($name),
+ array_map(
+ fn($extension) => filemtime((new \ReflectionObject($extension))->getFileName()),
+ $this->extensions,
+ ),
+ ];
+ }
+
+
+ /**
+ * Registers run-time filter.
+ */
+ public function addFilter(string $name, callable $callback): static
+ {
+ if (!preg_match('#^[a-z]\w*$#iD', $name)) {
+ throw new \LogicException("Invalid filter name '$name'.");
+ }
+
+ $this->filters->add($name, $callback);
+ return $this;
+ }
+
+
+ /**
+ * Registers filter loader.
+ */
+ public function addFilterLoader(callable $loader): static
+ {
+ $this->filters->add(null, $loader);
+ return $this;
+ }
+
+
+ /**
+ * Returns all run-time filters.
+ * @return callable[]
+ */
+ public function getFilters(): array
+ {
+ return $this->filters->getAll();
+ }
+
+
+ /**
+ * Call a run-time filter.
+ * @param mixed[] $args
+ */
+ public function invokeFilter(string $name, array $args): mixed
+ {
+ return ($this->filters->$name)(...$args);
+ }
+
+
+ /**
+ * Adds new extension.
+ */
+ public function addExtension(Extension $extension): static
+ {
+ $this->extensions[] = $extension;
+ foreach ($extension->getFilters() as $name => $value) {
+ $this->filters->add($name, $value);
+ }
+
+ foreach ($extension->getFunctions() as $name => $value) {
+ $this->functions->add($name, $value);
+ }
+
+ foreach ($extension->getProviders() as $name => $value) {
+ $this->providers->$name = $value;
+ }
+ return $this;
+ }
+
+
+ /** @return Extension[] */
+ public function getExtensions(): array
+ {
+ return $this->extensions;
+ }
+
+
+ /**
+ * Registers run-time function.
+ */
+ public function addFunction(string $name, callable $callback): static
+ {
+ if (!preg_match('#^[a-z]\w*$#iD', $name)) {
+ throw new \LogicException("Invalid function name '$name'.");
+ }
+
+ $this->functions->add($name, $callback);
+ return $this;
+ }
+
+
+ /**
+ * Call a run-time function.
+ * @param mixed[] $args
+ */
+ public function invokeFunction(string $name, array $args): mixed
+ {
+ return ($this->functions->$name)(null, ...$args);
+ }
+
+
+ /**
+ * @return callable[]
+ */
+ public function getFunctions(): array
+ {
+ return $this->functions->getAll();
+ }
+
+
+ /**
+ * Adds new provider.
+ */
+ public function addProvider(string $name, mixed $provider): static
+ {
+ if (!preg_match('#^[a-z]\w*$#iD', $name)) {
+ throw new \LogicException("Invalid provider name '$name'.");
+ }
+
+ $this->providers->$name = $provider;
+ return $this;
+ }
+
+
+ /**
+ * Returns all providers.
+ * @return mixed[]
+ */
+ public function getProviders(): array
+ {
+ return (array) $this->providers;
+ }
+
+
+ public function setPolicy(?Policy $policy): static
+ {
+ $this->policy = $policy;
+ return $this;
+ }
+
+
+ public function getPolicy(bool $effective = false): ?Policy
+ {
+ return !$effective || $this->sandboxed
+ ? $this->policy
+ : null;
+ }
+
+
+ public function setExceptionHandler(callable $handler): static
+ {
+ $this->providers->coreExceptionHandler = $handler;
+ return $this;
+ }
+
+
+ public function setSandboxMode(bool $state = true): static
+ {
+ $this->sandboxed = $state;
+ return $this;
+ }
+
+
+ public function setContentType(string $type): static
+ {
+ $this->contentType = $type;
+ return $this;
+ }
+
+
+ /**
+ * Sets path to temporary directory.
+ */
+ public function setTempDirectory(?string $path): static
+ {
+ $this->tempDirectory = $path;
+ return $this;
+ }
+
+
+ /**
+ * Sets auto-refresh mode.
+ */
+ public function setAutoRefresh(bool $state = true): static
+ {
+ $this->autoRefresh = $state;
+ return $this;
+ }
+
+
+ /**
+ * Enables declare(strict_types=1) in templates.
+ */
+ public function setStrictTypes(bool $state = true): static
+ {
+ $this->strictTypes = $state;
+ return $this;
+ }
+
+
+ public function setStrictParsing(bool $state = true): static
+ {
+ $this->strictParsing = $state;
+ return $this;
+ }
+
+
+ public function isStrictParsing(): bool
+ {
+ return $this->strictParsing;
+ }
+
+
+ /**
+ * Sets the locale. It uses the same identifiers as the PHP intl extension.
+ */
+ public function setLocale(?string $locale): static
+ {
+ if ($locale && !extension_loaded('intl')) {
+ throw new RuntimeException("Setting a locale requires the 'intl' extension to be installed.");
+ }
+ $this->locale = $locale;
+ return $this;
+ }
+
+
+ public function getLocale(): ?string
+ {
+ return $this->locale;
+ }
+
+
+ public function setLoader(Loader $loader): static
+ {
+ $this->loader = $loader;
+ return $this;
+ }
+
+
+ public function getLoader(): Loader
+ {
+ return $this->loader ??= new Loaders\FileLoader;
+ }
+
+
+ public function enablePhpLinter(?string $phpBinary): static
+ {
+ $this->phpBinary = $phpBinary;
+ return $this;
+ }
+
+
+ /**
+ * @param object|mixed[] $params
+ * @return mixed[]
+ */
+ private function processParams(object|array $params): array
+ {
+ if (is_array($params)) {
+ return $params;
+ }
+
+ $methods = (new \ReflectionClass($params))->getMethods(\ReflectionMethod::IS_PUBLIC);
+ foreach ($methods as $method) {
+ if ($method->getAttributes(Attributes\TemplateFilter::class)) {
+ $this->addFilter($method->name, [$params, $method->name]);
+ }
+
+ if ($method->getAttributes(Attributes\TemplateFunction::class)) {
+ $this->addFunction($method->name, [$params, $method->name]);
+ }
+
+ if (strpos((string) $method->getDocComment(), '@filter')) {
+ trigger_error('Annotation @filter is deprecated, use attribute #[Latte\Attributes\TemplateFilter]', E_USER_DEPRECATED);
+ $this->addFilter($method->name, [$params, $method->name]);
+ }
+
+ if (strpos((string) $method->getDocComment(), '@function')) {
+ trigger_error('Annotation @function is deprecated, use attribute #[Latte\Attributes\TemplateFunction]', E_USER_DEPRECATED);
+ $this->addFunction($method->name, [$params, $method->name]);
+ }
+ }
+
+ return array_filter((array) $params, fn($key) => $key[0] !== "\0", ARRAY_FILTER_USE_KEY);
+ }
+
+
+ public function __get(string $name)
+ {
+ if ($name === 'onCompile') {
+ $trace = debug_backtrace(0)[0];
+ $loc = isset($trace['file'], $trace['line'])
+ ? ' (in ' . $trace['file'] . ' on ' . $trace['line'] . ')'
+ : '';
+ throw new \LogicException('You use Latte 3 together with the code designed for Latte 2' . $loc);
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/AuxiliaryIterator.php b/vendor/latte/latte/src/Latte/Essential/AuxiliaryIterator.php
new file mode 100644
index 0000000..a4b6b0c
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/AuxiliaryIterator.php
@@ -0,0 +1,46 @@
+
+ */
+class AuxiliaryIterator implements \IteratorAggregate, \Countable
+{
+ /**
+ * @param array $pairs
+ */
+ public function __construct(
+ private array $pairs,
+ ) {
+ }
+
+
+ /**
+ * @return \Generator
+ */
+ public function getIterator(): \Generator
+ {
+ foreach ($this->pairs as [$key, $value]) {
+ yield $key => $value;
+ }
+ }
+
+
+ public function count(): int
+ {
+ return count($this->pairs);
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Blueprint.php b/vendor/latte/latte/src/Latte/Essential/Blueprint.php
new file mode 100644
index 0000000..f5738e3
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Blueprint.php
@@ -0,0 +1,183 @@
+addClass(Php\Helpers::extractShortName($name));
+ if ($extends) {
+ if (class_exists($extends)) {
+ if ((new \ReflectionClass($extends))->isFinal()) {
+ throw new \LogicException("Blueprint error: Unable to extend final class $extends");
+ }
+ $class->setExtends($extends);
+ } elseif (trait_exists($extends)) {
+ $class->addTrait($extends);
+ } else {
+ throw new \LogicException("Blueprint error: Class '$extends' doesn't exist.");
+ }
+ $params = array_diff_key($params, get_class_vars($extends));
+ }
+ $this->addProperties($class, $params);
+ return $class;
+ }
+
+
+ public function printClass(Php\ClassType $class): void
+ {
+ $this->printCode((string) $class->getNamespace());
+ }
+
+
+ public function clickableFile(string $file, int $line = 1): string
+ {
+ $link = 'editor://open/?file=' . rawurlencode(strtr($file, '/', DIRECTORY_SEPARATOR)) . '&line=' . $line;
+ return '' . htmlspecialchars($file) . ' ';
+ }
+
+
+ /**
+ * @param mixed[] $vars
+ */
+ public function printVars(array $vars): void
+ {
+ $res = '';
+ foreach ($vars as $name => $value) {
+ if (!str_starts_with($name, 'ʟ_')) {
+ $type = $this->getType($value);
+ $res .= "{varType $type $$name}\n";
+ }
+ }
+
+ $this->printHeader('varPrint');
+ $this->printCode($res ?: 'No variables', 'latte');
+ }
+
+
+ /**
+ * @param mixed[] $props
+ */
+ public function addProperties(Php\ClassType $class, array $props): void
+ {
+ foreach ($props as $name => $value) {
+ $class->removeProperty($name);
+ $type = $this->getType($value);
+ $prop = $class->addProperty($name);
+ $prop->setType($type);
+ }
+ }
+
+
+ /**
+ * @param callable[] $funcs
+ */
+ public function addFunctions(Php\ClassType $class, array $funcs): void
+ {
+ foreach ($funcs as $name => $func) {
+ $method = (new Php\Factory)->fromCallable($func);
+ $type = $this->printType($method->getReturnType(), $method->isReturnNullable(), $class->getNamespace()) ?: 'mixed';
+ $class->addComment("@method $type $name" . $this->printParameters($method, $class->getNamespace()));
+ }
+ }
+
+
+ private function printType(?string $type, bool $nullable, ?Php\PhpNamespace $namespace): string
+ {
+ if ($type === null) {
+ return '';
+ }
+
+ if ($namespace) {
+ $type = $namespace->simplifyName($type);
+ }
+
+ if ($nullable && strcasecmp($type, 'mixed')) {
+ $type = str_contains($type, '|')
+ ? $type . '|null'
+ : '?' . $type;
+ }
+
+ return $type;
+ }
+
+
+ public function printParameters(
+ Php\Closure|Php\GlobalFunction|Php\Method $function,
+ ?Php\PhpNamespace $namespace = null,
+ ): string
+ {
+ $params = [];
+ $list = $function->getParameters();
+ foreach ($list as $param) {
+ $variadic = $function->isVariadic() && $param === end($list);
+ $params[] = ltrim($this->printType($param->getType(), $param->isNullable(), $namespace) . ' ')
+ . ($param->isReference() ? '&' : '')
+ . ($variadic ? '...' : '')
+ . '$' . $param->getName()
+ . ($param->hasDefaultValue() && !$variadic ? ' = ' . var_export($param->getDefaultValue(), true) : '');
+ }
+
+ return '(' . implode(', ', $params) . ')';
+ }
+
+
+ public function printBegin(): void
+ {
+ echo '';
+ echo ' ';
+ echo "\n";
+ }
+
+
+ public function printEnd(): void
+ {
+ echo "
\n";
+ }
+
+
+ public function printHeader(string $string): void
+ {
+ echo "",
+ htmlspecialchars($string),
+ " \n";
+ }
+
+
+ public function printCode(string $code, string $lang = 'php'): void
+ {
+ echo '',
+ htmlspecialchars($code),
+ " \n";
+ }
+
+
+ private function getType($value): string
+ {
+ return $value === null ? 'mixed' : get_debug_type($value);
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/CachingIterator.php b/vendor/latte/latte/src/Latte/Essential/CachingIterator.php
new file mode 100644
index 0000000..c4cb718
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/CachingIterator.php
@@ -0,0 +1,227 @@
+getIterator();
+ } while (!$iterator instanceof \Iterator);
+ } elseif ($iterator instanceof \Traversable) {
+ if (!$iterator instanceof \Iterator) {
+ $iterator = new \IteratorIterator($iterator);
+ }
+ } else {
+ throw new \InvalidArgumentException(sprintf('Invalid argument passed to foreach; array or Traversable expected, %s given.', get_debug_type($iterator)));
+ }
+
+ parent::__construct($iterator, 0);
+ $this->parent = $parent;
+ }
+
+
+ /**
+ * Is the current element the first one?
+ */
+ public function isFirst(?int $width = null): bool
+ {
+ return $this->counter === 1 || ($width && $this->counter !== 0 && (($this->counter - 1) % $width) === 0);
+ }
+
+
+ /**
+ * Is the current element the last one?
+ */
+ public function isLast(?int $width = null): bool
+ {
+ return !$this->hasNext() || ($width && ($this->counter % $width) === 0);
+ }
+
+
+ /**
+ * Is the iterator empty?
+ */
+ public function isEmpty(): bool
+ {
+ return $this->counter === 0;
+ }
+
+
+ /**
+ * Is the counter odd?
+ */
+ public function isOdd(): bool
+ {
+ return $this->counter % 2 === 1;
+ }
+
+
+ /**
+ * Is the counter even?
+ */
+ public function isEven(): bool
+ {
+ return $this->counter % 2 === 0;
+ }
+
+
+ /**
+ * Returns the 1-indexed counter.
+ */
+ public function getCounter(): int
+ {
+ return $this->counter;
+ }
+
+
+ /**
+ * Returns the 0-indexed counter.
+ */
+ public function getCounter0(): int
+ {
+ return max(0, $this->counter - 1);
+ }
+
+
+ /**
+ * Decrements counter.
+ */
+ public function skipRound(): void
+ {
+ $this->counter = max($this->counter - 1, 0);
+ }
+
+
+ /**
+ * Returns the counter as string
+ */
+ public function __toString(): string
+ {
+ return (string) $this->counter;
+ }
+
+
+ /**
+ * Returns the count of elements.
+ */
+ public function count(): int
+ {
+ $inner = $this->getInnerIterator();
+ if ($inner instanceof \Countable) {
+ return $inner->count();
+
+ } else {
+ throw new \LogicException('Iterator is not countable.');
+ }
+ }
+
+
+ /**
+ * Forwards to the next element.
+ */
+ public function next(): void
+ {
+ parent::next();
+ if (parent::valid()) {
+ $this->counter++;
+ }
+ }
+
+
+ /**
+ * Rewinds the Iterator.
+ */
+ public function rewind(): void
+ {
+ parent::rewind();
+ $this->counter = parent::valid() ? 1 : 0;
+ }
+
+
+ /**
+ * Returns the next key or null if position is not valid.
+ */
+ public function getNextKey(): mixed
+ {
+ $iterator = $this->getInnerIterator();
+ return $iterator->valid() ? $iterator->key() : null;
+ }
+
+
+ /**
+ * Returns the next element or null if position is not valid.
+ */
+ public function getNextValue(): mixed
+ {
+ $iterator = $this->getInnerIterator();
+ return $iterator->valid() ? $iterator->current() : null;
+ }
+
+
+ /**
+ * Returns the iterator surrounding the current one.
+ */
+ public function getParent(): ?self
+ {
+ return $this->parent;
+ }
+
+
+ /********************* property accessor ****************d*g**/
+
+
+ /**
+ * Returns property value.
+ * @throws \LogicException if the property is not defined.
+ */
+ public function __get(string $name): mixed
+ {
+ if (method_exists($this, $m = 'get' . $name) || method_exists($this, $m = 'is' . $name)) {
+ return $this->$m();
+ }
+
+ throw new \LogicException('Attempt to read undeclared property ' . static::class . "::\$$name.");
+ }
+
+
+ /**
+ * Is property defined?
+ */
+ public function __isset(string $name): bool
+ {
+ return method_exists($this, 'get' . $name) || method_exists($this, 'is' . $name);
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/CoreExtension.php b/vendor/latte/latte/src/Latte/Essential/CoreExtension.php
new file mode 100644
index 0000000..4e4eacc
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/CoreExtension.php
@@ -0,0 +1,257 @@
+filters = new Filters;
+ }
+
+
+ public function beforeCompile(Latte\Engine $engine): void
+ {
+ $this->engine = $engine;
+ }
+
+
+ public function beforeRender(Runtime\Template $template): void
+ {
+ $this->filters->locale = $template->getEngine()->getLocale();
+ }
+
+
+ public function getTags(): array
+ {
+ return [
+ 'embed' => [Nodes\EmbedNode::class, 'create'],
+ 'define' => [Nodes\DefineNode::class, 'create'],
+ 'block' => [Nodes\BlockNode::class, 'create'],
+ 'layout' => [Nodes\ExtendsNode::class, 'create'],
+ 'extends' => [Nodes\ExtendsNode::class, 'create'],
+ 'import' => [Nodes\ImportNode::class, 'create'],
+ 'include' => \Closure::fromCallable([$this, 'includeSplitter']),
+
+ 'n:attr' => [Nodes\NAttrNode::class, 'create'],
+ 'n:class' => [Nodes\NClassNode::class, 'create'],
+ 'n:tag' => [Nodes\NTagNode::class, 'create'],
+
+ 'parameters' => [Nodes\ParametersNode::class, 'create'],
+ 'varType' => [Nodes\VarTypeNode::class, 'create'],
+ 'varPrint' => [Nodes\VarPrintNode::class, 'create'],
+ 'templateType' => [Nodes\TemplateTypeNode::class, 'create'],
+ 'templatePrint' => [Nodes\TemplatePrintNode::class, 'create'],
+
+ '=' => [Nodes\PrintNode::class, 'create'],
+ 'do' => [Nodes\DoNode::class, 'create'],
+ 'php' => [Nodes\DoNode::class, 'create'], // obsolete
+ 'contentType' => [Nodes\ContentTypeNode::class, 'create'],
+ 'spaceless' => [Nodes\SpacelessNode::class, 'create'],
+ 'capture' => [Nodes\CaptureNode::class, 'create'],
+ 'l' => fn(Tag $tag) => new TextNode('{', $tag->position),
+ 'r' => fn(Tag $tag) => new TextNode('}', $tag->position),
+ 'syntax' => \Closure::fromCallable([$this, 'parseSyntax']),
+
+ 'dump' => [Nodes\DumpNode::class, 'create'],
+ 'debugbreak' => [Nodes\DebugbreakNode::class, 'create'],
+ 'trace' => [Nodes\TraceNode::class, 'create'],
+
+ 'var' => [Nodes\VarNode::class, 'create'],
+ 'default' => [Nodes\VarNode::class, 'create'],
+
+ 'try' => [Nodes\TryNode::class, 'create'],
+ 'rollback' => [Nodes\RollbackNode::class, 'create'],
+
+ 'foreach' => [Nodes\ForeachNode::class, 'create'],
+ 'for' => [Nodes\ForNode::class, 'create'],
+ 'while' => [Nodes\WhileNode::class, 'create'],
+ 'iterateWhile' => [Nodes\IterateWhileNode::class, 'create'],
+ 'sep' => [Nodes\FirstLastSepNode::class, 'create'],
+ 'last' => [Nodes\FirstLastSepNode::class, 'create'],
+ 'first' => [Nodes\FirstLastSepNode::class, 'create'],
+ 'skipIf' => [Nodes\JumpNode::class, 'create'],
+ 'breakIf' => [Nodes\JumpNode::class, 'create'],
+ 'exitIf' => [Nodes\JumpNode::class, 'create'],
+ 'continueIf' => [Nodes\JumpNode::class, 'create'],
+
+ 'if' => [Nodes\IfNode::class, 'create'],
+ 'ifset' => [Nodes\IfNode::class, 'create'],
+ 'ifchanged' => [Nodes\IfChangedNode::class, 'create'],
+ 'n:ifcontent' => [Nodes\IfContentNode::class, 'create'],
+ 'n:else' => [Nodes\NElseNode::class, 'create'],
+ 'switch' => [Nodes\SwitchNode::class, 'create'],
+ ];
+ }
+
+
+ public function getFilters(): array
+ {
+ return [
+ 'batch' => [$this->filters, 'batch'],
+ 'breakLines' => [$this->filters, 'breaklines'],
+ 'breaklines' => [$this->filters, 'breaklines'],
+ 'bytes' => [$this->filters, 'bytes'],
+ 'capitalize' => extension_loaded('mbstring')
+ ? [$this->filters, 'capitalize']
+ : fn() => throw new RuntimeException('Filter |capitalize requires mbstring extension.'),
+ 'ceil' => [$this->filters, 'ceil'],
+ 'checkUrl' => [Latte\Runtime\Filters::class, 'safeUrl'],
+ 'clamp' => [$this->filters, 'clamp'],
+ 'dataStream' => [$this->filters, 'dataStream'],
+ 'datastream' => [$this->filters, 'dataStream'],
+ 'date' => [$this->filters, 'date'],
+ 'escape' => [Latte\Runtime\Filters::class, 'nop'],
+ 'escapeCss' => [Latte\Runtime\Filters::class, 'escapeCss'],
+ 'escapeHtml' => [Latte\Runtime\Filters::class, 'escapeHtml'],
+ 'escapeHtmlComment' => [Latte\Runtime\Filters::class, 'escapeHtmlComment'],
+ 'escapeICal' => [Latte\Runtime\Filters::class, 'escapeICal'],
+ 'escapeJs' => [Latte\Runtime\Filters::class, 'escapeJs'],
+ 'escapeUrl' => 'rawurlencode',
+ 'escapeXml' => [Latte\Runtime\Filters::class, 'escapeXml'],
+ 'explode' => [$this->filters, 'explode'],
+ 'filter' => [$this->filters, 'filter'],
+ 'first' => [$this->filters, 'first'],
+ 'firstUpper' => extension_loaded('mbstring')
+ ? [$this->filters, 'firstUpper']
+ : fn() => throw new RuntimeException('Filter |firstUpper requires mbstring extension.'),
+ 'floor' => [$this->filters, 'floor'],
+ 'group' => [$this->filters, 'group'],
+ 'implode' => [$this->filters, 'implode'],
+ 'indent' => [$this->filters, 'indent'],
+ 'join' => [$this->filters, 'implode'],
+ 'last' => [$this->filters, 'last'],
+ 'length' => [$this->filters, 'length'],
+ 'localDate' => [$this->filters, 'localDate'],
+ 'lower' => extension_loaded('mbstring')
+ ? [$this->filters, 'lower']
+ : fn() => throw new RuntimeException('Filter |lower requires mbstring extension.'),
+ 'number' => [$this->filters, 'number'],
+ 'padLeft' => [$this->filters, 'padLeft'],
+ 'padRight' => [$this->filters, 'padRight'],
+ 'query' => [$this->filters, 'query'],
+ 'random' => [$this->filters, 'random'],
+ 'repeat' => [$this->filters, 'repeat'],
+ 'replace' => [$this->filters, 'replace'],
+ 'replaceRe' => [$this->filters, 'replaceRe'],
+ 'replaceRE' => [$this->filters, 'replaceRe'],
+ 'reverse' => [$this->filters, 'reverse'],
+ 'round' => [$this->filters, 'round'],
+ 'slice' => [$this->filters, 'slice'],
+ 'sort' => [$this->filters, 'sort'],
+ 'spaceless' => [$this->filters, 'strip'],
+ 'split' => [$this->filters, 'explode'],
+ 'strip' => [$this->filters, 'strip'], // obsolete
+ 'stripHtml' => [$this->filters, 'stripHtml'],
+ 'striphtml' => [$this->filters, 'stripHtml'],
+ 'stripTags' => [$this->filters, 'stripTags'],
+ 'striptags' => [$this->filters, 'stripTags'],
+ 'substr' => [$this->filters, 'substring'],
+ 'trim' => [$this->filters, 'trim'],
+ 'truncate' => [$this->filters, 'truncate'],
+ 'upper' => extension_loaded('mbstring')
+ ? [$this->filters, 'upper']
+ : fn() => throw new RuntimeException('Filter |upper requires mbstring extension.'),
+ 'webalize' => class_exists(Nette\Utils\Strings::class)
+ ? [Nette\Utils\Strings::class, 'webalize']
+ : fn() => throw new RuntimeException('Filter |webalize requires nette/utils package.'),
+ ];
+ }
+
+
+ public function getFunctions(): array
+ {
+ return [
+ 'clamp' => [$this->filters, 'clamp'],
+ 'divisibleBy' => [$this->filters, 'divisibleBy'],
+ 'even' => [$this->filters, 'even'],
+ 'first' => [$this->filters, 'first'],
+ 'group' => [$this->filters, 'group'],
+ 'last' => [$this->filters, 'last'],
+ 'odd' => [$this->filters, 'odd'],
+ 'slice' => [$this->filters, 'slice'],
+ 'hasBlock' => fn(Runtime\Template $template, string $name): bool => $template->hasBlock($name),
+ ];
+ }
+
+
+ public function getPasses(): array
+ {
+ $passes = new Passes($this->engine);
+ return [
+ 'internalVariables' => [$passes, 'forbiddenVariablesPass'],
+ 'overwrittenVariables' => [Nodes\ForeachNode::class, 'overwrittenVariablesPass'],
+ 'customFunctions' => [$passes, 'customFunctionsPass'],
+ 'moveTemplatePrintToHead' => [Nodes\TemplatePrintNode::class, 'moveToHeadPass'],
+ 'nElse' => [Nodes\NElseNode::class, 'processPass'],
+ ];
+ }
+
+
+ /**
+ * {include [file] "file" [with blocks] [,] [params]}
+ * {include [block] name [,] [params]}
+ */
+ private function includeSplitter(Tag $tag, TemplateParser $parser): Nodes\IncludeBlockNode|Nodes\IncludeFileNode
+ {
+ $tag->expectArguments();
+ $mod = $tag->parser->tryConsumeTokenBeforeUnquotedString('block', 'file');
+ if ($mod) {
+ $block = $mod->text === 'block';
+ } elseif ($tag->parser->stream->tryConsume('#')) {
+ $block = true;
+ } else {
+ $name = $tag->parser->parseUnquotedStringOrExpression();
+ $block = $name instanceof Scalar\StringNode && preg_match('~[\w-]+$~DA', $name->value);
+ }
+ $tag->parser->stream->seek(0);
+
+ return $block
+ ? Nodes\IncludeBlockNode::create($tag, $parser)
+ : Nodes\IncludeFileNode::create($tag);
+ }
+
+
+ /**
+ * {syntax ...}
+ */
+ private function parseSyntax(Tag $tag, TemplateParser $parser): \Generator
+ {
+ if ($tag->isNAttribute() && $tag->prefix !== $tag::PrefixNone) {
+ throw new Latte\CompileException("Use n:syntax instead of {$tag->getNotation()}", $tag->position);
+ }
+ $tag->expectArguments();
+ $token = $tag->parser->stream->consume();
+ $lexer = $parser->getLexer();
+ $lexer->setSyntax($token->text, $tag->isNAttribute() ? null : $tag->name);
+ [$inner] = yield;
+ if (!$tag->isNAttribute()) {
+ $lexer->popSyntax();
+ }
+ return $inner;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Filters.php b/vendor/latte/latte/src/Latte/Essential/Filters.php
new file mode 100644
index 0000000..ace901d
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Filters.php
@@ -0,0 +1,753 @@
+validate([null, 'html', 'html/attr', 'xml', 'xml/attr'], __FUNCTION__);
+ $info->contentType = ContentType::Text;
+ return Latte\Runtime\Filters::convertHtmlToText((string) $s);
+ }
+
+
+ /**
+ * Removes tags from HTML (but remains HTML entities).
+ */
+ public static function stripTags(FilterInfo $info, $s): string
+ {
+ $info->contentType ??= ContentType::Html;
+ $info->validate(['html', 'html/attr', 'xml', 'xml/attr'], __FUNCTION__);
+ return strip_tags((string) $s);
+ }
+
+
+ /**
+ * Replaces all repeated white spaces with a single space.
+ */
+ public static function strip(FilterInfo $info, string $s): string
+ {
+ return $info->contentType === ContentType::Html
+ ? trim(self::spacelessHtml($s))
+ : trim(self::spacelessText($s));
+ }
+
+
+ /**
+ * Replaces all repeated white spaces with a single space.
+ */
+ public static function spacelessHtml(string $s, bool &$strip = true): string
+ {
+ return preg_replace_callback(
+ '#[ \t\r\n]+|<(/)?(textarea|pre|script)(?=\W)#si',
+ function ($m) use (&$strip) {
+ if (empty($m[2])) {
+ return $strip ? ' ' : $m[0];
+ } else {
+ $strip = !empty($m[1]);
+ return $m[0];
+ }
+ },
+ $s,
+ );
+ }
+
+
+ /**
+ * Output buffering handler for spacelessHtml.
+ */
+ public static function spacelessHtmlHandler(string $s, ?int $phase = null): string
+ {
+ static $strip;
+ $left = $right = '';
+
+ if ($phase & PHP_OUTPUT_HANDLER_START) {
+ $strip = true;
+ $tmp = ltrim($s);
+ $left = substr($s, 0, strlen($s) - strlen($tmp));
+ $s = $tmp;
+ }
+
+ if ($phase & PHP_OUTPUT_HANDLER_FINAL) {
+ $tmp = rtrim($s);
+ $right = substr($s, strlen($tmp));
+ $s = $tmp;
+ }
+
+ return $left . self::spacelessHtml($s, $strip) . $right;
+ }
+
+
+ /**
+ * Replaces all repeated white spaces with a single space.
+ */
+ public static function spacelessText(string $s): string
+ {
+ return preg_replace('#[ \t\r\n]+#', ' ', $s);
+ }
+
+
+ /**
+ * Indents plain text or HTML the content from the left.
+ */
+ public static function indent(FilterInfo $info, string $s, int $level = 1, string $chars = "\t"): string
+ {
+ if ($level < 1) {
+ // do nothing
+ } elseif ($info->contentType === ContentType::Html) {
+ $s = preg_replace_callback('#<(textarea|pre).*?\1#si', fn($m) => strtr($m[0], " \t\r\n", "\x1F\x1E\x1D\x1A"), $s);
+ if (preg_last_error()) {
+ throw new Latte\RuntimeException(preg_last_error_msg());
+ }
+
+ $s = preg_replace('#(?:^|[\r\n]+)(?=[^\r\n])#', '$0' . str_repeat($chars, $level), $s);
+ $s = strtr($s, "\x1F\x1E\x1D\x1A", " \t\r\n");
+ } else {
+ $s = preg_replace('#(?:^|[\r\n]+)(?=[^\r\n])#', '$0' . str_repeat($chars, $level), $s);
+ }
+
+ return $s;
+ }
+
+
+ /**
+ * Join array of text or HTML elements with a string.
+ * @param string[] $arr
+ */
+ public static function implode(array $arr, string $glue = ''): string
+ {
+ return implode($glue, $arr);
+ }
+
+
+ /**
+ * Splits a string by a string.
+ */
+ public static function explode(string $value, string $separator = ''): array
+ {
+ return $separator === ''
+ ? preg_split('//u', $value, -1, PREG_SPLIT_NO_EMPTY)
+ : explode($separator, $value);
+ }
+
+
+ /**
+ * Repeats text.
+ */
+ public static function repeat(FilterInfo $info, $s, int $count): string
+ {
+ return str_repeat((string) $s, $count);
+ }
+
+
+ /**
+ * Date/time formatting.
+ */
+ public static function date(string|int|\DateTimeInterface|\DateInterval|null $time, ?string $format = null): ?string
+ {
+ $format ??= Latte\Runtime\Filters::$dateFormat;
+ if ($time == null) { // intentionally ==
+ return null;
+ } elseif ($time instanceof \DateInterval) {
+ return $time->format($format);
+ } elseif (is_numeric($time)) {
+ $time = (new \DateTime)->setTimestamp((int) $time);
+ } elseif (!$time instanceof \DateTimeInterface) {
+ $time = new \DateTime($time);
+ }
+
+ if (str_contains($format, '%')) {
+ if (PHP_VERSION_ID >= 80100) {
+ trigger_error("Function strftime() used by filter |date is deprecated since PHP 8.1, use format without % characters like 'Y-m-d'.", E_USER_DEPRECATED);
+ }
+
+ return @strftime($format, $time->format('U') + 0);
+ }
+
+ return $time->format($format);
+ }
+
+
+ /**
+ * Date/time formatting according to locale.
+ */
+ public function localDate(
+ string|int|\DateTimeInterface|null $value,
+ ?string $format = null,
+ ?string $date = null,
+ ?string $time = null,
+ ): ?string
+ {
+ if ($this->locale === null) {
+ throw new Latte\RuntimeException('Filter |localDate requires the locale to be set using Engine::setLocale()');
+ } elseif ($value == null) { // intentionally ==
+ return null;
+ } elseif (is_numeric($value)) {
+ $value = (new \DateTime)->setTimestamp((int) $value);
+ } elseif (!$value instanceof \DateTimeInterface) {
+ $value = new \DateTime($value);
+ $errors = \DateTime::getLastErrors();
+ if (!empty($errors['warnings'])) {
+ throw new \InvalidArgumentException(reset($errors['warnings']));
+ }
+ }
+
+ if ($format === null) {
+ $xlt = ['' => \IntlDateFormatter::NONE, 'full' => \IntlDateFormatter::FULL, 'long' => \IntlDateFormatter::LONG, 'medium' => \IntlDateFormatter::MEDIUM, 'short' => \IntlDateFormatter::SHORT,
+ 'relative-full' => \IntlDateFormatter::RELATIVE_FULL, 'relative-long' => \IntlDateFormatter::RELATIVE_LONG, 'relative-medium' => \IntlDateFormatter::RELATIVE_MEDIUM, 'relative-short' => \IntlDateFormatter::RELATIVE_SHORT];
+ $date ??= $time === null ? 'long' : null;
+ $formatter = new \IntlDateFormatter($this->locale, $xlt[$date], $xlt[$time]);
+ } else {
+ $formatter = new \IntlDateFormatter($this->locale, pattern: (new \IntlDatePatternGenerator($this->locale))->getBestPattern($format));
+ }
+
+ $res = $formatter->format($value);
+ $res = preg_replace('~(\d\.) ~', "\$1\u{a0}", $res);
+ return $res;
+ }
+
+
+ /**
+ * Formats a number with grouped thousands and optionally decimal digits according to locale.
+ */
+ public function number(
+ float $number,
+ string|int $patternOrDecimals = 0,
+ string $decimalSeparator = '.',
+ string $thousandsSeparator = ',',
+ ): string
+ {
+ if (is_int($patternOrDecimals) && $patternOrDecimals < 0) {
+ throw new Latte\RuntimeException('Filter |number: the number of decimal must not be negative');
+ } elseif ($this->locale === null || func_num_args() > 2) {
+ return number_format($number, $patternOrDecimals, $decimalSeparator, $thousandsSeparator);
+ }
+
+ $formatter = new \NumberFormatter($this->locale, \NumberFormatter::DECIMAL);
+ if (is_string($patternOrDecimals)) {
+ $formatter->setPattern($patternOrDecimals);
+ } else {
+ $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $patternOrDecimals);
+ }
+ return $formatter->format($number);
+ }
+
+
+ /**
+ * Converts to human-readable file size.
+ */
+ public function bytes(float $bytes, int $precision = 2): string
+ {
+ $bytes = round($bytes);
+ $units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB'];
+ foreach ($units as $unit) {
+ if (abs($bytes) < 1024 || $unit === end($units)) {
+ break;
+ }
+
+ $bytes /= 1024;
+ }
+
+ if ($this->locale === null) {
+ $bytes = (string) round($bytes, $precision);
+ } else {
+ $formatter = new \NumberFormatter($this->locale, \NumberFormatter::DECIMAL);
+ $formatter->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $precision);
+ $bytes = $formatter->format($bytes);
+ }
+
+ return $bytes . ' ' . $unit;
+ }
+
+
+ /**
+ * Performs a search and replace.
+ */
+ public static function replace(
+ FilterInfo $info,
+ string|array $subject,
+ string|array $search,
+ string|array|null $replace = null,
+ ): string
+ {
+ $subject = (string) $subject;
+ if (is_array($search)) {
+ if (is_array($replace)) {
+ return strtr($subject, array_combine($search, $replace));
+ } elseif ($replace === null && is_string(key($search))) {
+ return strtr($subject, $search);
+ } else {
+ return strtr($subject, array_fill_keys($search, $replace));
+ }
+ }
+
+ return str_replace($search, $replace ?? '', $subject);
+ }
+
+
+ /**
+ * Perform a regular expression search and replace.
+ */
+ public static function replaceRe(string $subject, string $pattern, string $replacement = ''): string
+ {
+ $res = preg_replace($pattern, $replacement, $subject);
+ if (preg_last_error()) {
+ throw new Latte\RuntimeException(preg_last_error_msg());
+ }
+
+ return $res;
+ }
+
+
+ /**
+ * The data: URI generator.
+ */
+ public static function dataStream(string $data, ?string $type = null): string
+ {
+ $type ??= finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $data);
+ return 'data:' . ($type ? "$type;" : '') . 'base64,' . base64_encode($data);
+ }
+
+
+ public static function breaklines(string|Stringable|null $s): Html
+ {
+ $s = htmlspecialchars((string) $s, ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8');
+ return new Html(nl2br($s, false));
+ }
+
+
+ /**
+ * Returns a part of string.
+ */
+ public static function substring(string|Stringable|null $s, int $start, ?int $length = null): string
+ {
+ $s = (string) $s;
+ return match (true) {
+ extension_loaded('mbstring') => mb_substr($s, $start, $length, 'UTF-8'),
+ extension_loaded('iconv') => iconv_substr($s, $start, $length, 'UTF-8'),
+ default => throw new Latte\RuntimeException("Filter |substr requires 'mbstring' or 'iconv' extension."),
+ };
+ }
+
+
+ /**
+ * Truncates string to maximal length.
+ */
+ public static function truncate(string|Stringable|null $s, int $length, string $append = "\u{2026}"): string
+ {
+ $s = (string) $s;
+ if (self::strLength($s) > $length) {
+ $length -= self::strLength($append);
+ if ($length < 1) {
+ return $append;
+
+ } elseif (preg_match('#^.{1,' . $length . '}(?=[\s\x00-/:-@\[-`{-~])#us', $s, $matches)) {
+ return $matches[0] . $append;
+
+ } else {
+ return self::substring($s, 0, $length) . $append;
+ }
+ }
+
+ return $s;
+ }
+
+
+ /**
+ * Convert to lower case.
+ */
+ public static function lower($s): string
+ {
+ return mb_strtolower((string) $s, 'UTF-8');
+ }
+
+
+ /**
+ * Convert to upper case.
+ */
+ public static function upper($s): string
+ {
+ return mb_strtoupper((string) $s, 'UTF-8');
+ }
+
+
+ /**
+ * Convert first character to upper case.
+ */
+ public static function firstUpper($s): string
+ {
+ $s = (string) $s;
+ return self::upper(self::substring($s, 0, 1)) . self::substring($s, 1);
+ }
+
+
+ /**
+ * Capitalize string.
+ */
+ public static function capitalize($s): string
+ {
+ return mb_convert_case((string) $s, MB_CASE_TITLE, 'UTF-8');
+ }
+
+
+ /**
+ * Returns length of string or iterable.
+ */
+ public static function length(array|\Countable|\Traversable|string $val): int
+ {
+ if (is_array($val) || $val instanceof \Countable) {
+ return count($val);
+ } elseif ($val instanceof \Traversable) {
+ return iterator_count($val);
+ } else {
+ return self::strLength($val);
+ }
+ }
+
+
+ private static function strLength(string $s): int
+ {
+ return match (true) {
+ extension_loaded('mbstring') => mb_strlen($s, 'UTF-8'),
+ extension_loaded('iconv') => iconv_strlen($s, 'UTF-8'),
+ default => strlen(@utf8_decode($s)), // deprecated
+ };
+ }
+
+
+ /**
+ * Strips whitespace.
+ */
+ public static function trim(FilterInfo $info, string $s, string $charlist = " \t\n\r\0\x0B\u{A0}"): string
+ {
+ $charlist = preg_quote($charlist, '#');
+ $s = preg_replace('#^[' . $charlist . ']+|[' . $charlist . ']+$#Du', '', (string) $s);
+ if (preg_last_error()) {
+ throw new Latte\RuntimeException(preg_last_error_msg());
+ }
+
+ return $s;
+ }
+
+
+ /**
+ * Pad a string to a certain length with another string.
+ */
+ public static function padLeft($s, int $length, string $append = ' '): string
+ {
+ $s = (string) $s;
+ $length = max(0, $length - self::strLength($s));
+ $l = self::strLength($append);
+ return str_repeat($append, (int) ($length / $l)) . self::substring($append, 0, $length % $l) . $s;
+ }
+
+
+ /**
+ * Pad a string to a certain length with another string.
+ */
+ public static function padRight($s, int $length, string $append = ' '): string
+ {
+ $s = (string) $s;
+ $length = max(0, $length - self::strLength($s));
+ $l = self::strLength($append);
+ return $s . str_repeat($append, (int) ($length / $l)) . self::substring($append, 0, $length % $l);
+ }
+
+
+ /**
+ * Reverses string or array.
+ */
+ public static function reverse(string|iterable $val, bool $preserveKeys = false): string|array
+ {
+ if (is_array($val)) {
+ return array_reverse($val, $preserveKeys);
+ } elseif ($val instanceof \Traversable) {
+ return array_reverse(iterator_to_array($val), $preserveKeys);
+ } else {
+ return iconv('UTF-32LE', 'UTF-8', strrev(iconv('UTF-8', 'UTF-32BE', (string) $val)));
+ }
+ }
+
+
+ /**
+ * Chunks items by returning an array of arrays with the given number of items.
+ */
+ public static function batch(iterable $list, int $length, $rest = null): \Generator
+ {
+ $batch = [];
+ foreach ($list as $key => $value) {
+ $batch[$key] = $value;
+ if (count($batch) >= $length) {
+ yield $batch;
+ $batch = [];
+ }
+ }
+
+ if ($batch) {
+ if ($rest !== null) {
+ while (count($batch) < $length) {
+ $batch[] = $rest;
+ }
+ }
+
+ yield $batch;
+ }
+ }
+
+
+ /**
+ * Sorts elements using the comparison function and preserves the key association.
+ * @template K
+ * @template V
+ * @param iterable $data
+ * @return iterable
+ */
+ public function sort(
+ iterable $data,
+ ?\Closure $comparison = null,
+ string|int|\Closure|null $by = null,
+ string|int|\Closure|bool $byKey = false,
+ ): iterable
+ {
+ if ($byKey !== false) {
+ if ($by !== null) {
+ throw new \InvalidArgumentException('Filter |sort cannot use both $by and $byKey.');
+ }
+ $by = $byKey === true ? null : $byKey;
+ }
+
+ if ($comparison) {
+ } elseif ($this->locale === null) {
+ $comparison = fn($a, $b) => $a <=> $b;
+ } else {
+ $collator = new \Collator($this->locale);
+ $comparison = fn($a, $b) => is_string($a) && is_string($b)
+ ? $collator->compare($a, $b)
+ : $a <=> $b;
+ }
+
+ $comparison = match (true) {
+ $by === null => $comparison,
+ $by instanceof \Closure => fn($a, $b) => $comparison($by($a), $by($b)),
+ default => fn($a, $b) => $comparison(is_array($a) ? $a[$by] : $a->$by, is_array($b) ? $b[$by] : $b->$by),
+ };
+
+ if (is_array($data)) {
+ $byKey ? uksort($data, $comparison) : uasort($data, $comparison);
+ return $data;
+ }
+
+ $pairs = [];
+ foreach ($data as $key => $value) {
+ $pairs[] = [$key, $value];
+ }
+ uasort($pairs, fn($a, $b) => $byKey ? $comparison($a[0], $b[0]) : $comparison($a[1], $b[1]));
+
+ return new AuxiliaryIterator($pairs);
+ }
+
+
+ /**
+ * Groups elements by the element indices and preserves the key association and order.
+ * @template K
+ * @template V
+ * @param iterable $data
+ * @return iterable>
+ */
+ public static function group(iterable $data, string|int|\Closure $by): iterable
+ {
+ $fn = $by instanceof \Closure ? $by : fn($a) => is_array($a) ? $a[$by] : $a->$by;
+ $keys = $groups = [];
+
+ foreach ($data as $k => $v) {
+ $groupKey = $fn($v, $k);
+ if (!$groups || $prevKey !== $groupKey) {
+ $index = array_search($groupKey, $keys, true);
+ if ($index === false) {
+ $index = count($keys);
+ $keys[$index] = $groupKey;
+ }
+ $prevKey = $groupKey;
+ }
+ $groups[$index][] = [$k, $v];
+ }
+
+ return new AuxiliaryIterator(array_map(
+ fn($key, $group) => [$key, new AuxiliaryIterator($group)],
+ $keys,
+ $groups,
+ ));
+ }
+
+
+ /**
+ * Filters elements according to a given $predicate. Maintains original keys.
+ * @template K
+ * @template V
+ * @param iterable $iterable
+ * @param callable(V, K, iterable): bool $predicate
+ * @return iterable
+ */
+ public static function filter(iterable $iterable, callable $predicate): iterable
+ {
+ foreach ($iterable as $k => $v) {
+ if ($predicate($v, $k, $iterable)) {
+ yield $k => $v;
+ }
+ }
+ }
+
+
+ /**
+ * Returns value clamped to the inclusive range of min and max.
+ */
+ public static function clamp(int|float $value, int|float $min, int|float $max): int|float
+ {
+ if ($min > $max) {
+ throw new \InvalidArgumentException("Minimum ($min) is not less than maximum ($max).");
+ }
+
+ return min(max($value, $min), $max);
+ }
+
+
+ /**
+ * Generates URL-encoded query string
+ */
+ public static function query(string|array $data): string
+ {
+ return is_array($data)
+ ? http_build_query($data, '', '&')
+ : urlencode($data);
+ }
+
+
+ /**
+ * Is divisible by?
+ */
+ public static function divisibleBy(int $value, int $by): bool
+ {
+ return $value % $by === 0;
+ }
+
+
+ /**
+ * Is odd?
+ */
+ public static function odd(int $value): bool
+ {
+ return $value % 2 !== 0;
+ }
+
+
+ /**
+ * Is even?
+ */
+ public static function even(int $value): bool
+ {
+ return $value % 2 === 0;
+ }
+
+
+ /**
+ * Returns the first element in an array or character in a string, or null if none.
+ */
+ public static function first(string|iterable $value): mixed
+ {
+ if (is_string($value)) {
+ return self::substring($value, 0, 1);
+ }
+
+ foreach ($value as $item) {
+ return $item;
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns the last element in an array or character in a string, or null if none.
+ */
+ public static function last(string|array $value): mixed
+ {
+ return is_array($value)
+ ? ($value[array_key_last($value)] ?? null)
+ : self::substring($value, -1);
+ }
+
+
+ /**
+ * Extracts a slice of an array or string.
+ */
+ public static function slice(
+ string|array $value,
+ int $start,
+ ?int $length = null,
+ bool $preserveKeys = false,
+ ): string|array
+ {
+ return is_array($value)
+ ? array_slice($value, $start, $length, $preserveKeys)
+ : self::substring($value, $start, $length);
+ }
+
+
+ public static function round(float $value, int $precision = 0): float
+ {
+ return round($value, $precision);
+ }
+
+
+ public static function floor(float $value, int $precision = 0): float
+ {
+ return floor($value * 10 ** $precision) / 10 ** $precision;
+ }
+
+
+ public static function ceil(float $value, int $precision = 0): float
+ {
+ return ceil($value * 10 ** $precision) / 10 ** $precision;
+ }
+
+
+ /**
+ * Picks random element/char.
+ */
+ public static function random(string|array $values): mixed
+ {
+ if (is_string($values)) {
+ $values = preg_split('//u', $values, -1, PREG_SPLIT_NO_EMPTY);
+ }
+
+ return $values
+ ? $values[array_rand($values, 1)]
+ : null;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/BlockNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/BlockNode.php
new file mode 100644
index 0000000..3c74c4f
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/BlockNode.php
@@ -0,0 +1,160 @@
+ */
+ public static function create(Tag $tag, TemplateParser $parser): \Generator
+ {
+ $tag->outputMode = $tag::OutputRemoveIndentation;
+ $stream = $tag->parser->stream;
+ $node = $tag->node = new static;
+
+ if (!$stream->is('|', Token::End)) {
+ $layer = $tag->parser->tryConsumeTokenBeforeUnquotedString('local')
+ ? Template::LayerLocal
+ : $parser->blockLayer;
+ $stream->tryConsume('#');
+ $name = $tag->parser->parseUnquotedStringOrExpression();
+ $node->block = new Block($name, $layer, $tag);
+
+ if (!$node->block->isDynamic()) {
+ $parser->checkBlockIsUnique($node->block);
+ }
+ }
+
+ $node->modifier = $tag->parser->parseModifier();
+ $node->modifier->escape = (bool) $node->modifier->filters;
+ if ($node->modifier->hasFilter('noescape') && count($node->modifier->filters) === 1) {
+ throw new CompileException('Filter |noescape is not expected here.', $tag->position);
+ }
+
+ [$node->content, $endTag] = yield;
+
+ if ($node->block && $endTag && $name instanceof Scalar\StringNode) {
+ $endTag->parser->stream->tryConsume($name->value);
+ }
+
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ if (!$this->block) {
+ return $this->printFilter($context);
+
+ } elseif ($this->block->isDynamic()) {
+ return $this->printDynamic($context);
+ }
+
+ return $this->printStatic($context);
+ }
+
+
+ private function printFilter(PrintContext $context): string
+ {
+ return $context->format(
+ <<<'XX'
+ ob_start(fn() => '') %line;
+ try {
+ (function () { extract(func_get_arg(0));
+ %node
+ })(get_defined_vars());
+ } finally {
+ $ʟ_fi = new LR\FilterInfo(%dump);
+ echo %modifyContent(ob_get_clean());
+ }
+
+ XX,
+ $this->position,
+ $this->content,
+ $context->getEscaper()->export(),
+ $this->modifier,
+ );
+ }
+
+
+ private function printStatic(PrintContext $context): string
+ {
+ $this->modifier->escape = $this->modifier->escape || $context->getEscaper()->getState() === Escaper::HtmlAttribute;
+ $context->addBlock($this->block);
+ $this->block->content = $this->content->print($context); // must be compiled after is added
+
+ return $context->format(
+ '$this->renderBlock(%node, get_defined_vars()'
+ . ($this->modifier->filters || $this->modifier->escape
+ ? ', function ($s, $type) { $ʟ_fi = new LR\FilterInfo($type); return %modifyContent($s); }'
+ : '')
+ . ') %2.line;',
+ $this->block->name,
+ $this->modifier,
+ $this->position,
+ );
+ }
+
+
+ private function printDynamic(PrintContext $context): string
+ {
+ $context->addBlock($this->block);
+ $this->block->content = $this->content->print($context); // must be compiled after is added
+ $escaper = $context->getEscaper();
+ $this->modifier->escape = $this->modifier->escape || $escaper->getState() === Escaper::HtmlAttribute;
+
+ return $context->format(
+ '$this->addBlock(%node, %dump, [[$this, %dump]], %dump);
+ $this->renderBlock($ʟ_nm, get_defined_vars()'
+ . ($this->modifier->filters || $this->modifier->escape
+ ? ', function ($s, $type) { $ʟ_fi = new LR\FilterInfo($type); return %modifyContent($s); }'
+ : '')
+ . ');',
+ new AssignNode(new VariableNode('ʟ_nm'), $this->block->name),
+ $escaper->export(),
+ $this->block->method,
+ $this->block->layer,
+ $this->modifier,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ if ($this->block) {
+ yield $this->block->name;
+ }
+ yield $this->modifier;
+ yield $this->content;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php
new file mode 100644
index 0000000..19f062a
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/CaptureNode.php
@@ -0,0 +1,87 @@
+ */
+ public static function create(Tag $tag): \Generator
+ {
+ $tag->expectArguments();
+ $variable = $tag->parser->parseExpression();
+ if (!$variable->isWritable()) {
+ $text = '';
+ $i = 0;
+ while ($token = $tag->parser->stream->peek(--$i)) {
+ $text = $token->text . $text;
+ }
+
+ throw new CompileException("It is not possible to write into '$text' in " . $tag->getNotation(), $tag->position);
+ }
+ $node = $tag->node = new static;
+ $node->variable = $variable;
+ $node->modifier = $tag->parser->parseModifier();
+ [$node->content] = yield;
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $escaper = $context->getEscaper();
+ return $context->format(
+ <<<'XX'
+ ob_start(fn() => '') %line;
+ try {
+ %node
+ } finally {
+ $ʟ_tmp = %raw;
+ }
+ $ʟ_fi = new LR\FilterInfo(%dump); %node = %modifyContent($ʟ_tmp);
+
+
+ XX,
+ $this->position,
+ $this->content,
+ $escaper->getState() === Escaper::HtmlText
+ ? 'ob_get_length() ? new LR\Html(ob_get_clean()) : ob_get_clean()'
+ : 'ob_get_clean()',
+ $escaper->export(),
+ $this->variable,
+ $this->modifier,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->variable;
+ yield $this->modifier;
+ yield $this->content;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php
new file mode 100644
index 0000000..45822aa
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/ContentTypeNode.php
@@ -0,0 +1,87 @@
+expectArguments();
+ while (!$tag->parser->stream->consume()->isEnd());
+ $type = trim($tag->parser->text);
+
+ if (!$tag->isInHead() && !($tag->htmlElement?->is('script') && str_contains($type, 'html'))) {
+ throw new CompileException('{contentType} is allowed only in template header.', $tag->position);
+ }
+
+ $node = new static;
+ $node->inScript = (bool) $tag->htmlElement;
+ $node->contentType = match (true) {
+ str_contains($type, 'html') => ContentType::Html,
+ str_contains($type, 'xml') => ContentType::Xml,
+ str_contains($type, 'javascript') => ContentType::JavaScript,
+ str_contains($type, 'css') => ContentType::Css,
+ str_contains($type, 'calendar') => ContentType::ICal,
+ default => ContentType::Text
+ };
+ $parser->setContentType($node->contentType);
+
+ if (strpos($type, '/') && !$tag->htmlElement) {
+ $node->mimeType = $type;
+ }
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ if ($this->inScript) {
+ $context->getEscaper()->enterHtmlRaw($this->contentType);
+ return '';
+ }
+
+ $context->beginEscape()->enterContentType($this->contentType);
+
+ return $this->mimeType
+ ? $context->format(
+ <<<'XX'
+ if (empty($this->global->coreCaptured) && in_array($this->getReferenceType(), ['extends', null], true)) {
+ header(%dump) %line;
+ }
+
+ XX,
+ 'Content-Type: ' . $this->mimeType,
+ $this->position,
+ )
+ : '';
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ false && yield;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/DebugbreakNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/DebugbreakNode.php
new file mode 100644
index 0000000..4a1ca99
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/DebugbreakNode.php
@@ -0,0 +1,53 @@
+condition = $tag->parser->isEnd() ? null : $tag->parser->parseExpression();
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ if (function_exists($func = 'debugbreak') || function_exists($func = 'xdebug_break')) {
+ return $context->format(
+ ($this->condition ? 'if (%1.node) ' : '') . $func . '() %0.line;',
+ $this->position,
+ $this->condition,
+ );
+ }
+ return '';
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ if ($this->condition) {
+ yield $this->condition;
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/DefineNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/DefineNode.php
new file mode 100644
index 0000000..d983993
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/DefineNode.php
@@ -0,0 +1,133 @@
+ */
+ public static function create(Tag $tag, TemplateParser $parser): \Generator
+ {
+ $tag->expectArguments();
+ $layer = $tag->parser->tryConsumeTokenBeforeUnquotedString('local')
+ ? Template::LayerLocal
+ : $parser->blockLayer;
+ $tag->parser->stream->tryConsume('#');
+ $name = $tag->parser->parseUnquotedStringOrExpression();
+
+ $node = $tag->node = new static;
+ $node->block = new Block($name, $layer, $tag);
+ if (!$node->block->isDynamic()) {
+ $parser->checkBlockIsUnique($node->block);
+ $tag->parser->stream->tryConsume(',');
+ $node->block->parameters = self::parseParameters($tag);
+ }
+
+ [$node->content, $endTag] = yield;
+ if ($endTag && $name instanceof Scalar\StringNode) {
+ $endTag->parser->stream->tryConsume($name->value);
+ }
+
+ return $node;
+ }
+
+
+ private static function parseParameters(Tag $tag): array
+ {
+ $stream = $tag->parser->stream;
+ $params = [];
+ while (!$stream->is(Token::End)) {
+ $type = $tag->parser->parseType();
+
+ $save = $stream->getIndex();
+ $expr = $stream->is(Token::Php_Variable) ? $tag->parser->parseExpression() : null;
+ if ($expr instanceof VariableNode && is_string($expr->name)) {
+ $params[] = new ParameterNode($expr, new Scalar\NullNode, $type);
+ } elseif (
+ $expr instanceof AssignNode
+ && $expr->var instanceof VariableNode
+ && is_string($expr->var->name)
+ ) {
+ $params[] = new ParameterNode($expr->var, $expr->expr, $type);
+ } else {
+ $stream->seek($save);
+ $stream->throwUnexpectedException(addendum: ' in ' . $tag->getNotation());
+ }
+
+ if (!$stream->tryConsume(',')) {
+ break;
+ }
+ }
+
+ return $params;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $this->block->isDynamic()
+ ? $this->printDynamic($context)
+ : $this->printStatic($context);
+ }
+
+
+ private function printStatic(PrintContext $context): string
+ {
+ $context->addBlock($this->block);
+ $this->block->content = $this->content->print($context); // must be compiled after is added
+ return '';
+ }
+
+
+ private function printDynamic(PrintContext $context): string
+ {
+ $context->addBlock($this->block);
+ $this->block->content = $this->content->print($context); // must be compiled after is added
+
+ return $context->format(
+ '$this->addBlock(%node, %dump, [[$this, %dump]], %dump);',
+ new AssignNode(new VariableNode('ʟ_nm'), $this->block->name),
+ $context->getEscaper()->export(),
+ $this->block->method,
+ $this->block->layer,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->block->name;
+ foreach ($this->block->parameters as &$param) {
+ yield $param;
+ }
+
+ yield $this->content;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/DoNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/DoNode.php
new file mode 100644
index 0000000..e5ec56c
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/DoNode.php
@@ -0,0 +1,61 @@
+expectArguments();
+
+ $token = $tag->parser->stream->peek();
+ if ($token->is(...self::RefusedKeywords)) {
+ $tag->parser->throwReservedKeywordException($token);
+ }
+
+ $node = new static;
+ $node->expression = $tag->parser->parseExpression();
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $context->format(
+ '%node %line;',
+ $this->expression,
+ $this->position,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->expression;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/DumpNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/DumpNode.php
new file mode 100644
index 0000000..0499154
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/DumpNode.php
@@ -0,0 +1,58 @@
+expression = $tag->parser->isEnd()
+ ? null
+ : $tag->parser->parseExpression();
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $this->expression
+ ? $context->format(
+ 'Tracy\Debugger::barDump(%node, %dump) %line;',
+ $this->expression,
+ $this->expression->print($context),
+ $this->position,
+ )
+ : $context->format(
+ "Tracy\\Debugger::barDump(get_defined_vars(), 'variables') %line;",
+ $this->position,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ if ($this->expression) {
+ yield $this->expression;
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php
new file mode 100644
index 0000000..409c12c
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/EmbedNode.php
@@ -0,0 +1,125 @@
+ */
+ public static function create(Tag $tag, TemplateParser $parser): \Generator
+ {
+ if ($tag->isNAttribute()) {
+ throw new CompileException('Attribute n:embed is not supported.', $tag->position);
+ }
+
+ $tag->outputMode = $tag::OutputRemoveIndentation;
+ $tag->expectArguments();
+
+ $node = $tag->node = new static;
+ $mode = $tag->parser->tryConsumeTokenBeforeUnquotedString('block', 'file')?->text;
+ $node->name = $tag->parser->parseUnquotedStringOrExpression();
+ $node->mode = $mode ?? ($node->name instanceof StringNode && preg_match('~[\w-]+$~DA', $node->name->value) ? 'block' : 'file');
+ $tag->parser->stream->tryConsume(',');
+ $node->args = $tag->parser->parseArguments();
+
+ $prevIndex = $parser->blockLayer;
+ $parser->blockLayer = $node->layer = count($parser->blocks);
+ $parser->blocks[$parser->blockLayer] = [];
+ [$node->blocks] = yield;
+
+ foreach ($node->blocks->children as $child) {
+ if (!$child instanceof ImportNode && !$child instanceof BlockNode && !$child instanceof TextNode) {
+ throw new CompileException('Unexpected content inside {embed} tags.', $child->position);
+ }
+ }
+
+ $parser->blockLayer = $prevIndex;
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $imports = '';
+ foreach ($this->blocks->children as $child) {
+ if ($child instanceof ImportNode) {
+ $imports .= $child->print($context);
+ } else {
+ $child->print($context);
+ }
+ }
+
+ return $this->mode === 'file'
+ ? $context->format(
+ <<<'XX'
+ $this->enterBlockLayer(%dump, get_defined_vars()) %line; %raw
+ try {
+ $this->createTemplate(%node, %node, "embed")->renderToContentType(%dump) %1.line;
+ } finally {
+ $this->leaveBlockLayer();
+ }
+
+ XX,
+ $this->layer,
+ $this->position,
+ $imports,
+ $this->name,
+ $this->args,
+ $context->getEscaper()->export(),
+ )
+ : $context->format(
+ <<<'XX'
+ $this->enterBlockLayer(%dump, get_defined_vars()) %line; %raw
+ $this->copyBlockLayer();
+ try {
+ $this->renderBlock(%node, %node, %dump) %1.line;
+ } finally {
+ $this->leaveBlockLayer();
+ }
+
+ XX,
+ $this->layer,
+ $this->position,
+ $imports,
+ $this->name,
+ $this->args,
+ $context->getEscaper()->export(),
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->name;
+ yield $this->args;
+ yield $this->blocks;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php
new file mode 100644
index 0000000..1f0988c
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/ExtendsNode.php
@@ -0,0 +1,57 @@
+expectArguments();
+ $node = new static;
+ if (!$tag->isInHead()) {
+ throw new CompileException("{{$tag->name}} must be placed in template head.", $tag->position);
+ } elseif ($tag->parser->stream->tryConsume('auto')) {
+ $node->extends = new NullNode;
+ } elseif ($tag->parser->stream->tryConsume('none')) {
+ $node->extends = new BooleanNode(false);
+ } else {
+ $node->extends = $tag->parser->parseUnquotedStringOrExpression();
+ }
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $context->format('$this->parentName = %node;', $this->extends);
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->extends;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php
new file mode 100644
index 0000000..6671aff
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/FirstLastSepNode.php
@@ -0,0 +1,81 @@
+ */
+ public static function create(Tag $tag): \Generator
+ {
+ $node = $tag->node = new static;
+ $node->name = $tag->name;
+ $node->width = $tag->parser->isEnd() ? null : $tag->parser->parseExpression();
+
+ [$node->then, $nextTag] = yield ['else'];
+ if ($nextTag?->name === 'else') {
+ $node->elseLine = $nextTag->position;
+ [$node->else] = yield;
+ }
+
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $cond = match ($this->name) {
+ 'first' => '$iterator->isFirst',
+ 'last' => '$iterator->isLast',
+ 'sep' => '!$iterator->isLast',
+ };
+ return $context->format(
+ $this->else
+ ? "if ($cond(%node)) %line { %node } else %line { %node }\n"
+ : "if ($cond(%node)) %line { %node }\n",
+ $this->width,
+ $this->position,
+ $this->then,
+ $this->elseLine,
+ $this->else,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ if ($this->width) {
+ yield $this->width;
+ }
+ yield $this->then;
+ if ($this->else) {
+ yield $this->else;
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/ForNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/ForNode.php
new file mode 100644
index 0000000..cfdc76d
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/ForNode.php
@@ -0,0 +1,91 @@
+ */
+ public static function create(Tag $tag): \Generator
+ {
+ $tag->expectArguments();
+ $stream = $tag->parser->stream;
+ $node = $tag->node = new static;
+ while (!$stream->is(';')) {
+ $node->init[] = $tag->parser->parseExpression();
+ $stream->tryConsume(',');
+ }
+
+ $stream->consume(';');
+ $node->condition = $stream->is(';') ? null : $tag->parser->parseExpression();
+ $stream->consume(';');
+ while (!$tag->parser->isEnd()) {
+ $node->next[] = $tag->parser->parseExpression();
+ $stream->tryConsume(',');
+ }
+
+ [$node->content] = yield;
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $context->format(
+ <<<'XX'
+ for (%args; %node; %args) %line {
+ %node
+ }
+
+ XX,
+ $this->init,
+ $this->condition,
+ $this->next,
+ $this->position,
+ $this->content,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ foreach ($this->init as &$item) {
+ yield $item;
+ }
+
+ if ($this->condition) {
+ yield $this->condition;
+ }
+
+ foreach ($this->next as &$item) {
+ yield $item;
+ }
+
+ yield $this->content;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php
new file mode 100644
index 0000000..9befdb0
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/ForeachNode.php
@@ -0,0 +1,182 @@
+ $value} & {else}
+ */
+class ForeachNode extends StatementNode
+{
+ public ExpressionNode $expression;
+ public ?ExpressionNode $key = null;
+ public bool $byRef = false;
+ public ExpressionNode|ListNode $value;
+ public AreaNode $content;
+ public ?AreaNode $else = null;
+ public ?Position $elseLine = null;
+ public ?bool $iterator = null;
+ public bool $checkArgs = true;
+
+
+ /** @return \Generator */
+ public static function create(Tag $tag): \Generator
+ {
+ $tag->expectArguments();
+ $node = $tag->node = new static;
+ self::parseArguments($tag->parser, $node);
+
+ $modifier = $tag->parser->parseModifier();
+ foreach ($modifier->filters as $filter) {
+ match ($filter->name->name) {
+ 'nocheck', 'noCheck' => $node->checkArgs = false,
+ 'noiterator', 'noIterator' => $node->iterator = false,
+ default => throw new CompileException('Only modifiers |noiterator and |nocheck are allowed here.', $tag->position),
+ };
+ }
+
+ if ($tag->void) {
+ $node->content = new NopNode;
+ return $node;
+ }
+
+ [$node->content, $nextTag] = yield ['else'];
+ if ($nextTag?->name === 'else') {
+ $node->elseLine = $nextTag->position;
+ [$node->else] = yield;
+ }
+
+ return $node;
+ }
+
+
+ private static function parseArguments(TagParser $parser, self $node): void
+ {
+ $stream = $parser->stream;
+ $node->expression = $parser->parseExpression();
+ $stream->consume('as');
+ [$node->key, $node->value, $node->byRef] = $parser->parseForeach();
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $content = $this->content->print($context);
+ $iterator = $this->else || ($this->iterator ?? preg_match('#\$iterator\W|\Wget_defined_vars\W#', $content));
+
+ if ($this->else) {
+ $content .= $context->format(
+ '} if ($iterator->isEmpty()) %line { ',
+ $this->elseLine,
+ ) . $this->else->print($context);
+ }
+
+ if ($iterator) {
+ return $context->format(
+ <<<'XX'
+ foreach ($iterator = $ʟ_it = new Latte\Essential\CachingIterator(%node, $ʟ_it ?? null) as %raw) %line {
+ %raw
+ }
+ $iterator = $ʟ_it = $ʟ_it->getParent();
+
+
+ XX,
+ $this->expression,
+ $this->printArgs($context),
+ $this->position,
+ $content,
+ );
+
+ } else {
+ return $context->format(
+ <<<'XX'
+ foreach (%node as %raw) %line {
+ %raw
+ }
+
+
+ XX,
+ $this->expression,
+ $this->printArgs($context),
+ $this->position,
+ $content,
+ );
+ }
+ }
+
+
+ private function printArgs(PrintContext $context): string
+ {
+ return ($this->key ? $this->key->print($context) . ' => ' : '')
+ . ($this->byRef ? '&' : '')
+ . $this->value->print($context);
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->expression;
+ if ($this->key) {
+ yield $this->key;
+ }
+ yield $this->value;
+ yield $this->content;
+ if ($this->else) {
+ yield $this->else;
+ }
+ }
+
+
+ /**
+ * Pass: checks if foreach overrides template variables.
+ */
+ public static function overwrittenVariablesPass(TemplateNode $node): void
+ {
+ $vars = [];
+ (new NodeTraverser)->traverse($node, function (Node $node) use (&$vars) {
+ if ($node instanceof self && $node->checkArgs) {
+ foreach ([$node->key, $node->value] as $var) {
+ if ($var instanceof VariableNode) {
+ $vars[$var->name][] = $node->position->line;
+ }
+ }
+ }
+ });
+ if ($vars) {
+ array_unshift($node->head->children, new AuxiliaryNode(fn(PrintContext $context) => $context->format(
+ <<<'XX'
+ if (!$this->getReferringTemplate() || $this->getReferenceType() === 'extends') {
+ foreach (array_intersect_key(%dump, $this->params) as $ʟ_v => $ʟ_l) {
+ trigger_error("Variable \$$ʟ_v overwritten in foreach on line $ʟ_l");
+ }
+ }
+
+ XX,
+ array_map(fn($l) => implode(', ', $l), $vars),
+ )));
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php
new file mode 100644
index 0000000..3e3f048
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/IfChangedNode.php
@@ -0,0 +1,141 @@
+ */
+ public static function create(Tag $tag): \Generator
+ {
+ $node = $tag->node = new static;
+ $node->conditions = $tag->parser->parseArguments();
+
+ [$node->then, $nextTag] = yield ['else'];
+ if ($nextTag?->name === 'else') {
+ $node->elseLine = $nextTag->position;
+ [$node->else] = yield;
+ }
+
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $this->conditions->items
+ ? $this->printExpression($context)
+ : $this->printCapturing($context);
+ }
+
+
+ private function printExpression(PrintContext $context): string
+ {
+ return $this->else
+ ? $context->format(
+ <<<'XX'
+ if (($ʟ_loc[%dump] ?? null) !== ($ʟ_tmp = %node)) {
+ $ʟ_loc[%0.dump] = $ʟ_tmp;
+ %node
+ } else %line {
+ %node
+ }
+
+
+ XX,
+ $context->generateId(),
+ $this->conditions,
+ $this->then,
+ $this->elseLine,
+ $this->else,
+ )
+ : $context->format(
+ <<<'XX'
+ if (($ʟ_loc[%dump] ?? null) !== ($ʟ_tmp = %node)) {
+ $ʟ_loc[%0.dump] = $ʟ_tmp;
+ %2.node
+ }
+
+
+ XX,
+ $context->generateId(),
+ $this->conditions,
+ $this->then,
+ );
+ }
+
+
+ private function printCapturing(PrintContext $context): string
+ {
+ return $this->else
+ ? $context->format(
+ <<<'XX'
+ ob_start(fn() => '');
+ try %line {
+ %node
+ } finally { $ʟ_tmp = ob_get_clean(); }
+ if (($ʟ_loc[%dump] ?? null) !== $ʟ_tmp) {
+ echo $ʟ_loc[%2.dump] = $ʟ_tmp;
+ } else %line {
+ %node
+ }
+
+
+ XX,
+ $this->position,
+ $this->then,
+ $context->generateId(),
+ $this->elseLine,
+ $this->else,
+ )
+ : $context->format(
+ <<<'XX'
+ ob_start(fn() => '');
+ try %line {
+ %node
+ } finally { $ʟ_tmp = ob_get_clean(); }
+ if (($ʟ_loc[%dump] ?? null) !== $ʟ_tmp) {
+ echo $ʟ_loc[%2.dump] = $ʟ_tmp;
+ }
+
+
+ XX,
+ $this->position,
+ $this->then,
+ $context->generateId(),
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->conditions;
+ yield $this->then;
+ if ($this->else) {
+ yield $this->else;
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php
new file mode 100644
index 0000000..a772ca0
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/IfContentNode.php
@@ -0,0 +1,85 @@
+ */
+ public static function create(Tag $tag, TemplateParser $parser): \Generator
+ {
+ $node = $tag->node = new static;
+ $node->id = $parser->generateId();
+ [$node->content] = yield;
+ $node->htmlElement = $tag->htmlElement;
+ if (!$node->htmlElement->content) {
+ throw new CompileException("Unnecessary n:ifcontent on empty element <{$node->htmlElement->name}>", $tag->position);
+ }
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ try {
+ $saved = $this->htmlElement->content;
+ $else = $this->else ?? new AuxiliaryNode(fn() => '');
+ $this->htmlElement->content = new AuxiliaryNode(fn() => <<print($context)}
+ } finally {
+ \$ʟ_ifc[$this->id] = rtrim(ob_get_flush()) === '';
+ }
+
+ XX);
+ return << '');
+ try {
+ {$this->content->print($context)}
+ } finally {
+ if (\$ʟ_ifc[$this->id] ?? null) {
+ ob_end_clean();
+ {$else->print($context)}
+ } else {
+ echo ob_get_clean();
+ }
+ }
+
+ XX;
+ } finally {
+ $this->htmlElement->content = $saved;
+ }
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->content;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/IfNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/IfNode.php
new file mode 100644
index 0000000..9012d08
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/IfNode.php
@@ -0,0 +1,182 @@
+ */
+ public static function create(Tag $tag, TemplateParser $parser): \Generator
+ {
+ $node = $tag->node = new static;
+ $node->ifset = in_array($tag->name, ['ifset', 'elseifset'], true);
+ $node->capture = !$tag->isNAttribute() && $tag->name === 'if' && $tag->parser->isEnd();
+ $node->position = $tag->position;
+ if (!$node->capture) {
+ $node->condition = $node->ifset
+ ? self::buildCondition($tag->parser)
+ : $tag->parser->parseExpression();
+ }
+
+ [$node->then, $nextTag] = yield $node->capture ? ['else'] : ['else', 'elseif', 'elseifset'];
+
+ if ($nextTag?->name === 'else') {
+ if ($nextTag->parser->stream->is('if')) {
+ throw new CompileException('Arguments are not allowed in {else}, did you mean {elseif}?', $nextTag->position);
+ }
+ $node->elseLine = $nextTag->position;
+ [$node->else, $nextTag] = yield;
+
+ } elseif ($nextTag?->name === 'elseif' || $nextTag?->name === 'elseifset') {
+ if ($node->capture) {
+ throw new CompileException('Tag ' . $nextTag->getNotation() . ' is unexpected here.', $nextTag->position);
+ }
+ $node->else = yield from self::create($nextTag, $parser);
+ }
+
+ if ($node->capture) {
+ $node->condition = $nextTag->parser->parseExpression();
+ }
+
+ return $node;
+ }
+
+
+ private static function buildCondition(TagParser $parser): ExpressionNode
+ {
+ $list = [];
+ do {
+ $block = $parser->tryConsumeTokenBeforeUnquotedString('block') ?? $parser->stream->tryConsume('#');
+ $name = $parser->parseUnquotedStringOrExpression();
+ $list[] = $block || $name instanceof StringNode
+ ? new Expression\AuxiliaryNode(
+ fn(PrintContext $context, ExpressionNode $name) => '$this->hasBlock(' . $name->print($context) . ')',
+ [$name],
+ )
+ : new Expression\IssetNode([$name]);
+ } while ($parser->stream->tryConsume(','));
+
+ return Expression\BinaryOpNode::nest('&&', ...$list);
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $this->capture
+ ? $this->printCapturing($context)
+ : $this->printCommon($context);
+ }
+
+
+ private function printCommon(PrintContext $context): string
+ {
+ if ($this->else) {
+ return $context->format(
+ ($this->else instanceof self
+ ? "if (%node) %line { %node } else%node\n"
+ : "if (%node) %line { %node } else %4.line { %3.node }\n"),
+ $this->condition,
+ $this->position,
+ $this->then,
+ $this->else,
+ $this->elseLine,
+ );
+ }
+ return $context->format(
+ "if (%node) %line { %node }\n",
+ $this->condition,
+ $this->position,
+ $this->then,
+ );
+ }
+
+
+ private function printCapturing(PrintContext $context): string
+ {
+ if ($this->else) {
+ return $context->format(
+ <<<'XX'
+ ob_start(fn() => '') %line;
+ try {
+ %node
+ ob_start(fn() => '') %line;
+ try {
+ %node
+ } finally {
+ $ʟ_ifB = ob_get_clean();
+ }
+ } finally {
+ $ʟ_ifA = ob_get_clean();
+ }
+ echo (%node) ? $ʟ_ifA : $ʟ_ifB %0.line;
+
+
+ XX,
+ $this->position,
+ $this->then,
+ $this->elseLine,
+ $this->else,
+ $this->condition,
+ );
+ }
+
+ return $context->format(
+ <<<'XX'
+ ob_start(fn() => '') %line;
+ try {
+ %node
+ } finally {
+ $ʟ_ifA = ob_get_clean();
+ }
+ if (%node) %0.line { echo $ʟ_ifA; }
+
+ XX,
+ $this->position,
+ $this->then,
+ $this->condition,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->condition;
+ yield $this->then;
+ if ($this->else) {
+ yield $this->else;
+ }
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/ImportNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/ImportNode.php
new file mode 100644
index 0000000..9236562
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/ImportNode.php
@@ -0,0 +1,55 @@
+expectArguments();
+ $node = new static;
+ $node->file = $tag->parser->parseUnquotedStringOrExpression();
+ $tag->parser->stream->tryConsume(',');
+ $node->args = $tag->parser->parseArguments();
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $context->format(
+ '$this->createTemplate(%node, %node? + $this->params, "import")->render() %line;',
+ $this->file,
+ $this->args,
+ $this->position,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->file;
+ yield $this->args;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php
new file mode 100644
index 0000000..8afc821
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeBlockNode.php
@@ -0,0 +1,143 @@
+outputMode = $tag::OutputRemoveIndentation;
+
+ $tag->expectArguments();
+ $node = new static;
+ $tag->parser->tryConsumeTokenBeforeUnquotedString('block') ?? $tag->parser->stream->tryConsume('#');
+ $node->name = $tag->parser->parseUnquotedStringOrExpression();
+ $tokenName = $tag->parser->stream->peek(-1);
+
+ $stream = $tag->parser->stream;
+ if ($stream->tryConsume('from')) {
+ $node->from = $tag->parser->parseUnquotedStringOrExpression();
+ $tag->parser->stream->tryConsume(',');
+ }
+
+ $stream->tryConsume(',');
+ $node->args = $tag->parser->parseArguments();
+ $node->modifier = $tag->parser->parseModifier();
+ $node->modifier->escape = (bool) $node->modifier->filters;
+
+ $node->parent = $tokenName->is('parent');
+ if ($node->parent && $node->modifier->filters) {
+ throw new CompileException('Filters are not allowed in {include parent}', $tag->position);
+
+ } elseif ($node->parent || $tokenName->is('this')) {
+ $item = $tag->closestTag(
+ [BlockNode::class, DefineNode::class],
+ fn($item) => $item->node?->block && !$item->node->block->isDynamic() && $item->node->block->name !== ''
+ );
+ if (!$item) {
+ throw new CompileException("Cannot include $tokenName->text block outside of any block.", $tag->position);
+ }
+
+ $node->name = $item->node->block->name;
+ }
+
+ $node->blocks = &$parser->blocks;
+ $node->layer = $parser->blockLayer;
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $noEscape = $this->modifier->hasFilter('noescape');
+ $modArg = count($this->modifier->filters) > (int) $noEscape
+ ? $context->format(
+ 'function ($s, $type) { $ʟ_fi = new LR\FilterInfo($type); return %modifyContent($s); }',
+ $this->modifier,
+ )
+ : ($noEscape || $this->parent ? '' : PhpHelpers::dump($context->getEscaper()->export()));
+
+ return $this->from
+ ? $this->printBlockFrom($context, $modArg)
+ : $this->printBlock($context, $modArg);
+ }
+
+
+ private function printBlock(PrintContext $context, string $modArg): string
+ {
+ if ($this->name instanceof Scalar\StringNode || $this->name instanceof Scalar\IntegerNode) {
+ $staticName = (string) $this->name->value;
+ $block = $this->blocks[$this->layer][$staticName] ?? $this->blocks[Template::LayerLocal][$staticName] ?? null;
+ }
+
+ return $context->format(
+ '$this->renderBlock' . ($this->parent ? 'Parent' : '')
+ . '(%node, %node? + '
+ . (isset($block) && !$block->parameters ? 'get_defined_vars()' : '[]')
+ . '%raw) %line;',
+ $this->name,
+ $this->args,
+ $modArg ? ", $modArg" : '',
+ $this->position,
+ );
+ }
+
+
+ private function printBlockFrom(PrintContext $context, string $modArg): string
+ {
+ return $context->format(
+ '$this->createTemplate(%node, %node? + $this->params, "include")->renderToContentType(%raw, %node) %line;',
+ $this->from,
+ $this->args,
+ $modArg,
+ $this->name,
+ $this->position,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->name;
+ if ($this->from) {
+ yield $this->from;
+ }
+ yield $this->args;
+ yield $this->modifier;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeFileNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeFileNode.php
new file mode 100644
index 0000000..8c8fcf4
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/IncludeFileNode.php
@@ -0,0 +1,81 @@
+outputMode = $tag::OutputRemoveIndentation;
+
+ $tag->expectArguments();
+ $node = new static;
+ $tag->parser->tryConsumeTokenBeforeUnquotedString('file');
+ $node->file = $tag->parser->parseUnquotedStringOrExpression();
+ $node->mode = 'include';
+
+ $stream = $tag->parser->stream;
+ if ($stream->tryConsume('with')) {
+ $stream->consume('blocks');
+ $node->mode = 'includeblock';
+ }
+
+ $stream->tryConsume(',');
+ $node->args = $tag->parser->parseArguments();
+ $node->modifier = $tag->parser->parseModifier();
+ $node->modifier->escape = (bool) $node->modifier->filters;
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $noEscape = $this->modifier->hasFilter('noescape');
+ return $context->format(
+ '$this->createTemplate(%node, %node? + $this->params, %dump)->renderToContentType(%raw) %line;',
+ $this->file,
+ $this->args,
+ $this->mode,
+ count($this->modifier->filters) > (int) $noEscape
+ ? $context->format(
+ 'function ($s, $type) { $ʟ_fi = new LR\FilterInfo($type); return %modifyContent($s); }',
+ $this->modifier,
+ )
+ : PhpHelpers::dump($noEscape ? null : $context->getEscaper()->export()),
+ $this->position,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->file;
+ yield $this->args;
+ yield $this->modifier;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php
new file mode 100644
index 0000000..aa57c94
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/IterateWhileNode.php
@@ -0,0 +1,96 @@
+ */
+ public static function create(Tag $tag): \Generator
+ {
+ $foreach = $tag->closestTag([ForeachNode::class])?->node;
+ if (!$foreach) {
+ throw new CompileException("Tag {{$tag->name}} must be inside {foreach} ... {/foreach}.", $tag->position);
+ }
+
+ $node = $tag->node = new static;
+ $node->postTest = $tag->parser->isEnd();
+ if (!$node->postTest) {
+ $node->condition = $tag->parser->parseExpression();
+ }
+
+ $node->key = $foreach->key;
+ $node->value = $foreach->value;
+ [$node->content, $nextTag] = yield;
+ if ($node->postTest) {
+ $nextTag->expectArguments();
+ $node->condition = $nextTag->parser->parseExpression();
+ }
+
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $stmt = $context->format(
+ <<<'XX'
+ if (!$iterator->hasNext() || !(%node)) {
+ break;
+ }
+ $iterator->next();
+ [%node, %node] = [$iterator->key(), $iterator->current()];
+ XX,
+ $this->condition,
+ $this->key,
+ $this->value,
+ );
+
+ $stmt = $this->postTest
+ ? $this->content->print($context) . "\n" . $stmt
+ : $stmt . "\n" . $this->content->print($context);
+
+ return $context->format(
+ <<<'XX'
+ do %line {
+ %raw
+ } while (true);
+
+ XX,
+ $this->position,
+ $stmt,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->condition;
+ yield $this->content;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/JumpNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/JumpNode.php
new file mode 100644
index 0000000..4d7526d
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/JumpNode.php
@@ -0,0 +1,88 @@
+expectArguments();
+ $tag->outputMode = $tag->name === 'exitIf' // to not be in prepare()
+ ? $tag::OutputRemoveIndentation
+ : $tag::OutputNone;
+
+ for (
+ $parent = $tag->parent;
+ $parent?->node instanceof IfNode || $parent?->node instanceof IfContentNode;
+ $parent = $parent->parent
+ );
+ $pnode = $parent?->node;
+ if (!match ($tag->name) {
+ 'breakIf', 'continueIf' => $pnode instanceof ForNode || $pnode instanceof ForeachNode || $pnode instanceof WhileNode,
+ 'skipIf' => $pnode instanceof ForeachNode,
+ 'exitIf' => !$pnode || $pnode instanceof BlockNode || $pnode instanceof DefineNode,
+ }) {
+ throw new CompileException("Tag {{$tag->name}} is unexpected here.", $tag->position);
+ }
+
+ $last = $parent?->prefix === Tag::PrefixNone
+ ? $parent->htmlElement->parent
+ : $parent?->htmlElement;
+ $el = $tag->htmlElement;
+ while ($el && $el !== $last) {
+ $el->breakable = true;
+ $el = $el->parent;
+ }
+
+ $node = new static;
+ $node->type = $tag->name;
+ $node->condition = $tag->parser->parseExpression();
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $context->format(
+ "if (%node) %line %raw\n",
+ $this->condition,
+ $this->position,
+ match ($this->type) {
+ 'breakIf' => 'break;',
+ 'continueIf' => 'continue;',
+ 'skipIf' => '{ $iterator->skipRound(); continue; }',
+ 'exitIf' => 'return;',
+ },
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->condition;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/NAttrNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/NAttrNode.php
new file mode 100644
index 0000000..a775cc3
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/NAttrNode.php
@@ -0,0 +1,105 @@
+expectArguments();
+ $node = new static;
+ $node->args = $tag->parser->parseArguments();
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $context->format(
+ '$ʟ_tmp = %node;
+ echo %raw::attrs(isset($ʟ_tmp[0]) && is_array($ʟ_tmp[0]) ? $ʟ_tmp[0] : $ʟ_tmp, %dump) %line;',
+ $this->args,
+ self::class,
+ $context->getEscaper()->getContentType() === Latte\ContentType::Xml,
+ $this->position,
+ );
+ }
+
+
+ /** @internal */
+ public static function attrs($attrs, bool $xml): string
+ {
+ if (!is_array($attrs)) {
+ return '';
+ }
+
+ $s = '';
+ foreach ($attrs as $key => $value) {
+ if ($value === null || $value === false) {
+ continue;
+
+ } elseif ($value === true) {
+ $s .= ' ' . $key . ($xml ? '="' . $key . '"' : '');
+ continue;
+
+ } elseif (is_array($value)) {
+ $tmp = null;
+ foreach ($value as $k => $v) {
+ if ($v != null) { // intentionally ==, skip nulls & empty string
+ // composite 'style' vs. 'others'
+ $tmp[] = $v === true
+ ? $k
+ : (is_string($k) ? $k . ':' . $v : $v);
+ }
+ }
+
+ if ($tmp === null) {
+ continue;
+ }
+
+ $value = implode($key === 'style' || !strncmp($key, 'on', 2) ? ';' : ' ', $tmp);
+
+ } else {
+ $value = (string) $value;
+ }
+
+ $q = !str_contains($value, '"') ? '"' : "'";
+ $s .= ' ' . $key . '=' . $q
+ . str_replace(
+ ['&', $q, '<'],
+ ['&', $q === '"' ? '"' : ''', $xml ? '<' : '<'],
+ $value,
+ )
+ . (str_contains($value, '`') && strpbrk($value, ' <>"\'') === false ? ' ' : '')
+ . $q;
+ }
+
+ return $s;
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->args;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/NClassNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/NClassNode.php
new file mode 100644
index 0000000..ac230b3
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/NClassNode.php
@@ -0,0 +1,54 @@
+htmlElement->getAttribute('class')) {
+ throw new CompileException('It is not possible to combine class with n:class.', $tag->position);
+ }
+
+ $tag->expectArguments();
+ $node = new static;
+ $node->args = $tag->parser->parseArguments();
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $context->format(
+ 'echo ($ʟ_tmp = array_filter(%node)) ? \' class="\' . LR\Filters::escapeHtmlAttr(implode(" ", array_unique($ʟ_tmp))) . \'"\' : "" %line;',
+ $this->args,
+ $this->position,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->args;
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/NElseNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/NElseNode.php
new file mode 100644
index 0000000..4533c7a
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/NElseNode.php
@@ -0,0 +1,88 @@
+ */
+ public static function create(Tag $tag): \Generator
+ {
+ $node = $tag->node = new static;
+ [$node->content] = yield;
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ throw new \LogicException('Cannot directly print');
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->content;
+ }
+
+
+ public static function processPass(Node $node): void
+ {
+ (new NodeTraverser)->traverse($node, function (Node $node) {
+ if ($node instanceof Nodes\FragmentNode) {
+ for ($i = count($node->children) - 1; $i >= 0; $i--) {
+ $nElse = $node->children[$i];
+ if (!$nElse instanceof self) {
+ continue;
+ }
+
+ array_splice($node->children, $i, 1);
+ $prev = $node->children[--$i] ?? null;
+ if ($prev instanceof Nodes\TextNode && trim($prev->content) === '') {
+ array_splice($node->children, $i, 1);
+ $prev = $node->children[--$i] ?? null;
+ }
+
+ if (
+ $prev instanceof IfNode
+ || $prev instanceof ForeachNode
+ || $prev instanceof TryNode
+ || $prev instanceof IfChangedNode
+ || $prev instanceof IfContentNode
+ ) {
+ if ($prev->else) {
+ throw new CompileException('Multiple "else" found.', $nElse->position);
+ }
+ $prev->else = $nElse->content;
+ } else {
+ throw new CompileException('n:else must be immediately after n:if, n:foreach etc', $nElse->position);
+ }
+ }
+ } elseif ($node instanceof self) {
+ throw new CompileException('n:else must be immediately after n:if, n:foreach etc', $node->position);
+ }
+ });
+ }
+}
diff --git a/vendor/latte/latte/src/Latte/Essential/Nodes/NTagNode.php b/vendor/latte/latte/src/Latte/Essential/Nodes/NTagNode.php
new file mode 100644
index 0000000..944ddf2
--- /dev/null
+++ b/vendor/latte/latte/src/Latte/Essential/Nodes/NTagNode.php
@@ -0,0 +1,71 @@
+htmlElement->name)) {
+ throw new CompileException('Attribute n:tag is not allowed in
+
+
+
+
= $message[0] ?>
+
+
+
+
+
+
= $message[0] ?>
+
+
= $message[1] ?>
+
+
error = $code ?>
+
+
+
+
diff --git a/vendor/nette/application/src/Bridges/ApplicationDI/ApplicationExtension.php b/vendor/nette/application/src/Bridges/ApplicationDI/ApplicationExtension.php
new file mode 100644
index 0000000..5acd5bf
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationDI/ApplicationExtension.php
@@ -0,0 +1,291 @@
+scanDirs = (array) $scanDirs;
+ }
+
+
+ public function getConfigSchema(): Nette\Schema\Schema
+ {
+ return Expect::structure([
+ 'debugger' => Expect::bool(),
+ 'errorPresenter' => Expect::anyOf(
+ Expect::structure([
+ '4xx' => Expect::string('Nette:Error')->dynamic(),
+ '5xx' => Expect::string('Nette:Error')->dynamic(),
+ ])->castTo('array'),
+ Expect::string()->dynamic(),
+ )->firstIsDefault(),
+ 'catchExceptions' => Expect::bool(false)->dynamic(),
+ 'mapping' => Expect::anyOf(
+ Expect::string(),
+ Expect::arrayOf('string|array'),
+ ),
+ 'aliases' => Expect::arrayOf('string'),
+ 'scanDirs' => Expect::anyOf(
+ Expect::arrayOf('string')->default($this->scanDirs)->mergeDefaults(),
+ false,
+ )->firstIsDefault(),
+ 'scanComposer' => Expect::bool(class_exists(ClassLoader::class)),
+ 'scanFilter' => Expect::string('*Presenter'),
+ 'silentLinks' => Expect::bool(),
+ ]);
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ $config = $this->config;
+ $builder = $this->getContainerBuilder();
+ $builder->addExcludedClasses([UI\Presenter::class]);
+
+ $this->invalidLinkMode = $this->debugMode
+ ? UI\Presenter::InvalidLinkTextual | ($config->silentLinks ? 0 : UI\Presenter::InvalidLinkWarning)
+ : UI\Presenter::InvalidLinkWarning;
+
+ $application = $builder->addDefinition($this->prefix('application'))
+ ->setFactory(Nette\Application\Application::class);
+ if ($config->catchExceptions || !$this->debugMode) {
+ $application->addSetup('$error4xxPresenter', [is_array($config->errorPresenter) ? $config->errorPresenter['4xx'] : $config->errorPresenter]);
+ $application->addSetup('$errorPresenter', [is_array($config->errorPresenter) ? $config->errorPresenter['5xx'] : $config->errorPresenter]);
+ }
+
+ $this->compiler->addExportedType(Nette\Application\Application::class);
+
+ if ($this->debugMode && ($config->scanDirs || $this->robotLoader) && $this->tempDir) {
+ $touch = $this->tempDir . '/touch';
+ Nette\Utils\FileSystem::createDir($this->tempDir);
+ $this->getContainerBuilder()->addDependency($touch);
+ }
+
+ $presenterFactory = $builder->addDefinition($this->prefix('presenterFactory'))
+ ->setType(Nette\Application\IPresenterFactory::class)
+ ->setFactory(Nette\Application\PresenterFactory::class, [new Definitions\Statement(
+ Nette\Bridges\ApplicationDI\PresenterFactoryCallback::class,
+ [1 => $this->invalidLinkMode, $touch ?? null],
+ )]);
+
+ if ($config->mapping) {
+ $presenterFactory->addSetup('setMapping', [
+ is_string($config->mapping) ? ['*' => $config->mapping] : $config->mapping,
+ ]);
+ }
+
+ if ($config->aliases) {
+ $presenterFactory->addSetup('setAliases', [$config->aliases]);
+ }
+
+ $builder->addDefinition($this->prefix('linkGenerator'))
+ ->setFactory(Nette\Application\LinkGenerator::class, [
+ 1 => new Definitions\Statement([new Definitions\Statement('@Nette\Http\IRequest::getUrl'), 'withoutUserInfo']),
+ ]);
+
+ if ($this->name === 'application') {
+ $builder->addAlias('application', $this->prefix('application'));
+ $builder->addAlias('nette.presenterFactory', $this->prefix('presenterFactory'));
+ }
+ }
+
+
+ public function beforeCompile(): void
+ {
+ $builder = $this->getContainerBuilder();
+
+ if ($this->config->debugger ?? $builder->getByType(Tracy\BlueScreen::class)) {
+ $builder->getDefinition($this->prefix('application'))
+ ->addSetup([self::class, 'initializeBlueScreenPanel']);
+ }
+
+ $all = [];
+
+ foreach ($builder->findByType(Nette\Application\IPresenter::class) as $def) {
+ $all[$def->getType()] = $def;
+ }
+
+ $counter = 0;
+ foreach ($this->findPresenters() as $class) {
+ $this->checkPresenter($class);
+ if (empty($all[$class])) {
+ $all[$class] = $builder->addDefinition($this->prefix((string) ++$counter))
+ ->setType($class);
+ }
+ }
+
+ foreach ($all as $def) {
+ $def->addTag(Nette\DI\Extensions\InjectExtension::TagInject)
+ ->setAutowired(false);
+
+ if (is_subclass_of($def->getType(), UI\Presenter::class) && $def instanceof Definitions\ServiceDefinition) {
+ $def->addSetup('$invalidLinkMode', [$this->invalidLinkMode]);
+ }
+
+ $this->compiler->addExportedType($def->getType());
+ }
+ }
+
+
+ /** @return string[] */
+ private function findPresenters(): array
+ {
+ $config = $this->getConfig();
+
+ if ($config->scanDirs) {
+ if (!class_exists(Nette\Loaders\RobotLoader::class)) {
+ throw new Nette\NotSupportedException("RobotLoader is required to find presenters, install package `nette/robot-loader` or disable option {$this->prefix('scanDirs')}: false");
+ }
+
+ $robot = new Nette\Loaders\RobotLoader;
+ $robot->addDirectory(...$config->scanDirs);
+ $robot->acceptFiles = [$config->scanFilter . '.php'];
+ if ($this->tempDir) {
+ $robot->setTempDirectory($this->tempDir);
+ $robot->refresh();
+ } else {
+ $robot->rebuild();
+ }
+ } elseif ($this->robotLoader && $config->scanDirs !== false) {
+ $robot = $this->robotLoader;
+ $robot->refresh();
+ }
+
+ $classes = [];
+ if (isset($robot)) {
+ $classes = array_keys($robot->getIndexedClasses());
+ }
+
+ if ($config->scanComposer) {
+ $rc = new \ReflectionClass(ClassLoader::class);
+ $classFile = dirname($rc->getFileName()) . '/autoload_classmap.php';
+ if (is_file($classFile)) {
+ $this->getContainerBuilder()->addDependency($classFile);
+ $classes = array_merge($classes, array_keys((fn($path) => require $path)($classFile)));
+ }
+ }
+
+ $presenters = [];
+ foreach (array_unique($classes) as $class) {
+ if (
+ fnmatch($config->scanFilter, $class)
+ && class_exists($class)
+ && ($rc = new \ReflectionClass($class))
+ && $rc->implementsInterface(Nette\Application\IPresenter::class)
+ && !$rc->isAbstract()
+ ) {
+ $presenters[] = $rc->getName();
+ }
+ }
+
+ return $presenters;
+ }
+
+
+ /** @internal */
+ public static function initializeBlueScreenPanel(
+ Tracy\BlueScreen $blueScreen,
+ Nette\Application\Application $application,
+ ): void
+ {
+ $blueScreen->addPanel(function (?\Throwable $e) use ($application, $blueScreen): ?array {
+ $dumper = $blueScreen->getDumper();
+ return $e ? null : [
+ 'tab' => 'Nette Application',
+ 'panel' => '
Requests ' . $dumper($application->getRequests())
+ . '
Presenter ' . $dumper($application->getPresenter()),
+ ];
+ });
+ if (
+ version_compare(Tracy\Debugger::Version, '2.9.0', '>=')
+ && version_compare(Tracy\Debugger::Version, '3.0', '<')
+ ) {
+ $blueScreen->addFileGenerator(self::generateNewPresenterFileContents(...));
+ }
+ }
+
+
+ public static function generateNewPresenterFileContents(string $file, ?string $class = null): ?string
+ {
+ if (!$class || !str_ends_with($file, 'Presenter.php')) {
+ return null;
+ }
+
+ $res = "checked[$class])) {
+ return;
+ }
+ $this->checked[$class] = true;
+
+ $rc = new \ReflectionClass($class);
+ if ($rc->getParentClass()) {
+ $this->checkPresenter($rc->getParentClass()->getName());
+ }
+
+ foreach ($rc->getProperties() as $rp) {
+ if (($rp->getAttributes($attr = Attributes\Parameter::class) || $rp->getAttributes($attr = Attributes\Persistent::class))
+ && (!$rp->isPublic() || $rp->isStatic() || $rp->isReadOnly())
+ ) {
+ throw new Nette\InvalidStateException(sprintf('Property %s: attribute %s can be used only with public non-static property.', Reflection::toString($rp), $attr));
+ }
+ }
+
+ $re = $class::formatActionMethod('') . '.|' . $class::formatRenderMethod('') . '.|' . $class::formatSignalMethod('') . '.';
+ foreach ($rc->getMethods() as $rm) {
+ if (preg_match("#^(?!handleInvalidLink)($re)#", $rm->getName()) && (!$rm->isPublic() || $rm->isStatic())) {
+ throw new Nette\InvalidStateException(sprintf('Method %s: this method must be public non-static.', Reflection::toString($rm)));
+ } elseif (preg_match('#^createComponent.#', $rm->getName()) && ($rm->isPrivate() || $rm->isStatic())) {
+ throw new Nette\InvalidStateException(sprintf('Method %s: this method must be non-private non-static.', Reflection::toString($rm)));
+ } elseif ($rm->getAttributes(Attributes\Requires::class, \ReflectionAttribute::IS_INSTANCEOF)
+ && !preg_match("#^$re|createComponent.#", $rm->getName())
+ ) {
+ throw new Nette\InvalidStateException(sprintf('Method %s: attribute %s can be used only with action, render, handle or createComponent methods.', Reflection::toString($rm), Attributes\Requires::class));
+ } elseif ($rm->getAttributes(Attributes\Deprecated::class) && !preg_match("#^$re#", $rm->getName())) {
+ throw new Nette\InvalidStateException(sprintf('Method %s: attribute %s can be used only with action, render or handle methods.', Reflection::toString($rm), Attributes\Deprecated::class));
+ }
+ }
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationDI/LatteExtension.php b/vendor/nette/application/src/Bridges/ApplicationDI/LatteExtension.php
new file mode 100644
index 0000000..e2ad438
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationDI/LatteExtension.php
@@ -0,0 +1,177 @@
+ Expect::anyOf(true, false, 'all'),
+ 'macros' => Expect::arrayOf('string'),
+ 'extensions' => Expect::arrayOf('string|Nette\DI\Definitions\Statement'),
+ 'templateClass' => Expect::string(),
+ 'strictTypes' => Expect::bool(false),
+ 'strictParsing' => Expect::bool(false),
+ 'phpLinter' => Expect::string(),
+ 'locale' => Expect::string(),
+ ]);
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ if (!class_exists(Latte\Engine::class)) {
+ return;
+ }
+
+ $config = $this->config;
+ $builder = $this->getContainerBuilder();
+
+ $latteFactory = $builder->addFactoryDefinition($this->prefix('latteFactory'))
+ ->setImplement(ApplicationLatte\LatteFactory::class)
+ ->getResultDefinition()
+ ->setFactory(Latte\Engine::class)
+ ->addSetup('setTempDirectory', [$this->tempDir])
+ ->addSetup('setAutoRefresh', [$this->debugMode])
+ ->addSetup('setStrictTypes', [$config->strictTypes]);
+
+ if (version_compare(Latte\Engine::VERSION, '3', '<')) {
+ foreach ($config->macros as $macro) {
+ $this->addMacro($macro);
+ }
+ } else {
+ $latteFactory->addSetup('setStrictParsing', [$config->strictParsing])
+ ->addSetup('enablePhpLinter', [$config->phpLinter])
+ ->addSetup('setLocale', [$config->locale]);
+
+ $builder->getDefinition($this->prefix('latteFactory'))
+ ->getResultDefinition()
+ ->addSetup('?', [$builder::literal('func_num_args() && $service->addExtension(new Nette\Bridges\ApplicationLatte\UIExtension(func_get_arg(0)))')]);
+
+ if ($builder->getByType(Nette\Caching\Storage::class)) {
+ $this->addExtension(new Statement(Nette\Bridges\CacheLatte\CacheExtension::class));
+ }
+ if (class_exists(Nette\Bridges\FormsLatte\FormsExtension::class)) {
+ $this->addExtension(new Statement(Nette\Bridges\FormsLatte\FormsExtension::class));
+ }
+
+ foreach ($config->extensions as $extension) {
+ if ($extension === Latte\Essential\TranslatorExtension::class) {
+ $extension = new Statement($extension, [new Nette\DI\Definitions\Reference(Nette\Localization\Translator::class)]);
+ }
+ $this->addExtension($extension);
+ }
+ }
+
+ $builder->addDefinition($this->prefix('templateFactory'))
+ ->setFactory(ApplicationLatte\TemplateFactory::class)
+ ->setArguments(['templateClass' => $config->templateClass]);
+
+ if ($this->name === 'latte') {
+ $builder->addAlias('nette.latteFactory', $this->prefix('latteFactory'));
+ $builder->addAlias('nette.templateFactory', $this->prefix('templateFactory'));
+ }
+ }
+
+
+ public function beforeCompile(): void
+ {
+ $builder = $this->getContainerBuilder();
+
+ if (
+ $this->debugMode
+ && ($this->config->debugger ?? $builder->getByType(Tracy\Bar::class))
+ && class_exists(Latte\Bridges\Tracy\LattePanel::class)
+ ) {
+ $factory = $builder->getDefinition($this->prefix('templateFactory'));
+ $factory->addSetup([self::class, 'initLattePanel'], [$factory, 'all' => $this->config->debugger === 'all']);
+ }
+ }
+
+
+ public static function initLattePanel(
+ Nette\Application\UI\TemplateFactory $factory,
+ Tracy\Bar $bar,
+ bool $all = false,
+ ): void
+ {
+ if (!$factory instanceof ApplicationLatte\TemplateFactory) {
+ return;
+ }
+
+ $factory->onCreate[] = function (ApplicationLatte\Template $template) use ($bar, $all) {
+ $control = $template->getLatte()->getProviders()['uiControl'] ?? null;
+ if ($all || $control instanceof Nette\Application\UI\Presenter) {
+ $name = $all && $control ? (new \ReflectionObject($control))->getShortName() : '';
+ if (version_compare(Latte\Engine::VERSION, '3', '<')) {
+ $bar->addPanel(new Latte\Bridges\Tracy\LattePanel($template->getLatte(), $name));
+ } else {
+ $template->getLatte()->addExtension(new Latte\Bridges\Tracy\TracyExtension($name));
+ }
+ }
+ };
+ }
+
+
+ public function addMacro(string $macro): void
+ {
+ $builder = $this->getContainerBuilder();
+ $definition = $builder->getDefinition($this->prefix('latteFactory'))->getResultDefinition();
+
+ if (($macro[0] ?? null) === '@') {
+ if (str_contains($macro, '::')) {
+ [$macro, $method] = explode('::', $macro);
+ } else {
+ $method = 'install';
+ }
+
+ $definition->addSetup('?->onCompile[] = function ($engine) { ?->' . $method . '($engine->getCompiler()); }', ['@self', $macro]);
+
+ } else {
+ if (!str_contains($macro, '::') && class_exists($macro)) {
+ $macro .= '::install';
+ }
+
+ $definition->addSetup('?->onCompile[] = function ($engine) { ' . $macro . '($engine->getCompiler()); }', ['@self']);
+ }
+ }
+
+
+ public function addExtension(Statement|string $extension): void
+ {
+ $extension = is_string($extension)
+ ? new Statement($extension)
+ : $extension;
+
+ $builder = $this->getContainerBuilder();
+ $builder->getDefinition($this->prefix('latteFactory'))
+ ->getResultDefinition()
+ ->addSetup('addExtension', [$extension]);
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationDI/PresenterFactoryCallback.php b/vendor/nette/application/src/Bridges/ApplicationDI/PresenterFactoryCallback.php
new file mode 100644
index 0000000..7e60db7
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationDI/PresenterFactoryCallback.php
@@ -0,0 +1,64 @@
+container->findByType($class);
+ if (count($services) > 1) {
+ $services = array_values(array_filter($services, fn($service) => $this->container->getServiceType($service) === $class));
+ if (count($services) > 1) {
+ throw new Nette\Application\InvalidPresenterException("Multiple services of type $class found: " . implode(', ', $services) . '.');
+ }
+ }
+
+ if (count($services) === 1) {
+ return $this->container->createService($services[0]);
+ }
+
+ if ($this->touchToRefresh) {
+ touch($this->touchToRefresh);
+ }
+
+ try {
+ $presenter = $this->container->createInstance($class);
+ $this->container->callInjects($presenter);
+ } catch (Nette\DI\MissingServiceException | Nette\DI\ServiceCreationException $e) {
+ if ($this->touchToRefresh && class_exists($class)) {
+ throw new \Exception("Refresh your browser. New presenter $class was found.", 0, $e);
+ }
+
+ throw $e;
+ }
+
+ if ($presenter instanceof Nette\Application\UI\Presenter && !isset($presenter->invalidLinkMode)) {
+ $presenter->invalidLinkMode = $this->invalidLinkMode;
+ }
+
+ return $presenter;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationDI/RoutingExtension.php b/vendor/nette/application/src/Bridges/ApplicationDI/RoutingExtension.php
new file mode 100644
index 0000000..3166cb2
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationDI/RoutingExtension.php
@@ -0,0 +1,104 @@
+ Expect::bool(),
+ 'routes' => Expect::arrayOf('string'),
+ 'cache' => Expect::bool(false),
+ ]);
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ if (!$this->config->routes) {
+ return;
+ }
+
+ $builder = $this->getContainerBuilder();
+
+ $router = $builder->addDefinition($this->prefix('router'))
+ ->setFactory(Nette\Application\Routers\RouteList::class);
+
+ foreach ($this->config->routes as $mask => $action) {
+ $router->addSetup('$service->addRoute(?, ?)', [$mask, $action]);
+ }
+
+ if ($this->name === 'routing') {
+ $builder->addAlias('router', $this->prefix('router'));
+ }
+ }
+
+
+ public function beforeCompile(): void
+ {
+ $builder = $this->getContainerBuilder();
+
+ if (
+ $this->debugMode &&
+ ($this->config->debugger ?? $builder->getByType(Tracy\Bar::class)) &&
+ ($name = $builder->getByType(Nette\Application\Application::class)) &&
+ ($application = $builder->getDefinition($name)) instanceof Definitions\ServiceDefinition
+ ) {
+ $application->addSetup('@Tracy\Bar::addPanel', [
+ new Definitions\Statement(Nette\Bridges\ApplicationTracy\RoutingPanel::class),
+ ]);
+ }
+
+ if (!$builder->getByType(Nette\Routing\Router::class)) {
+ $builder->addDefinition($this->prefix('router'))
+ ->setType(Nette\Routing\Router::class)
+ ->setFactory(Nette\Routing\SimpleRouter::class);
+ $builder->addAlias('router', $this->prefix('router'));
+ }
+ }
+
+
+ public function afterCompile(Nette\PhpGenerator\ClassType $class): void
+ {
+ if ($this->config->cache) {
+ $builder = $this->getContainerBuilder();
+ $def = $builder->getDefinitionByType(Nette\Routing\Router::class);
+ $method = $class->getMethod(Nette\DI\Container::getMethodName($def->getName()));
+ try {
+ $router = eval($method->getBody());
+ if ($router instanceof Nette\Application\Routers\RouteList) {
+ $router->warmupCache();
+ }
+
+ $s = serialize($router);
+ } catch (\Throwable $e) {
+ throw new Nette\DI\ServiceCreationException('Unable to cache router due to error: ' . $e->getMessage(), 0, $e);
+ }
+
+ $method->setBody('return unserialize(?);', [$s]);
+ }
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/DefaultTemplate.php b/vendor/nette/application/src/Bridges/ApplicationLatte/DefaultTemplate.php
new file mode 100644
index 0000000..29d7616
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/DefaultTemplate.php
@@ -0,0 +1,55 @@
+$name = $value;
+ return $this;
+ }
+
+
+ /**
+ * Sets all parameters.
+ */
+ public function setParameters(array $params): static
+ {
+ return Nette\Utils\Arrays::toObject($params, $this);
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/LatteFactory.php b/vendor/nette/application/src/Bridges/ApplicationLatte/LatteFactory.php
new file mode 100644
index 0000000..e6d2c88
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/LatteFactory.php
@@ -0,0 +1,21 @@
+outputMode = $tag::OutputRemoveIndentation;
+ $tag->expectArguments();
+ $stream = $tag->parser->stream;
+ $node = new static;
+ $node->name = $tag->parser->parseUnquotedStringOrExpression(colon: false);
+ if ($stream->tryConsume(':')) {
+ $node->method = $tag->parser->parseExpression();
+ }
+
+ $stream->tryConsume(',');
+ $start = $stream->getIndex();
+ $node->args = $tag->parser->parseArguments();
+ $start -= $stream->getIndex();
+ $depth = $wrap = null;
+ for (; $start < 0; $start++) {
+ $token = $stream->peek($start);
+ match (true) {
+ $token->is('[') => $depth++,
+ $token->is(']') => $depth--,
+ $token->is('=>') && !$depth => $wrap = true,
+ default => null,
+ };
+ }
+
+ if ($wrap) {
+ $node->args = new ArrayNode([new ArrayItemNode($node->args)]);
+ }
+
+ $modifier = $tag->parser->parseModifier();
+ foreach ($modifier->filters as $filter) {
+ match ($filter->name->name) {
+ 'noescape' => $node->escape = false,
+ default => throw new Latte\CompileException('Only modifier |noescape is allowed here.', $tag->position),
+ };
+ }
+
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ if ($this->escape === null && $context->getEscaper()->getState() !== Escaper::HtmlText) {
+ $this->escape = true;
+ }
+
+ $method = match (true) {
+ !$this->method => 'render',
+ $this->method instanceof StringNode && Strings::match($this->method->value, '#^\w*$#D') => 'render' . ucfirst($this->method->value),
+ default => "{'render' . " . $this->method->print($context) . '}',
+ };
+
+ $fetchCode = $context->format(
+ $this->name instanceof StringNode
+ ? '$ʟ_tmp = $this->global->uiControl->getComponent(%node);'
+ : 'if (!is_object($ʟ_tmp = %node)) $ʟ_tmp = $this->global->uiControl->getComponent($ʟ_tmp);',
+ $this->name,
+ );
+
+ if ($this->escape) {
+ return $context->format(
+ <<<'XX'
+ %raw
+ if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->redrawControl(null, false);
+ ob_start(fn() => '');
+ $ʟ_tmp->%raw(%args) %line;
+ $ʟ_fi = new LR\FilterInfo(%dump); echo %modifyContent(ob_get_clean());
+
+
+ XX,
+ $fetchCode,
+ $method,
+ $this->args,
+ $this->position,
+ Latte\ContentType::Html,
+ new ModifierNode([], $this->escape),
+ );
+
+ } else {
+ return $context->format(
+ <<<'XX'
+ %raw
+ if ($ʟ_tmp instanceof Nette\Application\UI\Renderable) $ʟ_tmp->redrawControl(null, false);
+ $ʟ_tmp->%raw(%args) %line;
+
+
+ XX,
+ $fetchCode,
+ $method,
+ $this->args,
+ $this->position,
+ );
+ }
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->name;
+ if ($this->method) {
+ yield $this->method;
+ }
+ yield $this->args;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/IfCurrentNode.php b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/IfCurrentNode.php
new file mode 100644
index 0000000..dd1c681
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/IfCurrentNode.php
@@ -0,0 +1,70 @@
+position->line})", E_USER_DEPRECATED);
+ $node = $tag->node = new static;
+ if (!$tag->parser->isEnd()) {
+ $node->destination = $tag->parser->parseUnquotedStringOrExpression();
+ $tag->parser->stream->tryConsume(',');
+ $node->args = $tag->parser->parseArguments();
+ }
+
+ [$node->content] = yield;
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $this->destination
+ ? $context->format(
+ 'if ($this->global->uiPresenter->isLinkCurrent(%node, %args?)) { %node } ',
+ $this->destination,
+ $this->args,
+ $this->content,
+ )
+ : $context->format(
+ 'if ($this->global->uiPresenter->getLastCreatedRequestFlag("current")) { %node } ',
+ $this->content,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ if ($this->destination) {
+ yield $this->destination;
+ yield $this->args;
+ }
+ yield $this->content;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/LinkNode.php b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/LinkNode.php
new file mode 100644
index 0000000..897dd39
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/LinkNode.php
@@ -0,0 +1,92 @@
+outputMode = $tag::OutputKeepIndentation;
+ $tag->expectArguments();
+ $node = new static;
+ $node->destination = $tag->parser->parseUnquotedStringOrExpression();
+ $tag->parser->stream->tryConsume(',');
+ $node->args = $tag->parser->parseArguments();
+ $node->modifier = $tag->parser->parseModifier();
+ $node->modifier->escape = true;
+ $node->modifier->check = false;
+ $node->mode = $tag->name;
+
+ if ($tag->isNAttribute()) {
+ // move at the beginning
+ $node->position = $tag->position;
+ array_unshift($tag->htmlElement->attributes->children, $node);
+ return null;
+ }
+
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ if ($this->mode === 'href') {
+ $context->beginEscape()->enterHtmlAttribute(null, '"');
+ $res = $context->format(
+ <<<'XX'
+ echo ' href="'; echo %modify($this->global->uiControl->link(%node, %node?)) %line; echo '"';
+ XX,
+ $this->modifier,
+ $this->destination,
+ $this->args,
+ $this->position,
+ );
+ $context->restoreEscape();
+ return $res;
+ }
+
+ return $context->format(
+ 'echo %modify('
+ . ($this->mode === 'plink' ? '$this->global->uiPresenter' : '$this->global->uiControl')
+ . '->link(%node, %node?)) %line;',
+ $this->modifier,
+ $this->destination,
+ $this->args,
+ $this->position,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->destination;
+ yield $this->args;
+ yield $this->modifier;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/NNonceNode.php b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/NNonceNode.php
new file mode 100644
index 0000000..04176f4
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/NNonceNode.php
@@ -0,0 +1,37 @@
+global->uiNonce ? " nonce=\"{$this->global->uiNonce}\"" : "";';
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ false && yield;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetAreaNode.php b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetAreaNode.php
new file mode 100644
index 0000000..b4353f4
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetAreaNode.php
@@ -0,0 +1,88 @@
+ */
+ public static function create(Tag $tag, TemplateParser $parser): \Generator
+ {
+ $node = $tag->node = new static;
+ $name = $tag->parser->parseUnquotedStringOrExpression();
+ if (
+ $name instanceof Expression\ClassConstantFetchNode
+ && $name->class instanceof Php\NameNode
+ && $name->name instanceof Php\IdentifierNode
+ ) {
+ $name = new Scalar\StringNode(constant($name->class . '::' . $name->name), $name->position);
+ }
+ $node->block = new Block($name, Template::LayerSnippet, $tag);
+ $parser->checkBlockIsUnique($node->block);
+ [$node->content, $endTag] = yield;
+ if ($endTag && $name instanceof Scalar\StringNode) {
+ $endTag->parser->stream->tryConsume($name->value);
+ }
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ $context->addBlock($this->block);
+ $this->block->content = $context->format(
+ <<<'XX'
+ $this->global->snippetDriver->enter(%node, %dump);
+ try {
+ %node
+ } finally {
+ $this->global->snippetDriver->leave();
+ }
+
+ XX,
+ $this->block->name,
+ SnippetRuntime::TypeArea,
+ $this->content,
+ );
+
+ return $context->format(
+ '$this->renderBlock(%node, [], null, %dump) %line;',
+ $this->block->name,
+ Template::LayerSnippet,
+ $this->position,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->block->name;
+ yield $this->content;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetNode.php b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetNode.php
new file mode 100644
index 0000000..5c7c2b2
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/SnippetNode.php
@@ -0,0 +1,169 @@
+ */
+ public static function create(Tag $tag, TemplateParser $parser): \Generator
+ {
+ $tag->outputMode = $tag::OutputKeepIndentation;
+
+ $node = $tag->node = new static;
+ $node->htmlElement = $tag->isNAttribute() ? $tag->htmlElement : null;
+
+ if ($tag->parser->isEnd()) {
+ $name = null;
+ $node->block = new Block(new Scalar\StringNode(''), Template::LayerSnippet, $tag);
+ } else {
+ $name = $tag->parser->parseUnquotedStringOrExpression();
+ if (
+ $name instanceof Expression\ClassConstantFetchNode
+ && $name->class instanceof Php\NameNode
+ && $name->name instanceof Php\IdentifierNode
+ ) {
+ $name = new Scalar\StringNode(constant($name->class . '::' . $name->name), $name->position);
+ }
+ $node->block = new Block($name, Template::LayerSnippet, $tag);
+ if (!$node->block->isDynamic()) {
+ $parser->checkBlockIsUnique($node->block);
+ }
+ }
+
+ if ($tag->isNAttribute()) {
+ if ($tag->prefix !== $tag::PrefixNone) {
+ throw new CompileException("Use n:snippet instead of {$tag->getNotation()}", $tag->position);
+
+ } elseif ($tag->htmlElement->getAttribute(self::$snippetAttribute)) {
+ throw new CompileException('Cannot combine HTML attribute ' . self::$snippetAttribute . ' with n:snippet.', $tag->position);
+
+ } elseif (isset($tag->htmlElement->nAttributes['ifcontent'])) {
+ throw new CompileException('Cannot combine n:ifcontent with n:snippet.', $tag->position);
+
+ } elseif (isset($tag->htmlElement->nAttributes['foreach'])) {
+ throw new CompileException('Combination of n:snippet with n:foreach is invalid, use n:inner-foreach.', $tag->position);
+ }
+
+ $tag->replaceNAttribute(new AuxiliaryNode(
+ fn(PrintContext $context) => "echo ' " . $node->printAttribute($context) . "';",
+ ));
+ }
+
+ [$node->content, $endTag] = yield;
+ if ($endTag && $name instanceof Scalar\StringNode) {
+ $endTag->parser->stream->tryConsume($name->value);
+ }
+
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ if (!$this->block->isDynamic()) {
+ $context->addBlock($this->block);
+ }
+
+ if ($this->htmlElement) {
+ try {
+ $inner = $this->htmlElement->content;
+ $this->htmlElement->content = new AuxiliaryNode(fn() => $this->printContent($context, $inner));
+ return $this->content->print($context);
+ } finally {
+ $this->htmlElement->content = $inner;
+ }
+ } else {
+ return <<
printAttribute($context)}>';
+ {$this->printContent($context, $this->content)}
+ echo ' ';
+ XX;
+ }
+ }
+
+
+ private function printContent(PrintContext $context, AreaNode $inner): string
+ {
+ $dynamic = $this->block->isDynamic();
+ $res = $context->format(
+ <<<'XX'
+ $this->global->snippetDriver->enter(%node, %dump) %line;
+ try {
+ %node
+ } finally {
+ $this->global->snippetDriver->leave();
+ }
+
+ XX,
+ $dynamic ? new AuxiliaryNode(fn() => '$ʟ_nm') : $this->block->name,
+ $dynamic ? SnippetRuntime::TypeDynamic : SnippetRuntime::TypeStatic,
+ $this->position,
+ $inner,
+ );
+
+ if ($dynamic) {
+ return $res;
+ }
+
+ $this->block->content = $res;
+ return $context->format(
+ '$this->renderBlock(%node, [], null, %dump) %line;',
+ $this->block->name,
+ Template::LayerSnippet,
+ $this->position,
+ );
+ }
+
+
+ private function printAttribute(PrintContext $context): string
+ {
+ return $context->format(
+ <<<'XX'
+ %raw="', htmlspecialchars($this->global->snippetDriver->getHtmlId(%node)), '"
+ XX,
+ self::$snippetAttribute,
+ $this->block->isDynamic()
+ ? new Expression\AssignNode(new Expression\VariableNode('ʟ_nm'), $this->block->name)
+ : $this->block->name,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->block->name;
+ yield $this->content;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/TemplatePrintNode.php b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/TemplatePrintNode.php
new file mode 100644
index 0000000..151913a
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/Nodes/TemplatePrintNode.php
@@ -0,0 +1,61 @@
+getParameters(), ' . PhpHelpers::dump($this->template ?? Template::class) . '); exit;';
+ }
+
+
+ public static function printClass(array $params, string $parentClass): void
+ {
+ $bp = new Latte\Essential\Blueprint;
+ if (!method_exists($bp, 'generateTemplateClass')) {
+ throw new \LogicException("Please update 'latte/latte' to version 3.0.15 or newer.");
+ }
+
+ $control = $params['control'] ?? $params['presenter'] ?? null;
+ $name = 'Template';
+ if ($control instanceof UI\Control) {
+ $name = preg_replace('#(Control|Presenter)$#', '', $control::class) . 'Template';
+ unset($params[$control instanceof UI\Presenter ? 'control' : 'presenter']);
+ }
+ $class = $bp->generateTemplateClass($params, $name, $parentClass);
+ $code = (string) $class->getNamespace();
+
+ $bp->printBegin();
+ $bp->printCode($code);
+
+ if ($control instanceof UI\Control) {
+ $file = dirname((new \ReflectionClass($control))->getFileName()) . '/' . $class->getName() . '.php';
+ if (file_exists($file)) {
+ echo "unsaved, file {$bp->clickableFile($file)} already exists";
+ } else {
+ echo "saved to file {$bp->clickableFile($file)}";
+ file_put_contents($file, "printEnd();
+ exit;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/SnippetBridge.php b/vendor/nette/application/src/Bridges/ApplicationLatte/SnippetBridge.php
new file mode 100644
index 0000000..f5d62ef
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/SnippetBridge.php
@@ -0,0 +1,95 @@
+control = $control;
+ }
+
+
+ public function isSnippetMode(): bool
+ {
+ return (bool) $this->control->snippetMode;
+ }
+
+
+ public function setSnippetMode($snippetMode)
+ {
+ $this->control->snippetMode = $snippetMode;
+ }
+
+
+ public function needsRedraw($name): bool
+ {
+ return $this->control->isControlInvalid($name);
+ }
+
+
+ public function markRedrawn($name): void
+ {
+ if ($name !== '') {
+ $this->control->redrawControl($name, false);
+ }
+ }
+
+
+ public function getHtmlId($name): string
+ {
+ return $this->control->getSnippetId($name);
+ }
+
+
+ public function addSnippet($name, $content): void
+ {
+ if (!isset($this->payload)) {
+ $this->payload = $this->control->getPresenter()->getPayload();
+ }
+
+ $this->payload->snippets[$this->control->getSnippetId($name)] = $content;
+ }
+
+
+ public function renderChildren(): void
+ {
+ $queue = [$this->control];
+ do {
+ foreach (array_shift($queue)->getComponents() as $child) {
+ if ($child instanceof Renderable) {
+ if ($child->isControlInvalid()) {
+ $child->snippetMode = true;
+ $child->render();
+ $child->snippetMode = false;
+ }
+ } elseif ($child instanceof Nette\ComponentModel\IContainer) {
+ $queue[] = $child;
+ }
+ }
+ } while ($queue);
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/SnippetRuntime.php b/vendor/nette/application/src/Bridges/ApplicationLatte/SnippetRuntime.php
new file mode 100644
index 0000000..1856c33
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/SnippetRuntime.php
@@ -0,0 +1,141 @@
+ */
+ private array $stack = [];
+ private int $nestingLevel = 0;
+ private bool $renderingSnippets = false;
+
+ private ?\stdClass $payload;
+
+
+ public function __construct(
+ private readonly Control $control,
+ ) {
+ }
+
+
+ public function enter(string $name, string $type): void
+ {
+ if (!$this->renderingSnippets) {
+ if ($type === self::TypeDynamic && $this->nestingLevel === 0) {
+ trigger_error('Dynamic snippets are allowed only inside static snippet/snippetArea.', E_USER_WARNING);
+ }
+
+ $this->nestingLevel++;
+ return;
+ }
+
+ $obStarted = false;
+ if (
+ ($this->nestingLevel === 0 && $this->control->isControlInvalid($name))
+ || ($type === self::TypeDynamic && ($previous = end($this->stack)) && $previous[1] === true)
+ ) {
+ ob_start(fn() => null);
+ $this->nestingLevel = $type === self::TypeArea ? 0 : 1;
+ $obStarted = true;
+ } elseif ($this->nestingLevel > 0) {
+ $this->nestingLevel++;
+ }
+
+ $this->stack[] = [$name, $obStarted];
+ if ($name !== '') {
+ $this->control->redrawControl($name, false);
+ }
+ }
+
+
+ public function leave(): void
+ {
+ if (!$this->renderingSnippets) {
+ $this->nestingLevel--;
+ return;
+ }
+
+ [$name, $obStarted] = array_pop($this->stack);
+ if ($this->nestingLevel > 0 && --$this->nestingLevel === 0) {
+ $content = ob_get_clean();
+ $this->payload ??= $this->control->getPresenter()->getPayload();
+ $this->payload->snippets[$this->control->getSnippetId($name)] = $content;
+
+ } elseif ($obStarted) { // dynamic snippet wrapper or snippet area
+ ob_end_clean();
+ }
+ }
+
+
+ public function getHtmlId(string $name): string
+ {
+ return $this->control->getSnippetId($name);
+ }
+
+
+ /**
+ * @param Block[] $blocks
+ * @param mixed[] $params
+ */
+ public function renderSnippets(array $blocks, array $params): bool
+ {
+ if ($this->renderingSnippets || !$this->control->snippetMode) {
+ return false;
+ }
+
+ $this->renderingSnippets = true;
+ $this->control->snippetMode = false;
+ foreach ($blocks as $name => $block) {
+ if (!$this->control->isControlInvalid($name)) {
+ continue;
+ }
+
+ $function = reset($block->functions);
+ $function($params);
+ }
+
+ $this->control->snippetMode = true;
+ $this->renderChildren();
+ return true;
+ }
+
+
+ private function renderChildren(): void
+ {
+ $queue = [$this->control];
+ do {
+ foreach (array_shift($queue)->getComponents() as $child) {
+ if ($child instanceof Renderable) {
+ if ($child->isControlInvalid()) {
+ $child->snippetMode = true;
+ $child->render();
+ $child->snippetMode = false;
+ }
+ } elseif ($child instanceof Nette\ComponentModel\IContainer) {
+ $queue[] = $child;
+ }
+ }
+ } while ($queue);
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/Template.php b/vendor/nette/application/src/Bridges/ApplicationLatte/Template.php
new file mode 100644
index 0000000..c07ea99
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/Template.php
@@ -0,0 +1,159 @@
+latte;
+ }
+
+
+ /**
+ * Renders template to output.
+ */
+ public function render(?string $file = null, array $params = []): void
+ {
+ Nette\Utils\Arrays::toObject($params, $this);
+ if (isset($this->blueprint)) {
+ Nodes\TemplatePrintNode::printClass($this->getParameters(), $this->blueprint);
+ }
+ $this->latte->render($file ?: $this->file, $this);
+ }
+
+
+ /**
+ * Renders template to output.
+ */
+ public function renderToString(?string $file = null, array $params = []): string
+ {
+ Nette\Utils\Arrays::toObject($params, $this);
+ return $this->latte->renderToString($file ?: $this->file, $this);
+ }
+
+
+ /**
+ * Renders template to string.
+ */
+ public function __toString(): string
+ {
+ return $this->latte->renderToString($this->file, $this->getParameters());
+ }
+
+
+ /********************* template filters & helpers ****************d*g**/
+
+
+ /**
+ * Registers run-time filter.
+ */
+ public function addFilter(?string $name, callable $callback): static
+ {
+ $this->latte->addFilter($name, $callback);
+ return $this;
+ }
+
+
+ /**
+ * Registers run-time function.
+ */
+ public function addFunction(string $name, callable $callback): static
+ {
+ $this->latte->addFunction($name, $callback);
+ return $this;
+ }
+
+
+ /**
+ * Sets translate adapter.
+ */
+ public function setTranslator(?Nette\Localization\Translator $translator, ?string $language = null): static
+ {
+ if (version_compare(Latte\Engine::VERSION, '3', '<')) {
+ $this->latte->addFilter(
+ 'translate',
+ fn(Latte\Runtime\FilterInfo $fi, ...$args): string => $translator === null
+ ? $args[0]
+ : $translator->translate(...$args),
+ );
+ } else {
+ $this->latte->addExtension(new Latte\Essential\TranslatorExtension($translator, $language));
+ }
+ return $this;
+ }
+
+
+ /********************* template parameters ****************d*g**/
+
+
+ /**
+ * Sets the path to the template file.
+ */
+ public function setFile(string $file): static
+ {
+ $this->file = $file;
+ return $this;
+ }
+
+
+ final public function getFile(): ?string
+ {
+ return $this->file;
+ }
+
+
+ /**
+ * Returns array of all parameters.
+ */
+ final public function getParameters(): array
+ {
+ $res = [];
+ foreach ((new \ReflectionObject($this))->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
+ if ($prop->isInitialized($this)) {
+ $res[$prop->getName()] = $prop->getValue($this);
+ }
+ }
+
+ return $res;
+ }
+
+
+ public function blueprint(?string $parentClass = null): void
+ {
+ $this->blueprint = $parentClass ?? self::class;
+ }
+
+
+ /**
+ * Prevents unserialization.
+ */
+ final public function __wakeup()
+ {
+ throw new Nette\NotImplementedException('Object unserialization is not supported by class ' . static::class);
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/TemplateFactory.php b/vendor/nette/application/src/Bridges/ApplicationLatte/TemplateFactory.php
new file mode 100644
index 0000000..2fdcbc9
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/TemplateFactory.php
@@ -0,0 +1,138 @@
+ Occurs when a new template is created */
+ public array $onCreate = [];
+ private string $templateClass;
+
+
+ public function __construct(
+ private readonly LatteFactory $latteFactory,
+ private readonly ?Nette\Http\IRequest $httpRequest = null,
+ private readonly ?Nette\Security\User $user = null,
+ private readonly ?Nette\Caching\Storage $cacheStorage = null,
+ $templateClass = null,
+ ) {
+ if ($templateClass && (!class_exists($templateClass) || !is_a($templateClass, Template::class, true))) {
+ throw new Nette\InvalidArgumentException("Class $templateClass does not implement " . Template::class . ' or it does not exist.');
+ }
+
+ $this->templateClass = $templateClass ?: DefaultTemplate::class;
+ }
+
+
+ /** @return Template */
+ public function createTemplate(?UI\Control $control = null, ?string $class = null): UI\Template
+ {
+ $class ??= $this->templateClass;
+ if (!is_a($class, Template::class, allow_string: true)) {
+ throw new Nette\InvalidArgumentException("Class $class does not implement " . Template::class . ' or it does not exist.');
+ }
+
+ $latte = $this->latteFactory->create($control);
+ $template = new $class($latte);
+ $presenter = $control?->getPresenterIfExists();
+
+ if (version_compare(Latte\Engine::VERSION, '3', '<')) {
+ $this->setupLatte2($latte, $control, $presenter, $template);
+ } elseif (!Nette\Utils\Arrays::some($latte->getExtensions(), fn($e) => $e instanceof UIExtension)) {
+ $latte->addExtension(new UIExtension($control));
+ }
+
+ // default parameters
+ $baseUrl = $this->httpRequest
+ ? rtrim($this->httpRequest->getUrl()->withoutUserInfo()->getBaseUrl(), '/')
+ : null;
+ $flashes = $presenter instanceof UI\Presenter && $presenter->hasFlashSession()
+ ? (array) $presenter->getFlashSession()->get($control->getParameterId('flash'))
+ : [];
+
+ $params = [
+ 'user' => $this->user,
+ 'baseUrl' => $baseUrl,
+ 'basePath' => $baseUrl ? preg_replace('#https?://[^/]+#A', '', $baseUrl) : null,
+ 'flashes' => $flashes,
+ 'control' => $control,
+ 'presenter' => $presenter,
+ ];
+
+ foreach ($params as $key => $value) {
+ if ($value !== null && property_exists($template, $key)) {
+ $template->$key = $value;
+ }
+ }
+
+ Nette\Utils\Arrays::invoke($this->onCreate, $template);
+
+ return $template;
+ }
+
+
+ private function setupLatte2(
+ Latte\Engine $latte,
+ ?UI\Control $control,
+ ?UI\Presenter $presenter,
+ Template $template,
+ ): void
+ {
+ if ($latte->onCompile instanceof \Traversable) {
+ $latte->onCompile = iterator_to_array($latte->onCompile);
+ }
+
+ array_unshift($latte->onCompile, function (Latte\Engine $latte) use ($control, $template): void {
+ if ($this->cacheStorage) {
+ $latte->getCompiler()->addMacro('cache', new Nette\Bridges\CacheLatte\CacheMacro);
+ }
+
+ UIMacros::install($latte->getCompiler());
+ if (class_exists(Nette\Bridges\FormsLatte\FormMacros::class)) {
+ Nette\Bridges\FormsLatte\FormMacros::install($latte->getCompiler());
+ }
+
+ $control?->templatePrepareFilters($template);
+ });
+
+ $latte->addProvider('cacheStorage', $this->cacheStorage);
+
+ if ($control) {
+ $latte->addProvider('uiControl', $control);
+ $latte->addProvider('uiPresenter', $presenter);
+ $latte->addProvider('snippetBridge', new SnippetBridge($control));
+ if ($presenter) {
+ $header = $presenter->getHttpResponse()->getHeader('Content-Security-Policy')
+ ?: $presenter->getHttpResponse()->getHeader('Content-Security-Policy-Report-Only');
+ }
+
+ $nonce = $presenter && preg_match('#\s\'nonce-([\w+/]+=*)\'#', (string) $header, $m) ? $m[1] : null;
+ $latte->addProvider('uiNonce', $nonce);
+ }
+
+ if ($presenter) {
+ $latte->addFunction('isLinkCurrent', [$presenter, 'isLinkCurrent']);
+ $latte->addFunction('isModuleCurrent', [$presenter, 'isModuleCurrent']);
+ }
+
+ $latte->addFilter('modifyDate', fn($time, $delta, $unit = null) => $time
+ ? Nette\Utils\DateTime::from($time)->modify($delta . $unit)
+ : null);
+
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/UIExtension.php b/vendor/nette/application/src/Bridges/ApplicationLatte/UIExtension.php
new file mode 100644
index 0000000..eeff391
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/UIExtension.php
@@ -0,0 +1,133 @@
+ fn($time, $delta, $unit = null) => $time
+ ? Nette\Utils\DateTime::from($time)->modify($delta . $unit)
+ : null,
+ ];
+ }
+
+
+ public function getFunctions(): array
+ {
+ if ($presenter = $this->control?->getPresenterIfExists()) {
+ return [
+ 'isLinkCurrent' => $presenter->isLinkCurrent(...),
+ 'isModuleCurrent' => $presenter->isModuleCurrent(...),
+ ];
+ }
+ return [];
+ }
+
+
+ public function getProviders(): array
+ {
+ $presenter = $this->control?->getPresenterIfExists();
+ $httpResponse = $presenter?->getHttpResponse();
+ return [
+ 'coreParentFinder' => $this->findLayoutTemplate(...),
+ 'uiControl' => $this->control,
+ 'uiPresenter' => $presenter,
+ 'snippetDriver' => $this->control ? new SnippetRuntime($this->control) : null,
+ 'uiNonce' => $httpResponse ? $this->findNonce($httpResponse) : null,
+ ];
+ }
+
+
+ public function getTags(): array
+ {
+ return [
+ 'n:href' => Nodes\LinkNode::create(...),
+ 'n:nonce' => Nodes\NNonceNode::create(...),
+ 'control' => Nodes\ControlNode::create(...),
+ 'plink' => Nodes\LinkNode::create(...),
+ 'link' => Nodes\LinkNode::create(...),
+ 'ifCurrent' => Nodes\IfCurrentNode::create(...),
+ 'templatePrint' => Nodes\TemplatePrintNode::create(...),
+ 'snippet' => Nodes\SnippetNode::create(...),
+ 'snippetArea' => Nodes\SnippetAreaNode::create(...),
+ 'layout' => $this->createExtendsNode(...),
+ 'extends' => $this->createExtendsNode(...),
+ ];
+ }
+
+
+ public function getPasses(): array
+ {
+ return [
+ 'snippetRendering' => $this->snippetRenderingPass(...),
+ ];
+ }
+
+
+ /**
+ * Render snippets instead of template in snippet-mode.
+ */
+ public function snippetRenderingPass(TemplateNode $templateNode): void
+ {
+ array_unshift($templateNode->main->children, new Latte\Compiler\Nodes\AuxiliaryNode(fn() => <<<'XX'
+ if ($this->global->snippetDriver?->renderSnippets($this->blocks[self::LayerSnippet], $this->params)) { return; }
+
+
+ XX));
+ }
+
+
+ public static function findLayoutTemplate(Latte\Runtime\Template $template): ?string
+ {
+ $presenter = $template->global->uiControl ?? null;
+ return $presenter instanceof UI\Presenter && !empty($template::Blocks[$template::LayerTop])
+ ? $presenter->findLayoutTemplateFile()
+ : null;
+ }
+
+
+ private function findNonce(Nette\Http\IResponse $httpResponse): ?string
+ {
+ $header = $httpResponse->getHeader('Content-Security-Policy')
+ ?: $httpResponse->getHeader('Content-Security-Policy-Report-Only');
+ return preg_match('#\s\'nonce-([\w+/]+=*)\'#', (string) $header, $m) ? $m[1] : null;
+ }
+
+
+ public static function createExtendsNode(Tag $tag): ExtendsNode
+ {
+ $auto = $tag->parser->stream->is('auto');
+ $node = ExtendsNode::create($tag);
+ if ($auto) {
+ $node->extends = new AuxiliaryNode(fn() => '$this->global->uiPresenter->findLayoutTemplateFile()');
+ }
+ return $node;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/UIMacros.php b/vendor/nette/application/src/Bridges/ApplicationLatte/UIMacros.php
new file mode 100644
index 0000000..131c300
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/UIMacros.php
@@ -0,0 +1,187 @@
+addMacro('control', [$me, 'macroControl']);
+
+ $me->addMacro('href', null, null, fn(MacroNode $node, PhpWriter $writer): string => ' ?> href="macroLink($node, $writer) . ' ?>"addMacro('plink', [$me, 'macroLink']);
+ $me->addMacro('link', [$me, 'macroLink']);
+ $me->addMacro('ifCurrent', [$me, 'macroIfCurrent'], '}'); // deprecated; use n:class="$presenter->linkCurrent ? ..."
+ $me->addMacro('extends', [$me, 'macroExtends']);
+ $me->addMacro('layout', [$me, 'macroExtends']);
+ $me->addMacro('nonce', null, null, 'echo $this->global->uiNonce ? " nonce=\"{$this->global->uiNonce}\"" : "";');
+ $me->addMacro('templatePrint', [$me, 'macroTemplatePrint'], null, null, self::ALLOWED_IN_HEAD);
+ }
+
+
+ /**
+ * Initializes before template parsing.
+ */
+ public function initialize(): void
+ {
+ $this->extends = false;
+ }
+
+
+ /**
+ * Finishes template parsing.
+ * @return array(prolog, epilog)
+ */
+ public function finalize()
+ {
+ if ($this->printTemplate) {
+ return ["Nette\\Bridges\\ApplicationLatte\\UIRuntime::printClass(\$this, $this->printTemplate); exit;"];
+ }
+
+ return [$this->extends . 'Nette\Bridges\ApplicationLatte\UIRuntime::initialize($this, $this->parentName, $this->blocks);'];
+ }
+
+
+ /********************* macros ****************d*g**/
+
+
+ /**
+ * {control name[:method] [params]}
+ */
+ public function macroControl(MacroNode $node, PhpWriter $writer)
+ {
+ if ($node->context !== [Latte\Compiler::CONTENT_HTML, Latte\Compiler::CONTEXT_HTML_TEXT]) {
+ $escapeMod = Latte\Helpers::removeFilter($node->modifiers, 'noescape') ? '' : '|escape';
+ }
+
+ if ($node->modifiers) {
+ trigger_error('Modifiers are deprecated in ' . $node->getNotation(), E_USER_DEPRECATED);
+ }
+
+ $node->modifiers .= $escapeMod ?? '';
+
+ $words = $node->tokenizer->fetchWords();
+ if (!$words) {
+ throw new CompileException('Missing control name in {control}');
+ }
+
+ $name = $writer->formatWord($words[0]);
+ $method = ucfirst($words[1] ?? '');
+ $method = Strings::match($method, '#^\w*$#D')
+ ? "render$method"
+ : "{\"render$method\"}";
+
+ $tokens = $node->tokenizer;
+ $pos = $tokens->position;
+ $wrap = false;
+ while ($tokens->nextToken()) {
+ if ($tokens->isCurrent('=>', '(expand)') && !$tokens->depth) {
+ $wrap = true;
+ break;
+ }
+ }
+
+ $tokens->position = $pos;
+ $param = $wrap ? $writer->formatArray() : $writer->formatArgs();
+
+ return "/* line $node->startLine */ "
+ . ($name[0] === '$' ? "if (is_object($name)) \$_tmp = $name; else " : '')
+ . '$_tmp = $this->global->uiControl->getComponent(' . $name . '); '
+ . 'if ($_tmp instanceof Nette\Application\UI\Renderable) $_tmp->redrawControl(null, false); '
+ . ($node->modifiers === ''
+ ? "\$_tmp->$method($param);"
+ : $writer->write(
+ "ob_start(fn() => null); \$_tmp->$method($param); \$ʟ_fi = new LR\\FilterInfo(%var); echo %modifyContent(ob_get_clean());",
+ Latte\Engine::CONTENT_HTML,
+ )
+ );
+ }
+
+
+ /**
+ * {link destination [,] [params]}
+ * {plink destination [,] [params]}
+ * n:href="destination [,] [params]"
+ */
+ public function macroLink(MacroNode $node, PhpWriter $writer)
+ {
+ $node->modifiers = preg_replace('#\|safeurl\s*(?=\||$)#Di', '', $node->modifiers);
+ return $writer->using($node, $this->getCompiler())
+ ->write(
+ 'echo %escape(%modify('
+ . ($node->name === 'plink' ? '$this->global->uiPresenter' : '$this->global->uiControl')
+ . '->link(%node.word, %node.array?)))'
+ . ($node->startLine ? " /* line $node->startLine */;" : ';'),
+ );
+ }
+
+
+ /**
+ * {ifCurrent destination [,] [params]}
+ */
+ public function macroIfCurrent(MacroNode $node, PhpWriter $writer)
+ {
+ if ($node->modifiers) {
+ throw new CompileException('Modifiers are not allowed in ' . $node->getNotation());
+ }
+
+ return $writer->write(
+ $node->args
+ ? 'if ($this->global->uiPresenter->isLinkCurrent(%node.word, %node.array?)) {'
+ : 'if ($this->global->uiPresenter->getLastCreatedRequestFlag("current")) {',
+ );
+ }
+
+
+ /**
+ * {extends auto}
+ */
+ public function macroExtends(MacroNode $node, PhpWriter $writer)
+ {
+ if ($node->modifiers || $node->parentNode || $node->args !== 'auto') {
+ return $this->extends = false;
+ }
+
+ $this->extends = $writer->write('$this->parentName = $this->global->uiPresenter->findLayoutTemplateFile();');
+ }
+
+
+ /**
+ * {templatePrint [parentClass | default]}
+ */
+ public function macroTemplatePrint(MacroNode $node): void
+ {
+ if ($node->modifiers) {
+ throw new CompileException('Modifiers are not allowed in ' . $node->getNotation());
+ }
+
+ $this->printTemplate = var_export($node->tokenizer->fetchWord() ?: null, true);
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationLatte/UIRuntime.php b/vendor/nette/application/src/Bridges/ApplicationLatte/UIRuntime.php
new file mode 100644
index 0000000..ace3af7
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationLatte/UIRuntime.php
@@ -0,0 +1,84 @@
+global;
+ $blocks = array_filter(array_keys($blocks), fn(string $s): bool => $s[0] !== '_');
+ if (
+ $parentName === null
+ && $blocks
+ && !$template->getReferringTemplate()
+ && ($providers->uiControl ?? null) instanceof Nette\Application\UI\Presenter
+ ) {
+ $parentName = $providers->uiControl->findLayoutTemplateFile();
+ }
+ }
+
+
+ public static function printClass(Latte\Runtime\Template $template, ?string $parent = null): void
+ {
+ $blueprint = new Latte\Runtime\Blueprint;
+ $name = 'Template';
+ $params = $template->getParameters();
+ $control = $params['control'] ?? $params['presenter'] ?? null;
+ if ($control) {
+ $name = preg_replace('#(Control|Presenter)$#', '', $control::class) . 'Template';
+ unset($params[$control instanceof Presenter ? 'control' : 'presenter']);
+ }
+
+ if ($parent) {
+ if (!class_exists($parent)) {
+ $blueprint->printHeader("{templatePrint}: Class '$parent' doesn't exist.");
+ return;
+ }
+
+ $params = array_diff_key($params, get_class_vars($parent));
+ }
+
+ $funcs = array_diff_key((array) $template->global->fn, (new Latte\Runtime\Defaults)->getFunctions());
+ unset($funcs['isLinkCurrent'], $funcs['isModuleCurrent']);
+
+ $namespace = new Php\PhpNamespace(Php\Helpers::extractNamespace($name));
+ $class = $namespace->addClass(Php\Helpers::extractShortName($name));
+ $class->setExtends($parent ?: Template::class);
+ if (!$parent) {
+ $class->addTrait(Nette\SmartObject::class);
+ }
+
+ $blueprint->addProperties($class, $params, true);
+ $blueprint->addFunctions($class, $funcs);
+
+ $end = $blueprint->printCanvas();
+ $blueprint->printHeader('Native types');
+ $blueprint->printCode((string) $namespace);
+
+ $blueprint->addProperties($class, $params, false);
+
+ $blueprint->printHeader('phpDoc types');
+ $blueprint->printCode((string) $namespace);
+ echo $end;
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationTracy/RoutingPanel.php b/vendor/nette/application/src/Bridges/ApplicationTracy/RoutingPanel.php
new file mode 100644
index 0000000..a69c429
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationTracy/RoutingPanel.php
@@ -0,0 +1,145 @@
+routes = $this->analyse(
+ $this->router instanceof Routing\RouteList
+ ? $this->router
+ : (new Routing\RouteList)->add($this->router),
+ $this->httpRequest,
+ );
+ return Nette\Utils\Helpers::capture(function () {
+ $matched = $this->matched;
+ require __DIR__ . '/templates/RoutingPanel.tab.phtml';
+ });
+ }
+
+
+ /**
+ * Renders panel.
+ */
+ public function getPanel(): string
+ {
+ return Nette\Utils\Helpers::capture(function () {
+ $matched = $this->matched;
+ $routes = $this->routes;
+ $source = $this->matched ? $this->findSource() : null;
+ $url = $this->httpRequest->getUrl();
+ $method = $this->httpRequest->getMethod();
+ require __DIR__ . '/templates/RoutingPanel.panel.phtml';
+ });
+ }
+
+
+ private function analyse(Routing\RouteList $router, ?Nette\Http\IRequest $httpRequest): array
+ {
+ $res = [
+ 'path' => $router->getPath(),
+ 'domain' => $router->getDomain(),
+ 'module' => ($router instanceof Nette\Application\Routers\RouteList ? $router->getModule() : ''),
+ 'routes' => [],
+ ];
+ $httpRequest = $httpRequest
+ ? (fn() => $this->prepareRequest($httpRequest))->bindTo($router, Routing\RouteList::class)()
+ : null;
+ $flags = $router->getFlags();
+
+ foreach ($router->getRouters() as $i => $innerRouter) {
+ if ($innerRouter instanceof Routing\RouteList) {
+ $res['routes'][] = $this->analyse($innerRouter, $httpRequest);
+ continue;
+ }
+
+ $matched = $flags[$i] & $router::ONE_WAY ? 'oneway' : 'no';
+ $params = $e = null;
+ try {
+ if (
+ $httpRequest
+ && ($params = $innerRouter->match($httpRequest)) !== null
+ && ($params = (fn() => $this->completeParameters($params))->bindTo($router, Routing\RouteList::class)()) !== null
+ ) {
+ $matched = 'may';
+ if ($this->matched === null) {
+ $this->matched = $params;
+ $matched = 'yes';
+ }
+ }
+ } catch (\Throwable $e) {
+ $matched = 'error';
+ }
+
+ $res['routes'][] = (object) [
+ 'matched' => $matched,
+ 'class' => $innerRouter::class,
+ 'defaults' => $innerRouter instanceof Routing\Route || $innerRouter instanceof Routing\SimpleRouter ? $innerRouter->getDefaults() : [],
+ 'mask' => $innerRouter instanceof Routing\Route ? $innerRouter->getMask() : null,
+ 'params' => $params,
+ 'error' => $e,
+ ];
+ }
+ return $res;
+ }
+
+
+ private function findSource(): \ReflectionClass|\ReflectionMethod|string|null
+ {
+ $params = $this->matched;
+ $presenter = $params['presenter'] ?? '';
+ try {
+ $class = $this->presenterFactory->getPresenterClass($presenter);
+ } catch (Nette\Application\InvalidPresenterException) {
+ if ($this->presenterFactory instanceof Nette\Application\PresenterFactory) {
+ return $this->presenterFactory->formatPresenterClass($presenter);
+ }
+ return null;
+ }
+
+ if (is_a($class, Nette\Application\UI\Presenter::class, allow_string: true)) {
+ $rc = $class::getReflection();
+ if (isset($params[Presenter::SignalKey])) {
+ return $rc->getSignalMethod($params[Presenter::SignalKey]);
+ } elseif (isset($params[Presenter::ActionKey])
+ && ($method = $rc->getActionRenderMethod($params[Presenter::ActionKey]))
+ ) {
+ return $method;
+ }
+ }
+
+ return new \ReflectionClass($class);
+ }
+}
diff --git a/vendor/nette/application/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml b/vendor/nette/application/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml
new file mode 100644
index 0000000..6d499b1
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml
@@ -0,0 +1,182 @@
+
+
+
+
+
+ no route
+
+ = Helpers::escapeHtml($matched[Presenter::PresenterKey] . ':' . ($matched[Presenter::ActionKey] ?? Presenter::DefaultAction) . (isset($matched[Presenter::SignalKey]) ? " {$matched[Presenter::SignalKey]}!" : '')) ?>
+
+
+
+
+
+
+
+
+
No routes defined.
+
+
+
+
+
+
Mask / Class
+
Defaults
+
Matched as
+
+
+
+
+
+
+
+
+
+
+
= ['yes' => '✓', 'may' => '≈', 'no' => '', 'oneway' => '⛔', 'error' => '❌'][$route->matched] ?>
+
+
=
+ $path === '' ? '' : '' . Helpers::escapeHtml($path) . ' ',
+ isset($route->mask) ? str_replace(['/', '-'], ['/', '-'], Helpers::escapeHtml($route->mask)) : str_replace('\\', '\\', Helpers::escapeHtml($route->class))
+ ?>
+
+
+ defaults as $key => $value): ?>
+ = Helpers::escapeHtml($key), ' = ', is_string($value) ? Helpers::escapeHtml($value) . ' ' : Dumper::toHtml($value, [Dumper::COLLAPSE => true, Dumper::LIVE => true]) ?>
+
+
+
+
params): ?>
+ params; ?>
+
+ = Helpers::escapeHtml($params['presenter'] . ':' . ($params[Presenter::ActionKey] ?? Presenter::DefaultAction)) ?>
+
+
+ $value): ?>
+ = Helpers::escapeHtml($key), ' = ', is_string($value) ? Helpers::escapeHtml($value) . ' ' : Dumper::toHtml($value, [Dumper::COLLAPSE => true, Dumper::LIVE => true]) ?>
+
+ error): ?>= Helpers::escapeHtml($route->error->getMessage()) ?>
+
+
+
+
+
+
diff --git a/vendor/nette/application/src/Bridges/ApplicationTracy/templates/RoutingPanel.tab.phtml b/vendor/nette/application/src/Bridges/ApplicationTracy/templates/RoutingPanel.tab.phtml
new file mode 100644
index 0000000..b61c174
--- /dev/null
+++ b/vendor/nette/application/src/Bridges/ApplicationTracy/templates/RoutingPanel.tab.phtml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ no route
+
diff --git a/vendor/nette/application/src/compatibility-intf.php b/vendor/nette/application/src/compatibility-intf.php
new file mode 100644
index 0000000..5bee25b
--- /dev/null
+++ b/vendor/nette/application/src/compatibility-intf.php
@@ -0,0 +1,88 @@
+ Occurs after the compiler is created */
+ public array $onCompile = [];
+
+ public array $defaultExtensions = [
+ 'application' => [Nette\Bridges\ApplicationDI\ApplicationExtension::class, ['%debugMode%', ['%appDir%'], '%tempDir%/cache/nette.application']],
+ 'assets' => Nette\Bridges\Assets\DIExtension::class,
+ 'cache' => [Nette\Bridges\CacheDI\CacheExtension::class, ['%tempDir%/cache']],
+ 'constants' => Extensions\ConstantsExtension::class,
+ 'database' => [Nette\Bridges\DatabaseDI\DatabaseExtension::class, ['%debugMode%']],
+ 'decorator' => Nette\DI\Extensions\DecoratorExtension::class,
+ 'di' => [Nette\DI\Extensions\DIExtension::class, ['%debugMode%']],
+ 'extensions' => Nette\DI\Extensions\ExtensionsExtension::class,
+ 'forms' => Nette\Bridges\FormsDI\FormsExtension::class,
+ 'http' => [Nette\Bridges\HttpDI\HttpExtension::class, ['%consoleMode%']],
+ 'inject' => Nette\DI\Extensions\InjectExtension::class,
+ 'latte' => [Nette\Bridges\ApplicationDI\LatteExtension::class, ['%tempDir%/cache/latte', '%debugMode%']],
+ 'mail' => Nette\Bridges\MailDI\MailExtension::class,
+ 'php' => Extensions\PhpExtension::class,
+ 'routing' => [Nette\Bridges\ApplicationDI\RoutingExtension::class, ['%debugMode%']],
+ 'search' => [Nette\DI\Extensions\SearchExtension::class, ['%tempDir%/cache/nette.search']],
+ 'security' => [Nette\Bridges\SecurityDI\SecurityExtension::class, ['%debugMode%']],
+ 'session' => [Nette\Bridges\HttpDI\SessionExtension::class, ['%debugMode%', '%consoleMode%']],
+ 'tracy' => [Tracy\Bridges\Nette\TracyExtension::class, ['%debugMode%', '%consoleMode%']],
+ ];
+
+ /** @var string[] of classes which shouldn't be autowired */
+ public array $autowireExcludedClasses = [
+ \ArrayAccess::class,
+ \Countable::class,
+ \IteratorAggregate::class,
+ \stdClass::class,
+ \Traversable::class,
+ ];
+
+ protected array $staticParameters;
+ protected array $dynamicParameters = [];
+ protected array $services = [];
+
+ /** @var array
*/
+ protected array $configs = [];
+
+
+ public function __construct()
+ {
+ $this->staticParameters = $this->getDefaultParameters();
+
+ if (class_exists(InstalledVersions::class) // back compatibility
+ && InstalledVersions::isInstalled('nette/caching')
+ && version_compare(InstalledVersions::getVersion('nette/caching'), '3.3.0', '<')
+ ) {
+ $this->defaultExtensions['cache'][1][0] = '%tempDir%';
+ }
+ }
+
+
+ /**
+ * Set parameter %debugMode%.
+ */
+ public function setDebugMode(bool|string|array $value): static
+ {
+ if (is_string($value) || is_array($value)) {
+ $value = static::detectDebugMode($value);
+ }
+
+ $this->staticParameters['debugMode'] = $value;
+ $this->staticParameters['productionMode'] = !$this->staticParameters['debugMode']; // compatibility
+ return $this;
+ }
+
+
+ public function isDebugMode(): bool
+ {
+ return $this->staticParameters['debugMode'];
+ }
+
+
+ /**
+ * Sets path to temporary directory.
+ */
+ public function setTempDirectory(string $path): static
+ {
+ $this->staticParameters['tempDir'] = $path;
+ return $this;
+ }
+
+
+ /**
+ * Sets the default timezone.
+ */
+ public function setTimeZone(string $timezone): static
+ {
+ date_default_timezone_set($timezone);
+ @ini_set('date.timezone', $timezone); // @ - function may be disabled
+ return $this;
+ }
+
+
+ /** @deprecated use addStaticParameters() */
+ public function addParameters(array $params): static
+ {
+ return $this->addStaticParameters($params);
+ }
+
+
+ /**
+ * Adds new static parameters.
+ */
+ public function addStaticParameters(array $params): static
+ {
+ $this->staticParameters = DI\Config\Helpers::merge($params, $this->staticParameters);
+ return $this;
+ }
+
+
+ /**
+ * Adds new dynamic parameters.
+ */
+ public function addDynamicParameters(array $params): static
+ {
+ $this->dynamicParameters = $params + $this->dynamicParameters;
+ return $this;
+ }
+
+
+ /**
+ * Add instances of services.
+ */
+ public function addServices(array $services): static
+ {
+ $this->services = $services + $this->services;
+ return $this;
+ }
+
+
+ protected function getDefaultParameters(): array
+ {
+ $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+ $last = end($trace);
+ $debugMode = static::detectDebugMode();
+ $loaderRc = class_exists(ClassLoader::class)
+ ? new \ReflectionClass(ClassLoader::class)
+ : null;
+ $rootDir = class_exists(InstalledVersions::class) && ($tmp = InstalledVersions::getRootPackage()['install_path'] ?? null)
+ ? rtrim(Nette\Utils\FileSystem::normalizePath($tmp), '\\/')
+ : null;
+ return [
+ 'appDir' => isset($trace[1]['file']) ? dirname($trace[1]['file']) : null,
+ 'wwwDir' => isset($last['file']) ? dirname($last['file']) : null,
+ 'vendorDir' => $loaderRc ? dirname($loaderRc->getFileName(), 2) : null,
+ 'rootDir' => $rootDir,
+ 'debugMode' => $debugMode,
+ 'productionMode' => !$debugMode,
+ 'consoleMode' => PHP_SAPI === 'cli',
+ ];
+ }
+
+
+ public function enableTracy(?string $logDirectory = null, ?string $email = null): void
+ {
+ if (!class_exists(Tracy\Debugger::class)) {
+ throw new Nette\NotSupportedException('Tracy not found, do you have `tracy/tracy` package installed?');
+ }
+
+ Tracy\Debugger::$strictMode = true;
+ Tracy\Debugger::enable(!$this->staticParameters['debugMode'], $logDirectory, $email);
+ Tracy\Bridges\Nette\Bridge::initialize();
+ if (class_exists(Latte\Bridges\Tracy\BlueScreenPanel::class)) {
+ Latte\Bridges\Tracy\BlueScreenPanel::initialize();
+ }
+ }
+
+
+ /** @deprecated use enableTracy() */
+ public function enableDebugger(?string $logDirectory = null, ?string $email = null): void
+ {
+ $this->enableTracy($logDirectory, $email);
+ }
+
+
+ /**
+ * @throws Nette\NotSupportedException if RobotLoader is not available
+ */
+ public function createRobotLoader(): Nette\Loaders\RobotLoader
+ {
+ if (!class_exists(Nette\Loaders\RobotLoader::class)) {
+ throw new Nette\NotSupportedException('RobotLoader not found, do you have `nette/robot-loader` package installed?');
+ }
+
+ $loader = new Nette\Loaders\RobotLoader;
+ $loader->setTempDirectory($this->getCacheDirectory() . '/nette.robotLoader');
+ $loader->setAutoRefresh($this->staticParameters['debugMode']);
+
+ if (isset($this->defaultExtensions['application'])) {
+ $this->defaultExtensions['application'][1][1] = null;
+ $this->defaultExtensions['application'][1][3] = $loader;
+ }
+
+ return $loader;
+ }
+
+
+ /**
+ * Adds configuration file.
+ */
+ public function addConfig(string|array $config): static
+ {
+ $this->configs[] = $config;
+ return $this;
+ }
+
+
+ /**
+ * Returns system DI container.
+ */
+ public function createContainer(bool $initialize = true): DI\Container
+ {
+ $class = $this->loadContainer();
+ $container = new $class($this->dynamicParameters);
+ foreach ($this->services as $name => $service) {
+ $container->addService($name, $service);
+ }
+
+ if ($initialize) {
+ $container->initialize();
+ }
+
+ return $container;
+ }
+
+
+ /**
+ * Loads system DI container class and returns its name.
+ */
+ public function loadContainer(): string
+ {
+ $loader = new DI\ContainerLoader(
+ $this->getCacheDirectory() . '/nette.configurator',
+ $this->staticParameters['debugMode'],
+ );
+ return $loader->load(
+ [$this, 'generateContainer'],
+ $this->generateContainerKey(),
+ );
+ }
+
+
+ /**
+ * @internal
+ */
+ public function generateContainer(DI\Compiler $compiler): void
+ {
+ $loader = $this->createLoader();
+ $loader->setParameters($this->staticParameters);
+
+ foreach ($this->configs as $config) {
+ if (is_string($config)) {
+ $compiler->loadConfig($config, $loader);
+ } else {
+ $compiler->addConfig($config);
+ }
+ }
+
+ $compiler->addConfig(['parameters' => DI\Helpers::escape($this->staticParameters)]);
+ $compiler->setDynamicParameterNames(array_keys($this->dynamicParameters));
+
+ $builder = $compiler->getContainerBuilder();
+ $builder->addExcludedClasses($this->autowireExcludedClasses);
+
+ foreach ($this->defaultExtensions as $name => $extension) {
+ [$class, $args] = is_string($extension)
+ ? [$extension, []]
+ : $extension;
+ if (class_exists($class)) {
+ $args = DI\Helpers::expand($args, $this->staticParameters);
+ $compiler->addExtension($name, (new \ReflectionClass($class))->newInstanceArgs($args));
+ }
+ }
+
+ Nette\Utils\Arrays::invoke($this->onCompile, $this, $compiler);
+ }
+
+
+ protected function createLoader(): DI\Config\Loader
+ {
+ return new DI\Config\Loader;
+ }
+
+
+ protected function generateContainerKey(): array
+ {
+ return [
+ $this->staticParameters,
+ array_keys($this->dynamicParameters),
+ $this->configs,
+ PHP_VERSION_ID - PHP_RELEASE_VERSION, // minor PHP version
+ class_exists(ClassLoader::class) // composer update
+ ? filemtime((new \ReflectionClass(ClassLoader::class))->getFilename())
+ : null,
+ ];
+ }
+
+
+ protected function getCacheDirectory(): string
+ {
+ if (empty($this->staticParameters['tempDir'])) {
+ throw new Nette\InvalidStateException('Set path to temporary directory using setTempDirectory().');
+ }
+
+ $dir = $this->staticParameters['tempDir'] . '/cache';
+ Nette\Utils\FileSystem::createDir($dir);
+ return $dir;
+ }
+
+
+ /**
+ * Detects debug mode by IP addresses or computer names whitelist detection.
+ */
+ public static function detectDebugMode(string|array|null $list = null): bool
+ {
+ $addr = $_SERVER['REMOTE_ADDR'] ?? php_uname('n');
+ $secret = is_string($_COOKIE[self::CookieSecret] ?? null)
+ ? $_COOKIE[self::CookieSecret]
+ : null;
+ $list = is_string($list)
+ ? preg_split('#[,\s]+#', $list)
+ : (array) $list;
+ if (!isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !isset($_SERVER['HTTP_FORWARDED'])) {
+ $list[] = '127.0.0.1';
+ $list[] = '::1';
+ }
+
+ return in_array($addr, $list, strict: true) || in_array("$secret@$addr", $list, strict: true);
+ }
+}
+
+
+class_exists(Nette\Configurator::class);
diff --git a/vendor/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php b/vendor/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php
new file mode 100644
index 0000000..502cb06
--- /dev/null
+++ b/vendor/nette/bootstrap/src/Bootstrap/Extensions/ConstantsExtension.php
@@ -0,0 +1,36 @@
+dynamic(),
+ Expect::string(),
+ );
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ foreach ($this->getConfig() as $name => $value) {
+ $this->initialization->addBody('define(?, ?);', [$name, $value]);
+ }
+ }
+}
diff --git a/vendor/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.php b/vendor/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.php
new file mode 100644
index 0000000..b6bb2f8
--- /dev/null
+++ b/vendor/nette/bootstrap/src/Bootstrap/Extensions/PhpExtension.php
@@ -0,0 +1,42 @@
+dynamic(),
+ Expect::string(),
+ );
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ foreach ($this->getConfig() as $name => $value) {
+ if (!function_exists('ini_set')) {
+ throw new Nette\NotSupportedException('Required function ini_set() is disabled.');
+ }
+
+ if ($value !== null) {
+ $this->initialization->addBody('ini_set(?, (string) (?));', [$name, $value]);
+ }
+ }
+ }
+}
diff --git a/vendor/nette/bootstrap/src/Configurator.php b/vendor/nette/bootstrap/src/Configurator.php
new file mode 100644
index 0000000..6a49d9d
--- /dev/null
+++ b/vendor/nette/bootstrap/src/Configurator.php
@@ -0,0 +1,19 @@
+=3.0.0 <3.0.12"
+ },
+ "suggest": {
+ "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal"
+ },
+ "autoload": {
+ "classmap": ["src/"]
+ },
+ "minimum-stability": "dev",
+ "scripts": {
+ "phpstan": "phpstan analyse",
+ "tester": "tester tests -s"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ }
+}
diff --git a/vendor/nette/caching/license.md b/vendor/nette/caching/license.md
new file mode 100644
index 0000000..cf741bd
--- /dev/null
+++ b/vendor/nette/caching/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/nette/caching/readme.md b/vendor/nette/caching/readme.md
new file mode 100644
index 0000000..77a0953
--- /dev/null
+++ b/vendor/nette/caching/readme.md
@@ -0,0 +1,398 @@
+Nette Caching
+=============
+
+[](https://packagist.org/packages/nette/caching)
+[](https://github.com/nette/caching/actions)
+[](https://coveralls.io/github/nette/caching?branch=master)
+[](https://github.com/nette/caching/releases)
+[](https://github.com/nette/caching/blob/master/license.md)
+
+
+Introduction
+============
+
+Cache accelerates your application by storing data - once hardly retrieved - for future use.
+
+Documentation can be found on the [website](https://doc.nette.org/caching).
+
+
+[Support Me](https://github.com/sponsors/dg)
+--------------------------------------------
+
+Do you like Nette Caching? Are you looking forward to the new features?
+
+[](https://github.com/sponsors/dg)
+
+Thank you!
+
+
+Installation
+------------
+
+```
+composer require nette/caching
+```
+
+It requires PHP version 8.0 and supports PHP up to 8.4.
+
+
+Basic Usage
+===========
+
+The center of work with the cache is the object [Nette\Caching\Cache](https://api.nette.org/3.0/Nette/Caching/Cache.html). We create its instance and pass the so-called storage to the constructor as a parameter. Which is an object representing the place where the data will be physically stored (database, Memcached, files on disk, ...). You will find out all the essentials in [section Storages](#Storages).
+
+For the following examples, suppose we have an alias `Cache` and a storage in the variable `$storage`.
+
+```php
+use Nette\Caching\Cache;
+
+$storage // instance of Nette\Caching\IStorage
+```
+
+The cache is actually a *key–value store*, so we read and write data under keys just like associative arrays. Applications consist of a number of independent parts, and if they all used one storage (for idea: one directory on a disk), sooner or later there would be a key collision. The Nette Framework solves the problem by dividing the entire space into namespaces (subdirectories). Each part of the program then uses its own space with a unique name and no collisions can occur.
+
+The name of the space is specified as the second parameter of the constructor of the Cache class:
+
+```php
+$cache = new Cache($storage, 'Full Html Pages');
+```
+
+We can now use object `$cache` to read and write from the cache. The method `load()` is used for both. The first argument is the key and the second is the PHP callback, which is called when the key is not found in the cache. The callback generates a value, returns it and caches it:
+
+```php
+$value = $cache->load($key, function () use ($key) {
+ $computedValue = ...; // heavy computations
+ return $computedValue;
+});
+```
+
+If the second parameter is not specified `$value = $cache->load($key)`, the `null` is returned if the item is not in the cache.
+
+The great thing is that any serializable structures can be cached, not only strings. And the same applies for keys.
+
+The item is cleared from the cache using method `remove()`:
+
+```php
+$cache->remove($key);
+```
+
+You can also cache an item using method `$cache->save($key, $value, array $dependencies = [])`. However, the above method using `load()` is preferred.
+
+
+
+
+Memoization
+===========
+
+Memoization means caching the result of a function or method so you can use it next time instead of calculating the same thing again and again.
+
+Methods and functions can be called memoized using `call(callable $callback, ...$args)`:
+
+```php
+$result = $cache->call('gethostbyaddr', $ip);
+```
+
+The function `gethostbyaddr()` is called only once for each parameter `$ip` and the next time the value from the cache will be returned.
+
+It is also possible to create a memoized wrapper for a method or function that can be called later:
+
+```php
+function factorial($num)
+{
+ return ...;
+}
+
+$memoizedFactorial = $cache->wrap('factorial');
+
+$result = $memoizedFactorial(5); // counts it
+$result = $memoizedFactorial(5); // returns it from cache
+```
+
+
+Expiration & Invalidation
+=========================
+
+With caching, it is necessary to address the question that some of the previously saved data will become invalid over time. Nette Framework provides a mechanism, how to limit the validity of data and how to delete them in a controlled way ("to invalidate them", using the framework's terminology).
+
+The validity of the data is set at the time of saving using the third parameter of the method `save()`, eg:
+
+```php
+$cache->save($key, $value, [
+ Cache::Expire => '20 minutes',
+]);
+```
+
+Or using the `$dependencies` parameter passed by reference to the callback in the `load()` method, eg:
+
+```php
+$value = $cache->load($key, function (&$dependencies) {
+ $dependencies[Cache::Expire] = '20 minutes';
+ return ...;
+]);
+```
+
+Or using 3rd parameter in the `load()` method, eg:
+
+```php
+$value = $cache->load($key, function () {
+ return ...;
+], [Cache::Expire => '20 minutes']);
+```
+
+In the following examples, we will assume the second variant and thus the existence of a variable `$dependencies`.
+
+
+Expiration
+----------
+
+The simplest exiration is the time limit. Here's how to cache data valid for 20 minutes:
+
+```php
+// it also accepts the number of seconds or the UNIX timestamp
+$dependencies[Cache::Expire] = '20 minutes';
+```
+
+If we want to extend the validity period with each reading, it can be achieved this way, but beware, this will increase the cache overhead:
+
+```php
+$dependencies[Cache::Sliding] = true;
+```
+
+The handy option is the ability to let the data expire when a particular file is changed or one of several files. This can be used, for example, for caching data resulting from procession these files. Use absolute paths.
+
+```php
+$dependencies[Cache::Files] = '/path/to/data.yaml';
+// nebo
+$dependencies[Cache::Files] = ['/path/to/data1.yaml', '/path/to/data2.yaml'];
+```
+
+We can let an item in the cache expired when another item (or one of several others) expires. This can be used when we cache the entire HTML page and fragments of it under other keys. Once the snippet changes, the entire page becomes invalid. If we have fragments stored under keys such as `frag1` and `frag2`, we will use:
+
+```php
+$dependencies[Cache::Items] = ['frag1', 'frag2'];
+```
+
+Expiration can also be controlled using custom functions or static methods, which always decide when reading whether the item is still valid. For example, we can let the item expire whenever the PHP version changes. We will create a function that compares the current version with the parameter, and when saving we will add an array in the form `[function name, ...arguments]` to the dependencies:
+
+```php
+function checkPhpVersion($ver): bool
+{
+ return $ver === PHP_VERSION_ID;
+}
+
+$dependencies[Cache::Callbacks] = [
+ ['checkPhpVersion', PHP_VERSION_ID] // expire when checkPhpVersion(...) === false
+];
+```
+
+Of course, all criteria can be combined. The cache then expires when at least one criterion is not met.
+
+```php
+$dependencies[Cache::Expire] = '20 minutes';
+$dependencies[Cache::Files] = '/path/to/data.yaml';
+```
+
+
+
+Invalidation using Tags
+-----------------------
+
+Tags are a very useful invalidation tool. We can assign a list of tags, which are arbitrary strings, to each item stored in the cache. For example, suppose we have an HTML page with an article and comments, which we want to cache. So we specify tags when saving to cache:
+
+```php
+$dependencies[Cache::Tags] = ["article/$articleId", "comments/$articleId"];
+```
+
+Now, let's move to the administration. Here we have a form for article editing. Together with saving the article to a database, we call the `clean()` command, which will delete cached items by tag:
+
+```php
+$cache->clean([
+ Cache::Tags => ["article/$articleId"],
+]);
+```
+
+Likewise, in the place of adding a new comment (or editing a comment), we will not forget to invalidate the relevant tag:
+
+```php
+$cache->clean([
+ Cache::Tags => ["comments/$articleId"],
+]);
+```
+
+What have we achieved? That our HTML cache will be invalidated (deleted) whenever the article or comments change. When editing an article with ID = 10, the tag `article/10` is forced to be invalidated and the HTML page carrying the tag is deleted from the cache. The same happens when you insert a new comment under the relevant article.
+
+Tags require [Journal](#Journal).
+
+
+Invalidation by Priority
+------------------------
+
+We can set the priority for individual items in the cache, and it will be possible to delete them in a controlled way when, for example, the cache exceeds a certain size:
+
+```php
+$dependencies[Cache::Priority] = 50;
+```
+
+Delete all items with a priority equal to or less than 100:
+
+```php
+$cache->clean([
+ Cache::Priority => 100,
+]);
+```
+
+Priorities require so-called [Journal](#Journal).
+
+
+Clear Cache
+-----------
+
+The `Cache::All` parameter clears everything:
+
+```php
+$cache->clean([
+ Cache::All => true,
+]);
+```
+
+
+Bulk Reading
+============
+
+For bulk reading and writing to cache, the `bulkLoad()` method is used, where we pass an array of keys and obtain an array of values:
+
+```php
+$values = $cache->bulkLoad($keys);
+```
+
+Method `bulkLoad()` works similarly to `load()` with the second callback parameter, to which the key of the generated item is passed:
+
+```php
+$values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
+ $computedValue = ...; // heavy computations
+ return $computedValue;
+});
+```
+
+
+Output Caching
+==============
+
+The output can be captured and cached very elegantly:
+
+```php
+if ($capture = $cache->start($key)) {
+
+ echo ... // printing some data
+
+ $capture->end(); // save the output to the cache
+}
+```
+
+In case that the output is already present in the cache, the `start()` method prints it and returns `null`, so the condition will not be executed. Otherwise, it starts to buffer the output and returns the `$capture` object using which we finally save the data to the cache.
+
+
+Caching in Latte
+================
+
+Caching in templates [Latte](https://latte.nette.org) is very easy, just wrap part of the template with tags `{cache}...{/cache}`. The cache is automatically invalidated when the source template changes (including any included templates within the `{cache}` tags). Tags `{cache}` can be nested, and when a nested block is invalidated (for example, by a tag), the parent block is also invalidated.
+
+In the tag it is possible to specify the keys to which the cache will be bound (here the variable `$id`) and set the expiration and [invalidation tags](#invalidation-using-tags).
+
+```html
+{cache $id, expire => '20 minutes', tags => [tag1, tag2]}
+ ...
+{/cache}
+```
+
+All parameters are optional, so you don't have to specify expiration, tags, or keys.
+
+The use of the cache can also be conditioned by `if` - the content will then be cached only if the condition is met:
+
+```html
+{cache $id, if => !$form->isSubmitted()}
+ {$form}
+{/cache}
+```
+
+
+Storages
+========
+
+A storage is an object that represents where data is physically stored. We can use a database, a Memcached server, or the most available storage, which are files on disk.
+
+Storage | Description
+--------|----------------------
+FileStorage | default storage with saving to files on disk
+MemcachedStorage | uses the `Memcached` server
+MemoryStorage | data are temporarily in memory
+SQLiteStorage | data is stored in SQLite database
+DevNullStorage | data aren't stored - for testing purposes
+
+
+FileStorage
+-----------
+
+Writes the cache to files on disk. The storage `Nette\Caching\Storages\FileStorage` is very well optimized for performance and above all ensures full atomicity of operations. What does it mean? That when using the cache, it cannot happen that we read a file that has not yet been completely written by another thread, or that someone would delete it "under your hands". The use of the cache is therefore completely safe.
+
+This storage also has an important built-in feature that prevents an extreme increase in CPU usage when the cache is cleared or cold (ie not created). This is [cache stampede](https://en.wikipedia.org/wiki/Cache_stampede) prevention.
+It happens that at one moment there are several concurrent requests that want the same thing from the cache (eg the result of an expensive SQL query) and because it is not cached, all processes start executing the same SQL query.
+The processor load is multiplied and it can even happen that no thread can respond within the time limit, the cache is not created and the application crashes.
+Fortunately, the cache in Nette works in such a way that when there are multiple concurrent requests for one item, it is generated only by the first thread, the others wait and then use the generated result.
+
+Example of creating a FileStorage:
+
+```php
+// the storage will be the directory '/path/to/temp' on the disk
+$storage = new Nette\Caching\Storages\FileStorage('/path/to/temp');
+```
+
+MemcachedStorage
+----------------
+
+The server [Memcached](https://memcached.org) is a high-performance distributed storage system whose adapter is `Nette\Caching\Storages\MemcachedStorage`.
+
+Requires PHP extension `memcached`.
+
+```php
+$storage = new Nette\Caching\Storages\MemcachedStorage('10.0.0.158');
+```
+
+MemoryStorage
+-------------
+
+`Nette\Caching\Storages\MemoryStorage` is a storage that stores data in a PHP array and is thus lost when the request is terminated.
+
+```php
+$storage = new Nette\Caching\Storages\MemoryStorage;
+```
+
+
+SQLiteStorage
+-------------
+
+The SQLite database and adapter `Nette\Caching\Storages\SQLiteStorage` offer a way to cache in a single file on disk. The configuration will specify the path to this file.
+
+Requires PHP extensions `pdo` and `pdo_sqlite`.
+
+```php
+$storage = new Nette\Caching\Storages\SQLiteStorage('/path/to/cache.sdb');
+```
+
+
+DevNullStorage
+--------------
+
+A special implementation of storage is `Nette\Caching\Storages\DevNullStorage`, which does not actually store data at all. It is therefore suitable for testing if we want to eliminate the effect of the cache.
+
+```php
+$storage = new Nette\Caching\Storages\DevNullStorage;
+```
+
+
+Journal
+=======
+
+Nette stores tags and priorities in a so-called journal. By default, SQLite and file `journal.s3db` are used for this, and **PHP extensions `pdo` and `pdo_sqlite` are required.**
+
+If you like Nette, **[please make a donation now](https://github.com/sponsors/dg)**. Thank you!
diff --git a/vendor/nette/caching/src/Bridges/CacheDI/CacheExtension.php b/vendor/nette/caching/src/Bridges/CacheDI/CacheExtension.php
new file mode 100644
index 0000000..da6b1f8
--- /dev/null
+++ b/vendor/nette/caching/src/Bridges/CacheDI/CacheExtension.php
@@ -0,0 +1,57 @@
+tempDir)) {
+ throw new Nette\InvalidArgumentException("Cache directory must be absolute, '$this->tempDir' given.");
+ }
+ FileSystem::createDir($this->tempDir);
+ if (!is_writable($this->tempDir)) {
+ throw new Nette\InvalidStateException("Make directory '$this->tempDir' writable.");
+ }
+
+ $builder = $this->getContainerBuilder();
+
+ if (extension_loaded('pdo_sqlite')) {
+ $builder->addDefinition($this->prefix('journal'))
+ ->setType(Nette\Caching\Storages\Journal::class)
+ ->setFactory(Nette\Caching\Storages\SQLiteJournal::class, [$this->tempDir . '/journal.s3db']);
+ }
+
+ $builder->addDefinition($this->prefix('storage'))
+ ->setType(Nette\Caching\Storage::class)
+ ->setFactory(Nette\Caching\Storages\FileStorage::class, [$this->tempDir]);
+
+ if ($this->name === 'cache') {
+ if (extension_loaded('pdo_sqlite')) {
+ $builder->addAlias('nette.cacheJournal', $this->prefix('journal'));
+ }
+
+ $builder->addAlias('cacheStorage', $this->prefix('storage'));
+ }
+ }
+}
diff --git a/vendor/nette/caching/src/Bridges/CacheLatte/CacheExtension.php b/vendor/nette/caching/src/Bridges/CacheLatte/CacheExtension.php
new file mode 100644
index 0000000..3d38a9d
--- /dev/null
+++ b/vendor/nette/caching/src/Bridges/CacheLatte/CacheExtension.php
@@ -0,0 +1,75 @@
+storage = $storage;
+ }
+
+
+ public function beforeCompile(Latte\Engine $engine): void
+ {
+ $this->used = false;
+ }
+
+
+ public function getTags(): array
+ {
+ return [
+ 'cache' => function (Tag $tag): \Generator {
+ $this->used = true;
+ return yield from Nodes\CacheNode::create($tag);
+ },
+ ];
+ }
+
+
+ public function getPasses(): array
+ {
+ return [
+ 'cacheInitialization' => function (TemplateNode $node): void {
+ if ($this->used) {
+ $node->head->append(new AuxiliaryNode(fn() => '$this->global->cache->initialize($this);'));
+ }
+ },
+ ];
+ }
+
+
+ public function getProviders(): array
+ {
+ return [
+ 'cache' => new Runtime($this->storage),
+ ];
+ }
+
+
+ public function getCacheKey(Latte\Engine $engine): array
+ {
+ return ['version' => 2];
+ }
+}
diff --git a/vendor/nette/caching/src/Bridges/CacheLatte/CacheMacro.php b/vendor/nette/caching/src/Bridges/CacheLatte/CacheMacro.php
new file mode 100644
index 0000000..d6aeb5d
--- /dev/null
+++ b/vendor/nette/caching/src/Bridges/CacheLatte/CacheMacro.php
@@ -0,0 +1,168 @@
+used = false;
+ }
+
+
+ /**
+ * Finishes template parsing.
+ * @return array(prolog, epilog)
+ */
+ public function finalize()
+ {
+ if ($this->used) {
+ return ['Nette\Bridges\CacheLatte\CacheMacro::initRuntime($this);'];
+ }
+ }
+
+
+ /**
+ * New node is found.
+ * @return bool
+ */
+ public function nodeOpened(Latte\MacroNode $node)
+ {
+ if ($node->modifiers) {
+ throw new Latte\CompileException('Modifiers are not allowed in ' . $node->getNotation());
+ }
+
+ $this->used = true;
+ $node->empty = false;
+ $node->openingCode = Latte\PhpWriter::using($node)
+ ->write(
+ 'global->cacheStorage, %var, $this->global->cacheStack, %node.array?)) /* line %var */ try { ?>',
+ Nette\Utils\Random::generate(),
+ $node->startLine,
+ );
+ }
+
+
+ /**
+ * Node is closed.
+ * @return void
+ */
+ public function nodeClosed(Latte\MacroNode $node)
+ {
+ $node->closingCode = Latte\PhpWriter::using($node)
+ ->write(
+ 'global->cacheStack, %node.array?) /* line %var */;
+ } catch (\Throwable $ʟ_e) {
+ Nette\Bridges\CacheLatte\CacheMacro::rollback($this->global->cacheStack); throw $ʟ_e;
+ } ?>',
+ $node->startLine,
+ );
+ }
+
+
+ /********************* run-time helpers ****************d*g**/
+
+
+ public static function initRuntime(Latte\Runtime\Template $template): void
+ {
+ if (!empty($template->global->cacheStack)) {
+ $file = (new \ReflectionClass($template))->getFileName();
+ if (@is_file($file)) { // @ - may trigger error
+ end($template->global->cacheStack)->dependencies[Cache::Files][] = $file;
+ }
+ }
+ }
+
+
+ /**
+ * Starts the output cache. Returns Nette\Caching\OutputHelper object if buffering was started.
+ */
+ public static function createCache(
+ Nette\Caching\Storage $cacheStorage,
+ string $key,
+ ?array &$parents,
+ ?array $args = null,
+ ): Nette\Caching\OutputHelper|\stdClass|null
+ {
+ if ($args) {
+ if (array_key_exists('if', $args) && !$args['if']) {
+ return $parents[] = new \stdClass;
+ }
+
+ $key = array_merge([$key], array_intersect_key($args, range(0, count($args))));
+ }
+
+ if ($parents) {
+ end($parents)->dependencies[Cache::Items][] = $key;
+ }
+
+ $cache = new Cache($cacheStorage, 'Nette.Templating.Cache');
+ if ($helper = $cache->capture($key)) {
+ $parents[] = $helper;
+ }
+
+ return $helper;
+ }
+
+
+ /**
+ * Ends the output cache.
+ * @param Nette\Caching\OutputHelper[] $parents
+ */
+ public static function endCache(array &$parents, ?array $args = null): void
+ {
+ $helper = array_pop($parents);
+ if (!$helper instanceof Nette\Caching\OutputHelper) {
+ return;
+ }
+
+ if (isset($args['dependencies'])) {
+ $args += $args['dependencies']();
+ }
+
+ if (isset($args['expire'])) {
+ $args['expiration'] = $args['expire']; // back compatibility
+ }
+
+ $helper->dependencies[Cache::Tags] = $args['tags'] ?? null;
+ $helper->dependencies[Cache::Expire] = $args['expiration'] ?? '+ 7 days';
+ $helper->end();
+ }
+
+
+ /**
+ * @param Nette\Caching\OutputHelper[] $parents
+ */
+ public static function rollback(array &$parents): void
+ {
+ $helper = array_pop($parents);
+ if ($helper instanceof Nette\Caching\OutputHelper) {
+ $helper->rollback();
+ }
+ }
+}
diff --git a/vendor/nette/caching/src/Bridges/CacheLatte/Nodes/CacheNode.php b/vendor/nette/caching/src/Bridges/CacheLatte/Nodes/CacheNode.php
new file mode 100644
index 0000000..5e41a7e
--- /dev/null
+++ b/vendor/nette/caching/src/Bridges/CacheLatte/Nodes/CacheNode.php
@@ -0,0 +1,70 @@
+ */
+ public static function create(Tag $tag): \Generator
+ {
+ $node = $tag->node = new static;
+ $node->args = $tag->parser->parseArguments();
+ [$node->content, $endTag] = yield;
+ $node->endLine = $endTag?->position;
+ return $node;
+ }
+
+
+ public function print(PrintContext $context): string
+ {
+ return $context->format(
+ <<<'XX'
+ if ($this->global->cache->createCache(%dump, %node?)) %line
+ try {
+ %node
+ $this->global->cache->end() %line;
+ } catch (\Throwable $ʟ_e) {
+ $this->global->cache->rollback();
+ throw $ʟ_e;
+ }
+
+
+ XX,
+ base64_encode(random_bytes(10)),
+ $this->args,
+ $this->position,
+ $this->content,
+ $this->endLine,
+ );
+ }
+
+
+ public function &getIterator(): \Generator
+ {
+ yield $this->args;
+ yield $this->content;
+ }
+}
diff --git a/vendor/nette/caching/src/Bridges/CacheLatte/Runtime.php b/vendor/nette/caching/src/Bridges/CacheLatte/Runtime.php
new file mode 100644
index 0000000..d054669
--- /dev/null
+++ b/vendor/nette/caching/src/Bridges/CacheLatte/Runtime.php
@@ -0,0 +1,98 @@
+ */
+ private array $stack = [];
+
+
+ public function __construct(
+ private Nette\Caching\Storage $storage,
+ ) {
+ }
+
+
+ public function initialize(Latte\Runtime\Template $template): void
+ {
+ if ($this->stack) {
+ $file = (new \ReflectionClass($template))->getFileName();
+ if (@is_file($file)) { // @ - may trigger error
+ end($this->stack)->dependencies[Cache::Files][] = $file;
+ }
+ }
+ }
+
+
+ /**
+ * Starts the output cache. Returns true if buffering was started.
+ */
+ public function createCache(string $key, ?array $args = null): bool
+ {
+ if ($args) {
+ if (array_key_exists('if', $args) && !$args['if']) {
+ $this->stack[] = new \stdClass;
+ return true;
+ }
+
+ $key = array_merge([$key], array_intersect_key($args, range(0, count($args))));
+ }
+
+ if ($this->stack) {
+ end($this->stack)->dependencies[Cache::Items][] = $key;
+ }
+
+ $cache = new Cache($this->storage, 'Nette.Templating.Cache');
+ if ($helper = $cache->capture($key)) {
+ $this->stack[] = $helper;
+
+ if (isset($args['dependencies'])) {
+ $args += $args['dependencies']();
+ }
+
+ $helper->dependencies[Cache::Tags] = $args['tags'] ?? null;
+ $helper->dependencies[Cache::Expire] = $args['expiration'] ?? $args['expire'] ?? '+ 7 days';
+ }
+
+ return (bool) $helper;
+ }
+
+
+ /**
+ * Ends the output cache.
+ */
+ public function end(): void
+ {
+ $helper = array_pop($this->stack);
+ if ($helper instanceof OutputHelper) {
+ $helper->end();
+ }
+ }
+
+
+ public function rollback(): void
+ {
+ $helper = array_pop($this->stack);
+ if ($helper instanceof OutputHelper) {
+ $helper->rollback();
+ }
+ }
+}
diff --git a/vendor/nette/caching/src/Bridges/Psr/PsrCacheAdapter.php b/vendor/nette/caching/src/Bridges/Psr/PsrCacheAdapter.php
new file mode 100644
index 0000000..e06ea06
--- /dev/null
+++ b/vendor/nette/caching/src/Bridges/Psr/PsrCacheAdapter.php
@@ -0,0 +1,116 @@
+storage->read($key) ?? $default;
+ }
+
+
+ public function set(string $key, mixed $value, null|int|DateInterval $ttl = null): bool
+ {
+ $dependencies = [];
+ if ($ttl !== null) {
+ $dependencies[Nette\Caching\Cache::Expire] = self::ttlToSeconds($ttl);
+ }
+
+ $this->storage->write($key, $value, $dependencies);
+
+ return true;
+ }
+
+
+ public function delete(string $key): bool
+ {
+ $this->storage->remove($key);
+ return true;
+ }
+
+
+ public function clear(): bool
+ {
+ $this->storage->clean([Nette\Caching\Cache::All => true]);
+ return true;
+ }
+
+
+ /**
+ * @return \Generator
+ */
+ public function getMultiple(iterable $keys, mixed $default = null): \Generator
+ {
+ foreach ($keys as $name) {
+ yield $name => $this->get($name, $default);
+ }
+ }
+
+
+ /**
+ * @param iterable $values
+ */
+ public function setMultiple(iterable $values, null|int|DateInterval $ttl = null): bool
+ {
+ $ttl = self::ttlToSeconds($ttl);
+
+ foreach ($values as $key => $value) {
+ $this->set((string) $key, $value, $ttl);
+ }
+
+ return true;
+ }
+
+
+ public function deleteMultiple(iterable $keys): bool
+ {
+ foreach ($keys as $value) {
+ $this->delete($value);
+ }
+
+ return true;
+ }
+
+
+ public function has(string $key): bool
+ {
+ return $this->storage->read($key) !== null;
+ }
+
+
+ private static function ttlToSeconds(null|int|DateInterval $ttl = null): ?int
+ {
+ if ($ttl instanceof DateInterval) {
+ return self::dateIntervalToSeconds($ttl);
+ }
+
+ return $ttl;
+ }
+
+
+ private static function dateIntervalToSeconds(DateInterval $dateInterval): int
+ {
+ $now = new \DateTimeImmutable;
+ $expiresAt = $now->add($dateInterval);
+ return $expiresAt->getTimestamp() - $now->getTimestamp();
+ }
+}
diff --git a/vendor/nette/caching/src/Caching/BulkReader.php b/vendor/nette/caching/src/Caching/BulkReader.php
new file mode 100644
index 0000000..78dc174
--- /dev/null
+++ b/vendor/nette/caching/src/Caching/BulkReader.php
@@ -0,0 +1,26 @@
+ value pairs, missing items are omitted
+ */
+ function bulkRead(array $keys): array;
+}
+
+
+class_exists(IBulkReader::class);
diff --git a/vendor/nette/caching/src/Caching/BulkWriter.php b/vendor/nette/caching/src/Caching/BulkWriter.php
new file mode 100644
index 0000000..38d88fb
--- /dev/null
+++ b/vendor/nette/caching/src/Caching/BulkWriter.php
@@ -0,0 +1,28 @@
+storage = $storage;
+ $this->namespace = $namespace . self::NamespaceSeparator;
+ }
+
+
+ /**
+ * Returns cache storage.
+ */
+ final public function getStorage(): Storage
+ {
+ return $this->storage;
+ }
+
+
+ /**
+ * Returns cache namespace.
+ */
+ final public function getNamespace(): string
+ {
+ return substr($this->namespace, 0, -1);
+ }
+
+
+ /**
+ * Returns new nested cache object.
+ */
+ public function derive(string $namespace): static
+ {
+ return new static($this->storage, $this->namespace . $namespace);
+ }
+
+
+ /**
+ * Reads the specified item from the cache or generate it.
+ */
+ public function load(mixed $key, ?callable $generator = null, ?array $dependencies = null): mixed
+ {
+ $storageKey = $this->generateKey($key);
+ $data = $this->storage->read($storageKey);
+ if ($data === null && $generator) {
+ $this->storage->lock($storageKey);
+ try {
+ $data = $generator(...[&$dependencies]);
+ } catch (\Throwable $e) {
+ $this->storage->remove($storageKey);
+ throw $e;
+ }
+
+ $this->save($key, $data, $dependencies);
+ }
+
+ return $data;
+ }
+
+
+ /**
+ * Reads multiple items from the cache.
+ */
+ public function bulkLoad(array $keys, ?callable $generator = null): array
+ {
+ if (count($keys) === 0) {
+ return [];
+ }
+
+ foreach ($keys as $key) {
+ if (!is_scalar($key)) {
+ throw new Nette\InvalidArgumentException('Only scalar keys are allowed in bulkLoad()');
+ }
+ }
+
+ $result = [];
+ if (!$this->storage instanceof BulkReader) {
+ foreach ($keys as $key) {
+ $result[$key] = $this->load(
+ $key,
+ $generator
+ ? fn(&$dependencies) => $generator(...[$key, &$dependencies])
+ : null,
+ );
+ }
+
+ return $result;
+ }
+
+ $storageKeys = array_map([$this, 'generateKey'], $keys);
+ $cacheData = $this->storage->bulkRead($storageKeys);
+ foreach ($keys as $i => $key) {
+ $storageKey = $storageKeys[$i];
+ if (isset($cacheData[$storageKey])) {
+ $result[$key] = $cacheData[$storageKey];
+ } elseif ($generator) {
+ $result[$key] = $this->load($key, fn(&$dependencies) => $generator(...[$key, &$dependencies]));
+ } else {
+ $result[$key] = null;
+ }
+ }
+
+ return $result;
+ }
+
+
+ /**
+ * Writes item into the cache.
+ * Dependencies are:
+ * - Cache::Priority => (int) priority
+ * - Cache::Expire => (timestamp) expiration, infinite if null
+ * - Cache::Sliding => (bool) use sliding expiration?
+ * - Cache::Tags => (array) tags
+ * - Cache::Files => (array|string) file names
+ * - Cache::Items => (array|string) cache items
+ * - Cache::Constants => (array|string) cache items
+ * @return mixed value itself
+ * @throws Nette\InvalidArgumentException
+ */
+ public function save(mixed $key, mixed $data, ?array $dependencies = null): mixed
+ {
+ $key = $this->generateKey($key);
+
+ if ($data instanceof \Closure) {
+ $this->storage->lock($key);
+ try {
+ $data = $data(...[&$dependencies]);
+ } catch (\Throwable $e) {
+ $this->storage->remove($key);
+ throw $e;
+ }
+ }
+
+ if ($data === null) {
+ $this->storage->remove($key);
+ return null;
+ } else {
+ $dependencies = $this->completeDependencies($dependencies);
+ if (isset($dependencies[self::Expire]) && $dependencies[self::Expire] <= 0) {
+ $this->storage->remove($key);
+ } else {
+ $this->storage->write($key, $data, $dependencies);
+ }
+
+ return $data;
+ }
+ }
+
+
+ /**
+ * Writes multiple items into cache
+ */
+ public function bulkSave(array $items, ?array $dependencies = null): void
+ {
+ $write = $remove = [];
+
+ if (!$this->storage instanceof BulkWriter) {
+ foreach ($items as $key => $data) {
+ $this->save($key, $data, $dependencies);
+ }
+ return;
+ }
+
+ $dependencies = $this->completeDependencies($dependencies);
+ if (isset($dependencies[self::Expire]) && $dependencies[self::Expire] <= 0) {
+ $this->storage->bulkRemove(array_map(fn($key) => $this->generateKey($key), array_keys($items)));
+ return;
+ }
+
+ foreach ($items as $key => $data) {
+ $key = $this->generateKey($key);
+ if ($data === null) {
+ $remove[] = $key;
+ } else {
+ $write[$key] = $data;
+ }
+ }
+
+ if ($remove) {
+ $this->storage->bulkRemove($remove);
+ }
+
+ if ($write) {
+ $this->storage->bulkWrite($write, $dependencies);
+ }
+ }
+
+
+ private function completeDependencies(?array $dp): array
+ {
+ // convert expire into relative amount of seconds
+ if (isset($dp[self::Expire])) {
+ $dp[self::Expire] = Nette\Utils\DateTime::from($dp[self::Expire])->format('U') - time();
+ }
+
+ // make list from TAGS
+ if (isset($dp[self::Tags])) {
+ $dp[self::Tags] = array_values((array) $dp[self::Tags]);
+ }
+
+ // make list from NAMESPACES
+ if (isset($dp[self::Namespaces])) {
+ $dp[self::Namespaces] = array_values((array) $dp[self::Namespaces]);
+ }
+
+ // convert FILES into CALLBACKS
+ if (isset($dp[self::Files])) {
+ foreach (array_unique((array) $dp[self::Files]) as $item) {
+ $dp[self::Callbacks][] = [[self::class, 'checkFile'], $item, @filemtime($item) ?: null]; // @ - stat may fail
+ }
+
+ unset($dp[self::Files]);
+ }
+
+ // add namespaces to items
+ if (isset($dp[self::Items])) {
+ $dp[self::Items] = array_unique(array_map([$this, 'generateKey'], (array) $dp[self::Items]));
+ }
+
+ // convert CONSTS into CALLBACKS
+ if (isset($dp[self::Constants])) {
+ foreach (array_unique((array) $dp[self::Constants]) as $item) {
+ $dp[self::Callbacks][] = [[self::class, 'checkConst'], $item, constant($item)];
+ }
+
+ unset($dp[self::Constants]);
+ }
+
+ if (!is_array($dp)) {
+ $dp = [];
+ }
+
+ return $dp;
+ }
+
+
+ /**
+ * Removes item from the cache.
+ */
+ public function remove(mixed $key): void
+ {
+ $this->save($key, null);
+ }
+
+
+ /**
+ * Removes items from the cache by conditions.
+ * Conditions are:
+ * - Cache::Priority => (int) priority
+ * - Cache::Tags => (array) tags
+ * - Cache::All => true
+ */
+ public function clean(?array $conditions = null): void
+ {
+ $conditions = (array) $conditions;
+ if (isset($conditions[self::Tags])) {
+ $conditions[self::Tags] = array_values((array) $conditions[self::Tags]);
+ }
+
+ $this->storage->clean($conditions);
+ }
+
+
+ /**
+ * Caches results of function/method calls.
+ */
+ public function call(callable $function): mixed
+ {
+ $key = func_get_args();
+ if (is_array($function) && is_object($function[0])) {
+ $key[0][0] = get_class($function[0]);
+ }
+
+ return $this->load($key, fn() => $function(...array_slice($key, 1)));
+ }
+
+
+ /**
+ * Caches results of function/method calls.
+ */
+ public function wrap(callable $function, ?array $dependencies = null): \Closure
+ {
+ return function () use ($function, $dependencies) {
+ $key = [$function, $args = func_get_args()];
+ if (is_array($function) && is_object($function[0])) {
+ $key[0][0] = get_class($function[0]);
+ }
+
+ return $this->load($key, function (&$deps) use ($function, $args, $dependencies) {
+ $deps = $dependencies;
+ return $function(...$args);
+ });
+ };
+ }
+
+
+ /**
+ * Starts the output cache.
+ */
+ public function capture(mixed $key): ?OutputHelper
+ {
+ $data = $this->load($key);
+ if ($data === null) {
+ return new OutputHelper($this, $key);
+ }
+
+ echo $data;
+ return null;
+ }
+
+
+ /**
+ * @deprecated use capture()
+ */
+ public function start($key): ?OutputHelper
+ {
+ return $this->capture($key);
+ }
+
+
+ /**
+ * Generates internal cache key.
+ */
+ protected function generateKey($key): string
+ {
+ return $this->namespace . md5(is_scalar($key) ? (string) $key : serialize($key));
+ }
+
+
+ /********************* dependency checkers ****************d*g**/
+
+
+ /**
+ * Checks CALLBACKS dependencies.
+ */
+ public static function checkCallbacks(array $callbacks): bool
+ {
+ foreach ($callbacks as $callback) {
+ if (!array_shift($callback)(...$callback)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Checks CONSTS dependency.
+ */
+ private static function checkConst(string $const, $value): bool
+ {
+ return defined($const) && constant($const) === $value;
+ }
+
+
+ /**
+ * Checks FILES dependency.
+ */
+ private static function checkFile(string $file, ?int $time): bool
+ {
+ return @filemtime($file) == $time; // @ - stat may fail
+ }
+}
diff --git a/vendor/nette/caching/src/Caching/OutputHelper.php b/vendor/nette/caching/src/Caching/OutputHelper.php
new file mode 100644
index 0000000..2256a9b
--- /dev/null
+++ b/vendor/nette/caching/src/Caching/OutputHelper.php
@@ -0,0 +1,55 @@
+cache = $cache;
+ $this->key = $key;
+ ob_start();
+ }
+
+
+ /**
+ * Stops and saves the cache.
+ */
+ public function end(array $dependencies = []): void
+ {
+ if ($this->cache === null) {
+ throw new Nette\InvalidStateException('Output cache has already been saved.');
+ }
+
+ $this->cache->save($this->key, ob_get_flush(), $dependencies + $this->dependencies);
+ $this->cache = null;
+ }
+
+
+ /**
+ * Stops and throws away the output.
+ */
+ public function rollback(): void
+ {
+ ob_end_flush();
+ $this->cache = null;
+ }
+}
diff --git a/vendor/nette/caching/src/Caching/Storage.php b/vendor/nette/caching/src/Caching/Storage.php
new file mode 100644
index 0000000..e9565d8
--- /dev/null
+++ b/vendor/nette/caching/src/Caching/Storage.php
@@ -0,0 +1,46 @@
+ timestamp)
+ MetaCallbacks = 'callbacks'; // array of callbacks (function, args)
+
+ /** additional cache structure */
+ private const
+ File = 'file',
+ Handle = 'handle';
+
+ /** probability that the clean() routine is started */
+ public static float $gcProbability = 0.001;
+
+ private string $dir;
+ private ?Journal $journal;
+ private array $locks;
+
+
+ public function __construct(string $dir, ?Journal $journal = null)
+ {
+ if (!is_dir($dir) || !Nette\Utils\FileSystem::isAbsolute($dir)) {
+ throw new Nette\DirectoryNotFoundException("Directory '$dir' not found or is not absolute.");
+ }
+
+ $this->dir = $dir;
+ $this->journal = $journal;
+
+ if (mt_rand() / mt_getrandmax() < static::$gcProbability) {
+ $this->clean([]);
+ }
+ }
+
+
+ public function read(string $key): mixed
+ {
+ $meta = $this->readMetaAndLock($this->getCacheFile($key), LOCK_SH);
+ return $meta && $this->verify($meta)
+ ? $this->readData($meta) // calls fclose()
+ : null;
+ }
+
+
+ /**
+ * Verifies dependencies.
+ */
+ private function verify(array $meta): bool
+ {
+ do {
+ if (!empty($meta[self::MetaDelta])) {
+ // meta[file] was added by readMetaAndLock()
+ if (filemtime($meta[self::File]) + $meta[self::MetaDelta] < time()) {
+ break;
+ }
+
+ touch($meta[self::File]);
+
+ } elseif (!empty($meta[self::MetaExpire]) && $meta[self::MetaExpire] < time()) {
+ break;
+ }
+
+ if (!empty($meta[self::MetaCallbacks]) && !Cache::checkCallbacks($meta[self::MetaCallbacks])) {
+ break;
+ }
+
+ if (!empty($meta[self::MetaItems])) {
+ foreach ($meta[self::MetaItems] as $depFile => $time) {
+ $m = $this->readMetaAndLock($depFile, LOCK_SH);
+ if (($m[self::MetaTime] ?? null) !== $time || ($m && !$this->verify($m))) {
+ break 2;
+ }
+ }
+ }
+
+ return true;
+ } while (false);
+
+ $this->delete($meta[self::File], $meta[self::Handle]); // meta[handle] & meta[file] was added by readMetaAndLock()
+ return false;
+ }
+
+
+ public function lock(string $key): void
+ {
+ $cacheFile = $this->getCacheFile($key);
+ if (!is_dir($dir = dirname($cacheFile))) {
+ @mkdir($dir); // @ - directory may already exist
+ }
+
+ $handle = fopen($cacheFile, 'c+b');
+ if (!$handle) {
+ return;
+ }
+
+ $this->locks[$key] = $handle;
+ flock($handle, LOCK_EX);
+ }
+
+
+ public function write(string $key, $data, array $dp): void
+ {
+ $meta = [
+ self::MetaTime => microtime(),
+ ];
+
+ if (isset($dp[Cache::Expire])) {
+ if (empty($dp[Cache::Sliding])) {
+ $meta[self::MetaExpire] = $dp[Cache::Expire] + time(); // absolute time
+ } else {
+ $meta[self::MetaDelta] = (int) $dp[Cache::Expire]; // sliding time
+ }
+ }
+
+ if (isset($dp[Cache::Items])) {
+ foreach ($dp[Cache::Items] as $item) {
+ $depFile = $this->getCacheFile($item);
+ $m = $this->readMetaAndLock($depFile, LOCK_SH);
+ $meta[self::MetaItems][$depFile] = $m[self::MetaTime] ?? null;
+ unset($m);
+ }
+ }
+
+ if (isset($dp[Cache::Callbacks])) {
+ $meta[self::MetaCallbacks] = $dp[Cache::Callbacks];
+ }
+
+ if (!isset($this->locks[$key])) {
+ $this->lock($key);
+ if (!isset($this->locks[$key])) {
+ return;
+ }
+ }
+
+ $handle = $this->locks[$key];
+ unset($this->locks[$key]);
+
+ $cacheFile = $this->getCacheFile($key);
+
+ if (isset($dp[Cache::Tags]) || isset($dp[Cache::Priority])) {
+ if (!$this->journal) {
+ throw new Nette\InvalidStateException('CacheJournal has not been provided.');
+ }
+
+ $this->journal->write($cacheFile, $dp);
+ }
+
+ ftruncate($handle, 0);
+
+ if (!is_string($data)) {
+ $data = serialize($data);
+ $meta[self::MetaSerialized] = true;
+ }
+
+ $head = serialize($meta);
+ $head = str_pad((string) strlen($head), 6, '0', STR_PAD_LEFT) . $head;
+ $headLen = strlen($head);
+
+ do {
+ if (fwrite($handle, str_repeat("\x00", $headLen)) !== $headLen) {
+ break;
+ }
+
+ if (fwrite($handle, $data) !== strlen($data)) {
+ break;
+ }
+
+ fseek($handle, 0);
+ if (fwrite($handle, $head) !== $headLen) {
+ break;
+ }
+
+ flock($handle, LOCK_UN);
+ fclose($handle);
+ return;
+ } while (false);
+
+ $this->delete($cacheFile, $handle);
+ }
+
+
+ public function remove(string $key): void
+ {
+ unset($this->locks[$key]);
+ $this->delete($this->getCacheFile($key));
+ }
+
+
+ public function clean(array $conditions): void
+ {
+ $all = !empty($conditions[Cache::All]);
+ $collector = empty($conditions);
+ $namespaces = $conditions[Cache::Namespaces] ?? null;
+
+ // cleaning using file iterator
+ if ($all || $collector) {
+ $now = time();
+ foreach (Nette\Utils\Finder::find('_*')->from($this->dir)->childFirst() as $entry) {
+ $path = (string) $entry;
+ if ($entry->isDir()) { // collector: remove empty dirs
+ @rmdir($path); // @ - removing dirs is not necessary
+ continue;
+ }
+
+ if ($all) {
+ $this->delete($path);
+
+ } else { // collector
+ $meta = $this->readMetaAndLock($path, LOCK_SH);
+ if (!$meta) {
+ continue;
+ }
+
+ if ((!empty($meta[self::MetaDelta]) && filemtime($meta[self::File]) + $meta[self::MetaDelta] < $now)
+ || (!empty($meta[self::MetaExpire]) && $meta[self::MetaExpire] < $now)
+ ) {
+ $this->delete($path, $meta[self::Handle]);
+ continue;
+ }
+
+ flock($meta[self::Handle], LOCK_UN);
+ fclose($meta[self::Handle]);
+ }
+ }
+
+ if ($this->journal) {
+ $this->journal->clean($conditions);
+ }
+
+ return;
+
+ } elseif ($namespaces) {
+ foreach ($namespaces as $namespace) {
+ $dir = $this->dir . '/_' . urlencode($namespace);
+ if (!is_dir($dir)) {
+ continue;
+ }
+
+ foreach (Nette\Utils\Finder::findFiles('_*')->in($dir) as $entry) {
+ $this->delete((string) $entry);
+ }
+
+ @rmdir($dir); // may already contain new files
+ }
+ }
+
+ // cleaning using journal
+ if ($this->journal) {
+ foreach ($this->journal->clean($conditions) as $file) {
+ $this->delete($file);
+ }
+ }
+ }
+
+
+ /**
+ * Reads cache data from disk.
+ */
+ protected function readMetaAndLock(string $file, int $lock): ?array
+ {
+ $handle = @fopen($file, 'r+b'); // @ - file may not exist
+ if (!$handle) {
+ return null;
+ }
+
+ flock($handle, $lock);
+
+ $size = (int) stream_get_contents($handle, self::MetaHeaderLen);
+ if ($size) {
+ $meta = stream_get_contents($handle, $size, self::MetaHeaderLen);
+ $meta = unserialize($meta);
+ $meta[self::File] = $file;
+ $meta[self::Handle] = $handle;
+ return $meta;
+ }
+
+ flock($handle, LOCK_UN);
+ fclose($handle);
+ return null;
+ }
+
+
+ /**
+ * Reads cache data from disk and closes cache file handle.
+ */
+ protected function readData(array $meta): mixed
+ {
+ $data = stream_get_contents($meta[self::Handle]);
+ flock($meta[self::Handle], LOCK_UN);
+ fclose($meta[self::Handle]);
+
+ return empty($meta[self::MetaSerialized]) ? $data : unserialize($data);
+ }
+
+
+ /**
+ * Returns file name.
+ */
+ protected function getCacheFile(string $key): string
+ {
+ $file = urlencode($key);
+ if ($a = strrpos($file, '%00')) { // %00 = urlencode(Nette\Caching\Cache::NamespaceSeparator)
+ $file = substr_replace($file, '/_', $a, 3);
+ }
+
+ return $this->dir . '/_' . $file;
+ }
+
+
+ /**
+ * Deletes and closes file.
+ * @param resource $handle
+ */
+ private static function delete(string $file, $handle = null): void
+ {
+ if (@unlink($file)) { // @ - file may not already exist
+ if ($handle) {
+ flock($handle, LOCK_UN);
+ fclose($handle);
+ }
+
+ return;
+ }
+
+ if (!$handle) {
+ $handle = @fopen($file, 'r+'); // @ - file may not exist
+ }
+
+ if (!$handle) {
+ return;
+ }
+
+ flock($handle, LOCK_EX);
+ ftruncate($handle, 0);
+ flock($handle, LOCK_UN);
+ fclose($handle);
+ @unlink($file); // @ - file may not already exist
+ }
+}
diff --git a/vendor/nette/caching/src/Caching/Storages/Journal.php b/vendor/nette/caching/src/Caching/Storages/Journal.php
new file mode 100644
index 0000000..1815073
--- /dev/null
+++ b/vendor/nette/caching/src/Caching/Storages/Journal.php
@@ -0,0 +1,31 @@
+prefix = $prefix;
+ $this->journal = $journal;
+ $this->memcached = new \Memcached;
+ if ($host) {
+ $this->addServer($host, $port);
+ }
+ }
+
+
+ public function addServer(string $host = 'localhost', int $port = 11211): void
+ {
+ if (@$this->memcached->addServer($host, $port, 1) === false) { // @ is escalated to exception
+ $error = error_get_last();
+ throw new Nette\InvalidStateException("Memcached::addServer(): $error[message].");
+ }
+ }
+
+
+ public function getConnection(): \Memcached
+ {
+ return $this->memcached;
+ }
+
+
+ public function read(string $key): mixed
+ {
+ $key = urlencode($this->prefix . $key);
+ $meta = $this->memcached->get($key);
+ if (!$meta) {
+ return null;
+ }
+
+ // meta structure:
+ // array(
+ // data => stored data
+ // delta => relative (sliding) expiration
+ // callbacks => array of callbacks (function, args)
+ // )
+
+ // verify dependencies
+ if (!empty($meta[self::MetaCallbacks]) && !Cache::checkCallbacks($meta[self::MetaCallbacks])) {
+ $this->memcached->delete($key, 0);
+ return null;
+ }
+
+ if (!empty($meta[self::MetaDelta])) {
+ $this->memcached->replace($key, $meta, $meta[self::MetaDelta] + time());
+ }
+
+ return $meta[self::MetaData];
+ }
+
+
+ public function bulkRead(array $keys): array
+ {
+ $prefixedKeys = array_map(fn($key) => urlencode($this->prefix . $key), $keys);
+ $keys = array_combine($prefixedKeys, $keys);
+ $metas = $this->memcached->getMulti($prefixedKeys);
+ $result = [];
+ $deleteKeys = [];
+ foreach ($metas as $prefixedKey => $meta) {
+ if (!empty($meta[self::MetaCallbacks]) && !Cache::checkCallbacks($meta[self::MetaCallbacks])) {
+ $deleteKeys[] = $prefixedKey;
+ } else {
+ $result[$keys[$prefixedKey]] = $meta[self::MetaData];
+ }
+
+ if (!empty($meta[self::MetaDelta])) {
+ $this->memcached->replace($prefixedKey, $meta, $meta[self::MetaDelta] + time());
+ }
+ }
+
+ if (!empty($deleteKeys)) {
+ $this->memcached->deleteMulti($deleteKeys, 0);
+ }
+
+ return $result;
+ }
+
+
+ public function lock(string $key): void
+ {
+ }
+
+
+ public function write(string $key, $data, array $dp): void
+ {
+ if (isset($dp[Cache::Items])) {
+ throw new Nette\NotSupportedException('Dependent items are not supported by MemcachedStorage.');
+ }
+
+ $key = urlencode($this->prefix . $key);
+ $meta = [
+ self::MetaData => $data,
+ ];
+
+ $expire = 0;
+ if (isset($dp[Cache::Expire])) {
+ $expire = (int) $dp[Cache::Expire];
+ if (!empty($dp[Cache::Sliding])) {
+ $meta[self::MetaDelta] = $expire; // sliding time
+ }
+ }
+
+ if (isset($dp[Cache::Callbacks])) {
+ $meta[self::MetaCallbacks] = $dp[Cache::Callbacks];
+ }
+
+ if (isset($dp[Cache::Tags]) || isset($dp[Cache::Priority])) {
+ if (!$this->journal) {
+ throw new Nette\InvalidStateException('CacheJournal has not been provided.');
+ }
+
+ $this->journal->write($key, $dp);
+ }
+
+ $this->memcached->set($key, $meta, $expire);
+ }
+
+
+ public function bulkWrite(array $items, array $dp): void
+ {
+ if (isset($dp[Cache::Items])) {
+ throw new Nette\NotSupportedException('Dependent items are not supported by MemcachedStorage.');
+ }
+
+ $meta = $records = [];
+ $expire = 0;
+ if (isset($dp[Cache::Expire])) {
+ $expire = (int) $dp[Cache::Expire];
+ if (!empty($dp[Cache::Sliding])) {
+ $meta[self::MetaDelta] = $expire; // sliding time
+ }
+ }
+
+ if (isset($dp[Cache::Callbacks])) {
+ $meta[self::MetaCallbacks] = $dp[Cache::Callbacks];
+ }
+
+ foreach ($items as $key => $meta[self::MetaData]) {
+ $key = urlencode($this->prefix . $key);
+ $records[$key] = $meta;
+
+ if (isset($dp[Cache::Tags]) || isset($dp[Cache::Priority])) {
+ if (!$this->journal) {
+ throw new Nette\InvalidStateException('CacheJournal has not been provided.');
+ }
+
+ $this->journal->write($key, $dp);
+ }
+ }
+
+ $this->memcached->setMulti($records, $expire);
+ }
+
+
+ public function remove(string $key): void
+ {
+ $this->memcached->delete(urlencode($this->prefix . $key), 0);
+ }
+
+
+ public function bulkRemove(array $keys): void
+ {
+ $this->memcached->deleteMulti(array_map(fn($key) => urlencode($this->prefix . $key), $keys), 0);
+ }
+
+
+ public function clean(array $conditions): void
+ {
+ if (!empty($conditions[Cache::All])) {
+ $this->memcached->flush();
+
+ } elseif ($this->journal) {
+ foreach ($this->journal->clean($conditions) as $entry) {
+ $this->memcached->delete($entry, 0);
+ }
+ }
+ }
+}
diff --git a/vendor/nette/caching/src/Caching/Storages/MemoryStorage.php b/vendor/nette/caching/src/Caching/Storages/MemoryStorage.php
new file mode 100644
index 0000000..55abc05
--- /dev/null
+++ b/vendor/nette/caching/src/Caching/Storages/MemoryStorage.php
@@ -0,0 +1,52 @@
+data[$key] ?? null;
+ }
+
+
+ public function lock(string $key): void
+ {
+ }
+
+
+ public function write(string $key, $data, array $dependencies): void
+ {
+ $this->data[$key] = $data;
+ }
+
+
+ public function remove(string $key): void
+ {
+ unset($this->data[$key]);
+ }
+
+
+ public function clean(array $conditions): void
+ {
+ if (!empty($conditions[Nette\Caching\Cache::All])) {
+ $this->data = [];
+ }
+ }
+}
diff --git a/vendor/nette/caching/src/Caching/Storages/SQLiteJournal.php b/vendor/nette/caching/src/Caching/Storages/SQLiteJournal.php
new file mode 100644
index 0000000..2674783
--- /dev/null
+++ b/vendor/nette/caching/src/Caching/Storages/SQLiteJournal.php
@@ -0,0 +1,145 @@
+path = $path;
+ }
+
+
+ private function open(): void
+ {
+ if ($this->path !== ':memory:' && !is_file($this->path)) {
+ touch($this->path); // ensures ordinary file permissions
+ }
+
+ $this->pdo = new \PDO('sqlite:' . $this->path);
+ $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+ $this->pdo->exec('
+ PRAGMA foreign_keys = OFF;
+ PRAGMA journal_mode = WAL;
+ CREATE TABLE IF NOT EXISTS tags (
+ key BLOB NOT NULL,
+ tag BLOB NOT NULL
+ );
+ CREATE TABLE IF NOT EXISTS priorities (
+ key BLOB NOT NULL,
+ priority INT NOT NULL
+ );
+ CREATE INDEX IF NOT EXISTS idx_tags_tag ON tags(tag);
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_tags_key_tag ON tags(key, tag);
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_priorities_key ON priorities(key);
+ CREATE INDEX IF NOT EXISTS idx_priorities_priority ON priorities(priority);
+ PRAGMA synchronous = NORMAL;
+ ');
+ }
+
+
+ public function write(string $key, array $dependencies): void
+ {
+ if (!isset($this->pdo)) {
+ $this->open();
+ }
+
+ $this->pdo->exec('BEGIN');
+
+ if (!empty($dependencies[Cache::Tags])) {
+ $this->pdo->prepare('DELETE FROM tags WHERE key = ?')->execute([$key]);
+
+ foreach ($dependencies[Cache::Tags] as $tag) {
+ $arr[] = $key;
+ $arr[] = $tag;
+ }
+
+ $this->pdo->prepare('INSERT INTO tags (key, tag) SELECT ?, ?' . str_repeat('UNION SELECT ?, ?', count($arr) / 2 - 1))
+ ->execute($arr);
+ }
+
+ if (!empty($dependencies[Cache::Priority])) {
+ $this->pdo->prepare('REPLACE INTO priorities (key, priority) VALUES (?, ?)')
+ ->execute([$key, (int) $dependencies[Cache::Priority]]);
+ }
+
+ $this->pdo->exec('COMMIT');
+ }
+
+
+ public function clean(array $conditions): ?array
+ {
+ if (!isset($this->pdo)) {
+ $this->open();
+ }
+
+ if (!empty($conditions[Cache::All])) {
+ $this->pdo->exec('
+ BEGIN;
+ DELETE FROM tags;
+ DELETE FROM priorities;
+ COMMIT;
+ ');
+
+ return null;
+ }
+
+ $unions = $args = [];
+ if (!empty($conditions[Cache::Tags])) {
+ $tags = (array) $conditions[Cache::Tags];
+ $unions[] = 'SELECT DISTINCT key FROM tags WHERE tag IN (?' . str_repeat(', ?', count($tags) - 1) . ')';
+ $args = $tags;
+ }
+
+ if (!empty($conditions[Cache::Priority])) {
+ $unions[] = 'SELECT DISTINCT key FROM priorities WHERE priority <= ?';
+ $args[] = (int) $conditions[Cache::Priority];
+ }
+
+ if (empty($unions)) {
+ return [];
+ }
+
+ $unionSql = implode(' UNION ', $unions);
+
+ $this->pdo->exec('BEGIN IMMEDIATE');
+
+ $stmt = $this->pdo->prepare($unionSql);
+ $stmt->execute($args);
+ $keys = $stmt->fetchAll(\PDO::FETCH_COLUMN, 0);
+
+ if (empty($keys)) {
+ $this->pdo->exec('COMMIT');
+ return [];
+ }
+
+ $this->pdo->prepare("DELETE FROM tags WHERE key IN ($unionSql)")->execute($args);
+ $this->pdo->prepare("DELETE FROM priorities WHERE key IN ($unionSql)")->execute($args);
+ $this->pdo->exec('COMMIT');
+
+ return $keys;
+ }
+}
diff --git a/vendor/nette/caching/src/Caching/Storages/SQLiteStorage.php b/vendor/nette/caching/src/Caching/Storages/SQLiteStorage.php
new file mode 100644
index 0000000..5301a4e
--- /dev/null
+++ b/vendor/nette/caching/src/Caching/Storages/SQLiteStorage.php
@@ -0,0 +1,148 @@
+pdo = new \PDO('sqlite:' . $path);
+ $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+ $this->pdo->exec('
+ PRAGMA foreign_keys = ON;
+ CREATE TABLE IF NOT EXISTS cache (
+ key BLOB NOT NULL PRIMARY KEY,
+ data BLOB NOT NULL,
+ expire INTEGER,
+ slide INTEGER
+ );
+ CREATE TABLE IF NOT EXISTS tags (
+ key BLOB NOT NULL REFERENCES cache ON DELETE CASCADE,
+ tag BLOB NOT NULL
+ );
+ CREATE INDEX IF NOT EXISTS cache_expire ON cache(expire);
+ CREATE INDEX IF NOT EXISTS tags_key ON tags(key);
+ CREATE INDEX IF NOT EXISTS tags_tag ON tags(tag);
+ PRAGMA synchronous = OFF;
+ ');
+ }
+
+
+ public function read(string $key): mixed
+ {
+ $stmt = $this->pdo->prepare('SELECT data, slide FROM cache WHERE key=? AND (expire IS NULL OR expire >= ?)');
+ $stmt->execute([$key, time()]);
+ if (!$row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
+ return null;
+ }
+
+ if ($row['slide'] !== null) {
+ $this->pdo->prepare('UPDATE cache SET expire = ? + slide WHERE key=?')->execute([time(), $key]);
+ }
+
+ return unserialize($row['data']);
+ }
+
+
+ public function bulkRead(array $keys): array
+ {
+ $stmt = $this->pdo->prepare('SELECT key, data, slide FROM cache WHERE key IN (?' . str_repeat(',?', count($keys) - 1) . ') AND (expire IS NULL OR expire >= ?)');
+ $stmt->execute(array_merge($keys, [time()]));
+ $result = [];
+ $updateSlide = [];
+ foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
+ if ($row['slide'] !== null) {
+ $updateSlide[] = $row['key'];
+ }
+
+ $result[$row['key']] = unserialize($row['data']);
+ }
+
+ if (!empty($updateSlide)) {
+ $stmt = $this->pdo->prepare('UPDATE cache SET expire = ? + slide WHERE key IN(?' . str_repeat(',?', count($updateSlide) - 1) . ')');
+ $stmt->execute(array_merge([time()], $updateSlide));
+ }
+
+ return $result;
+ }
+
+
+ public function lock(string $key): void
+ {
+ }
+
+
+ public function write(string $key, $data, array $dependencies): void
+ {
+ $expire = isset($dependencies[Cache::Expire])
+ ? $dependencies[Cache::Expire] + time()
+ : null;
+ $slide = isset($dependencies[Cache::Sliding])
+ ? $dependencies[Cache::Expire]
+ : null;
+
+ $this->pdo->exec('BEGIN TRANSACTION');
+ $this->pdo->prepare('REPLACE INTO cache (key, data, expire, slide) VALUES (?, ?, ?, ?)')
+ ->execute([$key, serialize($data), $expire, $slide]);
+
+ if (!empty($dependencies[Cache::Tags])) {
+ foreach ($dependencies[Cache::Tags] as $tag) {
+ $arr[] = $key;
+ $arr[] = $tag;
+ }
+
+ $this->pdo->prepare('INSERT INTO tags (key, tag) SELECT ?, ?' . str_repeat('UNION SELECT ?, ?', count($arr) / 2 - 1))
+ ->execute($arr);
+ }
+
+ $this->pdo->exec('COMMIT');
+ }
+
+
+ public function remove(string $key): void
+ {
+ $this->pdo->prepare('DELETE FROM cache WHERE key=?')
+ ->execute([$key]);
+ }
+
+
+ public function clean(array $conditions): void
+ {
+ if (!empty($conditions[Cache::All])) {
+ $this->pdo->prepare('DELETE FROM cache')->execute();
+
+ } else {
+ $sql = 'DELETE FROM cache WHERE expire < ?';
+ $args = [time()];
+
+ if (!empty($conditions[Cache::Tags])) {
+ $tags = $conditions[Cache::Tags];
+ $sql .= ' OR key IN (SELECT key FROM tags WHERE tag IN (?' . str_repeat(',?', count($tags) - 1) . '))';
+ $args = array_merge($args, $tags);
+ }
+
+ $this->pdo->prepare($sql)->execute($args);
+ }
+ }
+}
diff --git a/vendor/nette/caching/src/compatibility.php b/vendor/nette/caching/src/compatibility.php
new file mode 100644
index 0000000..84336f2
--- /dev/null
+++ b/vendor/nette/caching/src/compatibility.php
@@ -0,0 +1,39 @@
+ '@']));
diff --git a/vendor/nette/component-model/composer.json b/vendor/nette/component-model/composer.json
new file mode 100644
index 0000000..52a8f9e
--- /dev/null
+++ b/vendor/nette/component-model/composer.json
@@ -0,0 +1,39 @@
+{
+ "name": "nette/component-model",
+ "description": "⚛ Nette Component Model",
+ "keywords": ["nette", "components"],
+ "homepage": "https://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.1 - 8.4",
+ "nette/utils": "^4.0"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5",
+ "tracy/tracy": "^2.9",
+ "phpstan/phpstan": "^1.0"
+ },
+ "autoload": {
+ "classmap": ["src/"]
+ },
+ "minimum-stability": "dev",
+ "scripts": {
+ "phpstan": "phpstan analyse",
+ "tester": "tester tests -s"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ }
+}
diff --git a/vendor/nette/component-model/license.md b/vendor/nette/component-model/license.md
new file mode 100644
index 0000000..cf741bd
--- /dev/null
+++ b/vendor/nette/component-model/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/nette/component-model/readme.md b/vendor/nette/component-model/readme.md
new file mode 100644
index 0000000..91c9b80
--- /dev/null
+++ b/vendor/nette/component-model/readme.md
@@ -0,0 +1,31 @@
+Nette Component Model
+=====================
+
+[](https://packagist.org/packages/nette/component-model)
+[](https://github.com/nette/component-model/actions)
+[](https://coveralls.io/github/nette/component-model?branch=v3.1)
+[](https://github.com/nette/component-model/releases)
+[](https://github.com/nette/component-model/blob/master/license.md)
+
+
+Introduction
+------------
+
+Components are the foundation of reusable code. They make your work easier and allow you to profit from community work. Components are wonderful.
+Nette Framework introduces several classes and interfaces for all these types of components.
+
+Documentation can be found on the [website](https://doc.nette.org/component-model).
+
+If you like Nette, **[please make a donation now](https://nette.org/donate)**. Thank you!
+
+
+Installation
+------------
+
+The recommended way to install is via Composer:
+
+```
+composer require nette/component-model
+```
+
+It requires PHP version 8.1 and supports PHP up to 8.4.
diff --git a/vendor/nette/component-model/src/ComponentModel/ArrayAccess.php b/vendor/nette/component-model/src/ComponentModel/ArrayAccess.php
new file mode 100644
index 0000000..1bded8c
--- /dev/null
+++ b/vendor/nette/component-model/src/ComponentModel/ArrayAccess.php
@@ -0,0 +1,66 @@
+addComponent($component, $name);
+ }
+
+
+ /**
+ * Returns component specified by name. Throws exception if component doesn't exist.
+ * @param string|int $name
+ * @throws Nette\InvalidArgumentException
+ */
+ public function offsetGet($name): IComponent
+ {
+ $name = is_int($name) ? (string) $name : $name;
+ return $this->getComponent($name);
+ }
+
+
+ /**
+ * Does component specified by name exists?
+ * @param string|int $name
+ */
+ public function offsetExists($name): bool
+ {
+ $name = is_int($name) ? (string) $name : $name;
+ return $this->getComponent($name, throw: false) !== null;
+ }
+
+
+ /**
+ * Removes component from the container.
+ * @param string|int $name
+ */
+ public function offsetUnset($name): void
+ {
+ $name = is_int($name) ? (string) $name : $name;
+ if ($component = $this->getComponent($name, throw: false)) {
+ $this->removeComponent($component);
+ }
+ }
+}
diff --git a/vendor/nette/component-model/src/ComponentModel/Component.php b/vendor/nette/component-model/src/ComponentModel/Component.php
new file mode 100644
index 0000000..64f77fc
--- /dev/null
+++ b/vendor/nette/component-model/src/ComponentModel/Component.php
@@ -0,0 +1,313 @@
+}> means [type => [obj, depth, path, [attached, detached]]] */
+ private array $monitors = [];
+
+
+ /**
+ * Finds the closest ancestor of specified type.
+ * @param bool $throw throw exception if component doesn't exist?
+ * @return ($throw is true ? IComponent : ?IComponent)
+ */
+ final public function lookup(?string $type, bool $throw = true): ?IComponent
+ {
+ if (!isset($this->monitors[$type])) { // not monitored or not processed yet
+ $obj = $this->parent;
+ $path = self::NameSeparator . $this->name;
+ $depth = 1;
+ while ($obj !== null) {
+ $parent = $obj->getParent();
+ if ($type ? $obj instanceof $type : $parent === null) {
+ break;
+ }
+
+ $path = self::NameSeparator . $obj->getName() . $path;
+ $depth++;
+ $obj = $parent; // IComponent::getParent()
+ if ($obj === $this) {
+ $obj = null; // prevent cycling
+ }
+ }
+
+ if ($obj) {
+ $this->monitors[$type] = [$obj, $depth, substr($path, 1), []];
+
+ } else {
+ $this->monitors[$type] = [null, null, null, []]; // not found
+ }
+ }
+
+ if ($throw && $this->monitors[$type][0] === null) {
+ $message = $this->name !== null
+ ? "Component '$this->name' is not attached to '$type'."
+ : "Component of type '" . static::class . "' is not attached to '$type'.";
+ throw new Nette\InvalidStateException($message);
+ }
+
+ return $this->monitors[$type][0];
+ }
+
+
+ /**
+ * Finds the closest ancestor specified by class or interface name and returns backtrace path.
+ * A path is the concatenation of component names separated by self::NAME_SEPARATOR.
+ * @return ($throw is true ? string : ?string)
+ */
+ final public function lookupPath(?string $type = null, bool $throw = true): ?string
+ {
+ $this->lookup($type, $throw);
+ return $this->monitors[$type][2];
+ }
+
+
+ /**
+ * Starts monitoring ancestors for attach/detach events.
+ */
+ final public function monitor(string $type, ?callable $attached = null, ?callable $detached = null): void
+ {
+ if (func_num_args() === 1) {
+ $attached = [$this, 'attached'];
+ $detached = [$this, 'detached'];
+ }
+
+ if (
+ ($obj = $this->lookup($type, throw: false))
+ && $attached
+ && !in_array([$attached, $detached], $this->monitors[$type][3], strict: true)
+ ) {
+ $attached($obj);
+ }
+
+ $this->monitors[$type][3][] = [$attached, $detached]; // mark as monitored
+ }
+
+
+ /**
+ * Stops monitoring ancestors of specified type.
+ */
+ final public function unmonitor(string $type): void
+ {
+ unset($this->monitors[$type]);
+ }
+
+
+ /**
+ * This method will be called when the component (or component's parent)
+ * becomes attached to a monitored object. Do not call this method yourself.
+ * @deprecated use monitor($type, $attached)
+ */
+ protected function attached(IComponent $obj): void
+ {
+ }
+
+
+ /**
+ * This method will be called before the component (or component's parent)
+ * becomes detached from a monitored object. Do not call this method yourself.
+ * @deprecated use monitor($type, null, $detached)
+ */
+ protected function detached(IComponent $obj): void
+ {
+ }
+
+
+ /********************* interface IComponent ****************d*g**/
+
+
+ final public function getName(): ?string
+ {
+ return $this->name;
+ }
+
+
+ /**
+ * Returns the parent container if any.
+ */
+ final public function getParent(): ?IContainer
+ {
+ return $this->parent;
+ }
+
+
+ /**
+ * Sets or removes the parent of this component. This method is managed by containers and should
+ * not be called by applications
+ * @throws Nette\InvalidStateException
+ * @internal
+ */
+ public function setParent(?IContainer $parent, ?string $name = null): static
+ {
+ if ($parent === null && $this->parent === null && $name !== null) {
+ $this->name = $name; // just rename
+ return $this;
+
+ } elseif ($parent === $this->parent && $name === null) {
+ return $this; // nothing to do
+ }
+
+ // A component cannot be given a parent if it already has a parent.
+ if ($this->parent !== null && $parent !== null) {
+ throw new Nette\InvalidStateException("Component '$this->name' already has a parent.");
+ }
+
+ // remove from parent?
+ if ($parent === null) {
+ $this->refreshMonitors(0);
+ $this->parent = null;
+
+ } else { // add to parent
+ $this->validateParent($parent);
+ $this->parent = $parent;
+ if ($name !== null) {
+ $this->name = $name;
+ }
+
+ $tmp = [];
+ $this->refreshMonitors(0, $tmp);
+ }
+
+ return $this;
+ }
+
+
+ /**
+ * Validates the new parent before it's set.
+ * Descendant classes can override this to implement custom validation logic.
+ * @throws Nette\InvalidStateException
+ */
+ protected function validateParent(IContainer $parent): void
+ {
+ }
+
+
+ /**
+ * Refreshes monitors.
+ * @param array|null $missing (array = attaching, null = detaching)
+ * @param array $listeners
+ */
+ private function refreshMonitors(int $depth, ?array &$missing = null, array &$listeners = []): void
+ {
+ if ($this instanceof IContainer) {
+ foreach ($this->getComponents() as $component) {
+ if ($component instanceof self) {
+ $component->refreshMonitors($depth + 1, $missing, $listeners);
+ }
+ }
+ }
+
+ if ($missing === null) { // detaching
+ foreach ($this->monitors as $type => $rec) {
+ if (isset($rec[1]) && $rec[1] > $depth) {
+ if ($rec[3]) { // monitored
+ $this->monitors[$type] = [null, null, null, $rec[3]];
+ foreach ($rec[3] as $pair) {
+ $listeners[] = [$pair[1], $rec[0]];
+ }
+ } else { // not monitored, just randomly cached
+ unset($this->monitors[$type]);
+ }
+ }
+ }
+ } else { // attaching
+ foreach ($this->monitors as $type => $rec) {
+ if (isset($rec[0])) { // is in cache yet
+ continue;
+
+ } elseif (!$rec[3]) { // not monitored, just randomly cached
+ unset($this->monitors[$type]);
+
+ } elseif (isset($missing[$type])) { // known from previous lookup
+ $this->monitors[$type] = [null, null, null, $rec[3]];
+
+ } else {
+ unset($this->monitors[$type]); // forces re-lookup
+ if ($obj = $this->lookup($type, throw: false)) {
+ foreach ($rec[3] as $pair) {
+ $listeners[] = [$pair[0], $obj];
+ }
+ } else {
+ $missing[$type] = true;
+ }
+
+ $this->monitors[$type][3] = $rec[3]; // mark as monitored
+ }
+ }
+ }
+
+ if ($depth === 0) { // call listeners
+ $prev = [];
+ foreach ($listeners as $item) {
+ if ($item[0] && !in_array($item, $prev, strict: true)) {
+ $item[0]($item[1]);
+ $prev[] = $item;
+ }
+ }
+ }
+ }
+
+
+ /********************* cloneable, serializable ****************d*g**/
+
+
+ /**
+ * Object cloning.
+ */
+ public function __clone()
+ {
+ if ($this->parent === null) {
+ return;
+
+ } elseif ($this->parent instanceof Container) {
+ $this->parent = $this->parent->_isCloning();
+ if ($this->parent === null) { // not cloning
+ $this->refreshMonitors(0);
+ }
+ } else {
+ $this->parent = null;
+ $this->refreshMonitors(0);
+ }
+ }
+
+
+ /**
+ * Prevents serialization.
+ */
+ final public function __sleep()
+ {
+ throw new Nette\NotImplementedException('Object serialization is not supported by class ' . static::class);
+ }
+
+
+ /**
+ * Prevents unserialization.
+ */
+ final public function __wakeup()
+ {
+ throw new Nette\NotImplementedException('Object unserialization is not supported by class ' . static::class);
+ }
+}
diff --git a/vendor/nette/component-model/src/ComponentModel/Container.php b/vendor/nette/component-model/src/ComponentModel/Container.php
new file mode 100644
index 0000000..256196f
--- /dev/null
+++ b/vendor/nette/component-model/src/ComponentModel/Container.php
@@ -0,0 +1,260 @@
+getName();
+ if ($name === null) {
+ throw new Nette\InvalidStateException("Missing component's name.");
+ }
+ }
+
+ if (!preg_match(self::NameRegexp, $name)) {
+ throw new Nette\InvalidArgumentException("Component name must be non-empty alphanumeric string, '$name' given.");
+ }
+
+ if (isset($this->components[$name])) {
+ throw new Nette\InvalidStateException("Component with name '$name' already exists.");
+ }
+
+ // check circular reference
+ $obj = $this;
+ do {
+ if ($obj === $component) {
+ throw new Nette\InvalidStateException("Circular reference detected while adding component '$name'.");
+ }
+
+ $obj = $obj->getParent();
+ } while ($obj !== null);
+
+ // user checking
+ $this->validateChildComponent($component);
+
+ if (isset($this->components[$insertBefore])) {
+ $tmp = [];
+ foreach ($this->components as $k => $v) {
+ if ((string) $k === $insertBefore) {
+ $tmp[$name] = $component;
+ }
+
+ $tmp[$k] = $v;
+ }
+
+ $this->components = $tmp;
+ } else {
+ $this->components[$name] = $component;
+ }
+
+ try {
+ $component->setParent($this, $name);
+ } catch (\Throwable $e) {
+ unset($this->components[$name]); // undo
+ throw $e;
+ }
+
+ return $this;
+ }
+
+
+ /**
+ * Removes a child component from the container.
+ */
+ public function removeComponent(IComponent $component): void
+ {
+ $name = $component->getName();
+ if (($this->components[$name] ?? null) !== $component) {
+ throw new Nette\InvalidArgumentException("Component named '$name' is not located in this container.");
+ }
+
+ unset($this->components[$name]);
+ $component->setParent(null);
+ }
+
+
+ /**
+ * Retrieves a child component by name or creates it if it doesn't exist.
+ * @param bool $throw throw exception if component doesn't exist?
+ * @return ($throw is true ? IComponent : ?IComponent)
+ */
+ final public function getComponent(string $name, bool $throw = true): ?IComponent
+ {
+ [$name] = $parts = explode(self::NameSeparator, $name, 2);
+
+ if (!isset($this->components[$name])) {
+ if (!preg_match(self::NameRegexp, $name)) {
+ if ($throw) {
+ throw new Nette\InvalidArgumentException("Component name must be non-empty alphanumeric string, '$name' given.");
+ }
+
+ return null;
+ }
+
+ $component = $this->createComponent($name);
+ if ($component && !isset($this->components[$name])) {
+ $this->addComponent($component, $name);
+ }
+ }
+
+ $component = $this->components[$name] ?? null;
+ if ($component !== null) {
+ if (!isset($parts[1])) {
+ return $component;
+
+ } elseif ($component instanceof IContainer) {
+ return $component->getComponent($parts[1], $throw);
+
+ } elseif ($throw) {
+ throw new Nette\InvalidArgumentException("Component with name '$name' is not container and cannot have '$parts[1]' component.");
+ }
+ } elseif ($throw) {
+ $hint = Nette\Utils\ObjectHelpers::getSuggestion(array_merge(
+ array_map('strval', array_keys($this->components)),
+ array_map('lcfirst', preg_filter('#^createComponent([A-Z0-9].*)#', '$1', get_class_methods($this))),
+ ), $name);
+ throw new Nette\InvalidArgumentException("Component with name '$name' does not exist" . ($hint ? ", did you mean '$hint'?" : '.'));
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Creates a new component. Delegates creation to createComponent method if it exists.
+ */
+ protected function createComponent(string $name): ?IComponent
+ {
+ $ucname = ucfirst($name);
+ $method = 'createComponent' . $ucname;
+ if (
+ $ucname !== $name
+ && method_exists($this, $method)
+ && (new \ReflectionMethod($this, $method))->getName() === $method
+ ) {
+ $component = $this->$method($name);
+ if (!$component instanceof IComponent && !isset($this->components[$name])) {
+ $class = static::class;
+ throw new Nette\UnexpectedValueException("Method $class::$method() did not return or create the desired component.");
+ }
+
+ return $component;
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns all immediate child components.
+ * @return array
+ */
+ final public function getComponents(): iterable
+ {
+ $filterType = func_get_args()[1] ?? null;
+ if (func_get_args()[0] ?? null) { // back compatibility
+ $iterator = new RecursiveComponentIterator($this->components);
+ $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
+ if ($filterType) {
+ $iterator = new \CallbackFilterIterator($iterator, fn($item) => $item instanceof $filterType);
+ }
+ return $iterator;
+ }
+
+ return $filterType
+ ? array_filter($this->components, fn($item) => $item instanceof $filterType)
+ : $this->components;
+ }
+
+
+ /**
+ * Retrieves the entire hierarchy of components, including all nested child components (depth-first).
+ * @return list
+ */
+ final public function getComponentTree(): array
+ {
+ $res = [];
+ foreach ($this->components as $component) {
+ $res[] = $component;
+ if ($component instanceof self) {
+ $res = array_merge($res, $component->getComponentTree());
+ }
+ }
+ return $res;
+ }
+
+
+ /**
+ * Validates a child component before it's added to the container.
+ * Descendant classes can override this to implement custom validation logic.
+ * @throws Nette\InvalidStateException
+ */
+ protected function validateChildComponent(IComponent $child): void
+ {
+ }
+
+
+ /********************* cloneable, serializable ****************d*g**/
+
+
+ /**
+ * Handles object cloning. Clones all child components and re-sets their parents.
+ */
+ public function __clone()
+ {
+ if ($this->components) {
+ $oldMyself = reset($this->components)->getParent();
+ assert($oldMyself instanceof self);
+ $oldMyself->cloning = $this;
+ foreach ($this->components as $name => $component) {
+ $this->components[$name] = clone $component;
+ }
+
+ $oldMyself->cloning = null;
+ }
+
+ parent::__clone();
+ }
+
+
+ /**
+ * Is container cloning now?
+ * @internal
+ */
+ final public function _isCloning(): ?self
+ {
+ return $this->cloning;
+ }
+}
diff --git a/vendor/nette/component-model/src/ComponentModel/IComponent.php b/vendor/nette/component-model/src/ComponentModel/IComponent.php
new file mode 100644
index 0000000..4573a50
--- /dev/null
+++ b/vendor/nette/component-model/src/ComponentModel/IComponent.php
@@ -0,0 +1,35 @@
+
+ */
+ function getComponents(): iterable;
+}
diff --git a/vendor/nette/component-model/src/ComponentModel/RecursiveComponentIterator.php b/vendor/nette/component-model/src/ComponentModel/RecursiveComponentIterator.php
new file mode 100644
index 0000000..3c1c003
--- /dev/null
+++ b/vendor/nette/component-model/src/ComponentModel/RecursiveComponentIterator.php
@@ -0,0 +1,44 @@
+current() instanceof IContainer;
+ }
+
+
+ /**
+ * The sub-iterator for the current element.
+ */
+ public function getChildren(): self
+ {
+ return new self($this->current()->getComponents());
+ }
+
+
+ /**
+ * Returns the count of elements.
+ */
+ public function count(): int
+ {
+ return iterator_count($this);
+ }
+}
diff --git a/vendor/nette/database/composer.json b/vendor/nette/database/composer.json
new file mode 100644
index 0000000..4dbddd8
--- /dev/null
+++ b/vendor/nette/database/composer.json
@@ -0,0 +1,44 @@
+{
+ "name": "nette/database",
+ "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.",
+ "keywords": ["nette", "database", "notorm", "queries", "pdo", "mysql", "postgresql", "sqlite", "mssql", "oracle"],
+ "homepage": "https://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.1 - 8.4",
+ "ext-pdo": "*",
+ "nette/caching": "^3.2",
+ "nette/utils": "^4.0"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5",
+ "nette/di": "^3.1",
+ "mockery/mockery": "^1.6",
+ "tracy/tracy": "^2.9",
+ "phpstan/phpstan-nette": "^1.0",
+ "jetbrains/phpstorm-attributes": "^1.0"
+ },
+ "autoload": {
+ "classmap": ["src/"]
+ },
+ "minimum-stability": "dev",
+ "scripts": {
+ "phpstan": "phpstan analyse",
+ "tester": "tester tests -s"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ }
+}
diff --git a/vendor/nette/database/license.md b/vendor/nette/database/license.md
new file mode 100644
index 0000000..cf741bd
--- /dev/null
+++ b/vendor/nette/database/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/nette/database/readme.md b/vendor/nette/database/readme.md
new file mode 100644
index 0000000..2f47421
--- /dev/null
+++ b/vendor/nette/database/readme.md
@@ -0,0 +1,141 @@
+Nette Database
+==============
+
+[](https://packagist.org/packages/nette/database)
+[](https://github.com/nette/database/actions)
+[](https://github.com/nette/database/releases)
+[](https://github.com/nette/database/blob/master/license.md)
+
+
+Introduction
+------------
+
+Nette provides a powerful layer for accessing your database easily.
+
+- composes SQL queries with ease
+- easily fetches data
+- uses efficient queries and does not transmit unnecessary data
+
+The [Nette Database Core](https://doc.nette.org/database-core) is a wrapper around the PDO and provides core functionality.
+
+The [Nette Database Explorer](https://doc.nette.org/database-explorer) layer helps you to fetch database data more easily and in a more optimized way.
+
+
+[Support Me](https://github.com/sponsors/dg)
+--------------------------------------------
+
+Do you like Nette Database? Are you looking forward to the new features?
+
+[](https://github.com/sponsors/dg)
+
+Thank you!
+
+
+Installation
+------------
+
+The recommended way to install is via Composer:
+
+```
+composer require nette/database
+```
+
+It requires PHP version 8.1 and supports PHP up to 8.4.
+
+
+Usage
+-----
+
+This is just a piece of documentation. [Please see our website](https://doc.nette.org/database).
+
+
+Database Core
+-------------
+
+To create a new database connection just create a new instance of `Nette\Database\Connection` class:
+
+```php
+$database = new Nette\Database\Connection($dsn, $user, $password); // the same arguments as uses PDO
+```
+
+Connection allows you to easily query your database by calling `query` method:
+
+```php
+$database->query('INSERT INTO users', [ // an array can be a parameter
+ 'name' => 'Jim',
+ 'created' => new DateTime, // or a DateTime object
+ 'avatar' => fopen('image.gif', 'r'), // or a file
+], ...); // it is even possible to use multiple inserts
+
+$database->query('UPDATE users SET ? WHERE id=?', $data, $id);
+$database->query('SELECT * FROM categories WHERE id=?', 123)->dump();
+```
+
+Database Explorer
+-----------------
+
+Nette Database Explorer layer helps you to fetch database data more easily and in a more optimized way. The primary attitude is to fetch data only from one table and fetch them at once. The data are fetched into `ActiveRow` instances. Data from other tables connected by relationships are delivered by another queries - this is maintained by Database Explorer layer itself.
+
+Let's take a look at common use-case. You need to fetch books and their authors. It is common 1:N relationship. The often used implementation fetches data by one SQL query with table joins. The second possibility is to fetch data separately, run one query for getting books and then get an author for each book by another query (e.g. in your foreach cycle). This could be easily optimized to run only two queries, one for books, and another for the needed authors - and this is just the way how Nette Database Explorer does it.
+
+Selecting data starts with the table, just call `$explorer->table()` on the `Nette\Database\Explorer` object. The easiest way to get it is [described here](https://doc.nette.org/database-core#toc-configuration), but if we use Nette Database Explorer alone, it can be [manually created](https://doc.nette.org/database-explorer#toc-manual-creating-nette-database-context).
+
+
+```php
+$selection = $explorer->table('book'); // db table name is "book"
+```
+
+We can simply iterate over the selection and pass through all the books. The rows are fetched as ActiveRow instances; you can read row data from their properties.
+
+```php
+$books = $explorer->table('book');
+foreach ($books as $book) {
+ echo $book->title;
+ echo $book->author_id;
+}
+```
+
+Getting just one specific row is done by `get()` method, which directly returns an ActiveRow instance.
+
+```php
+$book = $explorer->table('book')->get(2); // returns book with id 2
+echo $book->title;
+echo $book->author_id;
+```
+
+Working with relationships
+--------------------------
+
+```php
+$books = $explorer->table('book');
+
+foreach ($books as $book) {
+ echo 'title: ' . $book->title;
+ echo 'written by: ' . $book->author->name;
+
+ echo 'tags: ';
+ foreach ($book->related('book_tag') as $bookTag) {
+ echo $bookTag->tag->name . ', ';
+ }
+}
+```
+
+You will be pleased how efficiently the database layer works. The example above performs constant number of queries, see following 4 queries:
+
+```sql
+SELECT * FROM `book`
+SELECT * FROM `author` WHERE (`author`.`id` IN (11, 12))
+SELECT * FROM `book_tag` WHERE (`book_tag`.`book_id` IN (1, 4, 2, 3))
+SELECT * FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23))
+```
+
+If you use caching (defaults on), no columns will be queried unnecessarily. After the first query, cache will store the used column names and Nette Database Explorer will run queries only with the needed columns:
+
+```sql
+SELECT `id`, `title`, `author_id` FROM `book`
+SELECT `id`, `name` FROM `author` WHERE (`author`.`id` IN (11, 12))
+SELECT `book_id`, `tag_id` FROM `book_tag` WHERE (`book_tag`.`book_id` IN (1, 4, 2, 3))
+SELECT `id`, `name` FROM `tag` WHERE (`tag`.`id` IN (21, 22, 23))
+```
+
+[Continue…](https://doc.nette.org/database-explorer).
diff --git a/vendor/nette/database/src/Bridges/DatabaseDI/DatabaseExtension.php b/vendor/nette/database/src/Bridges/DatabaseDI/DatabaseExtension.php
new file mode 100644
index 0000000..703c18a
--- /dev/null
+++ b/vendor/nette/database/src/Bridges/DatabaseDI/DatabaseExtension.php
@@ -0,0 +1,139 @@
+debugMode = $debugMode;
+ }
+
+
+ public function getConfigSchema(): Nette\Schema\Schema
+ {
+ return Expect::arrayOf(
+ Expect::structure([
+ 'dsn' => Expect::string()->required()->dynamic(),
+ 'user' => Expect::string()->nullable()->dynamic(),
+ 'password' => Expect::string()->nullable()->dynamic(),
+ 'options' => Expect::array(),
+ 'debugger' => Expect::bool(),
+ 'explain' => Expect::bool(true),
+ 'reflection' => Expect::string(), // BC
+ 'conventions' => Expect::string('discovered'), // Nette\Database\Conventions\DiscoveredConventions
+ 'autowired' => Expect::bool(),
+ ]),
+ )->before(fn($val) => is_array(reset($val)) || reset($val) === null
+ ? $val
+ : ['default' => $val]);
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ $autowired = true;
+ foreach ($this->config as $name => $config) {
+ $config->autowired ??= $autowired;
+ $autowired = false;
+ $this->setupDatabase($config, $name);
+ }
+ }
+
+
+ public function beforeCompile(): void
+ {
+ $builder = $this->getContainerBuilder();
+
+ foreach ($this->config as $name => $config) {
+ if ($config->debugger ?? $builder->getByType(Tracy\BlueScreen::class)) {
+ $connection = $builder->getDefinition($this->prefix("$name.connection"));
+ $connection->addSetup(
+ [Nette\Bridges\DatabaseTracy\ConnectionPanel::class, 'initialize'],
+ [$connection, $this->debugMode, $name, !empty($config->explain)],
+ );
+ }
+ }
+ }
+
+
+ private function setupDatabase(\stdClass $config, string $name): void
+ {
+ $builder = $this->getContainerBuilder();
+
+ foreach ($config->options as $key => $value) {
+ if (is_string($value) && preg_match('#^PDO::\w+$#D', $value)) {
+ $config->options[$key] = $value = constant($value);
+ }
+
+ if (preg_match('#^PDO::\w+$#D', $key)) {
+ unset($config->options[$key]);
+ $config->options[constant($key)] = $value;
+ }
+ }
+
+ $connection = $builder->addDefinition($this->prefix("$name.connection"))
+ ->setFactory(Nette\Database\Connection::class, [$config->dsn, $config->user, $config->password, $config->options])
+ ->setAutowired($config->autowired);
+
+ $structure = $builder->addDefinition($this->prefix("$name.structure"))
+ ->setFactory(Nette\Database\Structure::class)
+ ->setArguments([$connection])
+ ->setAutowired($config->autowired);
+
+ if (!empty($config->reflection)) {
+ $conventionsServiceName = 'reflection';
+ $config->conventions = $config->reflection;
+ if (is_string($config->conventions) && strtolower($config->conventions) === 'conventional') {
+ $config->conventions = 'Static';
+ }
+ } else {
+ $conventionsServiceName = 'conventions';
+ }
+
+ if (!$config->conventions) {
+ $conventions = null;
+
+ } elseif (is_string($config->conventions)) {
+ $conventions = $builder->addDefinition($this->prefix("$name.$conventionsServiceName"))
+ ->setFactory(preg_match('#^[a-z]+$#Di', $config->conventions)
+ ? 'Nette\Database\Conventions\\' . ucfirst($config->conventions) . 'Conventions'
+ : $config->conventions)
+ ->setArguments(strtolower($config->conventions) === 'discovered' ? [$structure] : [])
+ ->setAutowired($config->autowired);
+
+ } else {
+ $conventions = Nette\DI\Helpers::filterArguments([$config->conventions])[0];
+ }
+
+ $builder->addDefinition($this->prefix("$name.explorer"))
+ ->setFactory(Nette\Database\Explorer::class, [$connection, $structure, $conventions])
+ ->setAutowired($config->autowired);
+
+ $builder->addAlias($this->prefix("$name.context"), $this->prefix("$name.explorer"));
+
+ if ($this->name === 'database') {
+ $builder->addAlias($this->prefix($name), $this->prefix("$name.connection"));
+ $builder->addAlias("nette.database.$name", $this->prefix($name));
+ $builder->addAlias("nette.database.$name.context", $this->prefix("$name.explorer"));
+ }
+ }
+}
diff --git a/vendor/nette/database/src/Bridges/DatabaseTracy/ConnectionPanel.php b/vendor/nette/database/src/Bridges/DatabaseTracy/ConnectionPanel.php
new file mode 100644
index 0000000..f122156
--- /dev/null
+++ b/vendor/nette/database/src/Bridges/DatabaseTracy/ConnectionPanel.php
@@ -0,0 +1,162 @@
+addPanel(self::renderException(...));
+
+ if ($addBarPanel) {
+ $panel = new self($connection, $blueScreen);
+ $panel->explain = $explain;
+ $panel->name = $name;
+ $bar ??= Tracy\Debugger::getBar();
+ $bar->addPanel($panel);
+ }
+
+ return $panel ?? null;
+ }
+
+
+ public function __construct(Connection $connection, Tracy\BlueScreen $blueScreen)
+ {
+ $connection->onQuery[] = $this->logQuery(...);
+ $this->blueScreen = $blueScreen;
+ }
+
+
+ private function logQuery(Connection $connection, $result): void
+ {
+ if ($this->disabled) {
+ return;
+ }
+
+ $this->count++;
+
+ $trace = $result instanceof \PDOException
+ ? array_map(fn($row) => array_diff_key($row, ['args' => null]), $result->getTrace())
+ : debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+
+ foreach ($trace as $row) {
+ if (preg_match('~\.(php.?|phtml)$~', $row['file'] ?? '') && !$this->blueScreen->isCollapsed($row['file'])) {
+ break;
+ }
+ array_shift($trace);
+ }
+
+ if ($result instanceof Nette\Database\ResultSet) {
+ $this->totalTime += $result->getTime();
+ if ($this->count < $this->maxQueries) {
+ $this->queries[] = [$connection, $result->getQueryString(), $result->getParameters(), $trace, $result->getTime(), $result->getRowCount(), null];
+ }
+ } elseif ($result instanceof \PDOException && $this->count < $this->maxQueries) {
+ $this->queries[] = [$connection, $result->queryString, null, $trace, null, null, $result->getMessage()];
+ }
+ }
+
+
+ public static function renderException(?\Throwable $e): ?array
+ {
+ if (!$e instanceof \PDOException) {
+ return null;
+ }
+
+ if (isset($e->queryString)) {
+ $sql = $e->queryString;
+
+ } elseif ($item = Tracy\Helpers::findTrace($e->getTrace(), 'PDO::prepare')) {
+ $sql = $item['args'][0];
+ }
+
+ return isset($sql) ? [
+ 'tab' => 'SQL',
+ 'panel' => Helpers::dumpSql($sql, $e->params ?? []),
+ ] : null;
+ }
+
+
+ public function getTab(): string
+ {
+ return Nette\Utils\Helpers::capture(function () {
+ $name = $this->name;
+ $count = $this->count;
+ $totalTime = $this->totalTime;
+ require __DIR__ . '/dist/tab.phtml';
+ });
+ }
+
+
+ public function getPanel(): ?string
+ {
+ if (!$this->count) {
+ return null;
+ }
+
+ $queries = [];
+ foreach ($this->queries as $query) {
+ [$connection, $sql, $params, , , , $error] = $query;
+ $explain = null;
+ $command = preg_match('#\s*\(?\s*(SELECT|INSERT|UPDATE|DELETE)\s#iA', $sql, $m)
+ ? strtolower($m[1])
+ : null;
+ if (!$error && $this->explain && $command === 'select') {
+ try {
+ $cmd = is_string($this->explain)
+ ? $this->explain
+ : 'EXPLAIN';
+ $explain = (new Nette\Database\ResultSet($connection, "$cmd $sql", $params))->fetchAll();
+ } catch (\PDOException) {
+ }
+ }
+
+ $query[] = $command;
+ $query[] = $explain;
+ $queries[] = $query;
+ }
+
+ return Nette\Utils\Helpers::capture(function () use ($queries, $connection) {
+ $name = $this->name;
+ $count = $this->count;
+ $totalTime = $this->totalTime;
+ $performanceScale = $this->performanceScale;
+ require __DIR__ . '/dist/panel.phtml';
+ });
+ }
+}
diff --git a/vendor/nette/database/src/Bridges/DatabaseTracy/dist/panel.phtml b/vendor/nette/database/src/Bridges/DatabaseTracy/dist/panel.phtml
new file mode 100644
index 0000000..84a178c
--- /dev/null
+++ b/vendor/nette/database/src/Bridges/DatabaseTracy/dist/panel.phtml
@@ -0,0 +1,83 @@
+
+
+
+Queries: = Tracy\Helpers::escapeHtml($count) ?>
+= Tracy\Helpers::escapeHtml($totalTime ? sprintf(', time: %0.3f ms', $totalTime * 1000) : '') ?>
+, = Tracy\Helpers::escapeHtml($name) ?>
+
+
+
+
+
+ Time ms
+ SQL Query
+ Rows
+
+
+
+
+ ERROR
+
+ = Tracy\Helpers::escapeHtml(sprintf('%0.3f', $time * 1000)) ?>
+
+
+
+ explain
+
+
+ trace
+
+
+
+
+ = Nette\Database\Helpers::dumpSql($sql, $params, $connection) ?>
+
+
+
+
+ $foo): ?> = Tracy\Helpers::escapeHtml($col) ?>
+
+
+
+ = Tracy\Helpers::escapeHtml($col) ?>
+
+
+
+
+ = substr_replace(Tracy\Helpers::editorLink($trace[0]['file'], $trace[0]['line']), ' class="nette-DbConnectionPanel-source"', 2, 0) ?>
+
+
+
+ = isset($row['file']) ? Tracy\Helpers::editorLink($row['file'], $row['line']) : '' ?>
+
+ = Tracy\Helpers::escapeHtml($row['class'] ?? '') ?>
+= Tracy\Helpers::escapeHtml($row['type'] ?? '') ?>
+= Tracy\Helpers::escapeHtml($row['function']) ?>
+()
+
+
+
+
+ = Tracy\Helpers::escapeHtml($rows) ?>
+
+
+
+
+
+
...and more
+
+
diff --git a/vendor/nette/database/src/Bridges/DatabaseTracy/dist/tab.phtml b/vendor/nette/database/src/Bridges/DatabaseTracy/dist/tab.phtml
new file mode 100644
index 0000000..8640ef8
--- /dev/null
+++ b/vendor/nette/database/src/Bridges/DatabaseTracy/dist/tab.phtml
@@ -0,0 +1,13 @@
+
+
+
+
+ = Tracy\Helpers::escapeHtml($totalTime ? sprintf('%0.1f ms / ', $totalTime * 1000) : '') ?>
+= Tracy\Helpers::escapeHtml($count) ?>
+
+
diff --git a/vendor/nette/database/src/Bridges/DatabaseTracy/panel.latte b/vendor/nette/database/src/Bridges/DatabaseTracy/panel.latte
new file mode 100644
index 0000000..39c66de
--- /dev/null
+++ b/vendor/nette/database/src/Bridges/DatabaseTracy/panel.latte
@@ -0,0 +1,71 @@
+
+
+Queries: {$count}{$totalTime ? sprintf(', time: %0.3f ms', $totalTime * 1000) : ''}, {$name}
+
+
+
+
+ Time ms
+ SQL Query
+ Rows
+
+
+ {foreach $queries as [$connection, $sql, $params, $trace, $time, $rows, $error, $command, $explain]}
+
+
+ {if $error}
+ ERROR
+ {elseif $time !== null}{sprintf('%0.3f', $time * 1000)}
+ {/if}
+
+ {if $explain}explain {/if}
+ {if $trace}trace {/if}
+
+
+
+ {Nette\Database\Helpers::dumpSql($sql, $params, $connection)|noescape}
+
+ {if $explain}
+
+
+ {foreach $explain[0] as $col => $foo}
+ {$col}
+ {/foreach}
+
+ {foreach $explain as $row}
+
+ {foreach $row as $col}
+ {$col}
+ {/foreach}
+
+ {/foreach}
+
+ {/if}
+
+ {if $trace}
+ {substr_replace(Tracy\Helpers::editorLink($trace[0][file], $trace[0][line]), ' class="nette-DbConnectionPanel-source"', 2, 0)}
+
+ {foreach $trace as $row}
+
+ {isset($row[file]) ? Tracy\Helpers::editorLink($row[file], $row[line]) : ''}
+ {$row[class] ?? ''}{$row[type] ?? ''}{$row[function]}()
+
+ {/foreach}
+
+ {/if}
+
+
+ {$rows}
+
+ {/foreach}
+
+
+ {if count($queries) < $count}
...and more
{/if}
+
diff --git a/vendor/nette/database/src/Bridges/DatabaseTracy/tab.latte b/vendor/nette/database/src/Bridges/DatabaseTracy/tab.latte
new file mode 100644
index 0000000..dfe92c6
--- /dev/null
+++ b/vendor/nette/database/src/Bridges/DatabaseTracy/tab.latte
@@ -0,0 +1,6 @@
+
+
+
+ {$totalTime ? sprintf('%0.1f ms / ', $totalTime * 1000) : ''}{$count}
+
diff --git a/vendor/nette/database/src/Database/Connection.php b/vendor/nette/database/src/Database/Connection.php
new file mode 100644
index 0000000..5898d0c
--- /dev/null
+++ b/vendor/nette/database/src/Database/Connection.php
@@ -0,0 +1,367 @@
+ Occurs after connection is established */
+ public array $onConnect = [];
+
+ /** @var array Occurs after query is executed */
+ public array $onQuery = [];
+ private Driver $driver;
+ private SqlPreprocessor $preprocessor;
+ private ?PDO $pdo = null;
+
+ /** @var callable(array, ResultSet): array */
+ private $rowNormalizer = [Helpers::class, 'normalizeRow'];
+ private ?string $sql = null;
+ private int $transactionDepth = 0;
+
+
+ public function __construct(
+ private readonly string $dsn,
+ #[\SensitiveParameter]
+ private readonly ?string $user = null,
+ #[\SensitiveParameter]
+ private readonly ?string $password = null,
+ private readonly array $options = [],
+ ) {
+ if (!empty($options['newDateTime'])) {
+ $this->rowNormalizer = fn($row, $resultSet) => Helpers::normalizeRow($row, $resultSet, DateTime::class);
+ }
+ if (empty($options['lazy'])) {
+ $this->connect();
+ }
+ }
+
+
+ /**
+ * @throws ConnectionException
+ */
+ public function connect(): void
+ {
+ if ($this->pdo) {
+ return;
+ }
+
+ try {
+ $this->pdo = new PDO($this->dsn, $this->user, $this->password, $this->options);
+ } catch (PDOException $e) {
+ throw ConnectionException::from($e);
+ }
+
+ $class = empty($this->options['driverClass'])
+ ? 'Nette\Database\Drivers\\' . ucfirst(str_replace('sql', 'Sql', $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME))) . 'Driver'
+ : $this->options['driverClass'];
+ $this->driver = new $class;
+ $this->preprocessor = new SqlPreprocessor($this);
+ $this->driver->initialize($this, $this->options);
+ Arrays::invoke($this->onConnect, $this);
+ }
+
+
+ /**
+ * Disconnects and connects to database again.
+ */
+ public function reconnect(): void
+ {
+ $this->disconnect();
+ $this->connect();
+ }
+
+
+ /**
+ * Disconnects from database.
+ */
+ public function disconnect(): void
+ {
+ $this->pdo = null;
+ }
+
+
+ public function getDsn(): string
+ {
+ return $this->dsn;
+ }
+
+
+ public function getPdo(): PDO
+ {
+ $this->connect();
+ return $this->pdo;
+ }
+
+
+ public function getDriver(): Driver
+ {
+ $this->connect();
+ return $this->driver;
+ }
+
+
+ /** @deprecated use getDriver() */
+ public function getSupplementalDriver(): Driver
+ {
+ $this->connect();
+ return $this->driver;
+ }
+
+
+ public function getReflection(): Reflection
+ {
+ return new Reflection($this->getDriver());
+ }
+
+
+ /**
+ * Sets callback for row preprocessing.
+ */
+ public function setRowNormalizer(?callable $normalizer): static
+ {
+ $this->rowNormalizer = $normalizer;
+ return $this;
+ }
+
+
+ /**
+ * Returns last inserted ID.
+ */
+ public function getInsertId(?string $sequence = null): string
+ {
+ try {
+ $res = $this->getPdo()->lastInsertId($sequence);
+ return $res === false ? '0' : $res;
+ } catch (PDOException $e) {
+ throw $this->driver->convertException($e);
+ }
+ }
+
+
+ /**
+ * Quotes string for use in SQL.
+ */
+ public function quote(string $string, int $type = PDO::PARAM_STR): string
+ {
+ try {
+ return $this->getPdo()->quote($string, $type);
+ } catch (PDOException $e) {
+ throw DriverException::from($e);
+ }
+ }
+
+
+ /**
+ * Starts a transaction.
+ * @throws \LogicException when called inside a transaction
+ */
+ public function beginTransaction(): void
+ {
+ if ($this->transactionDepth !== 0) {
+ throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
+ }
+
+ $this->query('::beginTransaction');
+ }
+
+
+ /**
+ * Commits current transaction.
+ * @throws \LogicException when called inside a transaction
+ */
+ public function commit(): void
+ {
+ if ($this->transactionDepth !== 0) {
+ throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
+ }
+
+ $this->query('::commit');
+ }
+
+
+ /**
+ * Rolls back current transaction.
+ * @throws \LogicException when called inside a transaction
+ */
+ public function rollBack(): void
+ {
+ if ($this->transactionDepth !== 0) {
+ throw new \LogicException(__METHOD__ . '() call is forbidden inside a transaction() callback');
+ }
+
+ $this->query('::rollBack');
+ }
+
+
+ /**
+ * Executes callback inside a transaction.
+ */
+ public function transaction(callable $callback): mixed
+ {
+ if ($this->transactionDepth === 0) {
+ $this->beginTransaction();
+ }
+
+ $this->transactionDepth++;
+ try {
+ $res = $callback($this);
+ } catch (\Throwable $e) {
+ $this->transactionDepth--;
+ if ($this->transactionDepth === 0) {
+ $this->rollback();
+ }
+
+ throw $e;
+ }
+
+ $this->transactionDepth--;
+ if ($this->transactionDepth === 0) {
+ $this->commit();
+ }
+
+ return $res;
+ }
+
+
+ /**
+ * Generates and executes SQL query.
+ * @param literal-string $sql
+ */
+ public function query(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ResultSet
+ {
+ [$this->sql, $params] = $this->preprocess($sql, ...$params);
+ try {
+ $result = new ResultSet($this, $this->sql, $params, $this->rowNormalizer);
+ } catch (PDOException $e) {
+ Arrays::invoke($this->onQuery, $this, $e);
+ throw $e;
+ }
+
+ Arrays::invoke($this->onQuery, $this, $result);
+ return $result;
+ }
+
+
+ /** @deprecated use query() */
+ public function queryArgs(string $sql, array $params): ResultSet
+ {
+ return $this->query($sql, ...$params);
+ }
+
+
+ /**
+ * @param literal-string $sql
+ * @return array{string, array}
+ */
+ public function preprocess(string $sql, ...$params): array
+ {
+ $this->connect();
+ return $params
+ ? $this->preprocessor->process(func_get_args())
+ : [$sql, []];
+ }
+
+
+ public function getLastQueryString(): ?string
+ {
+ return $this->sql;
+ }
+
+
+ /********************* shortcuts ****************d*g**/
+
+
+ /**
+ * Shortcut for query()->fetch()
+ * @param literal-string $sql
+ */
+ public function fetch(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ?Row
+ {
+ return $this->query($sql, ...$params)->fetch();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchAssoc()
+ * @param literal-string $sql
+ */
+ public function fetchAssoc(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ?array
+ {
+ return $this->query($sql, ...$params)->fetchAssoc();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchField()
+ * @param literal-string $sql
+ */
+ public function fetchField(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): mixed
+ {
+ return $this->query($sql, ...$params)->fetchField();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchList()
+ * @param literal-string $sql
+ */
+ public function fetchList(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ?array
+ {
+ return $this->query($sql, ...$params)->fetchList();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchList()
+ * @param literal-string $sql
+ */
+ public function fetchFields(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ?array
+ {
+ return $this->query($sql, ...$params)->fetchList();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchPairs()
+ * @param literal-string $sql
+ */
+ public function fetchPairs(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): array
+ {
+ return $this->query($sql, ...$params)->fetchPairs();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchAll()
+ * @param literal-string $sql
+ */
+ public function fetchAll(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): array
+ {
+ return $this->query($sql, ...$params)->fetchAll();
+ }
+
+
+ /**
+ * Creates SQL literal value.
+ */
+ public static function literal(string $value, ...$params): SqlLiteral
+ {
+ return new SqlLiteral($value, $params);
+ }
+}
diff --git a/vendor/nette/database/src/Database/Conventions.php b/vendor/nette/database/src/Database/Conventions.php
new file mode 100644
index 0000000..69dcb1b
--- /dev/null
+++ b/vendor/nette/database/src/Database/Conventions.php
@@ -0,0 +1,47 @@
+structure->getPrimaryKey($table);
+ }
+
+
+ public function getHasManyReference(string $nsTable, string $key): ?array
+ {
+ $candidates = $columnCandidates = [];
+ $targets = $this->structure->getHasManyReference($nsTable);
+ $table = preg_replace('#^(.*\.)?(.*)$#', '$2', $nsTable);
+
+ foreach ($targets as $targetNsTable => $targetColumns) {
+ $targetTable = preg_replace('#^(.*\.)?(.*)$#', '$2', $targetNsTable);
+ if (stripos($targetNsTable, $key) === false) {
+ continue;
+ }
+
+ foreach ($targetColumns as $targetColumn) {
+ if (stripos($targetColumn, $table) !== false) {
+ $columnCandidates[] = $candidate = [$targetNsTable, $targetColumn];
+ if (strcmp($targetTable, $key) === 0 || strcmp($targetNsTable, $key) === 0) {
+ return $candidate;
+ }
+ }
+
+ $candidates[] = [$targetTable, [$targetNsTable, $targetColumn]];
+ }
+ }
+
+ if (count($columnCandidates) === 1) {
+ return $columnCandidates[0];
+ } elseif (count($candidates) === 1) {
+ return $candidates[0][1];
+ }
+
+ foreach ($candidates as $candidate) {
+ if (strtolower($candidate[0]) === strtolower($key)) {
+ return $candidate[1];
+ }
+ }
+
+ if (!empty($candidates)) {
+ throw new AmbiguousReferenceKeyException('Ambiguous joining column in related call.');
+ }
+
+ if ($this->structure->isRebuilt()) {
+ return null;
+ }
+
+ $this->structure->rebuild();
+ return $this->getHasManyReference($nsTable, $key);
+ }
+
+
+ public function getBelongsToReference(string $table, string $key): ?array
+ {
+ $tableColumns = $this->structure->getBelongsToReference($table);
+
+ foreach ($tableColumns as $column => $targetTable) {
+ if (stripos($column, $key) !== false) {
+ return [$targetTable, $column];
+ }
+ }
+
+ if ($this->structure->isRebuilt()) {
+ return null;
+ }
+
+ $this->structure->rebuild();
+ return $this->getBelongsToReference($table, $key);
+ }
+}
diff --git a/vendor/nette/database/src/Database/Conventions/StaticConventions.php b/vendor/nette/database/src/Database/Conventions/StaticConventions.php
new file mode 100644
index 0000000..6344453
--- /dev/null
+++ b/vendor/nette/database/src/Database/Conventions/StaticConventions.php
@@ -0,0 +1,71 @@
+, %2$s for table name
+ * @param string $table %1$s stands for key used after ->, %2$s for table name
+ */
+ public function __construct(
+ protected readonly string $primary = 'id',
+ protected readonly string $foreign = '%s_id',
+ protected readonly string $table = '%s',
+ ) {
+ }
+
+
+ public function getPrimary(string $table): string
+ {
+ return sprintf($this->primary, $this->getColumnFromTable($table));
+ }
+
+
+ public function getHasManyReference(string $table, string $key): ?array
+ {
+ $table = $this->getColumnFromTable($table);
+ return [
+ sprintf($this->table, $key, $table),
+ sprintf($this->foreign, $table, $key),
+ ];
+ }
+
+
+ public function getBelongsToReference(string $table, string $key): ?array
+ {
+ $table = $this->getColumnFromTable($table);
+ return [
+ sprintf($this->table, $key, $table),
+ sprintf($this->foreign, $key, $table),
+ ];
+ }
+
+
+ protected function getColumnFromTable(string $name): string
+ {
+ if (
+ $this->table !== '%s'
+ && preg_match('(^' . str_replace('%s', '(.*)', preg_quote($this->table)) . '$)D', $name, $match)
+ ) {
+ return $match[1];
+ }
+
+ return $name;
+ }
+}
diff --git a/vendor/nette/database/src/Database/DateTime.php b/vendor/nette/database/src/Database/DateTime.php
new file mode 100644
index 0000000..ce9bbad
--- /dev/null
+++ b/vendor/nette/database/src/Database/DateTime.php
@@ -0,0 +1,34 @@
+format('c');
+ }
+
+
+ /**
+ * Returns the date and time in the format 'Y-m-d H:i:s.u'.
+ */
+ public function __toString(): string
+ {
+ return $this->format('Y-m-d H:i:s.u');
+ }
+}
diff --git a/vendor/nette/database/src/Database/Driver.php b/vendor/nette/database/src/Database/Driver.php
new file mode 100644
index 0000000..526b804
--- /dev/null
+++ b/vendor/nette/database/src/Database/Driver.php
@@ -0,0 +1,102 @@
+
+ */
+ function getTables(): array;
+
+ /**
+ * Returns metadata for all columns in a table.
+ * @return list
+ */
+ function getColumns(string $table): array;
+
+ /**
+ * Returns metadata for all indexes in a table.
+ * @return list, unique: bool, primary: bool}>
+ */
+ function getIndexes(string $table): array;
+
+ /**
+ * Returns metadata for all foreign keys in a table.
+ * @return list
+ */
+ function getForeignKeys(string $table): array;
+
+ /**
+ * Returns associative array of detected types (IStructure::FIELD_*) in result set.
+ * @return array
+ */
+ function getColumnTypes(\PDOStatement $statement): array;
+}
+
+
+interface_exists(ISupplementalDriver::class);
diff --git a/vendor/nette/database/src/Database/DriverException.php b/vendor/nette/database/src/Database/DriverException.php
new file mode 100644
index 0000000..aad02cd
--- /dev/null
+++ b/vendor/nette/database/src/Database/DriverException.php
@@ -0,0 +1,63 @@
+message, 0, $src);
+ $e->file = $src->file;
+ $e->line = $src->line;
+ if (!$src->errorInfo && preg_match('#SQLSTATE\[(.*?)\] \[(.*?)\] (.*)#A', $src->message, $m)) {
+ $m[2] = (int) $m[2];
+ $e->errorInfo = array_slice($m, 1);
+ $e->code = $m[1];
+ } else {
+ $e->errorInfo = $src->errorInfo;
+ $e->code = $src->code;
+ $e->code = $e->errorInfo[0] ?? $src->code;
+ }
+
+ return $e;
+ }
+
+
+ public function getDriverCode(): int|string|null
+ {
+ return $this->errorInfo[1] ?? null;
+ }
+
+
+ public function getSqlState(): ?string
+ {
+ return $this->errorInfo[0] ?? null;
+ }
+
+
+ public function getQueryString(): ?string
+ {
+ return $this->queryString;
+ }
+
+
+ public function getParameters(): ?array
+ {
+ return $this->params;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Drivers/MsSqlDriver.php b/vendor/nette/database/src/Database/Drivers/MsSqlDriver.php
new file mode 100644
index 0000000..5c71a7d
--- /dev/null
+++ b/vendor/nette/database/src/Database/Drivers/MsSqlDriver.php
@@ -0,0 +1,225 @@
+connection = $connection;
+ }
+
+
+ public function isSupported(string $feature): bool
+ {
+ return false;
+ }
+
+
+ public function convertException(\PDOException $e): Nette\Database\DriverException
+ {
+ return Nette\Database\DriverException::from($e);
+ }
+
+
+ /********************* SQL ****************d*g**/
+
+
+ public function delimite(string $name): string
+ {
+ // @see https://msdn.microsoft.com/en-us/library/ms176027.aspx
+ return '[' . str_replace(['[', ']'], ['[[', ']]'], $name) . ']';
+ }
+
+
+ public function formatDateTime(\DateTimeInterface $value): string
+ {
+ return $value->format("'Y-m-d H:i:s'");
+ }
+
+
+ public function formatDateInterval(\DateInterval $value): string
+ {
+ throw new Nette\NotSupportedException;
+ }
+
+
+ public function formatLike(string $value, int $pos): string
+ {
+ $value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
+ return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
+ }
+
+
+ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
+ {
+ if ($offset) {
+ throw new Nette\NotSupportedException('Offset is not supported by this database.');
+
+ } elseif ($limit < 0) {
+ throw new Nette\InvalidArgumentException('Negative offset or limit.');
+
+ } elseif ($limit !== null) {
+ $sql = preg_replace('#^\s*(SELECT(\s+DISTINCT|\s+ALL)?|UPDATE|DELETE)#i', '$0 TOP ' . $limit, $sql, 1, $count);
+ if (!$count) {
+ throw new Nette\InvalidArgumentException('SQL query must begin with SELECT, UPDATE or DELETE command.');
+ }
+ }
+ }
+
+
+ /********************* reflection ****************d*g**/
+
+
+ public function getTables(): array
+ {
+ $tables = [];
+ $rows = $this->connection->query('SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE FROM INFORMATION_SCHEMA.TABLES');
+ while ($row = $rows->fetch()) {
+ $tables[] = [
+ 'name' => $row['TABLE_SCHEMA'] . '.' . $row['TABLE_NAME'],
+ 'view' => ($row['TABLE_TYPE'] ?? null) === 'VIEW',
+ ];
+ }
+
+ return $tables;
+ }
+
+
+ public function getColumns(string $table): array
+ {
+ [$table_schema, $table_name] = explode('.', $table);
+ $columns = [];
+
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ COLUMN_NAME,
+ DATA_TYPE,
+ CHARACTER_MAXIMUM_LENGTH,
+ NUMERIC_PRECISION,
+ IS_NULLABLE,
+ COLUMN_DEFAULT,
+ DOMAIN_NAME
+ FROM
+ INFORMATION_SCHEMA.COLUMNS
+ WHERE
+ TABLE_SCHEMA = ?
+ AND TABLE_NAME = ?
+ X, $table_schema, $table_name);
+
+ while ($row = $rows->fetch()) {
+ $columns[] = [
+ 'name' => $row['COLUMN_NAME'],
+ 'table' => $table,
+ 'nativetype' => strtoupper($row['DATA_TYPE']),
+ 'size' => $row['CHARACTER_MAXIMUM_LENGTH'] ?? $row['NUMERIC_PRECISION'],
+ 'unsigned' => false,
+ 'nullable' => $row['IS_NULLABLE'] === 'YES',
+ 'default' => $row['COLUMN_DEFAULT'],
+ 'autoincrement' => $row['DOMAIN_NAME'] === 'COUNTER',
+ 'primary' => $row['COLUMN_NAME'] === 'ID',
+ 'vendor' => (array) $row,
+ ];
+ }
+
+ return $columns;
+ }
+
+
+ public function getIndexes(string $table): array
+ {
+ [, $table_name] = explode('.', $table);
+ $indexes = [];
+
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ name_index = ind.name,
+ id_column = ic.index_column_id,
+ name_column = col.name,
+ ind.is_unique,
+ ind.is_primary_key
+ FROM
+ sys.indexes ind
+ INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
+ INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
+ INNER JOIN sys.tables t ON ind.object_id = t.object_id
+ WHERE
+ t.name = ?
+ ORDER BY
+ t.name, ind.name, ind.index_id, ic.index_column_id
+ X, $table_name);
+
+ while ($row = $rows->fetch()) {
+ $id = $row['name_index'];
+ $indexes[$id]['name'] = $id;
+ $indexes[$id]['unique'] = $row['is_unique'] !== 'False';
+ $indexes[$id]['primary'] = $row['is_primary_key'] !== 'False';
+ $indexes[$id]['columns'][$row['id_column'] - 1] = $row['name_column'];
+ }
+
+ return array_values($indexes);
+ }
+
+
+ public function getForeignKeys(string $table): array
+ {
+ [$table_schema, $table_name] = explode('.', $table);
+ $keys = [];
+
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ obj.name AS [fk_name],
+ col1.name AS [column],
+ tab2.name AS [referenced_table],
+ col2.name AS [referenced_column]
+ FROM
+ sys.foreign_key_columns fkc
+ INNER JOIN sys.objects obj
+ ON obj.object_id = fkc.constraint_object_id
+ INNER JOIN sys.tables tab1
+ ON tab1.object_id = fkc.parent_object_id
+ INNER JOIN sys.schemas sch
+ ON tab1.schema_id = sch.schema_id
+ INNER JOIN sys.columns col1
+ ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
+ INNER JOIN sys.tables tab2
+ ON tab2.object_id = fkc.referenced_object_id
+ INNER JOIN sys.columns col2
+ ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
+ WHERE
+ tab1.name = ?
+ X, $table_name);
+
+ $id = 0;
+ while ($row = $rows->fetch()) {
+ $keys[$id]['name'] = $row['fk_name'];
+ $keys[$id]['local'] = $row['column'];
+ $keys[$id]['table'] = $table_schema . '.' . $row['referenced_table'];
+ $keys[$id++]['foreign'] = $row['referenced_column'];
+ }
+
+ return array_values($keys);
+ }
+
+
+ public function getColumnTypes(\PDOStatement $statement): array
+ {
+ return Nette\Database\Helpers::detectTypes($statement);
+ }
+}
diff --git a/vendor/nette/database/src/Database/Drivers/MySqlDriver.php b/vendor/nette/database/src/Database/Drivers/MySqlDriver.php
new file mode 100644
index 0000000..9fab9c3
--- /dev/null
+++ b/vendor/nette/database/src/Database/Drivers/MySqlDriver.php
@@ -0,0 +1,224 @@
+ character encoding to set (default is utf8mb4)
+ * - sqlmode => see http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html
+ * - convertBoolean => converts INT(1) to boolean
+ */
+ public function initialize(Nette\Database\Connection $connection, array $options): void
+ {
+ $this->connection = $connection;
+ $charset = $options['charset'] ?? 'utf8mb4';
+ if ($charset) {
+ $connection->query('SET NAMES ?', $charset);
+ }
+
+ if (isset($options['sqlmode'])) {
+ $connection->query('SET sql_mode=?', $options['sqlmode']);
+ }
+
+ $this->convertBoolean = (bool) ($options['convertBoolean'] ?? $options['supportBooleans'] ?? false);
+ }
+
+
+ public function isSupported(string $feature): bool
+ {
+ // MULTI_COLUMN_AS_OR_COND due to mysql bugs:
+ // - http://bugs.mysql.com/bug.php?id=31188
+ // - http://bugs.mysql.com/bug.php?id=35819
+ // and more.
+ return $feature === self::SupportSelectUngroupedColumns || $feature === self::SupportMultiColumnAsOrCondition;
+ }
+
+
+ public function convertException(\PDOException $e): Nette\Database\DriverException
+ {
+ $code = $e->errorInfo[1] ?? null;
+ if (in_array($code, [1216, 1217, 1451, 1452, 1701], strict: true)) {
+ return Nette\Database\ForeignKeyConstraintViolationException::from($e);
+
+ } elseif (in_array($code, [1062, 1557, 1569, 1586], strict: true)) {
+ return Nette\Database\UniqueConstraintViolationException::from($e);
+
+ } elseif ($code >= 2001 && $code <= 2028) {
+ return Nette\Database\ConnectionException::from($e);
+
+ } elseif (in_array($code, [1048, 1121, 1138, 1171, 1252, 1263, 1566], strict: true)) {
+ return Nette\Database\NotNullConstraintViolationException::from($e);
+
+ } else {
+ return Nette\Database\DriverException::from($e);
+ }
+ }
+
+
+ /********************* SQL ****************d*g**/
+
+
+ public function delimite(string $name): string
+ {
+ // @see http://dev.mysql.com/doc/refman/5.0/en/identifiers.html
+ return '`' . str_replace('`', '``', $name) . '`';
+ }
+
+
+ public function formatDateTime(\DateTimeInterface $value): string
+ {
+ return $value->format("'Y-m-d H:i:s'");
+ }
+
+
+ public function formatDateInterval(\DateInterval $value): string
+ {
+ return $value->format("'%r%h:%I:%S'");
+ }
+
+
+ public function formatLike(string $value, int $pos): string
+ {
+ $value = str_replace('\\', '\\\\', $value);
+ $value = addcslashes(substr($this->connection->quote($value), 1, -1), '%_');
+ return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
+ }
+
+
+ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
+ {
+ if ($limit < 0 || $offset < 0) {
+ throw new Nette\InvalidArgumentException('Negative offset or limit.');
+
+ } elseif ($limit !== null || $offset) {
+ // see http://dev.mysql.com/doc/refman/5.0/en/select.html
+ $sql .= ' LIMIT ' . ($limit ?? '18446744073709551615')
+ . ($offset ? ' OFFSET ' . $offset : '');
+ }
+ }
+
+
+ /********************* reflection ****************d*g**/
+
+
+ public function getTables(): array
+ {
+ $tables = [];
+ $rows = $this->connection->query('SHOW FULL TABLES');
+ while ($row = $rows->fetch()) {
+ $tables[] = [
+ 'name' => $row[0],
+ 'view' => ($row[1] ?? null) === 'VIEW',
+ ];
+ }
+
+ return $tables;
+ }
+
+
+ public function getColumns(string $table): array
+ {
+ $columns = [];
+ $rows = $this->connection->query('SHOW FULL COLUMNS FROM ' . $this->delimite($table));
+ while ($row = $rows->fetch()) {
+ $row = array_change_key_case((array) $row, CASE_LOWER);
+ $typeInfo = Nette\Database\Helpers::parseColumnType($row['type']);
+ $columns[] = [
+ 'name' => $row['field'],
+ 'table' => $table,
+ 'nativetype' => strtoupper($typeInfo['type']),
+ 'size' => $typeInfo['length'],
+ 'nullable' => $row['null'] === 'YES',
+ 'default' => $row['default'],
+ 'autoincrement' => $row['extra'] === 'auto_increment',
+ 'primary' => $row['key'] === 'PRI',
+ 'vendor' => $row,
+ ];
+ }
+
+ return $columns;
+ }
+
+
+ public function getIndexes(string $table): array
+ {
+ $indexes = [];
+ $rows = $this->connection->query('SHOW INDEX FROM ' . $this->delimite($table));
+ while ($row = $rows->fetch()) {
+ $id = $row['Key_name'];
+ $indexes[$id]['name'] = $id;
+ $indexes[$id]['unique'] = !$row['Non_unique'];
+ $indexes[$id]['primary'] = $row['Key_name'] === 'PRIMARY';
+ $indexes[$id]['columns'][$row['Seq_in_index'] - 1] = $row['Column_name'];
+ }
+
+ return array_values($indexes);
+ }
+
+
+ public function getForeignKeys(string $table): array
+ {
+ $keys = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
+ FROM information_schema.KEY_COLUMN_USAGE
+ WHERE TABLE_SCHEMA = DATABASE()
+ AND REFERENCED_TABLE_NAME IS NOT NULL
+ AND TABLE_NAME = ?
+ X, $table);
+
+ $id = 0;
+ while ($row = $rows->fetch()) {
+ $keys[$id]['name'] = $row['CONSTRAINT_NAME'];
+ $keys[$id]['local'] = $row['COLUMN_NAME'];
+ $keys[$id]['table'] = $row['REFERENCED_TABLE_NAME'];
+ $keys[$id++]['foreign'] = $row['REFERENCED_COLUMN_NAME'];
+ }
+
+ return array_values($keys);
+ }
+
+
+ public function getColumnTypes(\PDOStatement $statement): array
+ {
+ $types = [];
+ $count = $statement->columnCount();
+ for ($col = 0; $col < $count; $col++) {
+ $meta = $statement->getColumnMeta($col);
+ if (isset($meta['native_type'])) {
+ $types[$meta['name']] = match (true) {
+ $meta['native_type'] === 'NEWDECIMAL' && $meta['precision'] === 0 => Nette\Database\IStructure::FIELD_INTEGER,
+ $meta['native_type'] === 'TINY' && $meta['len'] === 1 && $this->convertBoolean => Nette\Database\IStructure::FIELD_BOOL,
+ $meta['native_type'] === 'TIME' => Nette\Database\IStructure::FIELD_TIME_INTERVAL,
+ default => Nette\Database\Helpers::detectType($meta['native_type']),
+ };
+ }
+ }
+
+ return $types;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Drivers/OciDriver.php b/vendor/nette/database/src/Database/Drivers/OciDriver.php
new file mode 100644
index 0000000..1976f62
--- /dev/null
+++ b/vendor/nette/database/src/Database/Drivers/OciDriver.php
@@ -0,0 +1,142 @@
+connection = $connection;
+ $this->fmtDateTime = $options['formatDateTime'] ?? 'U';
+ }
+
+
+ public function isSupported(string $feature): bool
+ {
+ return $feature === self::SupportSequence;
+ }
+
+
+ public function convertException(\PDOException $e): Nette\Database\DriverException
+ {
+ $code = $e->errorInfo[1] ?? null;
+ if (in_array($code, [1, 2299, 38911], strict: true)) {
+ return Nette\Database\UniqueConstraintViolationException::from($e);
+
+ } elseif (in_array($code, [1400], strict: true)) {
+ return Nette\Database\NotNullConstraintViolationException::from($e);
+
+ } elseif (in_array($code, [2266, 2291, 2292], strict: true)) {
+ return Nette\Database\ForeignKeyConstraintViolationException::from($e);
+
+ } else {
+ return Nette\Database\DriverException::from($e);
+ }
+ }
+
+
+ /********************* SQL ****************d*g**/
+
+
+ public function delimite(string $name): string
+ {
+ // @see http://download.oracle.com/docs/cd/B10500_01/server.920/a96540/sql_elements9a.htm
+ return '"' . str_replace('"', '""', $name) . '"';
+ }
+
+
+ public function formatDateTime(\DateTimeInterface $value): string
+ {
+ return $value->format($this->fmtDateTime);
+ }
+
+
+ public function formatDateInterval(\DateInterval $value): string
+ {
+ throw new Nette\NotSupportedException;
+ }
+
+
+ public function formatLike(string $value, int $pos): string
+ {
+ throw new Nette\NotImplementedException;
+ }
+
+
+ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
+ {
+ if ($limit < 0 || $offset < 0) {
+ throw new Nette\InvalidArgumentException('Negative offset or limit.');
+
+ } elseif ($offset) {
+ // see http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html
+ $sql = 'SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM (' . $sql . ') t '
+ . ($limit !== null ? 'WHERE ROWNUM <= ' . ($offset + $limit) : '')
+ . ') WHERE "__rnum" > ' . $offset;
+
+ } elseif ($limit !== null) {
+ $sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . $limit;
+ }
+ }
+
+
+ /********************* reflection ****************d*g**/
+
+
+ public function getTables(): array
+ {
+ $tables = [];
+ $rows = $this->connection->query('SELECT * FROM cat');
+ while ($row = $rows->fetch()) {
+ if ($row[1] === 'TABLE' || $row[1] === 'VIEW') {
+ $tables[] = [
+ 'name' => $row[0],
+ 'view' => $row[1] === 'VIEW',
+ ];
+ }
+ }
+
+ return $tables;
+ }
+
+
+ public function getColumns(string $table): array
+ {
+ throw new Nette\NotImplementedException;
+ }
+
+
+ public function getIndexes(string $table): array
+ {
+ throw new Nette\NotImplementedException;
+ }
+
+
+ public function getForeignKeys(string $table): array
+ {
+ throw new Nette\NotImplementedException;
+ }
+
+
+ public function getColumnTypes(\PDOStatement $statement): array
+ {
+ return [];
+ }
+}
diff --git a/vendor/nette/database/src/Database/Drivers/OdbcDriver.php b/vendor/nette/database/src/Database/Drivers/OdbcDriver.php
new file mode 100644
index 0000000..da1aa31
--- /dev/null
+++ b/vendor/nette/database/src/Database/Drivers/OdbcDriver.php
@@ -0,0 +1,113 @@
+format('#m/d/Y H:i:s#');
+ }
+
+
+ public function formatDateInterval(\DateInterval $value): string
+ {
+ throw new Nette\NotSupportedException;
+ }
+
+
+ public function formatLike(string $value, int $pos): string
+ {
+ $value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
+ return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
+ }
+
+
+ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
+ {
+ if ($offset) {
+ throw new Nette\NotSupportedException('Offset is not supported by this database.');
+
+ } elseif ($limit < 0) {
+ throw new Nette\InvalidArgumentException('Negative offset or limit.');
+
+ } elseif ($limit !== null) {
+ $sql = preg_replace('#^\s*(SELECT(\s+DISTINCT|\s+ALL)?|UPDATE|DELETE)#i', '$0 TOP ' . $limit, $sql, 1, $count);
+ if (!$count) {
+ throw new Nette\InvalidArgumentException('SQL query must begin with SELECT, UPDATE or DELETE command.');
+ }
+ }
+ }
+
+
+ /********************* reflection ****************d*g**/
+
+
+ public function getTables(): array
+ {
+ throw new Nette\NotImplementedException;
+ }
+
+
+ public function getColumns(string $table): array
+ {
+ throw new Nette\NotImplementedException;
+ }
+
+
+ public function getIndexes(string $table): array
+ {
+ throw new Nette\NotImplementedException;
+ }
+
+
+ public function getForeignKeys(string $table): array
+ {
+ throw new Nette\NotImplementedException;
+ }
+
+
+ public function getColumnTypes(\PDOStatement $statement): array
+ {
+ return [];
+ }
+}
diff --git a/vendor/nette/database/src/Database/Drivers/PgSqlDriver.php b/vendor/nette/database/src/Database/Drivers/PgSqlDriver.php
new file mode 100644
index 0000000..2c27561
--- /dev/null
+++ b/vendor/nette/database/src/Database/Drivers/PgSqlDriver.php
@@ -0,0 +1,260 @@
+connection = $connection;
+ }
+
+
+ public function isSupported(string $feature): bool
+ {
+ return $feature === self::SupportSequence || $feature === self::SupportSchema;
+ }
+
+
+ public function convertException(\PDOException $e): Nette\Database\DriverException
+ {
+ $code = $e->errorInfo[0] ?? null;
+ if ($code === '0A000' && str_contains($e->getMessage(), 'truncate')) {
+ return Nette\Database\ForeignKeyConstraintViolationException::from($e);
+
+ } elseif ($code === '23502') {
+ return Nette\Database\NotNullConstraintViolationException::from($e);
+
+ } elseif ($code === '23503') {
+ return Nette\Database\ForeignKeyConstraintViolationException::from($e);
+
+ } elseif ($code === '23505') {
+ return Nette\Database\UniqueConstraintViolationException::from($e);
+
+ } elseif ($code === '08006') {
+ return Nette\Database\ConnectionException::from($e);
+
+ } else {
+ return Nette\Database\DriverException::from($e);
+ }
+ }
+
+
+ /********************* SQL ****************d*g**/
+
+
+ public function delimite(string $name): string
+ {
+ // @see http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
+ return '"' . str_replace('"', '""', $name) . '"';
+ }
+
+
+ public function formatDateTime(\DateTimeInterface $value): string
+ {
+ return $value->format("'Y-m-d H:i:s'");
+ }
+
+
+ public function formatDateInterval(\DateInterval $value): string
+ {
+ throw new Nette\NotSupportedException;
+ }
+
+
+ public function formatLike(string $value, int $pos): string
+ {
+ $bs = substr($this->connection->quote('\\'), 1, -1); // standard_conforming_strings = on/off
+ $value = substr($this->connection->quote($value), 1, -1);
+ $value = strtr($value, ['%' => $bs . '%', '_' => $bs . '_', '\\' => '\\\\']);
+ return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
+ }
+
+
+ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
+ {
+ if ($limit < 0 || $offset < 0) {
+ throw new Nette\InvalidArgumentException('Negative offset or limit.');
+ }
+
+ if ($limit !== null) {
+ $sql .= ' LIMIT ' . $limit;
+ }
+
+ if ($offset) {
+ $sql .= ' OFFSET ' . $offset;
+ }
+ }
+
+
+ /********************* reflection ****************d*g**/
+
+
+ public function getTables(): array
+ {
+ $tables = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT DISTINCT ON (c.relname)
+ c.relname::varchar AS name,
+ c.relkind IN ('v', 'm') AS view,
+ n.nspname::varchar || '.' || c.relname::varchar AS "fullName"
+ FROM
+ pg_catalog.pg_class AS c
+ JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace
+ WHERE
+ c.relkind IN ('r', 'v', 'm', 'p')
+ AND n.nspname = ANY (pg_catalog.current_schemas(FALSE))
+ ORDER BY
+ c.relname
+ X);
+
+ while ($row = $rows->fetch()) {
+ $tables[] = (array) $row;
+ }
+
+ return $tables;
+ }
+
+
+ public function getColumns(string $table): array
+ {
+ $columns = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ a.attname::varchar AS name,
+ c.relname::varchar AS table,
+ upper(t.typname) AS nativetype,
+ CASE
+ WHEN a.atttypid IN (1700, 1231) THEN ((a.atttypmod - 4) >> 16) & 65535 -- precision for numeric/decimal
+ WHEN a.atttypmod > 0 THEN a.atttypmod - 4 -- length for varchar etc.
+ WHEN t.typlen > 0 THEN t.typlen -- length for fixed-length types
+ ELSE NULL
+ END AS size,
+ NOT (a.attnotnull OR t.typtype = 'd' AND t.typnotnull) AS nullable,
+ pg_catalog.pg_get_expr(ad.adbin, 'pg_catalog.pg_attrdef'::regclass)::varchar AS default,
+ coalesce(co.contype = 'p' AND (seq.relname IS NOT NULL OR strpos(pg_catalog.pg_get_expr(ad.adbin, ad.adrelid), 'nextval') = 1), FALSE) AS autoincrement,
+ coalesce(co.contype = 'p', FALSE) AS primary,
+ coalesce(seq.relname, substring(pg_catalog.pg_get_expr(ad.adbin, 'pg_catalog.pg_attrdef'::regclass) from 'nextval[(]''"?([^''"]+)')) AS sequence
+ FROM
+ pg_catalog.pg_attribute AS a
+ JOIN pg_catalog.pg_class AS c ON a.attrelid = c.oid
+ JOIN pg_catalog.pg_type AS t ON a.atttypid = t.oid
+ LEFT JOIN pg_catalog.pg_depend AS d ON d.refobjid = c.oid AND d.refobjsubid = a.attnum AND d.deptype = 'i'
+ LEFT JOIN pg_catalog.pg_class AS seq ON seq.oid = d.objid AND seq.relkind = 'S'
+ LEFT JOIN pg_catalog.pg_attrdef AS ad ON ad.adrelid = c.oid AND ad.adnum = a.attnum
+ LEFT JOIN pg_catalog.pg_constraint AS co ON co.connamespace = c.relnamespace AND contype = 'p' AND co.conrelid = c.oid AND a.attnum = ANY(co.conkey)
+ WHERE
+ c.relkind IN ('r', 'v', 'm', 'p')
+ AND c.oid = ?::regclass
+ AND a.attnum > 0
+ AND NOT a.attisdropped
+ ORDER BY
+ a.attnum
+ X, $this->delimiteFQN($table));
+
+ while ($row = $rows->fetch()) {
+ $column = (array) $row;
+ $column['vendor'] = $column;
+ unset($column['sequence']);
+
+ $columns[] = $column;
+ }
+
+ return $columns;
+ }
+
+
+ public function getIndexes(string $table): array
+ {
+ $indexes = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ c2.relname::varchar AS name,
+ i.indisunique AS unique,
+ i.indisprimary AS primary,
+ a.attname::varchar AS column
+ FROM
+ pg_catalog.pg_class AS c1
+ JOIN pg_catalog.pg_index AS i ON c1.oid = i.indrelid
+ JOIN pg_catalog.pg_class AS c2 ON i.indexrelid = c2.oid
+ LEFT JOIN pg_catalog.pg_attribute AS a ON c1.oid = a.attrelid AND a.attnum = ANY(i.indkey)
+ WHERE
+ c1.relkind IN ('r', 'p')
+ AND c1.oid = ?::regclass
+ X, $this->delimiteFQN($table));
+
+ while ($row = $rows->fetch()) {
+ $id = $row['name'];
+ $indexes[$id]['name'] = $id;
+ $indexes[$id]['unique'] = $row['unique'];
+ $indexes[$id]['primary'] = $row['primary'];
+ $indexes[$id]['columns'][] = $row['column'];
+ }
+
+ return array_values($indexes);
+ }
+
+
+ public function getForeignKeys(string $table): array
+ {
+ /* Doesn't work with multi-column foreign keys */
+ $keys = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ co.conname::varchar AS name,
+ al.attname::varchar AS local,
+ nf.nspname || '.' || cf.relname::varchar AS table,
+ af.attname::varchar AS foreign
+ FROM
+ pg_catalog.pg_constraint AS co
+ JOIN pg_catalog.pg_class AS cl ON co.conrelid = cl.oid
+ JOIN pg_catalog.pg_class AS cf ON co.confrelid = cf.oid
+ JOIN pg_catalog.pg_namespace AS nf ON nf.oid = cf.relnamespace
+ JOIN pg_catalog.pg_attribute AS al ON al.attrelid = cl.oid AND al.attnum = co.conkey[1]
+ JOIN pg_catalog.pg_attribute AS af ON af.attrelid = cf.oid AND af.attnum = co.confkey[1]
+ WHERE
+ co.contype = 'f'
+ AND cl.oid = ?::regclass
+ AND nf.nspname = ANY (pg_catalog.current_schemas(FALSE))
+ X, $this->delimiteFQN($table));
+
+ while ($row = $rows->fetch()) {
+ $keys[] = (array) $row;
+ }
+ return $keys;
+ }
+
+
+ public function getColumnTypes(\PDOStatement $statement): array
+ {
+ static $cache;
+ $item = &$cache[$statement->queryString];
+ $item ??= Nette\Database\Helpers::detectTypes($statement);
+ return $item;
+ }
+
+
+ /**
+ * Converts: schema.name => "schema"."name"
+ */
+ private function delimiteFQN(string $name): string
+ {
+ return implode('.', array_map([$this, 'delimite'], explode('.', $name)));
+ }
+}
diff --git a/vendor/nette/database/src/Database/Drivers/SqliteDriver.php b/vendor/nette/database/src/Database/Drivers/SqliteDriver.php
new file mode 100644
index 0000000..c50caa1
--- /dev/null
+++ b/vendor/nette/database/src/Database/Drivers/SqliteDriver.php
@@ -0,0 +1,252 @@
+connection = $connection;
+ $this->fmtDateTime = $options['formatDateTime'] ?? 'U';
+ }
+
+
+ public function isSupported(string $feature): bool
+ {
+ return $feature === self::SupportMultiInsertAsSelect || $feature === self::SupportMultiColumnAsOrCondition;
+ }
+
+
+ public function convertException(\PDOException $e): Nette\Database\DriverException
+ {
+ $code = $e->errorInfo[1] ?? null;
+ $msg = $e->getMessage();
+ if ($code !== 19) {
+ return Nette\Database\DriverException::from($e);
+
+ } elseif (
+ str_contains($msg, 'must be unique')
+ || str_contains($msg, 'is not unique')
+ || str_contains($msg, 'UNIQUE constraint failed')
+ ) {
+ return Nette\Database\UniqueConstraintViolationException::from($e);
+
+ } elseif (
+ str_contains($msg, 'may not be null')
+ || str_contains($msg, 'NOT NULL constraint failed')
+ ) {
+ return Nette\Database\NotNullConstraintViolationException::from($e);
+
+ } elseif (
+ str_contains($msg, 'foreign key constraint failed')
+ || str_contains($msg, 'FOREIGN KEY constraint failed')
+ ) {
+ return Nette\Database\ForeignKeyConstraintViolationException::from($e);
+
+ } else {
+ return Nette\Database\ConstraintViolationException::from($e);
+ }
+ }
+
+
+ /********************* SQL ****************d*g**/
+
+
+ public function delimite(string $name): string
+ {
+ return '[' . strtr($name, '[]', ' ') . ']';
+ }
+
+
+ public function formatDateTime(\DateTimeInterface $value): string
+ {
+ return $value->format($this->fmtDateTime);
+ }
+
+
+ public function formatDateInterval(\DateInterval $value): string
+ {
+ throw new Nette\NotSupportedException;
+ }
+
+
+ public function formatLike(string $value, int $pos): string
+ {
+ $value = addcslashes(substr($this->connection->quote($value), 1, -1), '%_\\');
+ return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'";
+ }
+
+
+ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
+ {
+ if ($limit < 0 || $offset < 0) {
+ throw new Nette\InvalidArgumentException('Negative offset or limit.');
+
+ } elseif ($limit !== null || $offset) {
+ $sql .= ' LIMIT ' . ($limit ?? '-1')
+ . ($offset ? ' OFFSET ' . $offset : '');
+ }
+ }
+
+
+ /********************* reflection ****************d*g**/
+
+
+ public function getTables(): array
+ {
+ $tables = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT name, type = 'view' as view
+ FROM sqlite_master
+ WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%'
+ UNION ALL
+ SELECT name, type = 'view' as view
+ FROM sqlite_temp_master
+ WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%'
+ ORDER BY name
+ X);
+
+ while ($row = $rows->fetch()) {
+ $tables[] = [
+ 'name' => $row['name'],
+ 'view' => (bool) $row['view'],
+ ];
+ }
+
+ return $tables;
+ }
+
+
+ public function getColumns(string $table): array
+ {
+ $createSql = $this->connection->query(<<<'X'
+ SELECT sql
+ FROM sqlite_master
+ WHERE type = 'table' AND name = ?
+ UNION ALL
+ SELECT sql
+ FROM sqlite_temp_master
+ WHERE type = 'table' AND name = ?
+ X, $table, $table)->fetch();
+
+ $columns = [];
+ $rows = $this->connection->query("PRAGMA table_info({$this->delimite($table)})");
+ while ($row = $rows->fetch()) {
+ $column = $row['name'];
+ $pattern = "/(\"$column\"|`$column`|\\[$column\\]|$column)\\s+[^,]+\\s+PRIMARY\\s+KEY\\s+AUTOINCREMENT/Ui";
+ $typeInfo = Nette\Database\Helpers::parseColumnType($row['type']);
+ $columns[] = [
+ 'name' => $column,
+ 'table' => $table,
+ 'nativetype' => strtoupper($typeInfo['type'] ?? 'BLOB'),
+ 'size' => $typeInfo['length'],
+ 'nullable' => $row['notnull'] == 0,
+ 'default' => $row['dflt_value'],
+ 'autoincrement' => $createSql && preg_match($pattern, $createSql['sql']),
+ 'primary' => $row['pk'] > 0,
+ 'vendor' => (array) $row,
+ ];
+ }
+
+ return $columns;
+ }
+
+
+ public function getIndexes(string $table): array
+ {
+ $indexes = [];
+ $rows = $this->connection->query("PRAGMA index_list({$this->delimite($table)})");
+ while ($row = $rows->fetch()) {
+ $id = $row['name'];
+ $indexes[$id]['name'] = $id;
+ $indexes[$id]['unique'] = (bool) $row['unique'];
+ $indexes[$id]['primary'] = false;
+ }
+
+ foreach ($indexes as $index => $values) {
+ $res = $this->connection->query("PRAGMA index_info({$this->delimite($index)})");
+ while ($row = $res->fetch()) {
+ $indexes[$index]['columns'][] = $row['name'];
+ }
+ }
+
+ $columns = $this->getColumns($table);
+ foreach ($indexes as $index => $values) {
+ $column = $values['columns'][0];
+ foreach ($columns as $info) {
+ if ($column === $info['name']) {
+ $indexes[$index]['primary'] = (bool) $info['primary'];
+ break;
+ }
+ }
+ }
+
+ if (!$indexes) { // @see http://www.sqlite.org/lang_createtable.html#rowid
+ foreach ($columns as $column) {
+ if ($column['vendor']['pk']) {
+ $indexes[] = [
+ 'name' => 'ROWID',
+ 'unique' => true,
+ 'primary' => true,
+ 'columns' => [$column['name']],
+ ];
+ break;
+ }
+ }
+ }
+
+ return array_values($indexes);
+ }
+
+
+ public function getForeignKeys(string $table): array
+ {
+ $keys = [];
+ $rows = $this->connection->query("PRAGMA foreign_key_list({$this->delimite($table)})");
+ while ($row = $rows->fetch()) {
+ $id = $row['id'];
+ $keys[$id]['name'] = $id;
+ $keys[$id]['local'] = $row['from'];
+ $keys[$id]['table'] = $row['table'];
+ $keys[$id]['foreign'] = $row['to'];
+ }
+
+ return array_values($keys);
+ }
+
+
+ public function getColumnTypes(\PDOStatement $statement): array
+ {
+ $types = [];
+ $count = $statement->columnCount();
+ for ($col = 0; $col < $count; $col++) {
+ $meta = $statement->getColumnMeta($col);
+ if (isset($meta['sqlite:decl_type'])) {
+ $types[$meta['name']] = $this->fmtDateTime === 'U' && in_array($meta['sqlite:decl_type'], ['DATE', 'DATETIME'], strict: true)
+ ? Nette\Database\IStructure::FIELD_UNIX_TIMESTAMP
+ : Nette\Database\Helpers::detectType($meta['sqlite:decl_type']);
+ } elseif (isset($meta['native_type'])) {
+ $types[$meta['name']] = Nette\Database\Helpers::detectType($meta['native_type']);
+ }
+ }
+
+ return $types;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Drivers/SqlsrvDriver.php b/vendor/nette/database/src/Database/Drivers/SqlsrvDriver.php
new file mode 100644
index 0000000..f00c574
--- /dev/null
+++ b/vendor/nette/database/src/Database/Drivers/SqlsrvDriver.php
@@ -0,0 +1,243 @@
+connection = $connection;
+ }
+
+
+ public function isSupported(string $feature): bool
+ {
+ return false;
+ }
+
+
+ public function convertException(\PDOException $e): Nette\Database\DriverException
+ {
+ return Nette\Database\DriverException::from($e);
+ }
+
+
+ /********************* SQL ****************d*g**/
+
+
+ public function delimite(string $name): string
+ {
+ /** @see https://msdn.microsoft.com/en-us/library/ms176027.aspx */
+ return '[' . str_replace(']', ']]', $name) . ']';
+ }
+
+
+ public function formatDateTime(\DateTimeInterface $value): string
+ {
+ /** @see https://msdn.microsoft.com/en-us/library/ms187819.aspx */
+ return $value->format("'Y-m-d\\TH:i:s'");
+ }
+
+
+ public function formatDateInterval(\DateInterval $value): string
+ {
+ throw new Nette\NotSupportedException;
+ }
+
+
+ public function formatLike(string $value, int $pos): string
+ {
+ /** @see https://msdn.microsoft.com/en-us/library/ms179859.aspx */
+ $value = strtr($value, ["'" => "''", '%' => '[%]', '_' => '[_]', '[' => '[[]']);
+ return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'");
+ }
+
+
+ public function applyLimit(string &$sql, ?int $limit, ?int $offset): void
+ {
+ if ($limit < 0 || $offset < 0) {
+ throw new Nette\InvalidArgumentException('Negative offset or limit.');
+
+ } elseif ($limit !== null || $offset) {
+ // requires ORDER BY, see https://technet.microsoft.com/en-us/library/gg699618(v=sql.110).aspx
+ $sql .= ' OFFSET ' . (int) $offset . ' ROWS '
+ . 'FETCH NEXT ' . (int) $limit . ' ROWS ONLY';
+ }
+ }
+
+
+ /********************* reflection ****************d*g**/
+
+
+ public function getTables(): array
+ {
+ $tables = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ name,
+ CASE type
+ WHEN 'U' THEN 0
+ WHEN 'V' THEN 1
+ END AS [view]
+ FROM
+ sys.objects
+ WHERE
+ type IN ('U', 'V')
+ X);
+
+ while ($row = $rows->fetch()) {
+ $tables[] = [
+ 'name' => $row['name'],
+ 'view' => (bool) $row['view'],
+ ];
+ }
+
+ return $tables;
+ }
+
+
+ public function getColumns(string $table): array
+ {
+ $columns = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ c.name AS name,
+ o.name AS [table],
+ UPPER(t.name) AS nativetype,
+ CASE
+ WHEN c.precision <> 0 THEN c.precision
+ WHEN c.max_length <> -1 THEN c.max_length
+ ELSE NULL
+ END AS size,
+ c.is_nullable AS nullable,
+ OBJECT_DEFINITION(c.default_object_id) AS [default],
+ c.is_identity AS autoincrement,
+ CASE WHEN i.index_id IS NULL
+ THEN 0
+ ELSE 1
+ END AS [primary]
+ FROM
+ sys.columns c
+ JOIN sys.objects o ON c.object_id = o.object_id
+ LEFT JOIN sys.types t ON c.user_type_id = t.user_type_id
+ LEFT JOIN sys.key_constraints k ON o.object_id = k.parent_object_id AND k.type = 'PK'
+ LEFT JOIN sys.index_columns i ON k.parent_object_id = i.object_id AND i.index_id = k.unique_index_id AND i.column_id = c.column_id
+ WHERE
+ o.type IN ('U', 'V')
+ AND o.name = ?
+ X, $table);
+
+ while ($row = $rows->fetch()) {
+ $row = (array) $row;
+ $row['vendor'] = $row;
+ $row['nullable'] = (bool) $row['nullable'];
+ $row['autoincrement'] = (bool) $row['autoincrement'];
+ $row['primary'] = (bool) $row['primary'];
+
+ $columns[] = $row;
+ }
+
+ return $columns;
+ }
+
+
+ public function getIndexes(string $table): array
+ {
+ $indexes = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ i.name AS name,
+ CASE WHEN i.is_unique = 1 OR i.is_unique_constraint = 1
+ THEN 1
+ ELSE 0
+ END AS [unique],
+ i.is_primary_key AS [primary],
+ c.name AS [column]
+ FROM
+ sys.indexes i
+ JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
+ JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
+ JOIN sys.tables t ON i.object_id = t.object_id
+ WHERE
+ t.name = ?
+ ORDER BY
+ i.index_id,
+ ic.index_column_id
+ X, $table);
+
+ while ($row = $rows->fetch()) {
+ $id = $row['name'];
+ $indexes[$id]['name'] = $id;
+ $indexes[$id]['unique'] = (bool) $row['unique'];
+ $indexes[$id]['primary'] = (bool) $row['primary'];
+ $indexes[$id]['columns'][] = $row['column'];
+ }
+
+ return array_values($indexes);
+ }
+
+
+ public function getForeignKeys(string $table): array
+ {
+ // Does't work with multicolumn foreign keys
+ $keys = [];
+ $rows = $this->connection->query(<<<'X'
+ SELECT
+ fk.name AS name,
+ cl.name AS local,
+ tf.name AS [table],
+ cf.name AS [foreign]
+ FROM
+ sys.foreign_keys fk
+ JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id
+ JOIN sys.tables tl ON fkc.parent_object_id = tl.object_id
+ JOIN sys.columns cl ON fkc.parent_object_id = cl.object_id AND fkc.parent_column_id = cl.column_id
+ JOIN sys.tables tf ON fkc.referenced_object_id = tf.object_id
+ JOIN sys.columns cf ON fkc.referenced_object_id = cf.object_id AND fkc.referenced_column_id = cf.column_id
+ WHERE
+ tl.name = ?
+ X, $table);
+
+ while ($row = $rows->fetch()) {
+ $keys[$row['name']] = (array) $row;
+ }
+
+ return array_values($keys);
+ }
+
+
+ public function getColumnTypes(\PDOStatement $statement): array
+ {
+ $types = [];
+ $count = $statement->columnCount();
+ for ($col = 0; $col < $count; $col++) {
+ $meta = $statement->getColumnMeta($col);
+ if (
+ isset($meta['sqlsrv:decl_type'])
+ && $meta['sqlsrv:decl_type'] !== 'timestamp'
+ ) { // timestamp does not mean time in sqlsrv
+ $types[$meta['name']] = Nette\Database\Helpers::detectType($meta['sqlsrv:decl_type']);
+ } elseif (isset($meta['native_type'])) {
+ $types[$meta['name']] = Nette\Database\Helpers::detectType($meta['native_type']);
+ }
+ }
+
+ return $types;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Explorer.php b/vendor/nette/database/src/Database/Explorer.php
new file mode 100644
index 0000000..99b152b
--- /dev/null
+++ b/vendor/nette/database/src/Database/Explorer.php
@@ -0,0 +1,209 @@
+conventions = $conventions ?: new StaticConventions;
+ }
+
+
+ public function beginTransaction(): void
+ {
+ $this->connection->beginTransaction();
+ }
+
+
+ public function commit(): void
+ {
+ $this->connection->commit();
+ }
+
+
+ public function rollBack(): void
+ {
+ $this->connection->rollBack();
+ }
+
+
+ public function transaction(callable $callback): mixed
+ {
+ return $this->connection->transaction(fn() => $callback($this));
+ }
+
+
+ public function getInsertId(?string $sequence = null): string
+ {
+ return $this->connection->getInsertId($sequence);
+ }
+
+
+ /**
+ * Generates and executes SQL query.
+ * @param literal-string $sql
+ */
+ public function query(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ResultSet
+ {
+ return $this->connection->query($sql, ...$params);
+ }
+
+
+ /** @deprecated use query() */
+ public function queryArgs(string $sql, array $params): ResultSet
+ {
+ return $this->connection->query($sql, ...$params);
+ }
+
+
+ /**
+ * Returns table selection.
+ */
+ public function table(string $table): Table\Selection
+ {
+ return new Table\Selection($this, $this->conventions, $table, $this->cacheStorage);
+ }
+
+
+ public function getConnection(): Connection
+ {
+ return $this->connection;
+ }
+
+
+ public function getStructure(): IStructure
+ {
+ return $this->structure;
+ }
+
+
+ public function getConventions(): Conventions
+ {
+ return $this->conventions;
+ }
+
+
+ public function createActiveRow(array $data, Table\Selection $selection): Table\ActiveRow
+ {
+ return new Table\ActiveRow($data, $selection);
+ }
+
+
+ /** @internal */
+ public function createGroupedSelection(
+ Table\Selection $refSelection,
+ string $table,
+ string $column,
+ ): Table\GroupedSelection
+ {
+ return new Table\GroupedSelection($this, $this->conventions, $table, $column, $refSelection, $this->cacheStorage);
+ }
+
+
+ /********************* shortcuts ****************d*g**/
+
+
+ /**
+ * Shortcut for query()->fetch()
+ * @param literal-string $sql
+ */
+ public function fetch(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ?Row
+ {
+ return $this->connection->query($sql, ...$params)->fetch();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchAssoc()
+ * @param literal-string $sql
+ */
+ public function fetchAssoc(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ?array
+ {
+ return $this->connection->query($sql, ...$params)->fetchAssoc();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchField()
+ * @param literal-string $sql
+ */
+ public function fetchField(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): mixed
+ {
+ return $this->connection->query($sql, ...$params)->fetchField();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchList()
+ * @param literal-string $sql
+ */
+ public function fetchList(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ?array
+ {
+ return $this->connection->query($sql, ...$params)->fetchList();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchList()
+ * @param literal-string $sql
+ */
+ public function fetchFields(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): ?array
+ {
+ return $this->connection->query($sql, ...$params)->fetchList();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchPairs()
+ * @param literal-string $sql
+ */
+ public function fetchPairs(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): array
+ {
+ return $this->connection->query($sql, ...$params)->fetchPairs();
+ }
+
+
+ /**
+ * Shortcut for query()->fetchAll()
+ * @param literal-string $sql
+ */
+ public function fetchAll(#[Language('SQL')] string $sql, #[Language('GenericSQL')] ...$params): array
+ {
+ return $this->connection->query($sql, ...$params)->fetchAll();
+ }
+
+
+ /**
+ * Creates SQL literal value.
+ */
+ public static function literal(string $value, ...$params): SqlLiteral
+ {
+ return new SqlLiteral($value, $params);
+ }
+}
+
+
+class_exists(Context::class);
diff --git a/vendor/nette/database/src/Database/Helpers.php b/vendor/nette/database/src/Database/Helpers.php
new file mode 100644
index 0000000..5878bee
--- /dev/null
+++ b/vendor/nette/database/src/Database/Helpers.php
@@ -0,0 +1,403 @@
+ IStructure::FIELD_TEXT, // PostgreSQL arrays
+ '(TINY|SMALL|SHORT|MEDIUM|BIG|LONG)(INT)?|INT(EGER|\d+| IDENTITY| UNSIGNED)?|(SMALL|BIG|)SERIAL\d*|COUNTER|YEAR|BYTE|LONGLONG|UNSIGNED BIG INT' => IStructure::FIELD_INTEGER,
+ '(NEW)?DEC(IMAL)?(\(.*)?|NUMERIC|(SMALL)?MONEY|CURRENCY|NUMBER' => IStructure::FIELD_DECIMAL,
+ 'REAL|DOUBLE( PRECISION)?|FLOAT\d*' => IStructure::FIELD_FLOAT,
+ 'BOOL(EAN)?' => IStructure::FIELD_BOOL,
+ 'TIME' => IStructure::FIELD_TIME,
+ 'DATE' => IStructure::FIELD_DATE,
+ '(SMALL)?DATETIME(OFFSET)?\d*|TIME(STAMP.*)?' => IStructure::FIELD_DATETIME,
+ 'BYTEA|(TINY|MEDIUM|LONG|)BLOB|(LONG )?(VAR)?BINARY|IMAGE' => IStructure::FIELD_BINARY,
+ ];
+
+
+ /**
+ * Displays result set as HTML table.
+ */
+ public static function dumpResult(ResultSet $result): void
+ {
+ echo "\n\n" . htmlspecialchars($result->getQueryString(), ENT_IGNORE, 'UTF-8') . " \n";
+ if (!$result->getColumnCount()) {
+ echo "\t\n\t\tAffected rows: \n\t\t", $result->getRowCount(), " \n\t \n
\n";
+ return;
+ }
+
+ $i = 0;
+ foreach ($result as $row) {
+ if ($i === 0) {
+ echo "\n\t\n\t\t#row \n";
+ foreach ($row as $col => $foo) {
+ echo "\t\t" . htmlspecialchars($col, ENT_NOQUOTES, 'UTF-8') . " \n";
+ }
+
+ echo "\t \n \n\n";
+ }
+
+ echo "\t\n\t\t", $i, " \n";
+ foreach ($row as $col) {
+ if (is_bool($col)) {
+ $s = $col ? 'TRUE' : 'FALSE';
+ } elseif ($col === null) {
+ $s = 'NULL';
+ } else {
+ $s = (string) $col;
+ }
+
+ echo "\t\t", htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8'), " \n";
+ }
+
+ echo "\t \n";
+ $i++;
+ }
+
+ if ($i === 0) {
+ echo "\t\n\t\tempty result set \n\t \n\n";
+ } else {
+ echo " \n\n";
+ }
+ }
+
+
+ /**
+ * Returns syntax highlighted SQL command.
+ */
+ public static function dumpSql(string $sql, ?array $params = null, ?Connection $connection = null): string
+ {
+ $keywords1 = 'SELECT|(?:ON\s+DUPLICATE\s+KEY)?UPDATE|INSERT(?:\s+INTO)?|REPLACE(?:\s+INTO)?|DELETE|CALL|UNION|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|OFFSET|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN|TRUNCATE';
+ $keywords2 = 'ALL|DISTINCT|DISTINCTROW|IGNORE|AS|USING|ON|AND|OR|IN|IS|NOT|NULL|[RI]?LIKE|REGEXP|TRUE|FALSE';
+
+ // insert new lines
+ $sql = " $sql ";
+ $sql = preg_replace("#(?<=[\\s,(])($keywords1)(?=[\\s,)])#i", "\n\$1", $sql);
+
+ // reduce spaces
+ $sql = preg_replace('#[ \t]{2,}#', ' ', $sql);
+
+ $sql = wordwrap($sql, 100);
+ $sql = preg_replace('#([ \t]*\r?\n){2,}#', "\n", $sql);
+
+ // syntax highlight
+ $sql = htmlspecialchars($sql, ENT_IGNORE, 'UTF-8');
+ $sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|(?<=[\\s,(])($keywords1)(?=[\\s,)])|(?<=[\\s,(=])($keywords2)(?=[\\s,)=])#is", function (array $matches) {
+ if (!empty($matches[1])) { // comment
+ return '' . $matches[1] . ' ';
+
+ } elseif (!empty($matches[2])) { // error
+ return '' . $matches[2] . ' ';
+
+ } elseif (!empty($matches[3])) { // most important keywords
+ return '' . $matches[3] . ' ';
+
+ } elseif (!empty($matches[4])) { // other keywords
+ return '' . $matches[4] . ' ';
+ }
+ }, $sql);
+
+ // parameters
+ $sql = preg_replace_callback('#\?#', function () use ($params, $connection): string {
+ static $i = 0;
+ if (!isset($params[$i])) {
+ return '?';
+ }
+
+ $param = $params[$i++];
+ if (
+ is_string($param)
+ && (
+ preg_match('#[^\x09\x0A\x0D\x20-\x7E\xA0-\x{10FFFF}]#u', $param)
+ || preg_last_error()
+ )
+ ) {
+ return '<binary> ';
+
+ } elseif (is_string($param)) {
+ $length = Nette\Utils\Strings::length($param);
+ $truncated = Nette\Utils\Strings::truncate($param, self::$maxLength);
+ $text = htmlspecialchars($connection ? $connection->quote($truncated) : '\'' . $truncated . '\'', ENT_NOQUOTES, 'UTF-8');
+ return '' . $text . ' ';
+
+ } elseif (is_resource($param)) {
+ $type = get_resource_type($param);
+ if ($type === 'stream') {
+ $info = stream_get_meta_data($param);
+ }
+
+ return '<' . htmlspecialchars($type, ENT_NOQUOTES, 'UTF-8') . ' resource> ';
+
+ } elseif (is_bool($param)) {
+ return (string) (int) $param;
+
+ } else {
+ return htmlspecialchars((string) $param, ENT_NOQUOTES, 'UTF-8');
+ }
+ }, $sql);
+
+ return '' . trim($sql) . " \n";
+ }
+
+
+ /**
+ * Returns column types from result set.
+ */
+ public static function detectTypes(\PDOStatement $statement): array
+ {
+ $types = [];
+ $count = $statement->columnCount(); // driver must be meta-aware, see PHP bugs #53782, #54695
+ for ($col = 0; $col < $count; $col++) {
+ $meta = $statement->getColumnMeta($col);
+ if (isset($meta['native_type'])) {
+ $types[$meta['name']] = self::detectType($meta['native_type']);
+ }
+ }
+
+ return $types;
+ }
+
+
+ /**
+ * Detects column type from native type.
+ * @internal
+ */
+ public static function detectType(string $type): string
+ {
+ static $cache;
+ if (!isset($cache[$type])) {
+ $cache[$type] = 'string';
+ foreach (self::$typePatterns as $s => $val) {
+ if (preg_match("#^($s)$#i", $type)) {
+ return $cache[$type] = $val;
+ }
+ }
+ }
+
+ return $cache[$type];
+ }
+
+
+ /** @internal */
+ public static function normalizeRow(
+ array $row,
+ ResultSet $resultSet,
+ $dateTimeClass = Nette\Utils\DateTime::class,
+ ): array
+ {
+ foreach ($resultSet->getColumnTypes() as $key => $type) {
+ $value = $row[$key];
+ if ($value === null || $value === false || $type === IStructure::FIELD_TEXT) {
+ // do nothing
+ } elseif ($type === IStructure::FIELD_INTEGER) {
+ $row[$key] = is_float($tmp = $value * 1) ? $value : $tmp;
+
+ } elseif ($type === IStructure::FIELD_FLOAT || $type === IStructure::FIELD_DECIMAL) {
+ $row[$key] = (float) $value;
+
+ } elseif ($type === IStructure::FIELD_BOOL) {
+ $row[$key] = $value && $value !== 'f' && $value !== 'F';
+
+ } elseif ($type === IStructure::FIELD_DATETIME || $type === IStructure::FIELD_DATE) {
+ $row[$key] = str_starts_with($value, '0000-00')
+ ? null
+ : new $dateTimeClass($value);
+
+ } elseif ($type === IStructure::FIELD_TIME) {
+ $row[$key] = (new $dateTimeClass($value))->setDate(1, 1, 1);
+
+ } elseif ($type === IStructure::FIELD_TIME_INTERVAL) {
+ preg_match('#^(-?)(\d+)\D(\d+)\D(\d+)(\.\d+)?$#D', $value, $m);
+ $row[$key] = new \DateInterval("PT$m[2]H$m[3]M$m[4]S");
+ $row[$key]->f = isset($m[5]) ? (float) $m[5] : 0.0;
+ $row[$key]->invert = (int) (bool) $m[1];
+
+ } elseif ($type === IStructure::FIELD_UNIX_TIMESTAMP) {
+ $row[$key] = (new $dateTimeClass)->setTimestamp($value);
+ }
+ }
+
+ return $row;
+ }
+
+
+ /**
+ * Imports SQL dump from file.
+ * @param ?array $onProgress Called after each query
+ * @return int Number of executed commands
+ * @throws Nette\FileNotFoundException
+ */
+ public static function loadFromFile(Connection $connection, string $file, ?callable $onProgress = null): int
+ {
+ @set_time_limit(0); // @ function may be disabled
+
+ $handle = @fopen($file, 'r'); // @ is escalated to exception
+ if (!$handle) {
+ throw new Nette\FileNotFoundException("Cannot open file '$file'.");
+ }
+
+ $stat = fstat($handle);
+ $count = $size = 0;
+ $delimiter = ';';
+ $sql = '';
+ $pdo = $connection->getPdo(); // native query without logging
+ while (($s = fgets($handle)) !== false) {
+ $size += strlen($s);
+ if (!strncasecmp($s, 'DELIMITER ', 10)) {
+ $delimiter = trim(substr($s, 10));
+
+ } elseif (str_ends_with($ts = rtrim($s), $delimiter)) {
+ $sql .= substr($ts, 0, -strlen($delimiter));
+ $pdo->exec($sql);
+ $sql = '';
+ $count++;
+ if ($onProgress) {
+ $onProgress($count, isset($stat['size']) ? $size * 100 / $stat['size'] : null);
+ }
+ } else {
+ $sql .= $s;
+ }
+ }
+
+ if (rtrim($sql) !== '') {
+ $pdo->exec($sql);
+ $count++;
+ if ($onProgress) {
+ $onProgress($count, isset($stat['size']) ? 100 : null);
+ }
+ }
+
+ fclose($handle);
+ return $count;
+ }
+
+
+ /** @deprecated use Nette\Bridges\DatabaseTracy\ConnectionPanel::initialize() */
+ public static function createDebugPanel(
+ Connection $connection,
+ bool $explain,
+ string $name,
+ Tracy\Bar $bar,
+ Tracy\BlueScreen $blueScreen,
+ ): ?ConnectionPanel
+ {
+ return ConnectionPanel::initialize($connection, true, $name, $explain, $bar, $blueScreen);
+ }
+
+
+ /** @deprecated use Nette\Bridges\DatabaseTracy\ConnectionPanel::initialize() */
+ public static function initializeTracy(
+ Connection $connection,
+ bool $addBarPanel = false,
+ string $name = '',
+ bool $explain = true,
+ ?Tracy\Bar $bar = null,
+ ?Tracy\BlueScreen $blueScreen = null,
+ ): ?ConnectionPanel
+ {
+ return ConnectionPanel::initialize($connection, $addBarPanel, $name, $explain, $bar, $blueScreen);
+ }
+
+
+ /**
+ * Converts rows to key-value pairs.
+ */
+ public static function toPairs(array $rows, string|int|\Closure|null $key, string|int|null $value): array
+ {
+ if ($key === null && $value === null) {
+ if (!$rows) {
+ return [];
+ }
+ $keys = array_keys((array) reset($rows));
+ if (!count($keys)) {
+ throw new \LogicException('Result set does not contain any column.');
+ }
+ if (count($keys) === 1) {
+ [$value] = $keys;
+ } else {
+ [$key, $value] = $keys;
+ }
+ }
+
+ $return = [];
+ if ($key === null) {
+ foreach ($rows as $row) {
+ $return[] = ($value === null ? $row : $row[$value]);
+ }
+ } elseif ($key instanceof \Closure) {
+ foreach ($rows as $row) {
+ $tuple = $key($row);
+ if (count($tuple) === 1) {
+ $return[] = $tuple[0];
+ } else {
+ $return[$tuple[0]] = $tuple[1];
+ }
+ }
+ } else {
+ foreach ($rows as $row) {
+ $return[(string) $row[$key]] = ($value === null ? $row : $row[$value]);
+ }
+ }
+
+ return $return;
+ }
+
+
+ /**
+ * Returns duplicate columns from result set.
+ */
+ public static function findDuplicates(\PDOStatement $statement): string
+ {
+ $cols = [];
+ for ($i = 0; $i < $statement->columnCount(); $i++) {
+ $meta = $statement->getColumnMeta($i);
+ $cols[$meta['name']][] = $meta['table'] ?? '';
+ }
+
+ $duplicates = [];
+ foreach ($cols as $name => $tables) {
+ if (count($tables) > 1) {
+ $tables = array_filter(array_unique($tables));
+ $duplicates[] = "'$name'" . ($tables ? ' (from ' . implode(', ', $tables) . ')' : '');
+ }
+ }
+
+ return implode(', ', $duplicates);
+ }
+
+
+ /** @return array{type: ?string, length: ?null, scale: ?null, parameters: ?string} */
+ public static function parseColumnType(string $type): array
+ {
+ preg_match('/^([^(]+)(?:\((?:(\d+)(?:,(\d+))?|([^)]+))\))?/', $type, $m, PREG_UNMATCHED_AS_NULL);
+ return [
+ 'type' => $m[1] ?? null,
+ 'length' => isset($m[2]) ? (int) $m[2] : null,
+ 'scale' => isset($m[3]) ? (int) $m[3] : null,
+ 'parameters' => $m[4] ?? null,
+ ];
+ }
+}
diff --git a/vendor/nette/database/src/Database/IRow.php b/vendor/nette/database/src/Database/IRow.php
new file mode 100644
index 0000000..8c5ab16
--- /dev/null
+++ b/vendor/nette/database/src/Database/IRow.php
@@ -0,0 +1,16 @@
+ */
+ public readonly array $tables;
+
+
+ public function __construct(
+ private readonly Driver $driver,
+ ) {
+ unset($this->tables);
+ }
+
+
+ /** @return Table[] */
+ public function getTables(): array
+ {
+ return array_values($this->tables);
+ }
+
+
+ /**
+ * Returns table metadata.
+ * @throws \InvalidArgumentException if table does not exist
+ */
+ public function getTable(string $name): Table
+ {
+ $name = $this->getFullName($name);
+ return $this->tables[$name]
+ ?? $this->tryGetTable($name)
+ ?? throw new \InvalidArgumentException("Table '$name' not found.");
+ }
+
+
+ private function tryGetTable(string $name): ?Table
+ {
+ try {
+ $table = new Table($this, $name);
+ $table->columns;
+ return $table;
+ } catch (DriverException) {
+ }
+ return null;
+ }
+
+
+ public function hasTable(string $name): bool
+ {
+ $name = $this->getFullName($name);
+ return isset($this->tables[$name]);
+ }
+
+
+ private function getFullName(string $name): string
+ {
+ return $name;
+ }
+
+
+ /** @internal */
+ public function getDriver(): Driver
+ {
+ return $this->driver;
+ }
+
+
+ private function initTables(): void
+ {
+ $res = [];
+ foreach ($this->driver->getTables() as $row) {
+ $res[$row['fullName'] ?? $row['name']] = new Table($this, $row['name'], $row['view'], $row['fullName'] ?? null);
+ }
+ $this->tables = $res;
+ }
+
+
+ public function __get($name): mixed
+ {
+ match ($name) {
+ 'tables' => $this->initTables(),
+ default => throw new \LogicException("Undefined property '$name'."),
+ };
+ return $this->$name;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Reflection/Column.php b/vendor/nette/database/src/Database/Reflection/Column.php
new file mode 100644
index 0000000..871f826
--- /dev/null
+++ b/vendor/nette/database/src/Database/Reflection/Column.php
@@ -0,0 +1,37 @@
+name;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Reflection/ForeignKey.php b/vendor/nette/database/src/Database/Reflection/ForeignKey.php
new file mode 100644
index 0000000..3f59afb
--- /dev/null
+++ b/vendor/nette/database/src/Database/Reflection/ForeignKey.php
@@ -0,0 +1,34 @@
+name;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Reflection/Index.php b/vendor/nette/database/src/Database/Reflection/Index.php
new file mode 100644
index 0000000..3ddbe7e
--- /dev/null
+++ b/vendor/nette/database/src/Database/Reflection/Index.php
@@ -0,0 +1,33 @@
+name;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Reflection/Table.php b/vendor/nette/database/src/Database/Reflection/Table.php
new file mode 100644
index 0000000..2c20b48
--- /dev/null
+++ b/vendor/nette/database/src/Database/Reflection/Table.php
@@ -0,0 +1,118 @@
+ */
+ public readonly array $columns;
+
+ /** @var list */
+ public readonly array $indexes;
+ public readonly ?Index $primaryKey;
+
+ /** @var list */
+ public readonly array $foreignKeys;
+
+
+ /** @internal */
+ public function __construct(
+ private readonly Reflection $reflection,
+ public readonly string $name,
+ public readonly bool $view = false,
+ public readonly ?string $fullName = null,
+ ) {
+ unset($this->columns, $this->indexes, $this->primaryKey, $this->foreignKeys);
+ }
+
+
+ /**
+ * Returns column object or throws exception if column doesn't exist.
+ * @throws \InvalidArgumentException
+ */
+ public function getColumn(string $name): Column
+ {
+ return $this->columns[$name] ?? throw new \InvalidArgumentException("Column '$name' not found in table '$this->name'.");
+ }
+
+
+ private function initColumns(): void
+ {
+ $res = [];
+ foreach ($this->reflection->getDriver()->getColumns($this->name) as $row) {
+ $res[$row['name']] = new Column($row['name'], $this, $row['nativetype'], $row['size'], $row['nullable'], $row['default'], $row['autoincrement'], $row['primary'], $row['vendor']);
+ }
+ $this->columns = $res;
+ }
+
+
+ private function initIndexes(): void
+ {
+ $this->indexes = array_map(
+ fn($row) => new Index(
+ array_map(fn($name) => $this->getColumn($name), $row['columns']),
+ $row['unique'],
+ $row['primary'],
+ is_string($row['name']) ? $row['name'] : null,
+ ),
+ $this->reflection->getDriver()->getIndexes($this->name),
+ );
+ }
+
+
+ private function initPrimaryKey(): void
+ {
+ $res = array_filter(
+ $this->columns,
+ fn($row) => $row->primary,
+ );
+ $this->primaryKey = $res ? new Index(array_values($res), true, true) : null;
+ }
+
+
+ private function initForeignKeys(): void
+ {
+ $tmp = [];
+ foreach ($this->reflection->getDriver()->getForeignKeys($this->name) as $row) {
+ $id = $row['name'];
+ $foreignTable = $this->reflection->getTable($row['table']);
+ $tmp[$id][0] = $foreignTable;
+ $tmp[$id][1][] = $this->getColumn($row['local']);
+ $tmp[$id][2][] = $foreignTable->getColumn($row['foreign']);
+ $tmp[$id][3] = is_string($id) ? $id : null;
+ }
+ $this->foreignKeys = array_map(fn($row) => new ForeignKey(...$row), array_values($tmp));
+ }
+
+
+ public function __get($name): mixed
+ {
+ match ($name) {
+ 'columns' => $this->initColumns(),
+ 'indexes' => $this->initIndexes(),
+ 'primaryKey' => $this->initPrimaryKey(),
+ 'foreignKeys' => $this->initForeignKeys(),
+ default => throw new \LogicException("Undefined property '$name'."),
+ };
+ return $this->$name;
+ }
+
+
+ public function __toString(): string
+ {
+ return $this->name;
+ }
+}
diff --git a/vendor/nette/database/src/Database/ResultSet.php b/vendor/nette/database/src/Database/ResultSet.php
new file mode 100644
index 0000000..3489cea
--- /dev/null
+++ b/vendor/nette/database/src/Database/ResultSet.php
@@ -0,0 +1,270 @@
+normalizer = $normalizer;
+ $types = ['boolean' => PDO::PARAM_BOOL, 'integer' => PDO::PARAM_INT, 'resource' => PDO::PARAM_LOB, 'NULL' => PDO::PARAM_NULL];
+
+ try {
+ if (str_starts_with($queryString, '::')) {
+ $connection->getPdo()->{substr($queryString, 2)}();
+ } else {
+ $this->pdoStatement = $connection->getPdo()->prepare($queryString);
+ foreach ($params as $key => $value) {
+ $type = gettype($value);
+ $this->pdoStatement->bindValue(is_int($key) ? $key + 1 : $key, $value, $types[$type] ?? PDO::PARAM_STR);
+ }
+
+ $this->pdoStatement->setFetchMode(PDO::FETCH_ASSOC);
+ $this->pdoStatement->execute();
+ }
+ } catch (\PDOException $e) {
+ $e = $connection->getDriver()->convertException($e);
+ $e->queryString = $queryString;
+ $e->params = $params;
+ throw $e;
+ }
+
+ $this->time = microtime(true) - $time;
+ }
+
+
+ /** @deprecated */
+ public function getConnection(): Connection
+ {
+ return $this->connection;
+ }
+
+
+ /** @internal */
+ public function getPdoStatement(): ?\PDOStatement
+ {
+ return $this->pdoStatement;
+ }
+
+
+ public function getQueryString(): string
+ {
+ return $this->queryString;
+ }
+
+
+ public function getParameters(): array
+ {
+ return $this->params;
+ }
+
+
+ public function getColumnCount(): ?int
+ {
+ return $this->pdoStatement ? $this->pdoStatement->columnCount() : null;
+ }
+
+
+ public function getRowCount(): ?int
+ {
+ return $this->pdoStatement ? $this->pdoStatement->rowCount() : null;
+ }
+
+
+ public function getColumnTypes(): array
+ {
+ $this->types ??= $this->connection->getDriver()->getColumnTypes($this->pdoStatement);
+ return $this->types;
+ }
+
+
+ public function getTime(): float
+ {
+ return $this->time;
+ }
+
+
+ /** @internal */
+ public function normalizeRow(array $row): array
+ {
+ return $this->normalizer
+ ? ($this->normalizer)($row, $this)
+ : $row;
+ }
+
+
+ /********************* misc tools ****************d*g**/
+
+
+ /**
+ * Displays result set as HTML table.
+ */
+ public function dump(): void
+ {
+ Helpers::dumpResult($this);
+ }
+
+
+ /********************* interface Iterator ****************d*g**/
+
+
+ public function rewind(): void
+ {
+ if ($this->lastRow === false) {
+ throw new Nette\InvalidStateException(self::class . ' implements only one way iterator.');
+ }
+ }
+
+
+ public function current(): Row|false|null
+ {
+ return $this->lastRow;
+ }
+
+
+ public function key(): int
+ {
+ return $this->lastRowKey;
+ }
+
+
+ public function next(): void
+ {
+ $this->lastRow = false;
+ }
+
+
+ public function valid(): bool
+ {
+ if ($this->lastRow) {
+ return true;
+ }
+
+ return $this->fetch() !== null;
+ }
+
+
+ /********************* fetch ****************d*g**/
+
+
+ /**
+ * Returns the next row as an associative array or null if there are no more rows.
+ */
+ public function fetchAssoc(?string $path = null): ?array
+ {
+ if ($path !== null) {
+ return Arrays::associate($this->fetchAll(), $path);
+ }
+
+ $data = $this->pdoStatement ? $this->pdoStatement->fetch() : null;
+ if (!$data) {
+ $this->pdoStatement->closeCursor();
+ return null;
+
+ } elseif ($this->lastRow === null && count($data) !== $this->pdoStatement->columnCount()) {
+ $duplicates = Helpers::findDuplicates($this->pdoStatement);
+ trigger_error("Found duplicate columns in database result set: $duplicates.");
+ }
+
+ return $this->normalizeRow($data);
+ }
+
+
+ /**
+ * Returns the next row as a Row object or null if there are no more rows.
+ */
+ public function fetch(): ?Row
+ {
+ $data = $this->fetchAssoc();
+ if ($data === null) {
+ return null;
+ }
+
+ $this->lastRowKey++;
+ return $this->lastRow = Arrays::toObject($data, new Row);
+ }
+
+
+ /**
+ * Returns the first field of the next row or null if there are no more rows.
+ */
+ public function fetchField(): mixed
+ {
+ $row = $this->fetchAssoc();
+ return $row ? reset($row) : null;
+ }
+
+
+ /**
+ * Returns the next row as indexed array or null if there are no more rows.
+ */
+ public function fetchList(): ?array
+ {
+ $row = $this->fetchAssoc();
+ return $row ? array_values($row) : null;
+ }
+
+
+ /**
+ * Alias for fetchList().
+ */
+ public function fetchFields(): ?array
+ {
+ return $this->fetchList();
+ }
+
+
+ /**
+ * Returns all rows as associative array, where first argument specifies key column and second value column.
+ * For duplicate keys, the last value is used. When using null as key, array is indexed from zero.
+ * Alternatively accepts callback returning value or key-value pairs.
+ */
+ public function fetchPairs(string|int|\Closure|null $keyOrCallback = null, string|int|null $value = null): array
+ {
+ return Helpers::toPairs($this->fetchAll(), $keyOrCallback, $value);
+ }
+
+
+ /**
+ * Returns all remaining rows as array of Row objects.
+ * @return Row[]
+ */
+ public function fetchAll(): array
+ {
+ $this->rows ??= iterator_to_array($this);
+ return $this->rows;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Row.php b/vendor/nette/database/src/Database/Row.php
new file mode 100644
index 0000000..ce21ae6
--- /dev/null
+++ b/vendor/nette/database/src/Database/Row.php
@@ -0,0 +1,64 @@
+key);
+ }
+
+
+ /**
+ * Returns a item.
+ * @param string|int $key key or index
+ */
+ public function offsetGet($key): mixed
+ {
+ if (is_int($key)) {
+ $arr = array_slice((array) $this, $key, 1);
+ if (!$arr) {
+ throw new Nette\MemberAccessException("Cannot read an undeclared column '$key'.");
+ }
+
+ return current($arr);
+ }
+
+ return $this->$key;
+ }
+
+
+ /**
+ * Checks if $key exists.
+ * @param string|int $key key or index
+ */
+ public function offsetExists($key): bool
+ {
+ if (is_int($key)) {
+ return (bool) current(array_slice((array) $this, $key, 1));
+ }
+
+ return parent::offsetExists($key);
+ }
+}
diff --git a/vendor/nette/database/src/Database/SqlLiteral.php b/vendor/nette/database/src/Database/SqlLiteral.php
new file mode 100644
index 0000000..b95b0ed
--- /dev/null
+++ b/vendor/nette/database/src/Database/SqlLiteral.php
@@ -0,0 +1,41 @@
+value;
+ }
+
+
+ public function getParameters(): array
+ {
+ return $this->parameters;
+ }
+
+
+ public function __toString(): string
+ {
+ return $this->value;
+ }
+}
diff --git a/vendor/nette/database/src/Database/SqlPreprocessor.php b/vendor/nette/database/src/Database/SqlPreprocessor.php
new file mode 100644
index 0000000..d63fcb8
--- /dev/null
+++ b/vendor/nette/database/src/Database/SqlPreprocessor.php
@@ -0,0 +1,354 @@
+ self::ModeValues,
+ 'REPLACE' => self::ModeValues,
+ 'KEY UPDATE' => self::ModeSet,
+ 'SET' => self::ModeSet,
+ 'WHERE' => self::ModeAnd,
+ 'HAVING' => self::ModeAnd,
+ 'ORDER BY' => self::ModeOrder,
+ 'GROUP BY' => self::ModeOrder,
+ ];
+
+ private const ParametricCommands = [
+ 'SELECT' => 1,
+ 'INSERT' => 1,
+ 'UPDATE' => 1,
+ 'DELETE' => 1,
+ 'REPLACE' => 1,
+ 'EXPLAIN' => 1,
+ ];
+
+ private readonly Connection $connection;
+ private readonly Driver $driver;
+ private array $params;
+ private array $remaining;
+ private int $counter;
+ private bool $useParams;
+
+ /** values|set|and|order|items */
+ private ?string $arrayMode;
+
+
+ public function __construct(Connection $connection)
+ {
+ $this->connection = $connection;
+ $this->driver = $connection->getDriver();
+ }
+
+
+ /**
+ * Processes SQL query with parameter substitution.
+ * @return array{string, array}
+ */
+ public function process(array $params, bool $useParams = false): array
+ {
+ $this->params = $params;
+ $this->counter = 0;
+ $prev = -1;
+ $this->remaining = [];
+ $this->arrayMode = null;
+ $this->useParams = $useParams;
+ $res = [];
+
+ while ($this->counter < count($params)) {
+ $param = $params[$this->counter++];
+
+ if (($this->counter === 2 && count($params) === 2) || !is_scalar($param)) {
+ $res[] = $this->formatParameter($param);
+
+ } elseif (is_string($param) && $this->counter > $prev + 1) {
+ $prev = $this->counter;
+ $this->arrayMode = null;
+ $res[] = Nette\Utils\Strings::replace(
+ $param,
+ <<<'X'
+ ~
+ '[^']*+'
+ |"[^"]*+"
+ |\?[a-z]*
+ |^\s*+(?:\(?\s*SELECT|INSERT|UPDATE|DELETE|REPLACE|EXPLAIN)\b
+ |\b(?:SET|WHERE|HAVING|ORDER\ BY|GROUP\ BY|KEY\ UPDATE)(?=\s*$|\s*\?)
+ |\bIN\s+(?:\?|\(\?\))
+ |/\*.*?\*/
+ |--[^\n]*
+ ~Dsix
+ X,
+ $this->parsePart(...),
+ );
+ } else {
+ throw new Nette\InvalidArgumentException('There are more parameters than placeholders.');
+ }
+ }
+
+ return [implode(' ', $res), $this->remaining];
+ }
+
+
+ /**
+ * Handles SQL placeholders and skips string literals and comments.
+ */
+ private function parsePart(array $match): string
+ {
+ $match = $match[0];
+ if (in_array($match[0], ["'", '"', '/', '-'], true)) { // string or comment
+ return $match;
+
+ } elseif (!str_contains($match, '?')) { // command
+ $command = ltrim(strtoupper($match), "\t\n\r (");
+ $this->arrayMode = self::CommandToMode[$command] ?? null;
+ $this->useParams = isset(self::ParametricCommands[$command]) || $this->useParams;
+ return $match;
+
+ } elseif ($this->counter >= count($this->params)) {
+ throw new Nette\InvalidArgumentException('There are more placeholders than passed parameters.');
+ }
+
+ $param = $this->params[$this->counter++];
+ if ($match[0] === '?') { // ?[mode]
+ return $this->formatParameter($param, substr($match, 1) ?: null);
+ } else { // IN (?)
+ return 'IN (' . (is_array($param) ? $this->formatList($param) : $this->formatValue($param)) . ')';
+ }
+ }
+
+
+ /**
+ * Formats a value for use in SQL query where ? placeholder is used.
+ * For arrays, the formatting is determined by $mode or last SQL keyword before the placeholder
+ */
+ private function formatParameter(mixed $value, ?string $mode = null): string
+ {
+ if ($value instanceof \Traversable && !$value instanceof \Stringable) {
+ $value = iterator_to_array($value);
+ }
+ if (is_array($value)) {
+ $mode ??= $this->arrayMode ?? self::ModeSet;
+ }
+
+ $check = fn($value, $type) => "is_$type"($value)
+ ? $value
+ : throw new Nette\InvalidArgumentException("Placeholder ?$mode expects $type, " . get_debug_type($value) . ' given.');
+
+ return match ($mode) {
+ null => $this->formatValue($value),
+ self::ModeValues => array_key_exists(0, $check($value, 'iterable')) ? $this->formatMultiInsert($value) : $this->formatInsert($value),
+ self::ModeSet => $this->formatSet($check($value, 'iterable')),
+ self::ModeList => $this->formatList($check($value, 'iterable')),
+ self::ModeAnd, self::ModeOr => $this->formatWhere($check($value, 'iterable'), $mode),
+ self::ModeOrder => $this->formatOrderBy($check($value, 'iterable')),
+ self::ModeName => $this->delimit($check($value, 'string')),
+ default => throw new Nette\InvalidArgumentException("Unknown placeholder ?$mode."),
+ };
+ }
+
+
+ /**
+ * Formats a single value for use in SQL query.
+ */
+ private function formatValue(mixed $value): string
+ {
+ if ($this->useParams && (is_scalar($value) || is_resource($value))) {
+ $this->remaining[] = $value;
+ return '?';
+ }
+
+ return match (true) {
+ is_int($value) => (string) $value,
+ is_bool($value) => (string) (int) $value,
+ is_float($value) => rtrim(rtrim(number_format($value, 10, '.', ''), '0'), '.'),
+ is_resource($value) => $this->connection->quote(stream_get_contents($value)),
+ is_string($value) => $this->connection->quote($value),
+ $value === null => 'NULL',
+ $value instanceof SqlLiteral => $this->formatLiteral($value),
+ $value instanceof Table\ActiveRow => $this->formatValue($value->getPrimary()),
+ $value instanceof \DateTimeInterface => $this->driver->formatDateTime($value),
+ $value instanceof \DateInterval => $this->driver->formatDateInterval($value),
+ $value instanceof \BackedEnum && is_scalar($value->value) => $this->formatValue($value->value),
+ $value instanceof \Stringable => $this->formatValue((string) $value),
+ default => throw new Nette\InvalidArgumentException('Unexpected type of parameter: ' . get_debug_type($value))
+ };
+ }
+
+
+ /**
+ * Output: value, value, ... | (tuple), (tuple), ...
+ */
+ private function formatList(array $values): string
+ {
+ $res = [];
+ foreach ($values as $v) {
+ $res[] = is_array($v)
+ ? '(' . $this->formatList($v) . ')'
+ : $this->formatValue($v);
+ }
+
+ return implode(', ', $res);
+ }
+
+
+ /**
+ * Output format: (key, key, ...) VALUES (value, value, ...)
+ */
+ private function formatInsert(array $items): string
+ {
+ $cols = $vals = [];
+ foreach ($items as $k => $v) {
+ $cols[] = $this->delimit($k);
+ $vals[] = $this->formatValue($v);
+ }
+
+ return '(' . implode(', ', $cols) . ') VALUES (' . implode(', ', $vals) . ')';
+ }
+
+
+ /**
+ * Output format: (key, key, ...) VALUES (value, value, ...), (value, value, ...), ...
+ */
+ private function formatMultiInsert(array $groups): string
+ {
+ if (!is_array($groups[0]) && !$groups[0] instanceof Row) {
+ throw new Nette\InvalidArgumentException('Automaticaly detected multi-insert, but values aren\'t array. If you need try to change ?mode.');
+ }
+
+ $cols = array_keys(is_array($groups[0]) ? $groups[0] : iterator_to_array($groups[0]));
+ $vals = [];
+ foreach ($groups as $group) {
+ $rowVals = [];
+ foreach ($cols as $k) {
+ $rowVals[] = $this->formatValue($group[$k]);
+ }
+
+ $vals[] = implode(', ', $rowVals);
+ }
+
+ $useSelect = $this->driver->isSupported(Driver::SupportMultiInsertAsSelect);
+ return '(' . implode(', ', array_map($this->delimit(...), $cols))
+ . ($useSelect ? ') SELECT ' : ') VALUES (')
+ . implode($useSelect ? ' UNION ALL SELECT ' : '), (', $vals)
+ . ($useSelect ? '' : ')');
+ }
+
+
+ /**
+ * Output format: key=value, key=value, ...
+ */
+ private function formatSet(array $items): string
+ {
+ $res = [];
+ foreach ($items as $k => $v) {
+ if (is_int($k)) { // value, value, ...
+ $res[] = $this->formatValue($v);
+ } elseif (str_ends_with($k, '=')) { // key+=value, key-=value, ...
+ $col = $this->delimit(substr($k, 0, -2));
+ $res[] = $col . '=' . $col . ' ' . substr($k, -2, 1) . ' ' . $this->formatValue($v);
+ } else { // key=value, key=value, ...
+ $res[] = $this->delimit($k) . '=' . $this->formatValue($v);
+ }
+ }
+
+ return implode(', ', $res);
+ }
+
+
+ /**
+ * Output format: (key [operator] value) AND/OR ...
+ */
+ private function formatWhere(array $items, string $mode): string
+ {
+ $default = '1=1';
+ $res = [];
+ foreach ($items as $k => $v) {
+ if (is_int($k)) {
+ $res[] = $this->formatValue($v);
+ continue;
+ }
+
+ [$k, $operator] = explode(' ', $k, 2) + [1 => ''];
+ $k = $this->delimit($k);
+ if (is_array($v)) {
+ $kind = ['' => true, 'IN' => true, 'NOT' => false, 'NOT IN' => false][$operator] ?? null;
+ if ($v || $kind === null) {
+ $res[] = $k . ' ' . ($kind === null ? $operator : ($kind ? 'IN' : 'NOT IN')) . ' (' . $this->formatList(array_values($v)) . ')';
+
+ } else {
+ $default = $kind ? '1=0' : '1=1';
+ if ($kind === ($mode === self::ModeAnd)) {
+ return "($default)";
+ }
+ }
+
+ } else {
+ $v = $this->formatValue($v);
+ $operator = ['' => ['=', 'IS'], 'NOT' => ['!=', 'IS NOT']][$operator][$v === 'NULL'] ?? $operator;
+ $res[] = $k . ' ' . $operator . ' ' . $v;
+ }
+ }
+
+ return count($res) > 1
+ ? '((' . implode(') ' . strtoupper($mode) . ' (', $res) . '))'
+ : '(' . ($res[0] ?? $default) . ')';
+ }
+
+
+ /**
+ * Output format: key, key DESC, ...
+ */
+ private function formatOrderBy(array $items): string
+ {
+ $res = [];
+ foreach ($items as $k => $v) {
+ $res[] = $this->delimit($k) . ($v > 0 ? '' : ' DESC');
+ }
+
+ return implode(', ', $res);
+ }
+
+
+ /**
+ * Incorporates literal into SQL query.
+ */
+ private function formatLiteral(SqlLiteral $value): string
+ {
+ [$res, $params] = (clone $this)->process([$value->getSql(), ...$value->getParameters()], $this->useParams);
+ $this->remaining = array_merge($this->remaining, $params);
+ return $res;
+ }
+
+
+ /**
+ * Escapes and delimits identifier for use in SQL query.
+ */
+ private function delimit(string $name): string
+ {
+ return implode('.', array_map($this->driver->delimite(...), explode('.', $name)));
+ }
+}
diff --git a/vendor/nette/database/src/Database/Structure.php b/vendor/nette/database/src/Database/Structure.php
new file mode 100644
index 0000000..72a6630
--- /dev/null
+++ b/vendor/nette/database/src/Database/Structure.php
@@ -0,0 +1,284 @@
+connection = $connection;
+ $this->cache = new Nette\Caching\Cache($cacheStorage, 'Nette.Database.Structure.' . hash('xxh128', $connection->getDsn()));
+ }
+
+
+ public function getTables(): array
+ {
+ $this->needStructure();
+ return $this->structure['tables'];
+ }
+
+
+ public function getColumns(string $table): array
+ {
+ $this->needStructure();
+ $table = $this->resolveFQTableName($table);
+
+ return $this->structure['columns'][$table];
+ }
+
+
+ /**
+ * @return string|string[]|null
+ */
+ public function getPrimaryKey(string $table): string|array|null
+ {
+ $this->needStructure();
+ $table = $this->resolveFQTableName($table);
+ return $this->structure['primary'][$table] ?? null;
+ }
+
+
+ public function getPrimaryAutoincrementKey(string $table): ?string
+ {
+ $primaryKey = $this->getPrimaryKey($table);
+ if (!$primaryKey) {
+ return null;
+ }
+
+ // Search for autoincrement key from multi primary key
+ if (is_array($primaryKey)) {
+ $keys = array_flip($primaryKey);
+ foreach ($this->getColumns($table) as $column) {
+ if (isset($keys[$column['name']]) && $column['autoincrement']) {
+ return $column['name'];
+ }
+ }
+
+ return null;
+ }
+
+ // Search for autoincrement key from simple primary key
+ foreach ($this->getColumns($table) as $column) {
+ if ($column['name'] === $primaryKey) {
+ return $column['autoincrement'] ? $column['name'] : null;
+ }
+ }
+
+ return null;
+ }
+
+
+ public function getPrimaryKeySequence(string $table): ?string
+ {
+ $this->needStructure();
+ $table = $this->resolveFQTableName($table);
+
+ if (!$this->connection->getDriver()->isSupported(Driver::SupportSequence)) {
+ return null;
+ }
+
+ $autoincrementPrimaryKeyName = $this->getPrimaryAutoincrementKey($table);
+ if (!$autoincrementPrimaryKeyName) {
+ return null;
+ }
+
+ // Search for sequence from simple primary key
+ foreach ($this->structure['columns'][$table] as $columnMeta) {
+ if ($columnMeta['name'] === $autoincrementPrimaryKeyName) {
+ return $columnMeta['vendor']['sequence'] ?? null;
+ }
+ }
+
+ return null;
+ }
+
+
+ public function getHasManyReference(string $table, ?string $targetTable = null): ?array
+ {
+ $this->needStructure();
+ $table = $this->resolveFQTableName($table);
+
+ if ($targetTable) {
+ $targetTable = $this->resolveFQTableName($targetTable);
+ foreach ($this->structure['hasMany'][$table] as $key => $value) {
+ if (strtolower($key) === $targetTable) {
+ return $this->structure['hasMany'][$table][$key];
+ }
+ }
+
+ return null;
+
+ } else {
+ return $this->structure['hasMany'][$table] ?? [];
+ }
+ }
+
+
+ public function getBelongsToReference(string $table, ?string $column = null): ?array
+ {
+ $this->needStructure();
+ $table = $this->resolveFQTableName($table);
+
+ if ($column) {
+ $column = strtolower($column);
+ return isset($this->structure['belongsTo'][$table][$column])
+ ? [$this->structure['belongsTo'][$table][$column], $column]
+ : null;
+
+ } else {
+ return $this->structure['belongsTo'][$table] ?? [];
+ }
+ }
+
+
+ /**
+ * Rebuilds structure cache.
+ */
+ public function rebuild(): void
+ {
+ $this->structure = $this->loadStructure();
+ $this->cache->save('structure', $this->structure);
+ }
+
+
+ public function isRebuilt(): bool
+ {
+ return $this->isRebuilt;
+ }
+
+
+ protected function needStructure(): void
+ {
+ if (isset($this->structure)) {
+ return;
+ }
+
+ $this->structure = $this->cache->load('structure', $this->loadStructure(...));
+ }
+
+
+ /**
+ * Loads complete structure from database.
+ */
+ protected function loadStructure(): array
+ {
+ $driver = $this->connection->getDriver();
+
+ $structure = [];
+ $structure['tables'] = $driver->getTables();
+
+ foreach ($structure['tables'] as $tablePair) {
+ if (isset($tablePair['fullName'])) {
+ $table = $tablePair['fullName'];
+ $structure['aliases'][strtolower($tablePair['name'])] = strtolower($table);
+ } else {
+ $table = $tablePair['name'];
+ }
+
+ $structure['columns'][strtolower($table)] = $columns = $driver->getColumns($table);
+
+ if (!$tablePair['view']) {
+ $structure['primary'][strtolower($table)] = $this->analyzePrimaryKey($columns);
+ $this->analyzeForeignKeys($structure, $table);
+ }
+ }
+
+ if (isset($structure['hasMany'])) {
+ foreach ($structure['hasMany'] as &$table) {
+ uksort($table, fn($a, $b): int => strlen($a) <=> strlen($b));
+ }
+ }
+
+ $this->isRebuilt = true;
+
+ return $structure;
+ }
+
+
+ protected function analyzePrimaryKey(array $columns): string|array|null
+ {
+ $primary = [];
+ foreach ($columns as $column) {
+ if ($column['primary']) {
+ $primary[] = $column['name'];
+ }
+ }
+
+ if (count($primary) === 0) {
+ return null;
+ } elseif (count($primary) === 1) {
+ return reset($primary);
+ } else {
+ return $primary;
+ }
+ }
+
+
+ protected function analyzeForeignKeys(array &$structure, string $table): void
+ {
+ $lowerTable = strtolower($table);
+
+ $foreignKeys = $this->connection->getDriver()->getForeignKeys($table);
+
+ $fksColumnsCounts = [];
+ foreach ($foreignKeys as $foreignKey) {
+ $tmp = &$fksColumnsCounts[$foreignKey['name']];
+ $tmp++;
+ }
+
+ usort($foreignKeys, fn($a, $b): int => $fksColumnsCounts[$b['name']] <=> $fksColumnsCounts[$a['name']]);
+
+ foreach ($foreignKeys as $row) {
+ $structure['belongsTo'][$lowerTable][$row['local']] = $row['table'];
+ $structure['hasMany'][strtolower($row['table'])][$table][] = $row['local'];
+ }
+
+ if (isset($structure['belongsTo'][$lowerTable])) {
+ uksort($structure['belongsTo'][$lowerTable], fn($a, $b): int => strlen($a) <=> strlen($b));
+ }
+ }
+
+
+ /**
+ * Returns normalized table name.
+ */
+ protected function resolveFQTableName(string $table): string
+ {
+ $name = strtolower($table);
+ if (isset($this->structure['columns'][$name])) {
+ return $name;
+ }
+
+ if (isset($this->structure['aliases'][$name])) {
+ return $this->structure['aliases'][$name];
+ }
+
+ if (!$this->isRebuilt()) {
+ $this->rebuild();
+ return $this->resolveFQTableName($table);
+ }
+
+ throw new Nette\InvalidArgumentException("Table '$name' does not exist.");
+ }
+}
diff --git a/vendor/nette/database/src/Database/Table/ActiveRow.php b/vendor/nette/database/src/Database/Table/ActiveRow.php
new file mode 100644
index 0000000..35e0b23
--- /dev/null
+++ b/vendor/nette/database/src/Database/Table/ActiveRow.php
@@ -0,0 +1,295 @@
+table = $table;
+ }
+
+
+ /** @internal */
+ public function getTable(): Selection
+ {
+ return $this->table;
+ }
+
+
+ public function __toString()
+ {
+ return (string) $this->getPrimary();
+ }
+
+
+ public function toArray(): array
+ {
+ $this->accessColumn(null);
+ return $this->data;
+ }
+
+
+ /**
+ * Returns primary key value.
+ * @return mixed possible int, string, array, object (Nette\Utils\DateTime)
+ */
+ public function getPrimary(bool $throw = true): mixed
+ {
+ $primary = $this->table->getPrimary($throw);
+ if ($primary === null) {
+ return null;
+
+ } elseif (!is_array($primary)) {
+ if (isset($this->data[$primary])) {
+ return $this->data[$primary];
+ } elseif ($throw) {
+ throw new Nette\InvalidStateException("Row does not contain primary $primary column data.");
+ } else {
+ return null;
+ }
+ } else {
+ $primaryVal = [];
+ foreach ($primary as $key) {
+ if (!isset($this->data[$key])) {
+ if ($throw) {
+ throw new Nette\InvalidStateException("Row does not contain primary $key column data.");
+ } else {
+ return null;
+ }
+ }
+
+ $primaryVal[$key] = $this->data[$key];
+ }
+
+ return $primaryVal;
+ }
+ }
+
+
+ /**
+ * Returns row signature (composition of primary keys).
+ */
+ public function getSignature(bool $throw = true): string
+ {
+ return implode('|', (array) $this->getPrimary($throw));
+ }
+
+
+ /**
+ * Returns referenced row.
+ * @return self|null if the row does not exist
+ */
+ public function ref(string $key, ?string $throughColumn = null): ?self
+ {
+ $row = $this->table->getReferencedTable($this, $key, $throughColumn);
+ if ($row === false) {
+ throw new Nette\MemberAccessException("No reference found for \${$this->table->getName()}->ref($key).");
+ }
+
+ return $row;
+ }
+
+
+ /**
+ * Returns referencing rows collection.
+ */
+ public function related(string $key, ?string $throughColumn = null): GroupedSelection
+ {
+ $groupedSelection = $this->table->getReferencingTable($key, $throughColumn, $this[$this->table->getPrimary()]);
+ if (!$groupedSelection) {
+ throw new Nette\MemberAccessException("No reference found for \${$this->table->getName()}->related($key).");
+ }
+
+ return $groupedSelection;
+ }
+
+
+ /**
+ * Updates row data.
+ */
+ public function update(iterable $data): bool
+ {
+ if ($data instanceof \Traversable) {
+ $data = iterator_to_array($data);
+ }
+
+ $primary = $this->getPrimary();
+ if (!is_array($primary)) {
+ $primary = [$this->table->getPrimary() => $primary];
+ }
+
+ $selection = $this->table->createSelectionInstance()
+ ->wherePrimary($primary);
+
+ if ($selection->update($data)) {
+ if ($tmp = array_intersect_key($data, $primary)) {
+ $selection = $this->table->createSelectionInstance()
+ ->wherePrimary($tmp + $primary);
+ }
+
+ $selection->select('*');
+ if (($row = $selection->fetch()) === null) {
+ throw new Nette\InvalidStateException('Database refetch failed; row does not exist!');
+ }
+
+ $this->data = $row->data;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Deletes row from database.
+ * @return int number of affected rows
+ */
+ public function delete(): int
+ {
+ $res = $this->table->createSelectionInstance()
+ ->wherePrimary($this->getPrimary())
+ ->delete();
+
+ if ($res > 0 && ($signature = $this->getSignature(false))) {
+ unset($this->table[$signature]);
+ }
+
+ return $res;
+ }
+
+
+ /********************* interface IteratorAggregate ****************d*g**/
+
+
+ public function getIterator(): \Iterator
+ {
+ $this->accessColumn(null);
+ return new \ArrayIterator($this->data);
+ }
+
+
+ /********************* interface ArrayAccess & magic accessors ****************d*g**/
+
+
+ public function offsetSet($column, $value): void
+ {
+ $this->__set($column, $value);
+ }
+
+
+ public function offsetGet($column): mixed
+ {
+ return $this->__get($column);
+ }
+
+
+ public function offsetExists($column): bool
+ {
+ return $this->__isset($column);
+ }
+
+
+ public function offsetUnset($column): void
+ {
+ $this->__unset($column);
+ }
+
+
+ public function __set(string $column, mixed $value): void
+ {
+ throw new Nette\DeprecatedException('ActiveRow is read-only; use update() method instead.');
+ }
+
+
+ /**
+ * @return ActiveRow|mixed
+ * @throws Nette\MemberAccessException
+ */
+ public function &__get(string $key): mixed
+ {
+ if ($this->accessColumn($key)) {
+ return $this->data[$key];
+ }
+
+ $referenced = $this->table->getReferencedTable($this, $key);
+ if ($referenced !== false) {
+ $this->accessColumn($key, selectColumn: false);
+ return $referenced;
+ }
+
+ $this->removeAccessColumn($key);
+ $hint = Nette\Utils\Helpers::getSuggestion(array_keys($this->data), $key);
+ throw new Nette\MemberAccessException("Cannot read an undeclared column '$key'" . ($hint ? ", did you mean '$hint'?" : '.'));
+ }
+
+
+ public function __isset(string $key): bool
+ {
+ if ($this->accessColumn($key)) {
+ return isset($this->data[$key]);
+ }
+
+ $referenced = $this->table->getReferencedTable($this, $key);
+ if ($referenced !== false) {
+ $this->accessColumn($key, selectColumn: false);
+ return (bool) $referenced;
+ }
+
+ $this->removeAccessColumn($key);
+ return false;
+ }
+
+
+ public function __unset(string $key): void
+ {
+ throw new Nette\DeprecatedException('ActiveRow is read-only.');
+ }
+
+
+ /** @internal */
+ public function accessColumn(?string $key, bool $selectColumn = true): bool
+ {
+ if ($this->table->accessColumn($key, $selectColumn) && !$this->dataRefreshed) {
+ if (!isset($this->table[$this->getSignature()])) {
+ throw new Nette\InvalidStateException("Database refetch failed; row with signature '{$this->getSignature()}' does not exist!");
+ }
+
+ $this->data = $this->table[$this->getSignature()]->data;
+ $this->dataRefreshed = true;
+ }
+
+ return isset($this->data[$key]) || array_key_exists($key, $this->data);
+ }
+
+
+ protected function removeAccessColumn(string $key): void
+ {
+ $this->table->removeAccessColumn($key);
+ }
+}
diff --git a/vendor/nette/database/src/Database/Table/GroupedSelection.php b/vendor/nette/database/src/Database/Table/GroupedSelection.php
new file mode 100644
index 0000000..f82c2cc
--- /dev/null
+++ b/vendor/nette/database/src/Database/Table/GroupedSelection.php
@@ -0,0 +1,277 @@
+refTable = $refTable;
+ $this->column = $column;
+ parent::__construct($explorer, $conventions, $tableName, $cacheStorage);
+ }
+
+
+ /**
+ * Sets active group.
+ * @internal
+ * @param int|string $active primary key of grouped rows
+ */
+ public function setActive(int|string $active): static
+ {
+ $this->active = $active;
+ return $this;
+ }
+
+
+ public function select(string $columns, ...$params): static
+ {
+ if (!$this->sqlBuilder->getSelect()) {
+ $this->sqlBuilder->addSelect("$this->name.$this->column");
+ }
+
+ return parent::select($columns, ...$params);
+ }
+
+
+ public function order(string $columns, ...$params): static
+ {
+ if (!$this->sqlBuilder->getOrder()) {
+ // improve index utilization
+ $this->sqlBuilder->addOrder("$this->name.$this->column" . (preg_match('~\bDESC\z~i', $columns) ? ' DESC' : ''));
+ }
+
+ return parent::order($columns, ...$params);
+ }
+
+
+ /********************* aggregations ****************d*g**/
+
+
+ /**
+ * Calculates aggregation for this group.
+ */
+ public function aggregation(string $function, ?string $groupFunction = null): mixed
+ {
+ $aggregation = &$this->getRefTable($refPath)->aggregation[$refPath . $function . $this->sqlBuilder->getSelectQueryHash($this->getPreviousAccessedColumns())];
+
+ if ($aggregation === null) {
+ $aggregation = [];
+
+ $selection = $this->createSelectionInstance();
+ $selection->getSqlBuilder()->importConditions($this->getSqlBuilder());
+
+ if ($groupFunction && $selection->getSqlBuilder()->importGroupConditions($this->getSqlBuilder())) {
+ $selection->select("$function AS aggregate, $this->name.$this->column AS groupname");
+ $selection->group($selection->getSqlBuilder()->getGroup() . ", $this->name.$this->column");
+ $query = "SELECT $groupFunction(aggregate) AS groupaggregate, groupname FROM (" . $selection->getSql() . ') AS aggregates GROUP BY groupname';
+ foreach ($this->explorer->query($query, ...$selection->getSqlBuilder()->getParameters()) as $row) {
+ $aggregation[$row->groupname] = $row;
+ }
+ } else {
+ $selection->select($function);
+ $selection->select("$this->name.$this->column");
+ $selection->group("$this->name.$this->column");
+ foreach ($selection as $row) {
+ $aggregation[$row[$this->column]] = $row;
+ }
+ }
+ }
+
+ if (isset($aggregation[$this->active])) {
+ foreach ($aggregation[$this->active] as $val) {
+ return $val;
+ }
+ }
+
+ return 0;
+ }
+
+
+ public function count(?string $column = null): int
+ {
+ return parent::count($column);
+ }
+
+
+ /********************* internal ****************d*g**/
+
+
+ protected function execute(): void
+ {
+ if ($this->rows !== null) {
+ $this->observeCache = $this;
+ return;
+ }
+
+ $accessedColumns = $this->accessedColumns;
+ $this->loadRefCache();
+
+ if (!isset($this->refCacheCurrent['data'])) {
+ // we have not fetched any data yet => init accessedColumns by cached accessedColumns
+ $this->accessedColumns = $accessedColumns;
+
+ $limit = $this->sqlBuilder->getLimit();
+ $rows = count($this->refTable->rows);
+ if ($limit && $rows > 1) {
+ $this->sqlBuilder->setLimit(null, null);
+ }
+
+ parent::execute();
+ $this->sqlBuilder->setLimit($limit, null);
+ $data = [];
+ $offset = [];
+ $this->accessColumn($this->column);
+ foreach ((array) $this->rows as $key => $row) {
+ $ref = &$data[$row[$this->column]];
+ $skip = &$offset[$row[$this->column]];
+ if (
+ $limit === null
+ || $rows <= 1
+ || (count($ref ?? []) < $limit
+ && $skip >= $this->sqlBuilder->getOffset())
+ ) {
+ $ref[$key] = $row;
+ } else {
+ unset($this->rows[$key]);
+ }
+
+ $skip++;
+ unset($ref, $skip);
+ }
+
+ $this->refCacheCurrent['data'] = $data;
+ $this->data = &$this->refCacheCurrent['data'][$this->active];
+ }
+
+ $this->observeCache = $this;
+ if ($this->data === null) {
+ $this->data = [];
+ } else {
+ foreach ($this->data as $row) {
+ $row->setTable($this); // injects correct parent GroupedSelection
+ }
+
+ reset($this->data);
+ }
+ }
+
+
+ protected function getRefTable(&$refPath): Selection
+ {
+ $refObj = $this->refTable;
+ $refPath = $this->name . '.';
+ while ($refObj instanceof self) {
+ $refPath .= $refObj->name . '.';
+ $refObj = $refObj->refTable;
+ }
+
+ return $refObj;
+ }
+
+
+ protected function loadRefCache(): void
+ {
+ $hash = $this->getSpecificCacheKey();
+ $referencing = &$this->refCache['referencing'][$this->getGeneralCacheKey()];
+ $this->observeCache = &$referencing['observeCache'];
+ $this->refCacheCurrent = &$referencing[$hash];
+ $this->accessedColumns = &$referencing[$hash]['accessed'];
+ $this->rows = &$referencing[$hash]['rows'];
+
+ if (isset($referencing[$hash]['data'][$this->active])) {
+ $this->data = &$referencing[$hash]['data'][$this->active];
+ }
+ }
+
+
+ protected function emptyResultSet(bool $clearCache = true, bool $deleteReferencedCache = true): void
+ {
+ parent::emptyResultSet($clearCache, deleteReferencedCache: false);
+ }
+
+
+ /********************* manipulation ****************d*g**/
+
+
+ public function insert(iterable $data): ActiveRow|array|int|bool
+ {
+ if ($data instanceof \Traversable && !$data instanceof Selection) {
+ $data = iterator_to_array($data);
+ }
+
+ if (Nette\Utils\Arrays::isList($data)) {
+ foreach (array_keys($data) as $key) {
+ $data[$key][$this->column] = $this->active;
+ }
+ } else {
+ $data[$this->column] = $this->active;
+ }
+
+ return parent::insert($data);
+ }
+
+
+ public function update(iterable $data): int
+ {
+ $builder = $this->sqlBuilder;
+
+ $this->sqlBuilder = clone $this->sqlBuilder;
+ $this->where($this->column, $this->active);
+ $return = parent::update($data);
+
+ $this->sqlBuilder = $builder;
+ return $return;
+ }
+
+
+ public function delete(): int
+ {
+ $builder = $this->sqlBuilder;
+
+ $this->sqlBuilder = clone $this->sqlBuilder;
+ $this->where($this->column, $this->active);
+ $return = parent::delete();
+
+ $this->sqlBuilder = $builder;
+ return $return;
+ }
+}
diff --git a/vendor/nette/database/src/Database/Table/IRow.php b/vendor/nette/database/src/Database/Table/IRow.php
new file mode 100644
index 0000000..1a50755
--- /dev/null
+++ b/vendor/nette/database/src/Database/Table/IRow.php
@@ -0,0 +1,18 @@
+
+ * @implements \ArrayAccess
+ */
+class Selection implements \Iterator, IRowContainer, \ArrayAccess, \Countable
+{
+ protected readonly Explorer $explorer;
+
+ /** back compatibility */
+ protected Explorer $context;
+ protected readonly Conventions $conventions;
+ protected readonly ?Nette\Caching\Cache $cache;
+ protected SqlBuilder $sqlBuilder;
+
+ /** table name */
+ protected readonly string $name;
+
+ /** @var string|string[]|null primary key field name */
+ protected readonly string|array|null $primary;
+
+ /** primary column sequence name, false for autodetection */
+ protected string|bool|null $primarySequence = false;
+
+ /** @var array|null data read from database in [primary key => ActiveRow] format */
+ protected ?array $rows = null;
+
+ /** @var array|null modifiable data in [primary key => ActiveRow] format */
+ protected ?array $data = null;
+
+ protected bool $dataRefreshed = false;
+
+ /** cache array of Selection and GroupedSelection prototypes */
+ protected mixed $globalRefCache;
+
+ protected mixed $refCache;
+ protected ?string $generalCacheKey = null;
+ protected ?string $specificCacheKey = null;
+
+ /** of [conditions => [key => ActiveRow]]; used by GroupedSelection */
+ protected array $aggregation = [];
+ protected array|false|null $accessedColumns = null;
+ protected array|false|null $previousAccessedColumns = null;
+
+ /** should instance observe accessed columns caching */
+ protected ?self $observeCache = null;
+
+ /** of primary key values */
+ protected array $keys = [];
+
+
+ /**
+ * Creates filtered table representation.
+ */
+ public function __construct(
+ Explorer $explorer,
+ Conventions $conventions,
+ string $tableName,
+ ?Nette\Caching\Storage $cacheStorage = null,
+ ) {
+ $this->explorer = $this->context = $explorer;
+ $this->conventions = $conventions;
+ $this->name = $tableName;
+
+ $this->cache = $cacheStorage
+ ? new Nette\Caching\Cache($cacheStorage, 'Nette.Database.' . hash('xxh128', $explorer->getConnection()->getDsn()))
+ : null;
+ $this->primary = $conventions->getPrimary($tableName);
+ $this->sqlBuilder = new SqlBuilder($tableName, $explorer);
+ $this->refCache = &$this->getRefTable($refPath)->globalRefCache[$refPath];
+ }
+
+
+ public function __destruct()
+ {
+ $this->saveCacheState();
+ }
+
+
+ public function __clone()
+ {
+ $this->sqlBuilder = clone $this->sqlBuilder;
+ }
+
+
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+
+ /**
+ * Returns table primary key.
+ * @return string|string[]|null
+ */
+ public function getPrimary(bool $throw = true): string|array|null
+ {
+ if ($this->primary === null && $throw) {
+ throw new \LogicException("Table '{$this->name}' does not have a primary key.");
+ }
+
+ return $this->primary;
+ }
+
+
+ public function getPrimarySequence(): ?string
+ {
+ if ($this->primarySequence === false) {
+ $this->primarySequence = $this->explorer->getStructure()->getPrimaryKeySequence($this->name);
+ }
+
+ return $this->primarySequence;
+ }
+
+
+ /** @return static */
+ public function setPrimarySequence(string $sequence): static
+ {
+ $this->primarySequence = $sequence;
+ return $this;
+ }
+
+
+ public function getSql(): string
+ {
+ return $this->sqlBuilder->buildSelectQuery($this->getPreviousAccessedColumns());
+ }
+
+
+ /**
+ * Loads cache of previous accessed columns and returns it.
+ * @internal
+ */
+ public function getPreviousAccessedColumns(): array|bool
+ {
+ if ($this->cache && $this->previousAccessedColumns === null) {
+ $this->accessedColumns = $this->previousAccessedColumns = $this->cache->load($this->getGeneralCacheKey());
+ $this->previousAccessedColumns ??= [];
+ }
+
+ return array_keys(array_filter((array) $this->previousAccessedColumns));
+ }
+
+
+ /**
+ * @internal
+ */
+ public function getSqlBuilder(): SqlBuilder
+ {
+ return $this->sqlBuilder;
+ }
+
+
+ /********************* quick access ****************d*g**/
+
+
+ /**
+ * Returns row specified by primary key.
+ * @return T|null
+ */
+ public function get(mixed $key): ?ActiveRow
+ {
+ $clone = clone $this;
+ return $clone->wherePrimary($key)->fetch();
+ }
+
+
+ /**
+ * Returns the next row or null if there are no more rows.
+ * @return T|null
+ */
+ public function fetch(): ?ActiveRow
+ {
+ $this->execute();
+ $return = current($this->data);
+ next($this->data);
+ return $return === false ? null : $return;
+ }
+
+
+ /**
+ * Fetches single field.
+ * @deprecated
+ */
+ public function fetchField(?string $column = null): mixed
+ {
+ if ($column) {
+ $this->select($column);
+ }
+
+ $row = $this->fetch();
+ if ($row) {
+ return $column ? $row[$column] : array_values($row->toArray())[0];
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns all rows as associative array, where first argument specifies key column and second value column.
+ * For duplicate keys, the last value is used. When using null as key, array is indexed from zero.
+ * Alternatively accepts callback returning value or key-value pairs.
+ * @return array
+ */
+ public function fetchPairs(string|int|\Closure|null $keyOrCallback = null, string|int|null $value = null): array
+ {
+ return Nette\Database\Helpers::toPairs($this->fetchAll(), $keyOrCallback, $value);
+ }
+
+
+ /**
+ * Returns all rows.
+ * @return T[]
+ */
+ public function fetchAll(): array
+ {
+ return iterator_to_array($this);
+ }
+
+
+ /**
+ * Returns all rows as associative tree.
+ * @deprecated
+ */
+ public function fetchAssoc(string $path): array
+ {
+ $rows = array_map('iterator_to_array', $this->fetchAll());
+ return Nette\Utils\Arrays::associate($rows, $path);
+ }
+
+
+ /********************* sql selectors ****************d*g**/
+
+
+ /**
+ * Adds select clause, more calls append to the end.
+ * @param string $columns for example "column, MD5(column) AS column_md5"
+ * @return static
+ */
+ public function select(string $columns, ...$params): static
+ {
+ $this->emptyResultSet();
+ $this->sqlBuilder->addSelect($columns, ...$params);
+ return $this;
+ }
+
+
+ /**
+ * Adds condition for primary key.
+ * @return static
+ */
+ public function wherePrimary(mixed $key): static
+ {
+ if (is_array($this->primary) && Nette\Utils\Arrays::isList($key)) {
+ if (isset($key[0]) && is_array($key[0])) {
+ $this->where($this->primary, $key);
+ } else {
+ foreach ($this->primary as $i => $primary) {
+ $this->where($this->name . '.' . $primary, $key[$i]);
+ }
+ }
+ } elseif (is_array($key) && !Nette\Utils\Arrays::isList($key)) { // key contains column names
+ $this->where($key);
+ } else {
+ $this->where($this->name . '.' . $this->getPrimary(), $key);
+ }
+
+ return $this;
+ }
+
+
+ /**
+ * Adds where condition, more calls append with AND.
+ * @param string|array $condition possibly containing ?
+ * @return static
+ */
+ public function where(string|array $condition, ...$params): static
+ {
+ $this->condition($condition, $params);
+ return $this;
+ }
+
+
+ /**
+ * Adds ON condition when joining specified table, more calls appends with AND.
+ * @param string $tableChain table chain or table alias for which you need additional left join condition
+ * @param string $condition possibly containing ?
+ * @return static
+ */
+ public function joinWhere(string $tableChain, string $condition, ...$params): static
+ {
+ $this->condition($condition, $params, $tableChain);
+ return $this;
+ }
+
+
+ /**
+ * Adds condition, more calls appends with AND.
+ * @param string|string[] $condition possibly containing ?
+ */
+ protected function condition(string|array $condition, array $params, ?string $tableChain = null): void
+ {
+ $this->emptyResultSet();
+ if (is_array($condition) && $params === []) { // where(['column1' => 1, 'column2 > ?' => 2])
+ foreach ($condition as $key => $val) {
+ if (is_int($key)) {
+ $this->condition($val, [], $tableChain); // where('full condition')
+ } else {
+ $this->condition($key, [$val], $tableChain); // where('column', 1)
+ }
+ }
+ } elseif ($tableChain) {
+ $this->sqlBuilder->addJoinCondition($tableChain, $condition, ...$params);
+ } else {
+ $this->sqlBuilder->addWhere($condition, ...$params);
+ }
+ }
+
+
+ /**
+ * Adds where condition using the OR operator between parameters.
+ * More calls appends with AND.
+ * @param array $parameters ['column1' => 1, 'column2 > ?' => 2, 'full condition']
+ * @throws Nette\InvalidArgumentException
+ * @return static
+ */
+ public function whereOr(array $parameters): static
+ {
+ if (count($parameters) < 2) {
+ return $this->where($parameters);
+ }
+
+ $columns = [];
+ $values = [];
+ foreach ($parameters as $key => $val) {
+ if (is_int($key)) { // whereOr(['full condition'])
+ $columns[] = $val;
+ } elseif (!str_contains($key, '?')) { // whereOr(['column1' => 1])
+ $columns[] = $key . ' ?';
+ $values[] = $val;
+ } else { // whereOr(['column1 > ?' => 1])
+ $qNumber = substr_count($key, '?');
+ if ($qNumber > 1 && (!is_array($val) || $qNumber !== count($val))) {
+ throw new Nette\InvalidArgumentException('Argument count does not match placeholder count.');
+ }
+
+ $columns[] = $key;
+ $values = array_merge($values, $qNumber > 1 ? $val : [$val]);
+ }
+ }
+
+ $columnsString = '(' . implode(') OR (', $columns) . ')';
+ return $this->where($columnsString, $values);
+ }
+
+
+ /**
+ * Adds ORDER BY clause, more calls appends to the end.
+ * @param string $columns for example 'column1, column2 DESC'
+ * @return static
+ */
+ public function order(string $columns, ...$params): static
+ {
+ $this->emptyResultSet();
+ $this->sqlBuilder->addOrder($columns, ...$params);
+ return $this;
+ }
+
+
+ /**
+ * Sets LIMIT clause, more calls rewrite old values.
+ * @return static
+ */
+ public function limit(?int $limit, ?int $offset = null): static
+ {
+ $this->emptyResultSet();
+ $this->sqlBuilder->setLimit($limit, $offset);
+ return $this;
+ }
+
+
+ /**
+ * Sets OFFSET using page number, more calls rewrite old values.
+ * @return static
+ */
+ public function page(int $page, int $itemsPerPage, &$numOfPages = null): static
+ {
+ if (func_num_args() > 2) {
+ $numOfPages = (int) ceil($this->count('*') / $itemsPerPage);
+ }
+
+ if ($page < 1) {
+ $itemsPerPage = 0;
+ }
+
+ return $this->limit($itemsPerPage, ($page - 1) * $itemsPerPage);
+ }
+
+
+ /**
+ * Sets GROUP BY clause, more calls rewrite old value.
+ * @return static
+ */
+ public function group(string $columns, ...$params): static
+ {
+ $this->emptyResultSet();
+ $this->sqlBuilder->setGroup($columns, ...$params);
+ return $this;
+ }
+
+
+ /**
+ * Sets HAVING clause, more calls rewrite old value.
+ * @return static
+ */
+ public function having(string $having, ...$params): static
+ {
+ $this->emptyResultSet();
+ $this->sqlBuilder->setHaving($having, ...$params);
+ return $this;
+ }
+
+
+ /**
+ * Aliases table. Example ':book:book_tag.tag', 'tg'
+ * @return static
+ */
+ public function alias(string $tableChain, string $alias): static
+ {
+ $this->sqlBuilder->addAlias($tableChain, $alias);
+ return $this;
+ }
+
+
+ /********************* aggregations ****************d*g**/
+
+
+ /**
+ * Executes aggregation function.
+ * @param string $function select call in "FUNCTION(column)" format
+ */
+ public function aggregation(string $function, ?string $groupFunction = null): mixed
+ {
+ $selection = $this->createSelectionInstance();
+ $selection->getSqlBuilder()->importConditions($this->getSqlBuilder());
+ if ($groupFunction && $selection->getSqlBuilder()->importGroupConditions($this->getSqlBuilder())) {
+ $selection->select("$function AS aggregate");
+ $query = "SELECT $groupFunction(aggregate) AS groupaggregate FROM (" . $selection->getSql() . ') AS aggregates';
+ return $this->explorer->query($query, ...$selection->getSqlBuilder()->getParameters())->fetch()->groupaggregate;
+ } else {
+ $selection->select($function);
+ foreach ($selection->fetch() ?? [] as $val) {
+ return $val;
+ }
+ return null;
+ }
+ }
+
+
+ /**
+ * Counts number of rows. If column is not provided returns count of result rows, otherwise runs new sql counting query.
+ */
+ public function count(?string $column = null): int
+ {
+ if (!$column) {
+ $this->execute();
+ return count($this->data);
+ }
+
+ return (int) $this->aggregation("COUNT($column)", 'SUM');
+ }
+
+
+ /**
+ * Returns minimum value from a column.
+ */
+ public function min(string $column): mixed
+ {
+ return $this->aggregation("MIN($column)", 'MIN');
+ }
+
+
+ /**
+ * Returns maximum value from a column.
+ */
+ public function max(string $column): mixed
+ {
+ return $this->aggregation("MAX($column)", 'MAX');
+ }
+
+
+ /**
+ * Returns sum of values in a column.
+ */
+ public function sum(string $column): mixed
+ {
+ return $this->aggregation("SUM($column)", 'SUM');
+ }
+
+
+ /********************* internal ****************d*g**/
+
+
+ protected function execute(): void
+ {
+ if ($this->rows !== null) {
+ return;
+ }
+
+ $this->observeCache = $this;
+
+ if ($this->primary === null && $this->sqlBuilder->getSelect() === null) {
+ throw new Nette\InvalidStateException('Table with no primary key requires an explicit select clause.');
+ }
+
+ try {
+ $result = $this->query($this->getSql());
+
+ } catch (Nette\Database\DriverException $exception) {
+ if (!$this->sqlBuilder->getSelect() && $this->previousAccessedColumns) {
+ $this->previousAccessedColumns = false;
+ $this->accessedColumns = [];
+ $result = $this->query($this->getSql());
+ } else {
+ throw $exception;
+ }
+ }
+
+ $this->rows = [];
+ $usedPrimary = true;
+ foreach ($result->getPdoStatement() as $key => $row) {
+ $row = $this->createRow($result->normalizeRow($row));
+ $primary = $row->getSignature(false);
+ $usedPrimary = $usedPrimary && $primary !== '';
+ $this->rows[$usedPrimary ? $primary : $key] = $row;
+ }
+
+ $this->data = $this->rows;
+
+ if ($usedPrimary && $this->accessedColumns !== false) {
+ foreach ((array) $this->primary as $primary) {
+ $this->accessedColumns[$primary] = true;
+ }
+ }
+ }
+
+
+ /** @deprecated */
+ protected function createRow(array $row): ActiveRow
+ {
+ return $this->explorer->createActiveRow($row, $this);
+ }
+
+
+ /** @deprecated */
+ public function createSelectionInstance(?string $table = null): self
+ {
+ return $this->explorer->table($table ?: $this->name);
+ }
+
+
+ /** @deprecated */
+ protected function createGroupedSelectionInstance(string $table, string $column): GroupedSelection
+ {
+ return $this->explorer->createGroupedSelection($this, $table, $column);
+ }
+
+
+ protected function query(string $query): Nette\Database\ResultSet
+ {
+ return $this->explorer->query($query, ...$this->sqlBuilder->getParameters());
+ }
+
+
+ protected function emptyResultSet(bool $clearCache = true, bool $deleteReferencedCache = true): void
+ {
+ if ($this->rows !== null && $clearCache) {
+ $this->saveCacheState();
+ }
+
+ if ($clearCache) {
+ // NOT NULL in case of missing some column
+ $this->previousAccessedColumns = null;
+ $this->generalCacheKey = null;
+ }
+
+ $null = null;
+ $this->rows = &$null;
+ $this->specificCacheKey = null;
+ $this->refCache['referencingPrototype'] = [];
+ if ($deleteReferencedCache) {
+ $this->refCache['referenced'] = [];
+ }
+ }
+
+
+ protected function saveCacheState(): void
+ {
+ if (
+ $this->observeCache === $this
+ && $this->cache
+ && !$this->sqlBuilder->getSelect()
+ && $this->accessedColumns !== $this->previousAccessedColumns
+ ) {
+ $previousAccessed = $this->cache->load($this->getGeneralCacheKey());
+ $accessed = $this->accessedColumns;
+ $needSave = is_array($accessed) && is_array($previousAccessed)
+ ? array_intersect_key($accessed, $previousAccessed) !== $accessed
+ : $accessed !== $previousAccessed;
+
+ if ($needSave) {
+ $save = is_array($accessed) && is_array($previousAccessed)
+ ? $previousAccessed + $accessed
+ : $accessed;
+ $this->cache->save($this->getGeneralCacheKey(), $save);
+ $this->previousAccessedColumns = null;
+ }
+ }
+ }
+
+
+ /**
+ * Returns Selection parent for caching.
+ */
+ protected function getRefTable(&$refPath): self
+ {
+ return $this;
+ }
+
+
+ /**
+ * Loads refCache references
+ */
+ protected function loadRefCache(): void
+ {
+ }
+
+
+ /**
+ * Returns general cache key independent on query parameters or sql limit
+ * Used e.g. for previously accessed columns caching
+ */
+ protected function getGeneralCacheKey(): string
+ {
+ if ($this->generalCacheKey) {
+ return $this->generalCacheKey;
+ }
+
+ $key = [self::class, $this->name, $this->sqlBuilder->getConditions()];
+ $trace = [];
+ foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $item) {
+ $trace[] = isset($item['file'], $item['line'])
+ ? $item['file'] . $item['line']
+ : null;
+ }
+
+ $key[] = $trace;
+ return $this->generalCacheKey = hash('xxh128', serialize($key));
+ }
+
+
+ /**
+ * Returns object specific cache key dependent on query parameters
+ * Used e.g. for reference memory caching
+ */
+ protected function getSpecificCacheKey(): string
+ {
+ if ($this->specificCacheKey) {
+ return $this->specificCacheKey;
+ }
+
+ return $this->specificCacheKey = $this->sqlBuilder->getSelectQueryHash($this->getPreviousAccessedColumns());
+ }
+
+
+ /**
+ * @internal
+ * @param string|null column name or null to reload all columns
+ * @return bool if selection requeried for more columns.
+ */
+ public function accessColumn(?string $key, bool $selectColumn = true): bool
+ {
+ if (!$this->cache) {
+ return false;
+ }
+
+ if ($key === null) {
+ $this->accessedColumns = false;
+ $currentKey = key((array) $this->data);
+ } elseif ($this->accessedColumns !== false) {
+ $this->accessedColumns[$key] = $selectColumn;
+ }
+
+ if (
+ $selectColumn
+ && $this->previousAccessedColumns
+ && (
+ $key === null
+ || !isset($this->previousAccessedColumns[$key])
+ )
+ && !$this->sqlBuilder->getSelect()
+ ) {
+ if ($this->sqlBuilder->getLimit()) {
+ $generalCacheKey = $this->generalCacheKey;
+ $sqlBuilder = $this->sqlBuilder;
+
+ $primaryValues = [];
+ foreach ((array) $this->rows as $row) {
+ $primary = $row->getPrimary();
+ $primaryValues[] = is_array($primary)
+ ? array_values($primary)
+ : $primary;
+ }
+
+ $this->emptyResultSet(false);
+ $this->sqlBuilder = clone $this->sqlBuilder;
+ $this->sqlBuilder->setLimit(null, null);
+ $this->wherePrimary($primaryValues);
+
+ $this->generalCacheKey = $generalCacheKey;
+ $this->previousAccessedColumns = [];
+ $this->execute();
+ $this->sqlBuilder = $sqlBuilder;
+ } else {
+ $this->emptyResultSet(false);
+ $this->previousAccessedColumns = [];
+ $this->execute();
+ }
+
+ $this->dataRefreshed = true;
+
+ // move iterator to specific key
+ if (isset($currentKey)) {
+ while (key($this->data) !== null && key($this->data) !== $currentKey) {
+ next($this->data);
+ }
+ }
+ }
+
+ return $this->dataRefreshed;
+ }
+
+
+ /**
+ * @internal
+ */
+ public function removeAccessColumn(string $key): void
+ {
+ if ($this->cache && is_array($this->accessedColumns)) {
+ $this->accessedColumns[$key] = false;
+ }
+ }
+
+
+ /**
+ * Returns if selection requeried for more columns.
+ */
+ public function getDataRefreshed(): bool
+ {
+ return $this->dataRefreshed;
+ }
+
+
+ /********************* manipulation ****************d*g**/
+
+
+ /**
+ * Inserts row in a table. Returns ActiveRow or number of affected rows for Selection or table without primary key.
+ * @param iterable|Selection $data
+ * @return T|array|int|bool
+ */
+ public function insert(iterable $data): ActiveRow|array|int|bool
+ {
+ //should be called before query for not to spoil PDO::lastInsertId
+ $primarySequenceName = $this->getPrimarySequence();
+ $primaryAutoincrementKey = $this->explorer->getStructure()->getPrimaryAutoincrementKey($this->name);
+
+ if ($data instanceof self) {
+ $return = $this->explorer->query($this->sqlBuilder->buildInsertQuery() . ' ' . $data->getSql(), ...$data->getSqlBuilder()->getParameters());
+
+ } else {
+ if ($data instanceof \Traversable) {
+ $data = iterator_to_array($data);
+ }
+
+ $return = $this->explorer->query($this->sqlBuilder->buildInsertQuery() . ' ?values', $data);
+ }
+
+ $this->loadRefCache();
+
+ if ($data instanceof self || $this->primary === null) {
+ unset($this->refCache['referencing'][$this->getGeneralCacheKey()][$this->getSpecificCacheKey()]);
+ return $return->getRowCount();
+ }
+
+ $primaryKey = [];
+ foreach ((array) $this->primary as $key) {
+ if (isset($data[$key])) {
+ $primaryKey[$key] = $data[$key];
+ }
+ }
+
+ // First check sequence
+ if (!empty($primarySequenceName) && $primaryAutoincrementKey) {
+ $primaryKey[$primaryAutoincrementKey] = $this->explorer->getInsertId($this->explorer->getConnection()->getDriver()->delimite($primarySequenceName));
+
+ // Autoincrement primary without sequence
+ } elseif ($primaryAutoincrementKey) {
+ $primaryKey[$primaryAutoincrementKey] = $this->explorer->getInsertId($primarySequenceName);
+
+ // Multi column primary without autoincrement
+ } elseif (is_array($this->primary)) {
+ foreach ($this->primary as $key) {
+ if (!isset($data[$key])) {
+ return $data;
+ }
+ }
+
+ // Primary without autoincrement, try get primary from inserting data
+ } elseif ($this->primary && isset($data[$this->primary])) {
+ $primaryKey = $data[$this->primary];
+
+ // If primaryKey cannot be prepared, return inserted rows count
+ } else {
+ unset($this->refCache['referencing'][$this->getGeneralCacheKey()][$this->getSpecificCacheKey()]);
+ return $return->getRowCount();
+ }
+
+ $row = $this->createSelectionInstance()
+ ->select('*')
+ ->wherePrimary($primaryKey)
+ ->fetch();
+
+ if ($this->rows !== null) {
+ if ($signature = $row->getSignature(false)) {
+ $this->rows[$signature] = $row;
+ $this->data[$signature] = $row;
+ } else {
+ $this->rows[] = $row;
+ $this->data[] = $row;
+ }
+ }
+
+ return $row;
+ }
+
+
+ /**
+ * Updates all rows in result set.
+ * Joins in UPDATE are supported only in MySQL
+ * @return int number of affected rows
+ */
+ public function update(iterable $data): int
+ {
+ if ($data instanceof \Traversable) {
+ $data = iterator_to_array($data);
+ }
+
+ if (!$data) {
+ return 0;
+ }
+
+ return $this->explorer->query(
+ $this->sqlBuilder->buildUpdateQuery(),
+ ...array_merge([$data], $this->sqlBuilder->getParameters()),
+ )->getRowCount();
+ }
+
+
+ /**
+ * Deletes all rows in result set.
+ * @return int number of affected rows
+ */
+ public function delete(): int
+ {
+ return $this->query($this->sqlBuilder->buildDeleteQuery())->getRowCount();
+ }
+
+
+ /********************* references ****************d*g**/
+
+
+ /**
+ * Returns referenced row.
+ * @return ActiveRow|false|null null if the row does not exist, false if the relationship does not exist
+ */
+ public function getReferencedTable(ActiveRow $row, ?string $table, ?string $column = null): ActiveRow|false|null
+ {
+ if (!$column) {
+ $belongsTo = $this->conventions->getBelongsToReference($this->name, $table);
+ if (!$belongsTo) {
+ return false;
+ }
+
+ [$table, $column] = $belongsTo;
+ }
+
+ if (!$row->accessColumn($column)) {
+ return false;
+ }
+
+ $checkPrimaryKey = $row[$column];
+
+ $referenced = &$this->refCache['referenced'][$this->getSpecificCacheKey()]["$table.$column"];
+ $selection = &$referenced['selection'];
+ $cacheKeys = &$referenced['cacheKeys'];
+ if ($selection === null || ($checkPrimaryKey !== null && !isset($cacheKeys[$checkPrimaryKey]))) {
+ $this->execute();
+ $cacheKeys = [];
+ foreach ($this->rows as $row) {
+ if ($row[$column] === null) {
+ continue;
+ }
+
+ $key = $row[$column];
+ $cacheKeys[$key] = true;
+ }
+
+ if ($cacheKeys) {
+ $selection = $this->createSelectionInstance($table);
+ $selection->where($selection->getPrimary(), array_keys($cacheKeys));
+ } else {
+ $selection = [];
+ }
+ }
+
+ return $selection[$checkPrimaryKey] ?? null;
+ }
+
+
+ /**
+ * Returns referencing rows.
+ */
+ public function getReferencingTable(
+ string $table,
+ ?string $column = null,
+ int|string|null $active = null,
+ ): ?GroupedSelection
+ {
+ if (str_contains($table, '.')) {
+ [$table, $column] = explode('.', $table);
+ } elseif (!$column) {
+ $hasMany = $this->conventions->getHasManyReference($this->name, $table);
+ if (!$hasMany) {
+ return null;
+ }
+
+ [$table, $column] = $hasMany;
+ }
+
+ $prototype = &$this->refCache['referencingPrototype'][$this->getSpecificCacheKey()]["$table.$column"];
+ if (!$prototype) {
+ $prototype = $this->createGroupedSelectionInstance($table, $column);
+ $prototype->where("$table.$column", array_keys((array) $this->rows));
+ $prototype->getSpecificCacheKey();
+ }
+
+ $clone = clone $prototype;
+ $clone->setActive($active);
+ return $clone;
+ }
+
+
+ /********************* interface Iterator ****************d*g**/
+
+
+ public function rewind(): void
+ {
+ $this->execute();
+ $this->keys = array_keys($this->data);
+ reset($this->keys);
+ }
+
+
+ /** @return T|false */
+ public function current(): ActiveRow|false
+ {
+ return ($key = current($this->keys)) !== false
+ ? $this->data[$key]
+ : false;
+ }
+
+
+ public function key(): string|int
+ {
+ return current($this->keys);
+ }
+
+
+ public function next(): void
+ {
+ do {
+ next($this->keys);
+ } while (($key = current($this->keys)) !== false && !isset($this->data[$key]));
+ }
+
+
+ public function valid(): bool
+ {
+ return current($this->keys) !== false;
+ }
+
+
+ /********************* interface ArrayAccess ****************d*g**/
+
+
+ /**
+ * Mimic row.
+ * @param string $key
+ * @param ActiveRow $value
+ */
+ public function offsetSet($key, $value): void
+ {
+ $this->execute();
+ $this->rows[$key] = $value;
+ }
+
+
+ /**
+ * Returns specified row.
+ * @param string $key
+ * @return ?T
+ */
+ public function offsetGet($key): ?ActiveRow
+ {
+ $this->execute();
+ return $this->rows[$key];
+ }
+
+
+ /**
+ * Tests if row exists.
+ * @param string $key
+ */
+ public function offsetExists($key): bool
+ {
+ $this->execute();
+ return isset($this->rows[$key]);
+ }
+
+
+ /**
+ * Removes row from result set.
+ * @param string $key
+ */
+ public function offsetUnset($key): void
+ {
+ $this->execute();
+ unset($this->rows[$key], $this->data[$key]);
+ }
+}
diff --git a/vendor/nette/database/src/Database/Table/SqlBuilder.php b/vendor/nette/database/src/Database/Table/SqlBuilder.php
new file mode 100644
index 0000000..a48d64e
--- /dev/null
+++ b/vendor/nette/database/src/Database/Table/SqlBuilder.php
@@ -0,0 +1,861 @@
+ [],
+ 'joinCondition' => [],
+ 'where' => [],
+ 'group' => [],
+ 'having' => [],
+ 'order' => [],
+ ];
+ protected array $order = [];
+ protected ?int $limit = null;
+ protected ?int $offset = null;
+ protected string $group = '';
+ protected string $having = '';
+ protected array $reservedTableNames = [];
+ protected array $aliases = [];
+ protected string $currentAlias = '';
+ private readonly Driver $driver;
+ private readonly IStructure $structure;
+ private array $cacheTableList = [];
+ private array $expandingJoins = [];
+
+
+ public function __construct(string $tableName, Explorer $explorer)
+ {
+ $this->tableName = $tableName;
+ $this->driver = $explorer->getConnection()->getDriver();
+ $this->conventions = $explorer->getConventions();
+ $this->structure = $explorer->getStructure();
+ $tableNameParts = explode('.', $tableName);
+ $this->delimitedTable = implode('.', array_map($this->driver->delimite(...), $tableNameParts));
+ $this->checkUniqueTableName(end($tableNameParts), $tableName);
+ }
+
+
+ public function getTableName(): string
+ {
+ return $this->tableName;
+ }
+
+
+ public function buildInsertQuery(): string
+ {
+ return "INSERT INTO {$this->delimitedTable}";
+ }
+
+
+ public function buildUpdateQuery(): string
+ {
+ $query = "UPDATE {$this->delimitedTable} SET ?set" . $this->tryDelimite($this->buildConditions());
+
+ if ($this->order !== []) {
+ $query .= ' ORDER BY ' . implode(', ', $this->order);
+ }
+
+ if ($this->limit !== null || $this->offset) {
+ $this->driver->applyLimit($query, $this->limit, $this->offset);
+ }
+
+ return $query;
+ }
+
+
+ public function buildDeleteQuery(): string
+ {
+ $query = "DELETE FROM {$this->delimitedTable}" . $this->tryDelimite($this->buildConditions());
+ if ($this->limit !== null || $this->offset) {
+ $this->driver->applyLimit($query, $this->limit, $this->offset);
+ }
+
+ return $query;
+ }
+
+
+ /**
+ * Returns select query hash for caching.
+ */
+ public function getSelectQueryHash(?array $columns = null): string
+ {
+ $parts = [
+ 'delimitedTable' => $this->delimitedTable,
+ 'queryCondition' => $this->buildConditions(),
+ 'queryEnd' => $this->buildQueryEnd(),
+ $this->aliases,
+ $this->limit, $this->offset,
+ ];
+ if ($this->select) {
+ $parts[] = $this->select;
+ } elseif ($columns) {
+ $parts[] = [$this->delimitedTable, $columns];
+ } elseif ($this->group && !$this->driver->isSupported(Driver::SupportSelectUngroupedColumns)) {
+ $parts[] = [$this->group];
+ } else {
+ $parts[] = "{$this->delimitedTable}.*";
+ }
+
+ return $this->getConditionHash(json_encode($parts), [
+ $this->parameters['select'],
+ $this->parameters['joinCondition'],
+ $this->parameters['where'],
+ $this->parameters['group'],
+ $this->parameters['having'],
+ $this->parameters['order'],
+ ]);
+ }
+
+
+ /**
+ * Returns SQL query.
+ * @param string[] $columns
+ */
+ public function buildSelectQuery(?array $columns = null): string
+ {
+ if (!$this->order && ($this->limit !== null || $this->offset)) {
+ $this->order = array_map(
+ fn($col) => "$this->tableName.$col",
+ (array) $this->conventions->getPrimary($this->tableName),
+ );
+ }
+
+ $queryJoinConditions = $this->buildJoinConditions();
+ $queryCondition = $this->buildConditions();
+ $queryEnd = $this->buildQueryEnd();
+
+ $joins = [];
+ $finalJoinConditions = $this->parseJoinConditions($joins, $queryJoinConditions);
+ $this->parseJoins($joins, $queryCondition);
+ $this->parseJoins($joins, $queryEnd);
+
+ if ($this->select) {
+ $querySelect = $this->buildSelect($this->select);
+ $this->parseJoins($joins, $querySelect);
+
+ } elseif ($columns) {
+ $prefix = $joins ? "{$this->delimitedTable}." : '';
+ $cols = [];
+ foreach ($columns as $col) {
+ $cols[] = $prefix . $col;
+ }
+
+ $querySelect = $this->buildSelect($cols);
+
+ } elseif ($this->group && !$this->driver->isSupported(Driver::SupportSelectUngroupedColumns)) {
+ $querySelect = $this->buildSelect([$this->group]);
+ $this->parseJoins($joins, $querySelect);
+
+ } else {
+ $prefix = $joins ? "{$this->delimitedTable}." : '';
+ $querySelect = $this->buildSelect([$prefix . '*']);
+ }
+
+ $queryJoins = $this->buildQueryJoins($joins, $finalJoinConditions);
+ $query = "{$querySelect} FROM {$this->delimitedTable}{$queryJoins}{$queryCondition}{$queryEnd}";
+
+ $this->driver->applyLimit($query, $this->limit, $this->offset);
+
+ return $this->tryDelimite($query);
+ }
+
+
+ public function getParameters(): array
+ {
+ if (!isset($this->parameters['joinConditionSorted'])) {
+ $this->buildSelectQuery();
+ }
+
+ return array_merge(
+ $this->parameters['select'],
+ $this->parameters['joinConditionSorted'] ? array_merge(...array_values($this->parameters['joinConditionSorted'])) : [],
+ $this->parameters['where'],
+ $this->parameters['group'],
+ $this->parameters['having'],
+ $this->parameters['order'],
+ );
+ }
+
+
+ public function importConditions(self $builder): void
+ {
+ $this->where = $builder->where;
+ $this->joinCondition = $builder->joinCondition;
+ $this->parameters['where'] = $builder->parameters['where'];
+ $this->parameters['joinCondition'] = $builder->parameters['joinCondition'];
+ $this->conditions = $builder->conditions;
+ $this->aliases = $builder->aliases;
+ $this->reservedTableNames = $builder->reservedTableNames;
+ }
+
+
+ public function importGroupConditions(self $builder): bool
+ {
+ if ($builder->having) {
+ $this->group = $builder->group;
+ $this->having = $builder->having;
+ $this->parameters['group'] = $builder->parameters['group'];
+ $this->parameters['having'] = $builder->parameters['having'];
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /********************* SQL selectors ****************d*g**/
+
+
+ /**
+ * Adds SELECT clause, more calls append to the end.
+ */
+ public function addSelect(string $columns, ...$params): void
+ {
+ $this->select[] = $columns;
+ $this->parameters['select'] = array_merge($this->parameters['select'], $params);
+ }
+
+
+ public function getSelect(): array
+ {
+ return $this->select;
+ }
+
+
+ public function resetSelect(): void
+ {
+ $this->select = [];
+ $this->parameters['select'] = [];
+ }
+
+
+ /**
+ * Adds WHERE condition, more calls append with AND.
+ */
+ public function addWhere(string|array $condition, ...$params): bool
+ {
+ return $this->addCondition($condition, $params, $this->where, $this->parameters['where']);
+ }
+
+
+ /**
+ * Adds JOIN condition.
+ */
+ public function addJoinCondition(string $tableChain, string|array $condition, ...$params): bool
+ {
+ $this->parameters['joinConditionSorted'] = null;
+ if (!isset($this->joinCondition[$tableChain])) {
+ $this->joinCondition[$tableChain] = $this->parameters['joinCondition'][$tableChain] = [];
+ }
+
+ return $this->addCondition($condition, $params, $this->joinCondition[$tableChain], $this->parameters['joinCondition'][$tableChain]);
+ }
+
+
+ protected function addCondition(
+ string|array $condition,
+ array $params,
+ array &$conditions,
+ array &$conditionsParameters,
+ ): bool
+ {
+ if (is_array($condition) && !empty($params[0]) && is_array($params[0])) {
+ return $this->addConditionComposition($condition, $params[0], $conditions, $conditionsParameters);
+ }
+
+ $hash = $this->getConditionHash(is_string($condition) ? $condition : '', $params);
+ if (isset($this->conditions[$hash])) {
+ return false;
+ }
+
+ $this->conditions[$hash] = $condition;
+ $placeholderCount = substr_count($condition, '?');
+ if ($placeholderCount > 1 && count($params) === 1 && is_array($params[0])) {
+ $params = $params[0];
+ }
+
+ $condition = trim($condition);
+ if ($placeholderCount === 0 && count($params) === 1) {
+ $condition .= ' ?';
+ } elseif ($placeholderCount !== count($params)) {
+ throw new Nette\InvalidArgumentException('Argument count does not match placeholder count.');
+ }
+
+ $replace = null;
+ $placeholderNum = 0;
+ while (count($params)) {
+ $arg = array_shift($params);
+ preg_match(
+ '#(?:.*?\?.*?){' . $placeholderNum . '}(((?:&|\||^|~|\+|-|\*|/|%|\(|,|<|>|=|(?<=\W|^)(?:REGEXP|ALL|AND|ANY|BETWEEN|EXISTS|IN|[IR]?LIKE|OR|NOT|SOME|INTERVAL))\s*)?(?:\(\?\)|\?))#s',
+ $condition,
+ $match,
+ PREG_OFFSET_CAPTURE,
+ );
+ $hasOperator = ($match[1][0] === '?' && $match[1][1] === 0) || !empty($match[2][0]);
+
+ if ($arg === null) {
+ $replace = 'IS NULL';
+ if ($hasOperator) {
+ if (trim($match[2][0]) === 'NOT') {
+ $replace = 'IS NOT NULL';
+ } else {
+ throw new Nette\InvalidArgumentException('Column operator does not accept null argument.');
+ }
+ }
+ } elseif (is_array($arg) || $arg instanceof Selection) {
+ if ($hasOperator) {
+ if (trim($match[2][0]) === 'NOT') {
+ $match[2][0] = rtrim($match[2][0]) . ' IN ';
+ } elseif (trim($match[2][0]) !== 'IN') {
+ throw new Nette\InvalidArgumentException('Column operator does not accept array argument.');
+ }
+ } else {
+ $match[2][0] = 'IN ';
+ }
+
+ if ($arg instanceof Selection) {
+ $clone = clone $arg;
+ if (!$clone->getSqlBuilder()->select) {
+ try {
+ $clone->select($clone->getPrimary());
+ } catch (\LogicException | \TypeError $e) {
+ throw new Nette\InvalidArgumentException('Selection argument must have defined a select column.', 0, $e);
+ }
+ }
+
+ $arg = null;
+ $subSelectPlaceholderCount = substr_count($clone->getSql(), '?');
+ $replace = $match[2][0] . '(' . $clone->getSql() . (!$subSelectPlaceholderCount && count($clone->getSqlBuilder()->getParameters()) === 1 ? ' ?' : '') . ')';
+ if (count($clone->getSqlBuilder()->getParameters())) {
+ array_unshift($params, ...$clone->getSqlBuilder()->getParameters());
+ }
+ }
+
+ if ($arg !== null) {
+ if (!$arg) {
+ $hasBrackets = str_contains($condition, '(');
+ $hasOperators = preg_match('#AND|OR#', $condition);
+ $hasNot = str_contains($condition, 'NOT');
+ $hasPrefixNot = str_contains($match[2][0], 'NOT');
+ if (!$hasBrackets && ($hasOperators || ($hasNot && !$hasPrefixNot))) {
+ throw new Nette\InvalidArgumentException('Possible SQL query corruption. Add parentheses around operators.');
+ }
+
+ $replace = $hasPrefixNot
+ ? 'IS NULL OR TRUE'
+ : 'IS NULL AND FALSE';
+ $arg = null;
+ } else {
+ $replace = $match[2][0] . '(?)';
+ $conditionsParameters[] = $arg;
+ }
+ }
+ } elseif ($arg instanceof SqlLiteral) {
+ $conditionsParameters[] = $arg;
+ } else {
+ if (!$hasOperator) {
+ $replace = '= ?';
+ }
+
+ $conditionsParameters[] = $arg;
+ }
+
+ if ($replace) {
+ $condition = substr_replace($condition, $replace, $match[1][1], strlen($match[1][0]));
+ $replace = null;
+ }
+
+ if ($arg !== null) {
+ $placeholderNum++;
+ }
+ }
+
+ $conditions[] = $condition;
+ return true;
+ }
+
+
+ public function getConditions(): array
+ {
+ return array_values($this->conditions);
+ }
+
+
+ /**
+ * Adds alias AS.
+ */
+ public function addAlias(string $chain, string $alias): void
+ {
+ if (isset($chain[0]) && $chain[0] !== '.' && $chain[0] !== ':') {
+ $chain = '.' . $chain; // unified chain format
+ }
+
+ $this->checkUniqueTableName($alias, $chain);
+ $this->aliases[$alias] = $chain;
+ }
+
+
+ protected function checkUniqueTableName(string $tableName, string $chain): void
+ {
+ if (isset($this->aliases[$tableName]) && ($chain === '.' . $tableName)) {
+ $chain = $this->aliases[$tableName];
+ }
+
+ if (isset($this->reservedTableNames[$tableName])) {
+ if ($this->reservedTableNames[$tableName] === $chain) {
+ return;
+ }
+
+ throw new Nette\InvalidArgumentException("Table alias '$tableName' from chain '$chain' is already in use by chain '{$this->reservedTableNames[$tableName]}'. Please add/change alias for one of them.");
+ }
+
+ $this->reservedTableNames[$tableName] = $chain;
+ }
+
+
+ /**
+ * Adds ORDER BY clause, more calls append to the end.
+ */
+ public function addOrder(string|array $columns, ...$params): void
+ {
+ $this->order[] = $columns;
+ $this->parameters['order'] = array_merge($this->parameters['order'], $params);
+ }
+
+
+ public function setOrder(array $columns, array $parameters): void
+ {
+ $this->order = $columns;
+ $this->parameters['order'] = $parameters;
+ }
+
+
+ public function getOrder(): array
+ {
+ return $this->order;
+ }
+
+
+ /**
+ * Sets LIMIT/OFFSET clause.
+ */
+ public function setLimit(?int $limit, ?int $offset): void
+ {
+ $this->limit = $limit;
+ $this->offset = $offset;
+ }
+
+
+ public function getLimit(): ?int
+ {
+ return $this->limit;
+ }
+
+
+ public function getOffset(): ?int
+ {
+ return $this->offset;
+ }
+
+
+ /**
+ * Sets GROUP BY and HAVING clause.
+ */
+ public function setGroup(string|array $columns, ...$params): void
+ {
+ $this->group = $columns;
+ $this->parameters['group'] = $params;
+ }
+
+
+ public function getGroup(): string
+ {
+ return $this->group;
+ }
+
+
+ public function setHaving(string $having, ...$params): void
+ {
+ $this->having = $having;
+ $this->parameters['having'] = $params;
+ }
+
+
+ public function getHaving(): string
+ {
+ return $this->having;
+ }
+
+
+ /********************* SQL building ****************d*g**/
+
+
+ protected function buildSelect(array $columns): string
+ {
+ return 'SELECT ' . implode(', ', $columns);
+ }
+
+
+ protected function parseJoinConditions(array &$joins, array $joinConditions): array
+ {
+ $tableJoins = $leftJoinDependency = $finalJoinConditions = [];
+ foreach ($joinConditions as $tableChain => $joinCondition) {
+ $fooQuery = $tableChain . '.foo';
+ $requiredJoins = [];
+ $this->parseJoins($requiredJoins, $fooQuery);
+ $tableAlias = substr($fooQuery, 0, -4);
+ $tableJoins[$tableAlias] = $requiredJoins;
+ $leftJoinDependency[$tableAlias] = [];
+ $finalJoinConditions[$tableAlias] = preg_replace_callback($this->getColumnChainsRegxp(), function (array $match) use ($tableAlias, &$tableJoins, &$leftJoinDependency): string {
+ $requiredJoins = [];
+ $query = $this->parseJoinsCb($requiredJoins, $match);
+ $queryParts = explode('.', $query);
+ $tableJoins[$queryParts[0]] = $requiredJoins;
+ if ($queryParts[0] !== $tableAlias) {
+ foreach (array_keys($requiredJoins) as $requiredTable) {
+ $leftJoinDependency[$tableAlias][$requiredTable] = $requiredTable;
+ }
+ }
+
+ return $query;
+ }, $joinCondition);
+ }
+
+ $this->parameters['joinConditionSorted'] = [];
+ if (count($joinConditions)) {
+ while ($tableJoins) {
+ $this->getSortedJoins(key($tableJoins), $leftJoinDependency, $tableJoins, $joins);
+ }
+ }
+
+ return $finalJoinConditions;
+ }
+
+
+ protected function getSortedJoins(
+ string $table,
+ array &$leftJoinDependency,
+ array &$tableJoins,
+ array &$finalJoins,
+ ): void
+ {
+ if (isset($this->expandingJoins[$table])) {
+ $path = implode("' => '", array_map(
+ fn(string $value): string => $this->reservedTableNames[$value],
+ array_merge(array_keys($this->expandingJoins), [$table]),
+ ));
+ throw new Nette\InvalidArgumentException("Circular reference detected at left join conditions (tables '$path').");
+ }
+
+ if (isset($tableJoins[$table])) {
+ $this->expandingJoins[$table] = true;
+ if (isset($leftJoinDependency[$table])) {
+ foreach ($leftJoinDependency[$table] as $requiredTable) {
+ if ($requiredTable === $table) {
+ continue;
+ }
+
+ $this->getSortedJoins($requiredTable, $leftJoinDependency, $tableJoins, $finalJoins);
+ }
+ }
+
+ if ($tableJoins[$table]) {
+ foreach ($tableJoins[$table] as $requiredTable => $tmp) {
+ if ($requiredTable === $table) {
+ continue;
+ }
+
+ $this->getSortedJoins($requiredTable, $leftJoinDependency, $tableJoins, $finalJoins);
+ }
+ }
+
+ $finalJoins += $tableJoins[$table];
+ $key = isset($this->aliases[$table])
+ ? $table
+ : $this->reservedTableNames[$table];
+ if ($key[0] === '.') {
+ $key = substr($key, 1);
+ }
+
+ $this->parameters['joinConditionSorted'] += isset($this->parameters['joinCondition'][$key])
+ ? [$table => $this->parameters['joinCondition'][$key]]
+ : [];
+ unset($tableJoins[$table], $this->expandingJoins[$table]);
+ }
+ }
+
+
+ protected function parseJoins(array &$joins, string &$query): void
+ {
+ $query = preg_replace_callback($this->getColumnChainsRegxp(), function (array $match) use (&$joins): string {
+ return $this->parseJoinsCb($joins, $match);
+ }, $query);
+ }
+
+
+ private function getColumnChainsRegxp(): string
+ {
+ return '~
+ (?P (?!\.) (?: [.:]? (?>[\w_]*[a-z][\w_]*) (\([\w_]*[a-z][\w_]*\))? ) *) \. (?P (?>[\w_]*[a-z][\w_]*) | \* )
+ ~xi';
+ }
+
+
+ public function parseJoinsCb(array &$joins, array $match): string
+ {
+ $chain = $match['chain'];
+ if (!empty($chain[0]) && ($chain[0] !== '.' && $chain[0] !== ':')) {
+ $chain = '.' . $chain; // unified chain format
+ }
+
+ preg_match_all('~
+ (?P [.:])?(?P [\w_]*[a-z][\w_]* )(\((?P [\w_]*[a-z][\w_]* )\))?
+ ~xi', $chain, $keyMatches, PREG_SET_ORDER);
+
+ $parent = $this->tableName;
+ $parentAlias = preg_replace('#^(.*\.)?(.*)$#', '$2', $this->tableName);
+
+ // join schema keyMatch and table keyMatch to schema.table keyMatch
+ if ($this->driver->isSupported(Driver::SupportSchema) && count($keyMatches) > 1) {
+ $tables = $this->getCachedTableList();
+ if (
+ !isset($tables[$keyMatches[0]['key']])
+ && isset($tables[$keyMatches[0]['key'] . '.' . $keyMatches[1]['key']])
+ ) {
+ $keyMatch = array_shift($keyMatches);
+ $keyMatches[0]['key'] = $keyMatch['key'] . '.' . $keyMatches[0]['key'];
+ $keyMatches[0]['del'] = $keyMatch['del'];
+ }
+ }
+
+ // do not make a join when referencing to the current table column - inner conditions
+ // check it only when not making backjoin on itself - outer condition
+ if ($keyMatches[0]['del'] === '.') {
+ if (
+ count($keyMatches) > 1
+ && ($parent === $keyMatches[0]['key']
+ || $parentAlias === $keyMatches[0]['key'])
+ ) {
+ throw new Nette\InvalidArgumentException("Do not prefix table chain with origin table name '{$keyMatches[0]['key']}'. If you want to make self reference, please add alias.");
+ }
+
+ if ($parent === $keyMatches[0]['key']) {
+ return "{$parent}.{$match['column']}";
+ } elseif ($parentAlias === $keyMatches[0]['key']) {
+ return "{$parentAlias}.{$match['column']}";
+ }
+ }
+
+ $tableChain = null;
+ foreach ($keyMatches as $index => $keyMatch) {
+ $isLast = !isset($keyMatches[$index + 1]);
+ if (!$index && isset($this->aliases[$keyMatch['key']])) {
+ if ($keyMatch['del'] === ':') {
+ throw new Nette\InvalidArgumentException("You are using has many syntax with alias (':{$keyMatch['key']}'). You have to move it to alias definition.");
+ }
+
+ $previousAlias = $this->currentAlias;
+ $this->currentAlias = $keyMatch['key'];
+ $requiredJoins = [];
+ $query = $this->aliases[$keyMatch['key']] . '.foo';
+ $this->parseJoins($requiredJoins, $query);
+ $aliasJoin = array_pop($requiredJoins);
+ $joins += $requiredJoins;
+ [$table, , $parentAlias, $column, $primary] = $aliasJoin;
+ $this->currentAlias = $previousAlias;
+
+ } elseif ($keyMatch['del'] === ':') {
+ if (isset($keyMatch['throughColumn'])) {
+ $table = $keyMatch['key'];
+ $belongsTo = $this->conventions->getBelongsToReference($table, $keyMatch['throughColumn']);
+ if (!$belongsTo) {
+ throw new Nette\InvalidArgumentException("No reference found for \${$parent}->{$keyMatch['key']}.");
+ }
+
+ [, $primary] = $belongsTo;
+
+ } else {
+ $hasMany = $this->conventions->getHasManyReference($parent, $keyMatch['key']);
+ if (!$hasMany) {
+ throw new Nette\InvalidArgumentException("No reference found for \${$parent}->related({$keyMatch['key']}).");
+ }
+
+ [$table, $primary] = $hasMany;
+ }
+
+ $column = $this->conventions->getPrimary($parent);
+
+ } else {
+ $belongsTo = $this->conventions->getBelongsToReference($parent, $keyMatch['key']);
+ if (!$belongsTo) {
+ throw new Nette\InvalidArgumentException("No reference found for \${$parent}->{$keyMatch['key']}.");
+ }
+
+ [$table, $column] = $belongsTo;
+ $primary = $this->conventions->getPrimary($table);
+ }
+
+ if ($this->currentAlias && $isLast) {
+ $tableAlias = $this->currentAlias;
+ } elseif ($parent === $table) {
+ $tableAlias = $parentAlias . '_ref';
+ } elseif ($keyMatch['key']) {
+ $tableAlias = $keyMatch['key'];
+ } else {
+ $tableAlias = preg_replace('#^(.*\.)?(.*)$#', '$2', $table);
+ }
+
+ $tableChain .= $keyMatch[0];
+ if (!$isLast || !$this->currentAlias) {
+ $this->checkUniqueTableName($tableAlias, $tableChain);
+ }
+
+ $joins[$tableAlias] = [$table, $tableAlias, $parentAlias, $column, $primary];
+ $parent = $table;
+ $parentAlias = $tableAlias;
+ }
+
+ return $tableAlias . ".{$match['column']}";
+ }
+
+
+ protected function buildQueryJoins(array $joins, array $leftJoinConditions = []): string
+ {
+ $return = '';
+ foreach ($joins as [$joinTable, $joinAlias, $table, $tableColumn, $joinColumn]) {
+ $return .=
+ " LEFT JOIN {$joinTable}" . ($joinTable !== $joinAlias ? " {$joinAlias}" : '') .
+ " ON {$table}.{$tableColumn} = {$joinAlias}.{$joinColumn}" .
+ (isset($leftJoinConditions[$joinAlias]) ? " {$leftJoinConditions[$joinAlias]}" : '');
+ }
+
+ return $return;
+ }
+
+
+ protected function buildJoinConditions(): array
+ {
+ $conditions = [];
+ foreach ($this->joinCondition as $tableChain => $joinConditions) {
+ $conditions[$tableChain] = 'AND (' . implode(') AND (', $joinConditions) . ')';
+ }
+
+ return $conditions;
+ }
+
+
+ protected function buildConditions(): string
+ {
+ return $this->where
+ ? ' WHERE (' . implode(') AND (', $this->where) . ')'
+ : '';
+ }
+
+
+ protected function buildQueryEnd(): string
+ {
+ $return = '';
+ if ($this->group) {
+ $return .= ' GROUP BY ' . $this->group;
+ }
+
+ if ($this->having) {
+ $return .= ' HAVING ' . $this->having;
+ }
+
+ if ($this->order) {
+ $return .= ' ORDER BY ' . implode(', ', $this->order);
+ }
+
+ return $return;
+ }
+
+
+ protected function tryDelimite(string $s): string
+ {
+ return preg_replace_callback(
+ '#(?<=[^\w`"\[?:]|^)[a-z_][a-z0-9_]*(?=[^\w`"(\]]|$)#Di',
+ fn(array $m): string => strtoupper($m[0]) === $m[0]
+ ? $m[0]
+ : $this->driver->delimite($m[0]),
+ $s,
+ );
+ }
+
+
+ protected function addConditionComposition(
+ array $columns,
+ array $parameters,
+ array &$conditions,
+ array &$conditionsParameters,
+ ): bool
+ {
+ if ($this->driver->isSupported(Driver::SupportMultiColumnAsOrCondition)) {
+ $conditionFragment = '(' . implode(' = ? AND ', $columns) . ' = ?) OR ';
+ $condition = substr(str_repeat($conditionFragment, count($parameters)), 0, -4);
+ return $this->addCondition($condition, [Nette\Utils\Arrays::flatten($parameters)], $conditions, $conditionsParameters);
+ } else {
+ return $this->addCondition('(' . implode(', ', $columns) . ') IN', [$parameters], $conditions, $conditionsParameters);
+ }
+ }
+
+
+ private function getConditionHash(string $condition, array $parameters): string
+ {
+ foreach ($parameters as $key => &$parameter) {
+ if ($parameter instanceof Selection) {
+ $parameter = $this->getConditionHash($parameter->getSql(), $parameter->getSqlBuilder()->getParameters());
+ } elseif ($parameter instanceof SqlLiteral) {
+ $parameter = $this->getConditionHash($parameter->getSql(), $parameter->getParameters());
+ } elseif ($parameter instanceof \Stringable) {
+ $parameter = $parameter->__toString();
+ } elseif (is_array($parameter) || $parameter instanceof \ArrayAccess) {
+ $parameter = $this->getConditionHash((string) $key, $parameter);
+ }
+ }
+
+ return hash('xxh128', $condition . json_encode($parameters));
+ }
+
+
+ private function getCachedTableList(): array
+ {
+ if (!$this->cacheTableList) {
+ $this->cacheTableList = array_flip(array_map(
+ fn(array $pair): string => $pair['fullName'] ?? $pair['name'],
+ $this->structure->getTables(),
+ ));
+ }
+
+ return $this->cacheTableList;
+ }
+}
diff --git a/vendor/nette/database/src/Database/exceptions.php b/vendor/nette/database/src/Database/exceptions.php
new file mode 100644
index 0000000..491b244
--- /dev/null
+++ b/vendor/nette/database/src/Database/exceptions.php
@@ -0,0 +1,50 @@
+ '@']));
+override(\Nette\DI\ContainerBuilder::addDefinition(1), type(1));
diff --git a/vendor/nette/di/composer.json b/vendor/nette/di/composer.json
new file mode 100644
index 0000000..f834278
--- /dev/null
+++ b/vendor/nette/di/composer.json
@@ -0,0 +1,45 @@
+{
+ "name": "nette/di",
+ "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP features.",
+ "keywords": ["nette", "di", "dic", "ioc", "factory", "compiled", "static"],
+ "homepage": "https://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.1 - 8.4",
+ "ext-tokenizer": "*",
+ "ext-ctype": "*",
+ "nette/neon": "^3.3 || ^4.0",
+ "nette/php-generator": "^4.1.6",
+ "nette/robot-loader": "^4.0",
+ "nette/schema": "^1.2.5",
+ "nette/utils": "^4.0"
+ },
+ "require-dev": {
+ "nette/tester": "^2.5.2",
+ "tracy/tracy": "^2.9",
+ "phpstan/phpstan": "^1.0"
+ },
+ "autoload": {
+ "classmap": ["src/"]
+ },
+ "minimum-stability": "dev",
+ "scripts": {
+ "phpstan": "phpstan analyse",
+ "tester": "tester tests -s"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ }
+}
diff --git a/vendor/nette/di/license.md b/vendor/nette/di/license.md
new file mode 100644
index 0000000..cf741bd
--- /dev/null
+++ b/vendor/nette/di/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/nette/di/readme.md b/vendor/nette/di/readme.md
new file mode 100644
index 0000000..25acf64
--- /dev/null
+++ b/vendor/nette/di/readme.md
@@ -0,0 +1,364 @@
+[](https://doc.nette.org/dependency-injection)
+
+[](https://packagist.org/packages/nette/di)
+[](https://github.com/nette/di/actions)
+[](https://coveralls.io/github/nette/di?branch=master)
+[](https://github.com/nette/di/releases)
+[](https://github.com/nette/di/blob/master/license.md)
+
+
+
+Introduction
+------------
+
+Purpose of the Dependecy Injection (DI) is to free classes from the responsibility for obtaining objects that they need for its operation (these objects are called **services**). To pass them these services on their instantiation instead.
+
+Nette DI is one of the most interesting part of framework. It is compiled DI container, extremely fast and easy to configure.
+
+Documentation can be found on the [website](https://doc.nette.org/dependency-injection).
+
+
+
+[Support Me](https://github.com/sponsors/dg)
+--------------------------------------------
+
+Do you like Nette DI? Are you looking forward to the new features?
+
+[](https://github.com/sponsors/dg)
+
+Thank you!
+
+
+
+Installation
+------------
+
+The recommended way to install is via Composer:
+
+```
+composer require nette/di
+```
+
+It requires PHP version 8.1 and supports PHP up to 8.4.
+
+
+
+Usage
+-----
+
+Let's have an application for sending newsletters. The code is maximally simplified and is available on the [GitHub](https://github.com/dg/di-example).
+
+We have the object representing email:
+
+```php
+class Mail
+{
+ public string $subject;
+ public string $message;
+}
+```
+
+An object which can send emails:
+
+```php
+interface Mailer
+{
+ function send(Mail $mail, string $to): void;
+}
+```
+
+A support for logging:
+
+```php
+interface Logger
+{
+ function log(string $message): void;
+}
+```
+
+And finally, a class that provides sending newsletters:
+
+```php
+class NewsletterManager
+{
+ private Mailer $mailer;
+ private Logger $logger;
+
+ public function __construct(Mailer $mailer, Logger $logger)
+ {
+ $this->mailer = $mailer;
+ $this->logger = $logger;
+ }
+
+ public function distribute(array $recipients): void
+ {
+ $mail = new Mail;
+ $mail->subject = '...';
+ $mail->message = '...';
+
+ foreach ($recipients as $recipient) {
+ $this->mailer->send($mail, $recipient);
+ }
+ $this->logger->log('...');
+ }
+}
+```
+
+The code respects Dependency Injection, ie. **each object uses only variables which we had passed into it.**
+
+Also, we have a ability to implement own `Logger` or `Mailer`, like this:
+
+```php
+class SendMailMailer implements Mailer
+{
+ public function send(Mail $mail, string $to): void
+ {
+ mail($to, $mail->subject, $mail->message);
+ }
+}
+
+class FileLogger implements Logger
+{
+ private string $file;
+
+ public function __construct(string $file)
+ {
+ $this->file = $file;
+ }
+
+ public function log(string $message): void
+ {
+ file_put_contents($this->file, $message . "\n", FILE_APPEND);
+ }
+}
+```
+
+**DI container is the supreme architect** which can create individual objects (in the terminology DI called services) and assemble and configure them exactly according to our needs.
+
+Container for our application might look like this:
+
+```php
+class Container
+{
+ private ?Logger $logger;
+ private ?Mailer $mailer;
+
+ public function getLogger(): Logger
+ {
+ if (!isset($this->logger)) {
+ $this->logger = new FileLogger('log.txt');
+ }
+ return $this->logger;
+ }
+
+ public function getMailer(): Mailer
+ {
+ if (!isset($this->mailer)) {
+ $this->mailer = new SendMailMailer;
+ }
+ return $this->mailer;
+ }
+
+ public function createNewsletterManager(): NewsletterManager
+ {
+ return new NewsletterManager($this->getMailer(), $this->getLogger());
+ }
+}
+```
+
+The implementation looks like this because:
+- the individual services are created only on demand (lazy loading)
+- doubly called `createNewsletterManager` will use the same logger and mailer instances
+
+Let's instantiate `Container`, let it create manager and we can start spamming users with newsletters :-)
+
+```php
+$container = new Container;
+$manager = $container->createNewsletterManager();
+$manager->distribute(...);
+```
+
+Significant to Dependency Injection is that no class depends on the container. Thus it can be easily replaced with another one. For example with the container generated by Nette DI.
+
+
+
+Nette DI
+----------
+
+Nette DI is the generator of containers. We instruct it (usually) with configuration files. This is configuration that leads to generate nearly the same class as the class `Container` above:
+
+```neon
+services:
+ - FileLogger( log.txt )
+ - SendMailMailer
+ - NewsletterManager
+```
+
+The big advantage is the shortness of configuration.
+
+Nette DI actually generates PHP code of container. Therefore it is extremely fast. Developer can see the code, so he knows exactly what it is doing. He can even trace it.
+
+Usage of Nette DI is very easy. Save the (above) configuration to the file `config.neon` and let's create a container:
+
+```php
+$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp');
+$class = $loader->load(function($compiler) {
+ $compiler->loadConfig(__DIR__ . '/config.neon');
+});
+$container = new $class;
+```
+
+and then use container to create object `NewsletterManager` and we can send e-mails:
+
+```php
+$manager = $container->getByType(NewsletterManager::class);
+$manager->distribute(['john@example.com', ...]);
+```
+
+The container will be generated only once and the code is stored in cache (in directory `__DIR__ . '/temp'`). Therefore the loading of configuration file is placed in the closure in `$loader->load()`, so it is called only once.
+
+During development it is useful to activate auto-refresh mode which automatically regenerate the container when any class or configuration file is changed. Just in the constructor `ContainerLoader` append `true` as the second argument:
+
+```php
+$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', autoRebuild: true);
+```
+
+
+
+Services
+--------
+
+Services are registered in the DI container and their dependencies are automatically passed.
+
+```neon
+services:
+ manager: NewsletterManager
+```
+
+All dependencies declared in the constructor of this service will be automatically passed. Constructor passing is the preferred way of dependency injection for services.
+
+If we want to pass dependencies by the setter, we can add the `setup` section to the service definition:
+
+```neon
+services:
+ manager:
+ factory: NewsletterManager
+ setup:
+ - setAnotherService
+```
+
+Class of the service:
+
+```php
+class NewsletterManager
+{
+ private AnotherService $anotherService;
+
+ public function setAnotherService(AnotherService $service): void
+ {
+ $this->anotherService = $service;
+ }
+
+...
+```
+
+We can also add the `inject: yes` directive. This directive will enable automatic call of `inject*` methods and passing dependencies to public variables with #[Inject] attribute:
+
+```neon
+services:
+ foo:
+ factory: FooClass
+ inject: yes
+```
+
+Dependency `Service1` will be passed by calling the `inject*` method, dependency `Service2` will be assigned to the `$service2` variable:
+
+```php
+use Nette\DI\Attributes\Inject;
+
+class FooClass
+{
+ private Service1 $service1;
+
+ // 1) inject* method:
+
+ public function injectService1(Service1 $service): void
+ {
+ $this->service1 = $service1;
+ }
+
+ // 2) Assign to the variable with the #[Inject] attribute:
+
+ #[Inject]
+ public Service2 $service2;
+}
+```
+
+However, this method is not ideal, because the variable must be declared as public and there is no way how you can ensure that the passed object will be of the given type. We also lose the ability to handle the assigned dependency in our code and we violate the principles of encapsulation.
+
+
+
+
+Factories
+---------
+
+We can use factories generated from an interface. The interface must declare the returning type of the method. Nette will generate a proper implementation of the interface.
+
+The interface must have exactly one method named `create`. Our factory interface could be declared in the following way:
+
+```php
+interface BarFactory
+{
+ function create(): Bar;
+}
+```
+
+The `create` method will instantiate an `Bar` with the following definition:
+
+```php
+class Bar
+{
+ private Logger $logger;
+
+ public function __construct(Logger $logger)
+ {
+ $this->logger = $logger;
+ }
+}
+```
+
+The factory will be registered in the `config.neon` file:
+
+```neon
+services:
+ - BarFactory
+```
+
+Nette will check if the declared service is an interface. If yes, it will also generate the corresponding implementation of the factory. The definition can be also written in a more verbose form:
+
+```neon
+services:
+ barFactory:
+ implement: BarFactory
+```
+
+This full definition allows us to declare additional configuration of the object using the `arguments` and `setup` sections, similarly as for all other services.
+
+In our code, we only have to obtain the factory instance and call the `create` method:
+
+```php
+class Foo
+{
+ private BarFactory $barFactory;
+
+ function __construct(BarFactory $barFactory)
+ {
+ $this->barFactory = $barFactory;
+ }
+
+ function bar(): void
+ {
+ $bar = $this->barFactory->create();
+ }
+}
+```
diff --git a/vendor/nette/di/src/Bridges/DITracy/ContainerPanel.php b/vendor/nette/di/src/Bridges/DITracy/ContainerPanel.php
new file mode 100644
index 0000000..82051f9
--- /dev/null
+++ b/vendor/nette/di/src/Bridges/DITracy/ContainerPanel.php
@@ -0,0 +1,82 @@
+container = $container;
+ $this->elapsedTime = self::$compilationTime
+ ? microtime(true) - self::$compilationTime
+ : null;
+ }
+
+
+ /**
+ * Renders tab.
+ */
+ public function getTab(): string
+ {
+ return Nette\Utils\Helpers::capture(function () {
+ $elapsedTime = $this->elapsedTime;
+ require __DIR__ . '/templates/ContainerPanel.tab.phtml';
+ });
+ }
+
+
+ /**
+ * Renders panel.
+ */
+ public function getPanel(): string
+ {
+ $rc = (new \ReflectionClass($this->container));
+ $services = [];
+ foreach ($rc->getMethods() as $method) {
+ if (preg_match('#^createService.#', $method->getName())) {
+ $name = lcfirst(str_replace('__', '.', substr($method->getName(), 13)));
+ $services[$name] = (string) $method->getReturnType();
+ }
+ }
+ ksort($services, SORT_NATURAL);
+
+ $propertyTags = (fn() => $this->tags)->bindTo($this->container, $this->container)();
+ $tags = [];
+ foreach ($propertyTags as $tag => $tmp) {
+ foreach ($tmp as $service => $val) {
+ $tags[$service][$tag] = $val;
+ }
+ }
+
+ return Nette\Utils\Helpers::capture(function () use ($rc, $tags, $services) {
+ $container = $this->container;
+ $file = $rc->getFileName();
+ $instances = (fn() => $this->instances)->bindTo($this->container, Container::class)();
+ $wiring = (fn() => $this->wiring)->bindTo($this->container, $this->container)();
+ $parameters = $rc->getMethod('getStaticParameters')->getDeclaringClass()->getName() === Container::class
+ ? null
+ : $container->getParameters();
+ require __DIR__ . '/templates/ContainerPanel.panel.phtml';
+ });
+ }
+}
diff --git a/vendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.panel.phtml b/vendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.panel.phtml
new file mode 100644
index 0000000..b840229
--- /dev/null
+++ b/vendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.panel.phtml
@@ -0,0 +1,81 @@
+
+
+
+Nette DI Container
+
+
+
+
Source: = Helpers::editorLink($file) ?>
+
+
+
+
+ Name
+ Autowired
+ Service
+ Tags
+
+
+
+ $type): ?>
+
+
+
+ = is_numeric($name) ? "$name " : Helpers::escapeHtml($name) ?>
+ = $autowired ? 'yes' : (isset($wiring[$type]) ? 'no' : '?') ?>
+
+
+ = Dumper::toHtml($instances[$name], [Dumper::COLLAPSE => true, Dumper::LIVE => true, Dumper::DEPTH => 5]); ?>
+
+ = get_class($instances[$name]) ?>
+
+ = Helpers::escapeHtml($type) ?>
+
+
+ true])
+ : Dumper::toHtml($tags[$name], [Dumper::COLLAPSE => true]);
+ } ?>
+
+
+
+
+
+
Parameters
+
+
+ = $parameters === null ? "disabled via 'di › export › parameters' " : Dumper::toHtml($parameters) ?>
+
+
+
diff --git a/vendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.tab.phtml b/vendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.tab.phtml
new file mode 100644
index 0000000..640319d
--- /dev/null
+++ b/vendor/nette/di/src/Bridges/DITracy/templates/ContainerPanel.tab.phtml
@@ -0,0 +1,11 @@
+
+
+
+= $elapsedTime ? sprintf('%0.1f ms', $elapsedTime * 1000) : '' ?>
+
diff --git a/vendor/nette/di/src/DI/Attributes/Inject.php b/vendor/nette/di/src/DI/Attributes/Inject.php
new file mode 100644
index 0000000..325e2b2
--- /dev/null
+++ b/vendor/nette/di/src/DI/Attributes/Inject.php
@@ -0,0 +1,18 @@
+ services, used by getByType() */
+ private array $highPriority = [];
+
+ /** @var array[] type => services, used by findByType() */
+ private array $lowPriority = [];
+
+ /** @var string[] of classes excluded from autowiring */
+ private array $excludedClasses = [];
+
+
+ public function __construct(ContainerBuilder $builder)
+ {
+ $this->builder = $builder;
+ }
+
+
+ /**
+ * Resolves service name by type.
+ * @return ($throw is true ? string : ?string)
+ * @throws MissingServiceException when not found
+ * @throws ServiceCreationException when multiple found
+ */
+ public function getByType(string $type, bool $throw = false): ?string
+ {
+ $type = Helpers::normalizeClass($type);
+ $types = $this->highPriority;
+ if (empty($types[$type])) {
+ if ($throw) {
+ if (!class_exists($type) && !interface_exists($type)) {
+ throw new MissingServiceException(sprintf("Service of type '%s' not found. Check the class name because it cannot be found.", $type));
+ }
+
+ throw new MissingServiceException(sprintf('Service of type %s not found. Did you add it to configuration file?', $type));
+ }
+
+ return null;
+
+ } elseif (count($types[$type]) === 1) {
+ return $types[$type][0];
+
+ } else {
+ $list = $types[$type];
+ natsort($list);
+ $hint = count($list) === 2 && ($tmp = str_contains($list[0], '.') xor str_contains($list[1], '.'))
+ ? '. If you want to overwrite service ' . $list[$tmp ? 0 : 1] . ', give it proper name.'
+ : '';
+ throw new ServiceCreationException(sprintf(
+ "Multiple services of type $type found: %s%s",
+ implode(', ', $list),
+ $hint,
+ ));
+ }
+ }
+
+
+ /**
+ * Gets the service names and definitions of the specified type.
+ * @return Definitions\Definition[] service name is key
+ */
+ public function findByType(string $type): array
+ {
+ $type = Helpers::normalizeClass($type);
+ $definitions = $this->builder->getDefinitions();
+ $names = array_merge($this->highPriority[$type] ?? [], $this->lowPriority[$type] ?? []);
+ $res = [];
+ foreach ($names as $name) {
+ $res[$name] = $definitions[$name];
+ }
+
+ return $res;
+ }
+
+
+ /**
+ * @param string[] $types
+ */
+ public function addExcludedClasses(array $types): void
+ {
+ foreach ($types as $type) {
+ if (class_exists($type) || interface_exists($type)) {
+ $type = Helpers::normalizeClass($type);
+ $this->excludedClasses += class_parents($type) + class_implements($type) + [$type => $type];
+ }
+ }
+ }
+
+
+ public function getClassList(): array
+ {
+ return [$this->lowPriority, $this->highPriority];
+ }
+
+
+ public function rebuild(): void
+ {
+ $this->lowPriority = $this->highPriority = $preferred = [];
+
+ foreach ($this->builder->getDefinitions() as $name => $def) {
+ if (!($type = $def->getType())) {
+ continue;
+ }
+
+ $autowired = $def->getAutowired();
+ if (is_array($autowired)) {
+ foreach ($autowired as $k => $autowiredType) {
+ if ($autowiredType === ContainerBuilder::ThisService) {
+ $autowired[$k] = $type;
+ } elseif (!is_a($type, $autowiredType, allow_string: true)) {
+ throw new ServiceCreationException(sprintf(
+ "Incompatible class %s in autowiring definition of service '%s'.",
+ $autowiredType,
+ $name,
+ ));
+ }
+ }
+ }
+
+ foreach (class_parents($type) + class_implements($type) + [$type] as $parent) {
+ if (!$autowired || isset($this->excludedClasses[$parent])) {
+ continue;
+ } elseif (is_array($autowired)) {
+ $priority = false;
+ foreach ($autowired as $autowiredType) {
+ if (is_a($parent, $autowiredType, allow_string: true)) {
+ if (empty($preferred[$parent]) && isset($this->highPriority[$parent])) {
+ $this->lowPriority[$parent] = array_merge($this->lowPriority[$parent] ?? [], $this->highPriority[$parent]);
+ $this->highPriority[$parent] = [];
+ }
+
+ $preferred[$parent] = $priority = true;
+ break;
+ }
+ }
+ } else {
+ $priority = empty($preferred[$parent]);
+ }
+
+ $list = $priority ? 'highPriority' : 'lowPriority';
+ $this->$list[$parent][] = $name;
+ }
+ }
+ }
+}
diff --git a/vendor/nette/di/src/DI/Compiler.php b/vendor/nette/di/src/DI/Compiler.php
new file mode 100644
index 0000000..80e9d0f
--- /dev/null
+++ b/vendor/nette/di/src/DI/Compiler.php
@@ -0,0 +1,315 @@
+ array[]] */
+ private array $configs = [];
+ private string $sources = '';
+ private DependencyChecker $dependencies;
+ private string $className = 'Container';
+
+
+ public function __construct(?ContainerBuilder $builder = null)
+ {
+ $this->builder = $builder ?: new ContainerBuilder;
+ $this->dependencies = new DependencyChecker;
+ $this->addExtension(self::Services, new Extensions\ServicesExtension);
+ $this->addExtension(self::Parameters, new Extensions\ParametersExtension($this->configs));
+ }
+
+
+ /**
+ * Add custom configurator extension.
+ */
+ public function addExtension(?string $name, CompilerExtension $extension): static
+ {
+ if ($name === null) {
+ $name = '_' . count($this->extensions);
+ } elseif (isset($this->extensions[$name])) {
+ throw new Nette\InvalidArgumentException(sprintf("Name '%s' is already used or reserved.", $name));
+ }
+
+ $lname = strtolower($name);
+ foreach (array_keys($this->extensions) as $nm) {
+ if ($lname === strtolower((string) $nm)) {
+ throw new Nette\InvalidArgumentException(sprintf(
+ "Name of extension '%s' has the same name as '%s' in a case-insensitive manner.",
+ $name,
+ $nm,
+ ));
+ }
+ }
+
+ $this->extensions[$name] = $extension->setCompiler($this, $name);
+ return $this;
+ }
+
+
+ public function getExtensions(?string $type = null): array
+ {
+ return $type
+ ? array_filter($this->extensions, fn($item): bool => $item instanceof $type)
+ : $this->extensions;
+ }
+
+
+ public function getContainerBuilder(): ContainerBuilder
+ {
+ return $this->builder;
+ }
+
+
+ public function setClassName(string $className): static
+ {
+ $this->className = $className;
+ return $this;
+ }
+
+
+ /**
+ * Adds new configuration.
+ */
+ public function addConfig(array $config): static
+ {
+ foreach ($config as $section => $data) {
+ $this->configs[$section][] = $data;
+ }
+
+ $this->sources .= "// source: array\n";
+ return $this;
+ }
+
+
+ /**
+ * Adds new configuration from file.
+ */
+ public function loadConfig(string $file, ?Config\Loader $loader = null): static
+ {
+ $sources = $this->sources . "// source: $file\n";
+ $loader = $loader ?: new Config\Loader;
+ foreach ($loader->load($file, merge: false) as $data) {
+ $this->addConfig($data);
+ }
+
+ $this->dependencies->add($loader->getDependencies());
+ $this->sources = $sources;
+ return $this;
+ }
+
+
+ /**
+ * Returns configuration.
+ * @deprecated
+ */
+ public function getConfig(): array
+ {
+ return $this->config;
+ }
+
+
+ /**
+ * Sets the names of dynamic parameters.
+ */
+ public function setDynamicParameterNames(array $names): static
+ {
+ assert($this->extensions[self::Parameters] instanceof Extensions\ParametersExtension);
+ $this->extensions[self::Parameters]->dynamicParams = $names;
+ return $this;
+ }
+
+
+ /**
+ * Adds dependencies to the list.
+ * @param array $deps of ReflectionClass|\ReflectionFunctionAbstract|string
+ */
+ public function addDependencies(array $deps): static
+ {
+ $this->dependencies->add(array_filter($deps));
+ return $this;
+ }
+
+
+ /**
+ * Exports dependencies.
+ */
+ public function exportDependencies(): array
+ {
+ return $this->dependencies->export();
+ }
+
+
+ public function addExportedTag(string $tag): static
+ {
+ if (isset($this->extensions[self::DI])) {
+ assert($this->extensions[self::DI] instanceof Extensions\DIExtension);
+ $this->extensions[self::DI]->exportedTags[$tag] = true;
+ }
+
+ return $this;
+ }
+
+
+ public function addExportedType(string $type): static
+ {
+ if (isset($this->extensions[self::DI])) {
+ assert($this->extensions[self::DI] instanceof Extensions\DIExtension);
+ $this->extensions[self::DI]->exportedTypes[$type] = true;
+ }
+
+ return $this;
+ }
+
+
+ public function compile(): string
+ {
+ $this->processExtensions();
+ $this->processBeforeCompile();
+ return $this->generateCode();
+ }
+
+
+ /** @internal */
+ public function processExtensions(): void
+ {
+ $first = $this->getExtensions(Extensions\ParametersExtension::class) + $this->getExtensions(Extensions\ExtensionsExtension::class);
+ foreach ($first as $name => $extension) {
+ $config = $this->processSchema($extension->getConfigSchema(), $this->configs[$name] ?? [], $name);
+ $extension->setConfig($this->config[$name] = $config);
+ $extension->loadConfiguration();
+ }
+
+ $last = $this->getExtensions(Extensions\InjectExtension::class);
+ $this->extensions = array_merge(array_diff_key($this->extensions, $last), $last);
+
+ if ($decorator = $this->getExtensions(Extensions\DecoratorExtension::class)) {
+ Nette\Utils\Arrays::insertBefore($this->extensions, key($decorator), $this->getExtensions(Extensions\SearchExtension::class));
+ }
+
+ $extensions = array_diff_key($this->extensions, $first, [self::Services => 1]);
+ foreach ($extensions as $name => $extension) {
+ $config = $this->processSchema($extension->getConfigSchema(), $this->configs[$name] ?? [], $name);
+ $extension->setConfig($this->config[$name] = $config);
+ }
+
+ foreach ($extensions as $extension) {
+ $extension->loadConfiguration();
+ }
+
+ foreach ($this->getExtensions(Extensions\ServicesExtension::class) as $name => $extension) {
+ $config = $this->processSchema($extension->getConfigSchema(), $this->configs[$name] ?? [], $name);
+ $extension->setConfig($this->config[$name] = $config);
+ $extension->loadConfiguration();
+ }
+
+ if ($extra = array_diff_key($this->extensions, $extensions, $first, [self::Services => 1])) {
+ throw new Nette\DeprecatedException(sprintf(
+ "Extensions '%s' were added while container was being compiled.",
+ implode("', '", array_keys($extra)),
+ ));
+
+ } elseif ($extra = key(array_diff_key($this->configs, $this->extensions))) {
+ $hint = Nette\Utils\Helpers::getSuggestion(array_keys($this->extensions), $extra);
+ throw new InvalidConfigurationException(
+ sprintf("Found section '%s' in configuration, but corresponding extension is missing", $extra)
+ . ($hint ? ", did you mean '$hint'?" : '.'),
+ );
+ }
+ }
+
+
+ private function processBeforeCompile(): void
+ {
+ $this->builder->resolve();
+
+ foreach ($this->extensions as $extension) {
+ $extension->beforeCompile();
+ $this->dependencies->add([(new \ReflectionClass($extension))->getFileName()]);
+ }
+
+ $this->builder->complete();
+ }
+
+
+ /**
+ * Merges and validates configurations against scheme.
+ */
+ private function processSchema(Schema\Schema $schema, array $configs, $name = null): array|object
+ {
+ $processor = new Schema\Processor;
+ $processor->onNewContext[] = function (Schema\Context $context) use ($name) {
+ $context->path = $name ? [$name] : [];
+ $context->dynamics = &$this->extensions[self::Parameters]->dynamicValidators;
+ };
+ try {
+ $res = $processor->processMultiple($schema, $configs);
+ } catch (Schema\ValidationException $e) {
+ throw new Nette\DI\InvalidConfigurationException($e->getMessage());
+ }
+
+ foreach ($processor->getWarnings() as $warning) {
+ trigger_error($warning, E_USER_DEPRECATED);
+ }
+
+ return $res;
+ }
+
+
+ /** @internal */
+ public function generateCode(): string
+ {
+ $generator = $this->createPhpGenerator();
+ $class = $generator->generate($this->className);
+ $this->dependencies->add($this->builder->getDependencies());
+
+ foreach ($this->extensions as $extension) {
+ $extension->afterCompile($class);
+ $generator->addInitialization($class, $extension);
+ }
+
+ return $this->sources . "\n" . $generator->toString($class);
+ }
+
+
+ /**
+ * Loads list of service definitions from configuration.
+ */
+ public function loadDefinitionsFromConfig(array $configList): void
+ {
+ $configList = Helpers::expand($configList, $this->builder->parameters);
+ $extension = $this->extensions[self::Services];
+ assert($extension instanceof Extensions\ServicesExtension);
+ $extension->loadDefinitions($this->processSchema($extension->getConfigSchema(), [$configList]));
+ }
+
+
+ protected function createPhpGenerator(): PhpGenerator
+ {
+ return new PhpGenerator($this->builder);
+ }
+}
diff --git a/vendor/nette/di/src/DI/CompilerExtension.php b/vendor/nette/di/src/DI/CompilerExtension.php
new file mode 100644
index 0000000..8d623b8
--- /dev/null
+++ b/vendor/nette/di/src/DI/CompilerExtension.php
@@ -0,0 +1,170 @@
+initialization = new Nette\PhpGenerator\Closure;
+ $this->compiler = $compiler;
+ $this->name = $name;
+ return $this;
+ }
+
+
+ public function setConfig(array|object $config): static
+ {
+ $this->config = $config;
+ return $this;
+ }
+
+
+ /**
+ * Returns extension configuration.
+ */
+ public function getConfig(): array|object
+ {
+ return $this->config;
+ }
+
+
+ /**
+ * Returns configuration schema.
+ */
+ public function getConfigSchema(): Nette\Schema\Schema
+ {
+ return is_object($this->config)
+ ? Nette\Schema\Expect::from($this->config)
+ : Nette\Schema\Expect::array();
+ }
+
+
+ /**
+ * Checks whether $config contains only $expected items and returns combined array.
+ * @throws Nette\InvalidStateException
+ * @deprecated use getConfigSchema()
+ */
+ public function validateConfig(array $expected, ?array $config = null, ?string $name = null): array
+ {
+ if (func_num_args() === 1) {
+ return $this->config = $this->validateConfig($expected, $this->config);
+ }
+
+ if ($extra = array_diff_key((array) $config, $expected)) {
+ $name = $name ? str_replace('.', "\u{a0}›\u{a0}", $name) : $this->name;
+ $hint = Nette\Utils\Helpers::getSuggestion(array_keys($expected), key($extra));
+ throw new Nette\DI\InvalidConfigurationException(sprintf(
+ "Unknown configuration option '%s\u{a0}›\u{a0}%s'",
+ $name,
+ $hint ? key($extra) : implode("', '{$name}\u{a0}›\u{a0}", array_keys($extra)),
+ ) . ($hint ? ", did you mean '{$name}\u{a0}›\u{a0}{$hint}'?" : '.'));
+ }
+
+ return Nette\Schema\Helpers::merge($config, $expected);
+ }
+
+
+ public function getContainerBuilder(): ContainerBuilder
+ {
+ return $this->compiler->getContainerBuilder();
+ }
+
+
+ /**
+ * Reads configuration from file.
+ */
+ public function loadFromFile(string $file): array
+ {
+ $loader = $this->createLoader();
+ $res = $loader->load($file);
+ $this->compiler->addDependencies($loader->getDependencies());
+ return $res;
+ }
+
+
+ /**
+ * Loads list of service definitions from configuration.
+ * Prefixes its names and replaces @extension with name in definition.
+ */
+ public function loadDefinitionsFromConfig(array $configList): void
+ {
+ $res = [];
+ foreach ($configList as $key => $config) {
+ $key = is_string($key) ? $this->name . '.' . $key : $key;
+ $res[$key] = Helpers::prefixServiceName($config, $this->name);
+ }
+
+ $this->compiler->loadDefinitionsFromConfig($res);
+ }
+
+
+ protected function createLoader(): Config\Loader
+ {
+ return new Config\Loader;
+ }
+
+
+ public function getInitialization(): Nette\PhpGenerator\Closure
+ {
+ return $this->initialization;
+ }
+
+
+ /**
+ * Prepend extension name to identifier or service name.
+ */
+ public function prefix(string $id): string
+ {
+ return substr_replace($id, $this->name . '.', str_starts_with($id, '@') ? 1 : 0, 0);
+ }
+
+
+ /**
+ * Processes configuration data. Intended to be overridden by descendant.
+ * @return void
+ */
+ public function loadConfiguration()
+ {
+ }
+
+
+ /**
+ * Adjusts DI container before is compiled to PHP class. Intended to be overridden by descendant.
+ * @return void
+ */
+ public function beforeCompile()
+ {
+ }
+
+
+ /**
+ * Adjusts DI container compiled to PHP class. Intended to be overridden by descendant.
+ * @return void
+ */
+ public function afterCompile(Nette\PhpGenerator\ClassType $class)
+ {
+ }
+}
diff --git a/vendor/nette/di/src/DI/Config/Adapter.php b/vendor/nette/di/src/DI/Config/Adapter.php
new file mode 100644
index 0000000..25e9cec
--- /dev/null
+++ b/vendor/nette/di/src/DI/Config/Adapter.php
@@ -0,0 +1,25 @@
+file = $file;
+ $decoder = new Neon\Decoder;
+ $node = $decoder->parseToNode($input);
+ $traverser = new Neon\Traverser;
+ $node = $traverser->traverse($node, $this->firstClassCallableVisitor(...));
+ $node = $traverser->traverse($node, $this->removeUnderscoreVisitor(...));
+ $node = $traverser->traverse($node, $this->convertAtSignVisitor(...));
+ $node = $traverser->traverse($node, $this->deprecatedParametersVisitor(...));
+ $node = $traverser->traverse($node, $this->resolveConstantsVisitor(...));
+ return $this->process((array) $node->toValue());
+ }
+
+
+ /** @throws Nette\InvalidStateException */
+ public function process(array $arr): array
+ {
+ $res = [];
+ foreach ($arr as $key => $val) {
+ if (is_string($key) && str_ends_with($key, self::PreventMergingSuffix)) {
+ if (!is_array($val) && $val !== null) {
+ throw new Nette\DI\InvalidConfigurationException(sprintf(
+ "Replacing operator is available only for arrays, item '%s' is not array (used in '%s')",
+ $key,
+ $this->file,
+ ));
+ }
+
+ $key = substr($key, 0, -1);
+ $val[DI\Config\Helpers::PREVENT_MERGING] = true;
+ }
+
+ if (is_array($val)) {
+ $val = $this->process($val);
+
+ } elseif ($val instanceof Neon\Entity) {
+ if ($val->value === Neon\Neon::CHAIN) {
+ $tmp = null;
+ foreach ($this->process($val->attributes) as $st) {
+ $tmp = new Statement(
+ $tmp === null ? $st->getEntity() : [$tmp, ltrim(implode('::', (array) $st->getEntity()), ':')],
+ $st->arguments,
+ );
+ }
+
+ $val = $tmp;
+ } else {
+ $tmp = $this->process([$val->value]);
+ if (is_string($tmp[0]) && str_contains($tmp[0], '?')) {
+ throw new Nette\DI\InvalidConfigurationException("Operator ? is deprecated in config file (used in '$this->file')");
+ }
+
+ $val = new Statement($tmp[0], $this->process($val->attributes));
+ }
+ }
+
+ $res[$key] = $val;
+ }
+
+ return $res;
+ }
+
+
+ /**
+ * Generates configuration in NEON format.
+ */
+ public function dump(array $data): string
+ {
+ array_walk_recursive(
+ $data,
+ function (&$val): void {
+ if ($val instanceof Statement) {
+ $val = self::statementToEntity($val);
+ }
+ },
+ );
+ return "# generated by Nette\n\n" . Neon\Neon::encode($data, Neon\Neon::BLOCK);
+ }
+
+
+ private static function statementToEntity(Statement $val): Neon\Entity
+ {
+ array_walk_recursive(
+ $val->arguments,
+ function (&$val): void {
+ if ($val instanceof Statement) {
+ $val = self::statementToEntity($val);
+ } elseif ($val instanceof Reference) {
+ $val = '@' . $val->getValue();
+ }
+ },
+ );
+
+ $entity = $val->getEntity();
+ if ($entity instanceof Reference) {
+ $entity = '@' . $entity->getValue();
+ } elseif (is_array($entity)) {
+ if ($entity[0] instanceof Statement) {
+ return new Neon\Entity(
+ Neon\Neon::CHAIN,
+ [
+ self::statementToEntity($entity[0]),
+ new Neon\Entity('::' . $entity[1], $val->arguments),
+ ],
+ );
+ } elseif ($entity[0] instanceof Reference) {
+ $entity = '@' . $entity[0]->getValue() . '::' . $entity[1];
+ } elseif (is_string($entity[0])) {
+ $entity = $entity[0] . '::' . $entity[1];
+ }
+ }
+
+ return new Neon\Entity($entity, $val->arguments);
+ }
+
+
+ private function firstClassCallableVisitor(Node $node): void
+ {
+ if ($node instanceof Node\EntityNode
+ && count($node->attributes) === 1
+ && $node->attributes[0]->key === null
+ && $node->attributes[0]->value instanceof Node\LiteralNode
+ && $node->attributes[0]->value->value === '...'
+ ) {
+ $node->attributes[0]->value->value = Nette\DI\Resolver::getFirstClassCallable()[0];
+ }
+ }
+
+
+ private function removeUnderscoreVisitor(Node $node): void
+ {
+ if (!$node instanceof Node\EntityNode) {
+ return;
+ }
+
+ $index = false;
+ foreach ($node->attributes as $i => $attr) {
+ if ($attr->key !== null) {
+ continue;
+ }
+
+ $attr->key = $index ? new Node\LiteralNode((string) $i) : null;
+
+ if ($attr->value instanceof Node\LiteralNode && $attr->value->value === '_') {
+ unset($node->attributes[$i]);
+ $index = true;
+
+ } elseif ($attr->value instanceof Node\LiteralNode && $attr->value->value === '...') {
+ trigger_error("Replace ... with _ in configuration file '$this->file'.", E_USER_DEPRECATED);
+ unset($node->attributes[$i]);
+ $index = true;
+ }
+ }
+ }
+
+
+ private function convertAtSignVisitor(Node $node): void
+ {
+ if ($node instanceof Node\StringNode) {
+ if (str_starts_with($node->value, '@@')) {
+ trigger_error("There is no need to escape @ anymore, replace @@ with @ in: '$node->value' (used in $this->file)", E_USER_DEPRECATED);
+ } else {
+ $node->value = preg_replace('#^@#', '$0$0', $node->value); // escape
+ }
+
+ } elseif (
+ $node instanceof Node\LiteralNode
+ && is_string($node->value)
+ && str_starts_with($node->value, '@@')
+ ) {
+ trigger_error("There is no need to escape @ anymore, replace @@ with @ and put string in quotes: '$node->value' (used in $this->file)", E_USER_DEPRECATED);
+ }
+ }
+
+
+ private function deprecatedParametersVisitor(Node $node): void
+ {
+ if (($node instanceof Node\StringNode || $node instanceof Node\LiteralNode)
+ && is_string($node->value)
+ && str_contains($node->value, '%parameters%')
+ ) {
+ trigger_error('%parameters% is deprecated, use @container::getParameters() (in ' . $this->file . ')', E_USER_DEPRECATED);
+ }
+ }
+
+
+ private function resolveConstantsVisitor(Node $node): void
+ {
+ $items = match (true) {
+ $node instanceof Node\ArrayNode => $node->items,
+ $node instanceof Node\EntityNode => $node->attributes,
+ default => null,
+ };
+ if ($items) {
+ foreach ($items as $item) {
+ if ($item->value instanceof Node\LiteralNode
+ && is_string($item->value->value)
+ && preg_match('#^([\w\\\\]*)::[A-Z]\w+$#D', $item->value->value)
+ && defined(ltrim($item->value->value, ':'))
+ ) {
+ $item->value->value = constant(ltrim($item->value->value, ':'));
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/nette/di/src/DI/Config/Adapters/PhpAdapter.php b/vendor/nette/di/src/DI/Config/Adapters/PhpAdapter.php
new file mode 100644
index 0000000..5471307
--- /dev/null
+++ b/vendor/nette/di/src/DI/Config/Adapters/PhpAdapter.php
@@ -0,0 +1,36 @@
+dump($data) . ';';
+ }
+}
diff --git a/vendor/nette/di/src/DI/Config/Helpers.php b/vendor/nette/di/src/DI/Config/Helpers.php
new file mode 100644
index 0000000..9124a52
--- /dev/null
+++ b/vendor/nette/di/src/DI/Config/Helpers.php
@@ -0,0 +1,43 @@
+ Adapters\PhpAdapter::class,
+ 'neon' => Adapters\NeonAdapter::class,
+ ];
+ private array $dependencies = [];
+ private array $loadedFiles = [];
+ private array $parameters = [];
+
+
+ /**
+ * Reads configuration from file.
+ */
+ public function load(string $file, ?bool $merge = true): array
+ {
+ if (!is_file($file) || !is_readable($file)) {
+ throw new Nette\FileNotFoundException(sprintf("File '%s' is missing or is not readable.", $file));
+ }
+
+ if (isset($this->loadedFiles[$file])) {
+ throw new Nette\InvalidStateException(sprintf("Recursive included file '%s'", $file));
+ }
+
+ $this->loadedFiles[$file] = true;
+
+ $this->dependencies[] = $file;
+ $data = $this->getAdapter($file)->load($file);
+
+ $res = [];
+ if (isset($data[self::IncludesKey])) {
+ Validators::assert($data[self::IncludesKey], 'list', "section 'includes' in file '$file'");
+ $includes = Nette\DI\Helpers::expand($data[self::IncludesKey], $this->parameters);
+ foreach ($includes as $include) {
+ $include = $this->expandIncludedFile($include, $file);
+ $res = Nette\Schema\Helpers::merge($this->load($include, $merge), $res);
+ }
+ }
+
+ unset($data[self::IncludesKey], $this->loadedFiles[$file]);
+
+ if ($merge === false) {
+ $res[] = $data;
+ } else {
+ $res = Nette\Schema\Helpers::merge($data, $res);
+ }
+
+ return $res;
+ }
+
+
+ /**
+ * Returns configuration files.
+ */
+ public function getDependencies(): array
+ {
+ return array_unique($this->dependencies);
+ }
+
+
+ /**
+ * Expands included file name.
+ */
+ public function expandIncludedFile(string $includedFile, string $mainFile): string
+ {
+ return preg_match('#([a-z]+:)?[/\\\\]#Ai', $includedFile) // is absolute
+ ? $includedFile
+ : dirname($mainFile) . '/' . $includedFile;
+ }
+
+
+ /**
+ * Registers adapter for given file extension.
+ */
+ public function addAdapter(string $extension, string|Adapter $adapter): static
+ {
+ $this->adapters[strtolower($extension)] = $adapter;
+ return $this;
+ }
+
+
+ private function getAdapter(string $file): Adapter
+ {
+ $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
+ if (!isset($this->adapters[$extension])) {
+ throw new Nette\InvalidArgumentException(sprintf("Unknown file extension '%s'.", $file));
+ }
+
+ return is_object($this->adapters[$extension])
+ ? $this->adapters[$extension]
+ : new $this->adapters[$extension];
+ }
+
+
+ public function setParameters(array $params): static
+ {
+ $this->parameters = $params;
+ return $this;
+ }
+}
diff --git a/vendor/nette/di/src/DI/Container.php b/vendor/nette/di/src/DI/Container.php
new file mode 100644
index 0000000..d72639a
--- /dev/null
+++ b/vendor/nette/di/src/DI/Container.php
@@ -0,0 +1,383 @@
+ service name */
+ protected array $aliases = [];
+
+ /** @var array[] tag name => service name => tag value */
+ protected array $tags = [];
+
+ /** @var array[] type => (high, low, no) => services */
+ protected array $wiring = [];
+
+ /** @var object[] service name => instance */
+ private array $instances = [];
+
+ /** @var array circular reference detector */
+ private array $creating;
+
+ /** @var array */
+ private array $methods;
+
+ /** @var array service name => \Closure */
+ private array $factories = [];
+
+
+ public function __construct(array $params = [])
+ {
+ $this->parameters = $params + $this->getStaticParameters();
+ $this->methods = array_flip(get_class_methods($this));
+ }
+
+
+ public function getParameters(): array
+ {
+ return $this->parameters;
+ }
+
+
+ public function getParameter(string|int $key): mixed
+ {
+ if (!array_key_exists($key, $this->parameters)) {
+ $this->parameters[$key] = $this->preventDeadLock("%$key%", fn() => $this->getDynamicParameter($key));
+ }
+ return $this->parameters[$key];
+ }
+
+
+ protected function getStaticParameters(): array
+ {
+ return [];
+ }
+
+
+ protected function getDynamicParameter(string|int $key): mixed
+ {
+ throw new Nette\InvalidStateException(sprintf("Parameter '%s' not found. Check if 'di › export › parameters' is enabled.", $key));
+ }
+
+
+ /**
+ * Adds the service or its factory to the container.
+ * @param object $service service or its factory
+ */
+ public function addService(string $name, object $service): static
+ {
+ $name = $this->aliases[$name] ?? $name;
+ if (isset($this->instances[$name])) {
+ throw new Nette\InvalidStateException(sprintf("Service '%s' already exists.", $name));
+ }
+
+ if ($service instanceof \Closure) {
+ $rt = Nette\Utils\Type::fromReflection(new \ReflectionFunction($service));
+ $type = $rt ? Helpers::ensureClassType($rt, 'return type of closure') : '';
+ } else {
+ $type = $service::class;
+ }
+
+ if (isset($this->methods[self::getMethodName($name)])
+ && ($expectedType = $this->getServiceType($name))
+ && !is_a($type, $expectedType, allow_string: true)
+ ) {
+ throw new Nette\InvalidArgumentException(sprintf(
+ "Service '%s' must be instance of %s, %s.",
+ $name,
+ $expectedType,
+ $type ? "$type given" : 'add typehint to closure',
+ ));
+ }
+
+ if ($service instanceof \Closure) {
+ $this->factories[$name] = $service;
+ } else {
+ $this->instances[$name] = $service;
+ }
+
+ return $this;
+ }
+
+
+ /**
+ * Removes a service instance from the container.
+ */
+ public function removeService(string $name): void
+ {
+ $name = $this->aliases[$name] ?? $name;
+ unset($this->instances[$name]);
+ }
+
+
+ /**
+ * Returns the service instance. If it has not been created yet, it creates it.
+ * @throws MissingServiceException
+ */
+ public function getService(string $name): object
+ {
+ if (!isset($this->instances[$name])) {
+ if (isset($this->aliases[$name])) {
+ return $this->getService($this->aliases[$name]);
+ }
+
+ $this->instances[$name] = $this->createService($name);
+ }
+
+ return $this->instances[$name];
+ }
+
+
+ /**
+ * Returns the service instance. If it has not been created yet, it creates it.
+ * Alias for getService().
+ * @throws MissingServiceException
+ */
+ public function getByName(string $name): object
+ {
+ return $this->getService($name);
+ }
+
+
+ /**
+ * Returns type of the service.
+ * @throws MissingServiceException
+ */
+ public function getServiceType(string $name): string
+ {
+ $method = self::getMethodName($name);
+ if (isset($this->aliases[$name])) {
+ return $this->getServiceType($this->aliases[$name]);
+
+ } elseif (isset($this->methods[$method])) {
+ return (string) (new \ReflectionMethod($this, $method))->getReturnType();
+
+ } elseif ($cb = $this->factories[$name] ?? null) {
+ return (string) (new \ReflectionFunction($cb))->getReturnType();
+
+ } else {
+ throw new MissingServiceException(sprintf("Type of service '%s' not known.", $name));
+ }
+ }
+
+
+ /**
+ * Does the service exist?
+ */
+ public function hasService(string $name): bool
+ {
+ $name = $this->aliases[$name] ?? $name;
+ return isset($this->methods[self::getMethodName($name)]) || isset($this->instances[$name]) || isset($this->factories[$name]);
+ }
+
+
+ /**
+ * Has a service instance been created?
+ */
+ public function isCreated(string $name): bool
+ {
+ if (!$this->hasService($name)) {
+ throw new MissingServiceException(sprintf("Service '%s' not found.", $name));
+ }
+
+ $name = $this->aliases[$name] ?? $name;
+ return isset($this->instances[$name]);
+ }
+
+
+ /**
+ * Creates new instance of the service.
+ * @throws MissingServiceException
+ */
+ public function createService(string $name): object
+ {
+ $name = $this->aliases[$name] ?? $name;
+ $method = self::getMethodName($name);
+ if ($callback = ($this->factories[$name] ?? null)) {
+ $service = $this->preventDeadLock($name, fn() => $callback());
+ } elseif (isset($this->methods[$method])) {
+ $service = $this->preventDeadLock($name, fn() => $this->$method());
+ } else {
+ throw new MissingServiceException(sprintf("Service '%s' not found.", $name));
+ }
+
+ if (!is_object($service)) {
+ throw new Nette\UnexpectedValueException(sprintf(
+ "Unable to create service '$name', value returned by %s is not object.",
+ $callback instanceof \Closure ? 'closure' : "method $method()",
+ ));
+ }
+
+ return $service;
+ }
+
+
+ /**
+ * Returns an instance of the autowired service of the given type. If it has not been created yet, it creates it.
+ * @template T of object
+ * @param class-string $type
+ * @return ($throw is true ? T : ?T)
+ * @throws MissingServiceException
+ */
+ public function getByType(string $type, bool $throw = true): ?object
+ {
+ $type = Helpers::normalizeClass($type);
+ if (!empty($this->wiring[$type][0])) {
+ if (count($names = $this->wiring[$type][0]) === 1) {
+ return $this->getService($names[0]);
+ }
+
+ natsort($names);
+ throw new MissingServiceException(sprintf("Multiple services of type $type found: %s.", implode(', ', $names)));
+
+ } elseif ($throw) {
+ if (!class_exists($type) && !interface_exists($type)) {
+ throw new MissingServiceException(sprintf("Service of type '%s' not found. Check the class name because it cannot be found.", $type));
+ } elseif ($this->findByType($type)) {
+ throw new MissingServiceException(sprintf("Service of type %s is not autowired or is missing in di\u{a0}›\u{a0}export\u{a0}›\u{a0}types.", $type));
+ } else {
+ throw new MissingServiceException(sprintf('Service of type %s not found. Did you add it to configuration file?', $type));
+ }
+ }
+
+ return null;
+ }
+
+
+ /**
+ * Returns the names of autowired services of the given type.
+ * @return string[]
+ * @internal
+ */
+ public function findAutowired(string $type): array
+ {
+ $type = Helpers::normalizeClass($type);
+ return array_merge($this->wiring[$type][0] ?? [], $this->wiring[$type][1] ?? []);
+ }
+
+
+ /**
+ * Returns the names of all services of the given type.
+ * @return string[]
+ */
+ public function findByType(string $type): array
+ {
+ $type = Helpers::normalizeClass($type);
+ return empty($this->wiring[$type])
+ ? []
+ : array_merge(...array_values($this->wiring[$type]));
+ }
+
+
+ /**
+ * Returns the names of services with the given tag.
+ * @return array of [service name => tag attributes]
+ */
+ public function findByTag(string $tag): array
+ {
+ return $this->tags[$tag] ?? [];
+ }
+
+
+ /**
+ * Prevents circular references during service creation by checking if the service is already being created.
+ */
+ private function preventDeadLock(string $key, \Closure $callback): mixed
+ {
+ if (isset($this->creating[$key])) {
+ throw new Nette\InvalidStateException(sprintf('Circular reference detected for: %s.', implode(', ', array_keys($this->creating))));
+ }
+ try {
+ $this->creating[$key] = true;
+ return $callback();
+ } finally {
+ unset($this->creating[$key]);
+ }
+ }
+
+
+ /********************* autowiring ****************d*g**/
+
+
+ /**
+ * Creates an instance of the class and passes dependencies to the constructor using autowiring.
+ */
+ public function createInstance(string $class, array $args = []): object
+ {
+ $rc = new \ReflectionClass($class);
+ if (!$rc->isInstantiable()) {
+ throw new ServiceCreationException(sprintf('Class %s is not instantiable.', $class));
+
+ } elseif ($constructor = $rc->getConstructor()) {
+ return $rc->newInstanceArgs($this->autowireArguments($constructor, $args));
+
+ } elseif ($args) {
+ throw new ServiceCreationException(sprintf('Unable to pass arguments, class %s has no constructor.', $class));
+ }
+
+ return new $class;
+ }
+
+
+ /**
+ * Calls all methods starting with 'inject' and passes dependencies to them via autowiring.
+ */
+ public function callInjects(object $service): void
+ {
+ Extensions\InjectExtension::callInjects($this, $service);
+ }
+
+
+ /**
+ * Calls the method and passes dependencies to it via autowiring.
+ */
+ public function callMethod(callable $function, array $args = []): mixed
+ {
+ return $function(...$this->autowireArguments(Nette\Utils\Callback::toReflection($function), $args));
+ }
+
+
+ private function autowireArguments(\ReflectionFunctionAbstract $function, array $args = []): array
+ {
+ return Resolver::autowireArguments($function, $args, fn(string $type, bool $single) => $single
+ ? $this->getByType($type)
+ : array_map($this->getService(...), $this->findAutowired($type)));
+ }
+
+
+ /**
+ * Returns the method name for creating a service.
+ */
+ final public static function getMethodName(string $name): string
+ {
+ if ($name === '') {
+ throw new Nette\InvalidArgumentException('Service name must be a non-empty string.');
+ }
+
+ return 'createService' . str_replace('.', '__', ucfirst($name));
+ }
+
+
+ public function initialize(): void
+ {
+ }
+}
diff --git a/vendor/nette/di/src/DI/ContainerBuilder.php b/vendor/nette/di/src/DI/ContainerBuilder.php
new file mode 100644
index 0000000..f2844d5
--- /dev/null
+++ b/vendor/nette/di/src/DI/ContainerBuilder.php
@@ -0,0 +1,406 @@
+autowiring = new Autowiring($this);
+ $this->addImportedDefinition(self::ThisContainer)->setType(Container::class);
+ }
+
+
+ /**
+ * Adds new service definition.
+ * @return Definitions\ServiceDefinition
+ */
+ public function addDefinition(?string $name, ?Definition $definition = null): Definition
+ {
+ $this->needsResolve = true;
+ if ($name === null) {
+ for (
+ $i = 1;
+ isset($this->definitions['0' . $i]) || isset($this->aliases['0' . $i]);
+ $i++
+ );
+ $name = '0' . $i; // prevents converting to integer in array key
+
+ } elseif (is_int(key([$name => 1])) || !preg_match('#^\w+(\.\w+)*$#D', $name)) {
+ throw new Nette\InvalidArgumentException(sprintf("Service name must be a alpha-numeric string and not a number, '%s' given.", $name));
+
+ } else {
+ $name = $this->aliases[$name] ?? $name;
+ if (isset($this->definitions[$name])) {
+ throw new Nette\InvalidStateException(sprintf("Service '%s' has already been added.", $name));
+ }
+
+ $lname = strtolower($name);
+ foreach ($this->definitions as $nm => $foo) {
+ if ($lname === strtolower($nm)) {
+ throw new Nette\InvalidStateException(sprintf(
+ "Service '%s' has the same name as '%s' in a case-insensitive manner.",
+ $name,
+ $nm,
+ ));
+ }
+ }
+ }
+
+ $definition = $definition ?: new Definitions\ServiceDefinition;
+ $definition->setName($name);
+ $definition->setNotifier(function (): void {
+ $this->needsResolve = true;
+ });
+ return $this->definitions[$name] = $definition;
+ }
+
+
+ public function addAccessorDefinition(?string $name): Definitions\AccessorDefinition
+ {
+ return $this->addDefinition($name, new Definitions\AccessorDefinition);
+ }
+
+
+ public function addFactoryDefinition(?string $name): Definitions\FactoryDefinition
+ {
+ return $this->addDefinition($name, new Definitions\FactoryDefinition);
+ }
+
+
+ public function addLocatorDefinition(?string $name): Definitions\LocatorDefinition
+ {
+ return $this->addDefinition($name, new Definitions\LocatorDefinition);
+ }
+
+
+ public function addImportedDefinition(?string $name): Definitions\ImportedDefinition
+ {
+ return $this->addDefinition($name, new Definitions\ImportedDefinition);
+ }
+
+
+ /**
+ * Removes the specified service definition.
+ */
+ public function removeDefinition(string $name): void
+ {
+ $this->needsResolve = true;
+ $name = $this->aliases[$name] ?? $name;
+ unset($this->definitions[$name]);
+ }
+
+
+ /**
+ * Gets the service definition.
+ */
+ public function getDefinition(string $name): Definition
+ {
+ $service = $this->aliases[$name] ?? $name;
+ if (!isset($this->definitions[$service])) {
+ throw new MissingServiceException(sprintf("Service '%s' not found.", $name));
+ }
+
+ return $this->definitions[$service];
+ }
+
+
+ /**
+ * Gets all service definitions.
+ * @return Definition[]
+ */
+ public function getDefinitions(): array
+ {
+ return $this->definitions;
+ }
+
+
+ /**
+ * Does the service definition or alias exist?
+ */
+ public function hasDefinition(string $name): bool
+ {
+ $name = $this->aliases[$name] ?? $name;
+ return isset($this->definitions[$name]);
+ }
+
+
+ public function addAlias(string $alias, string $service): void
+ {
+ if (!$alias) { // builder is not ready for falsy names such as '0'
+ throw new Nette\InvalidArgumentException(sprintf("Alias name must be a non-empty string, '%s' given.", $alias));
+
+ } elseif (!$service) { // builder is not ready for falsy names such as '0'
+ throw new Nette\InvalidArgumentException(sprintf("Service name must be a non-empty string, '%s' given.", $service));
+
+ } elseif (isset($this->aliases[$alias])) {
+ throw new Nette\InvalidStateException(sprintf("Alias '%s' has already been added.", $alias));
+
+ } elseif (isset($this->definitions[$alias])) {
+ throw new Nette\InvalidStateException(sprintf("Service '%s' has already been added.", $alias));
+ }
+
+ $this->aliases[$alias] = $service;
+ }
+
+
+ /**
+ * Removes the specified alias.
+ */
+ public function removeAlias(string $alias): void
+ {
+ unset($this->aliases[$alias]);
+ }
+
+
+ /**
+ * Gets all service aliases.
+ */
+ public function getAliases(): array
+ {
+ return $this->aliases;
+ }
+
+
+ /**
+ * @param string[] $types
+ */
+ public function addExcludedClasses(array $types): static
+ {
+ $this->needsResolve = true;
+ $this->autowiring->addExcludedClasses($types);
+ return $this;
+ }
+
+
+ /**
+ * Resolves autowired service name by type.
+ * @return ($throw is true ? string : ?string)
+ * @throws MissingServiceException
+ */
+ public function getByType(string $type, bool $throw = false): ?string
+ {
+ $this->needResolved();
+ return $this->autowiring->getByType($type, $throw);
+ }
+
+
+ /**
+ * Gets autowired service definition of the specified type.
+ * @throws MissingServiceException
+ */
+ public function getDefinitionByType(string $type): Definition
+ {
+ return $this->getDefinition($this->getByType($type, throw: true));
+ }
+
+
+ /**
+ * Gets the autowired service names and definitions of the specified type.
+ * @return Definition[] service name is key
+ * @internal
+ */
+ public function findAutowired(string $type): array
+ {
+ $this->needResolved();
+ return $this->autowiring->findByType($type);
+ }
+
+
+ /**
+ * Gets the service names and definitions of the specified type.
+ * @return Definition[] service name is key
+ */
+ public function findByType(string $type): array
+ {
+ $this->needResolved();
+ $found = [];
+ foreach ($this->definitions as $name => $def) {
+ if (is_a($def->getType(), $type, allow_string: true)) {
+ $found[$name] = $def;
+ }
+ }
+
+ return $found;
+ }
+
+
+ /**
+ * Gets the service names and tag values.
+ * @return array of [service name => tag attributes]
+ */
+ public function findByTag(string $tag): array
+ {
+ $found = [];
+ foreach ($this->definitions as $name => $def) {
+ if (($tmp = $def->getTag($tag)) !== null) {
+ $found[$name] = $tmp;
+ }
+ }
+
+ return $found;
+ }
+
+
+ /********************* building ****************d*g**/
+
+
+ /**
+ * Checks services, resolves types and rebuilts autowiring classlist.
+ */
+ public function resolve(): void
+ {
+ if ($this->resolving) {
+ return;
+ }
+
+ $this->resolving = true;
+
+ $resolver = new Resolver($this);
+ foreach ($this->definitions as $def) {
+ $resolver->resolveDefinition($def);
+ }
+
+ $this->autowiring->rebuild();
+
+ $this->resolving = $this->needsResolve = false;
+ }
+
+
+ private function needResolved(): void
+ {
+ if ($this->resolving) {
+ throw new NotAllowedDuringResolvingException;
+ } elseif ($this->needsResolve) {
+ $this->resolve();
+ }
+ }
+
+
+ public function complete(): void
+ {
+ $this->resolve();
+ foreach ($this->definitions as $def) {
+ $def->setNotifier(null);
+ }
+
+ $resolver = new Resolver($this);
+ foreach ($this->definitions as $def) {
+ $resolver->completeDefinition($def);
+ }
+ }
+
+
+ /**
+ * Adds item to the list of dependencies.
+ * @internal
+ */
+ public function addDependency(\ReflectionClass|\ReflectionFunctionAbstract|string $dep): static
+ {
+ $this->dependencies[] = $dep;
+ return $this;
+ }
+
+
+ /**
+ * Returns the list of dependencies.
+ */
+ public function getDependencies(): array
+ {
+ return $this->dependencies;
+ }
+
+
+ /** @internal */
+ public function exportMeta(): array
+ {
+ $defs = $this->definitions;
+ ksort($defs);
+ foreach ($defs as $name => $def) {
+ foreach ($def->getTags() as $tag => $value) {
+ $meta['tags'][$tag][$name] = $value;
+ }
+ }
+
+ $meta['aliases'] = $this->aliases;
+ ksort($meta['aliases']);
+
+ $all = [];
+ foreach ($this->definitions as $name => $def) {
+ if ($type = $def->getType()) {
+ foreach (class_parents($type) + class_implements($type) + [$type] as $class) {
+ $all[$class][] = $name;
+ }
+ }
+ }
+
+ [$low, $high] = $this->autowiring->getClassList();
+ foreach ($all as $class => $names) {
+ $meta['wiring'][$class] = array_filter([
+ $high[$class] ?? [],
+ $low[$class] ?? [],
+ array_diff($names, $low[$class] ?? [], $high[$class] ?? []),
+ ]);
+ }
+
+ return $meta;
+ }
+
+
+ public static function literal(string $code, ?array $args = null): Nette\PhpGenerator\Literal
+ {
+ return new Nette\PhpGenerator\Literal(
+ $args === null ? $code : (new Nette\PhpGenerator\Dumper)->format($code, ...$args),
+ );
+ }
+
+
+ /** @deprecated */
+ public function formatPhp(string $statement, array $args): string
+ {
+ array_walk_recursive($args, function (&$val): void {
+ if ($val instanceof Nette\DI\Definitions\Statement) {
+ $val = (new Resolver($this))->completeStatement($val);
+
+ } elseif ($val instanceof Definition) {
+ $val = new Definitions\Reference($val->getName());
+ }
+ });
+ return (new PhpGenerator($this))->formatPhp($statement, $args);
+ }
+}
diff --git a/vendor/nette/di/src/DI/ContainerLoader.php b/vendor/nette/di/src/DI/ContainerLoader.php
new file mode 100644
index 0000000..8162013
--- /dev/null
+++ b/vendor/nette/di/src/DI/ContainerLoader.php
@@ -0,0 +1,112 @@
+getClassName($key);
+ if (!class_exists($class, autoload: false)) {
+ $this->loadFile($class, $generator);
+ }
+
+ return $class;
+ }
+
+
+ public function getClassName(mixed $key): string
+ {
+ return 'Container_' . substr(hash('xxh128', serialize($key)), 0, 10);
+ }
+
+
+ private function loadFile(string $class, callable $generator): void
+ {
+ $file = "$this->tempDirectory/$class.php";
+ if (!$this->isExpired($file) && (@include $file) !== false) { // @ file may not exist
+ return;
+ }
+
+ Nette\Utils\FileSystem::createDir($this->tempDirectory);
+
+ $handle = @fopen("$file.lock", 'c+'); // @ is escalated to exception
+ if (!$handle) {
+ throw new Nette\IOException(sprintf("Unable to create file '%s.lock'. %s", $file, Nette\Utils\Helpers::getLastError()));
+ } elseif (!@flock($handle, LOCK_EX)) { // @ is escalated to exception
+ throw new Nette\IOException(sprintf("Unable to acquire exclusive lock on '%s.lock'. %s", $file, Nette\Utils\Helpers::getLastError()));
+ }
+
+ if (!is_file($file) || $this->isExpired($file, $updatedMeta)) {
+ if (isset($updatedMeta)) {
+ $toWrite["$file.meta"] = $updatedMeta;
+ } else {
+ [$toWrite[$file], $toWrite["$file.meta"]] = $this->generate($class, $generator);
+ }
+
+ foreach ($toWrite as $name => $content) {
+ if (file_put_contents("$name.tmp", $content) !== strlen($content) || !rename("$name.tmp", $name)) {
+ @unlink("$name.tmp"); // @ - file may not exist
+ throw new Nette\IOException(sprintf("Unable to create file '%s'.", $name));
+ } elseif (function_exists('opcache_invalidate')) {
+ @opcache_invalidate($name, force: true); // @ can be restricted
+ }
+ }
+ }
+
+ if ((@include $file) === false) { // @ - error escalated to exception
+ throw new Nette\IOException(sprintf("Unable to include '%s'.", $file));
+ }
+ flock($handle, LOCK_UN);
+ }
+
+
+ private function isExpired(string $file, ?string &$updatedMeta = null): bool
+ {
+ if ($this->autoRebuild) {
+ $meta = @unserialize((string) file_get_contents("$file.meta")); // @ - file may not exist
+ $orig = $meta[2] ?? null;
+ return empty($meta[0])
+ || DependencyChecker::isExpired(...$meta)
+ || ($orig !== $meta[2] && $updatedMeta = serialize($meta));
+ }
+
+ return false;
+ }
+
+
+ /** @return array of (code, file[]) */
+ protected function generate(string $class, callable $generator): array
+ {
+ $compiler = new Compiler;
+ $compiler->setClassName($class);
+ $code = $generator(...[&$compiler]) ?: $compiler->compile();
+ return [
+ "exportDependencies()),
+ ];
+ }
+}
diff --git a/vendor/nette/di/src/DI/Definitions/AccessorDefinition.php b/vendor/nette/di/src/DI/Definitions/AccessorDefinition.php
new file mode 100644
index 0000000..bd6c1a1
--- /dev/null
+++ b/vendor/nette/di/src/DI/Definitions/AccessorDefinition.php
@@ -0,0 +1,128 @@
+getName(),
+ $interface,
+ ));
+ }
+
+ $rc = new \ReflectionClass($interface);
+
+ $method = $rc->getMethods()[0] ?? null;
+ if (
+ !$method
+ || $method->isStatic()
+ || $method->getName() !== self::MethodGet
+ || count($rc->getMethods()) > 1
+ ) {
+ throw new Nette\InvalidArgumentException(sprintf(
+ "Service '%s': Interface %s must have just one non-static method get().",
+ $this->getName(),
+ $interface,
+ ));
+ } elseif ($method->getNumberOfParameters()) {
+ throw new Nette\InvalidArgumentException(sprintf(
+ "Service '%s': Method %s::get() must have no parameters.",
+ $this->getName(),
+ $interface,
+ ));
+ }
+
+ Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::get()");
+ return parent::setType($interface);
+ }
+
+
+ public function getImplement(): ?string
+ {
+ return $this->getType();
+ }
+
+
+ public function setReference(string|Reference $reference): static
+ {
+ if ($reference instanceof Reference) {
+ $this->reference = $reference;
+ } else {
+ $this->reference = str_starts_with($reference, '@')
+ ? new Reference(substr($reference, 1))
+ : Reference::fromType($reference);
+ }
+
+ return $this;
+ }
+
+
+ public function getReference(): ?Reference
+ {
+ return $this->reference;
+ }
+
+
+ public function resolveType(Nette\DI\Resolver $resolver): void
+ {
+ }
+
+
+ public function complete(Nette\DI\Resolver $resolver): void
+ {
+ if (!$this->reference) {
+ if (!$this->getType()) {
+ throw new Nette\DI\ServiceCreationException('Type is missing in definition of service.');
+ }
+
+ $method = new \ReflectionMethod($this->getType(), self::MethodGet);
+ $this->setReference(Type::fromReflection($method)->getSingleName());
+ }
+
+ $this->reference = $resolver->normalizeReference($this->reference);
+ }
+
+
+ public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGenerator $generator): void
+ {
+ $class = (new Nette\PhpGenerator\ClassType)
+ ->addImplement($this->getType());
+
+ $class->addMethod('__construct')
+ ->addPromotedParameter('container')
+ ->setPrivate()
+ ->setType($generator->getClassName());
+
+ $rm = new \ReflectionMethod($this->getType(), self::MethodGet);
+
+ $class->addMethod(self::MethodGet)
+ ->setBody('return $this->container->getService(?);', [$this->reference->getValue()])
+ ->setReturnType((string) Type::fromReflection($rm));
+
+ $method->setBody('return new class ($this) ' . $class . ';');
+ }
+}
diff --git a/vendor/nette/di/src/DI/Definitions/Definition.php b/vendor/nette/di/src/DI/Definitions/Definition.php
new file mode 100644
index 0000000..ca96659
--- /dev/null
+++ b/vendor/nette/di/src/DI/Definitions/Definition.php
@@ -0,0 +1,181 @@
+name) {
+ throw new Nette\InvalidStateException('Name already has been set.');
+ }
+
+ $this->name = $name;
+ return $this;
+ }
+
+
+ final public function getName(): ?string
+ {
+ return $this->name;
+ }
+
+
+ protected function setType(?string $type): static
+ {
+ if ($this->autowired && $this->notifier && $this->type !== $type) {
+ ($this->notifier)();
+ }
+
+ if ($type === null) {
+ $this->type = null;
+ } elseif (!class_exists($type) && !interface_exists($type)) {
+ throw new Nette\InvalidArgumentException(sprintf(
+ "Service '%s': Class or interface '%s' not found.",
+ $this->name,
+ $type,
+ ));
+ } else {
+ $this->type = Nette\DI\Helpers::normalizeClass($type);
+ }
+
+ return $this;
+ }
+
+
+ final public function getType(): ?string
+ {
+ return $this->type;
+ }
+
+
+ final public function setTags(array $tags): static
+ {
+ $this->tags = $tags;
+ return $this;
+ }
+
+
+ final public function getTags(): array
+ {
+ return $this->tags;
+ }
+
+
+ final public function addTag(string $tag, mixed $attr = true): static
+ {
+ $this->tags[$tag] = $attr;
+ return $this;
+ }
+
+
+ final public function getTag(string $tag): mixed
+ {
+ return $this->tags[$tag] ?? null;
+ }
+
+
+ final public function setAutowired(bool|string|array $state = true): static
+ {
+ if ($this->notifier && $this->autowired !== $state) {
+ ($this->notifier)();
+ }
+
+ $this->autowired = is_string($state) || is_array($state)
+ ? (array) $state
+ : $state;
+ return $this;
+ }
+
+
+ /** @return bool|string[] */
+ final public function getAutowired(): bool|array
+ {
+ return $this->autowired;
+ }
+
+
+ public function setExported(bool $state = true): static
+ {
+ return $this->addTag('nette.exported', $state);
+ }
+
+
+ public function isExported(): bool
+ {
+ return (bool) $this->getTag('nette.exported');
+ }
+
+
+ public function __clone()
+ {
+ $this->notifier = $this->name = null;
+ }
+
+
+ /********************* life cycle ****************d*g**/
+
+
+ abstract public function resolveType(Nette\DI\Resolver $resolver): void;
+
+
+ abstract public function complete(Nette\DI\Resolver $resolver): void;
+
+
+ abstract public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGenerator $generator): void;
+
+
+ final public function setNotifier(?\Closure $notifier): void
+ {
+ $this->notifier = $notifier;
+ }
+
+
+ /********************* deprecated stuff from former ServiceDefinition ****************d*g**/
+
+
+ /** @deprecated Use setType() */
+ public function setClass(?string $type)
+ {
+ return $this->setType($type);
+ }
+
+
+ /** @deprecated Use getType() */
+ public function getClass(): ?string
+ {
+ return $this->getType();
+ }
+
+
+ /** @deprecated Use getAutowired() */
+ public function isAutowired()
+ {
+ return $this->autowired;
+ }
+}
diff --git a/vendor/nette/di/src/DI/Definitions/FactoryDefinition.php b/vendor/nette/di/src/DI/Definitions/FactoryDefinition.php
new file mode 100644
index 0000000..7c2e69c
--- /dev/null
+++ b/vendor/nette/di/src/DI/Definitions/FactoryDefinition.php
@@ -0,0 +1,230 @@
+resultDefinition = new ServiceDefinition;
+ }
+
+
+ public function setImplement(string $interface): static
+ {
+ if (!interface_exists($interface)) {
+ throw new Nette\InvalidArgumentException(sprintf(
+ "Service '%s': Interface '%s' not found.",
+ $this->getName(),
+ $interface,
+ ));
+ }
+
+ $rc = new \ReflectionClass($interface);
+ $method = $rc->getMethods()[0] ?? null;
+ if (!$method || $method->isStatic() || $method->name !== self::MethodCreate || count($rc->getMethods()) > 1) {
+ throw new Nette\InvalidArgumentException(sprintf(
+ "Service '%s': Interface %s must have just one non-static method create().",
+ $this->getName(),
+ $interface,
+ ));
+ }
+
+ Helpers::ensureClassType(Type::fromReflection($method), "return type of $interface::create()");
+ return parent::setType($interface);
+ }
+
+
+ public function getImplement(): ?string
+ {
+ return $this->getType();
+ }
+
+
+ public function getResultType(): ?string
+ {
+ return $this->resultDefinition->getType();
+ }
+
+
+ public function setResultDefinition(Definition $definition): static
+ {
+ $this->resultDefinition = $definition;
+ return $this;
+ }
+
+
+ /** @return ServiceDefinition */
+ public function getResultDefinition(): Definition
+ {
+ return $this->resultDefinition;
+ }
+
+
+ public function resolveType(Nette\DI\Resolver $resolver): void
+ {
+ if (!$this->getType()) {
+ throw new ServiceCreationException('Type is missing in definition of service.');
+ }
+
+ $type = Type::fromReflection(new \ReflectionMethod($this->getType(), self::MethodCreate));
+
+ $resultDef = $this->resultDefinition;
+ try {
+ $resolver->resolveDefinition($resultDef);
+ } catch (ServiceCreationException $e) {
+ if ($resultDef->getType()) {
+ throw $e;
+ }
+
+ $resultDef->setType($type->getSingleName());
+ $resolver->resolveDefinition($resultDef);
+ }
+
+ if (!$type->allows($resultDef->getType())) {
+ throw new ServiceCreationException(sprintf(
+ 'Factory for %s cannot create incompatible %s type.',
+ $type,
+ $resultDef->getType(),
+ ));
+ }
+ }
+
+
+ public function complete(Nette\DI\Resolver $resolver): void
+ {
+ $resultDef = $this->resultDefinition;
+
+ if ($resultDef instanceof ServiceDefinition) {
+ $this->completeParameters($resolver);
+ $this->convertArguments($resultDef->getCreator()->arguments);
+ foreach ($resultDef->getSetup() as $setup) {
+ $this->convertArguments($setup->arguments);
+ }
+
+ if ($resultDef->getEntity() instanceof Reference && !$resultDef->getCreator()->arguments) {
+ $resultDef->setCreator([ // render as $container->createMethod()
+ new Reference(Nette\DI\ContainerBuilder::ThisContainer),
+ Nette\DI\Container::getMethodName($resultDef->getEntity()->getValue()),
+ ]);
+ }
+ }
+
+ $resolver->completeDefinition($resultDef);
+ }
+
+
+ private function completeParameters(Nette\DI\Resolver $resolver): void
+ {
+ $interface = $this->getType();
+ $method = new \ReflectionMethod($interface, self::MethodCreate);
+
+ $ctorParams = [];
+ if (
+ ($class = $resolver->resolveEntityType($this->resultDefinition->getCreator()))
+ && ($ctor = (new \ReflectionClass($class))->getConstructor())
+ ) {
+ foreach ($ctor->getParameters() as $param) {
+ $ctorParams[$param->name] = $param;
+ }
+ }
+
+ foreach ($method->getParameters() as $param) {
+ if (isset($ctorParams[$param->name])) {
+ $ctorParam = $ctorParams[$param->name];
+ $ctorType = Type::fromReflection($ctorParam);
+ if ($ctorType && !$ctorType->allows((string) Type::fromReflection($param))) {
+ throw new ServiceCreationException(sprintf(
+ "Type of \$%s in %s::create() doesn't match type in %s constructor.",
+ $param->name,
+ $interface,
+ $class,
+ ));
+ }
+
+ $this->resultDefinition->getCreator()->arguments[$ctorParam->getPosition()] = new Php\Literal('$' . $ctorParam->name);
+
+ } elseif (!$this->resultDefinition->getSetup()) {
+ // [param1, param2] => '$param1, $param2'
+ $stringifyParams = fn(array $params): string => implode(
+ ', ',
+ array_map(fn(string $param) => '$' . $param, $params),
+ );
+ $ctorParamsKeys = array_keys($ctorParams);
+ $hint = Nette\Utils\Helpers::getSuggestion($ctorParamsKeys, $param->name);
+ throw new ServiceCreationException(sprintf(
+ 'Cannot implement %s::create(): factory method parameters (%s) are not matching %s::__construct() parameters (%s).',
+ $interface,
+ $stringifyParams(array_map(fn(\ReflectionParameter $param) => $param->name, $method->getParameters())),
+ $class,
+ $stringifyParams($ctorParamsKeys),
+ ) . ($hint ? " Did you mean to use '\${$hint}' in factory method?" : ''));
+ }
+ }
+ }
+
+
+ public function convertArguments(array &$args): void
+ {
+ foreach ($args as &$v) {
+ if (is_string($v) && $v && $v[0] === '$') {
+ $v = new Php\Literal($v);
+ }
+ }
+ }
+
+
+ public function generateMethod(Php\Method $method, Nette\DI\PhpGenerator $generator): void
+ {
+ $class = (new Php\ClassType)
+ ->addImplement($this->getType());
+
+ $class->addMethod('__construct')
+ ->addPromotedParameter('container')
+ ->setPrivate()
+ ->setType($generator->getClassName());
+
+ $methodCreate = $class->addMethod(self::MethodCreate);
+ $this->resultDefinition->generateMethod($methodCreate, $generator);
+ $body = $methodCreate->getBody();
+ $body = str_replace('$this', '$this->container', $body);
+ $body = str_replace('$this->container->container', '$this->container', $body);
+
+ $rm = new \ReflectionMethod($this->getType(), self::MethodCreate);
+ $methodCreate
+ ->setParameters(array_map((new Php\Factory)->fromParameterReflection(...), $rm->getParameters()))
+ ->setReturnType((string) Type::fromReflection($rm))
+ ->setBody($body);
+
+ $method->setBody('return new class ($this) ' . $class . ';');
+ }
+
+
+ public function __clone()
+ {
+ parent::__clone();
+ $this->resultDefinition = unserialize(serialize($this->resultDefinition));
+ }
+}
diff --git a/vendor/nette/di/src/DI/Definitions/ImportedDefinition.php b/vendor/nette/di/src/DI/Definitions/ImportedDefinition.php
new file mode 100644
index 0000000..501e558
--- /dev/null
+++ b/vendor/nette/di/src/DI/Definitions/ImportedDefinition.php
@@ -0,0 +1,44 @@
+setBody(
+ 'throw new Nette\\DI\\ServiceCreationException(?);',
+ ["Unable to create imported service '{$this->getName()}', it must be added using addService()"],
+ );
+ }
+}
diff --git a/vendor/nette/di/src/DI/Definitions/LocatorDefinition.php b/vendor/nette/di/src/DI/Definitions/LocatorDefinition.php
new file mode 100644
index 0000000..a9e3f73
--- /dev/null
+++ b/vendor/nette/di/src/DI/Definitions/LocatorDefinition.php
@@ -0,0 +1,176 @@
+getName(), $interface));
+ }
+
+ $methods = (new \ReflectionClass($interface))->getMethods();
+ if (!$methods) {
+ throw new Nette\InvalidArgumentException(sprintf("Service '%s': Interface %s must have at least one method.", $this->getName(), $interface));
+ }
+
+ foreach ($methods as $method) {
+ if ($method->isStatic() || !(
+ (preg_match('#^(get|create)$#', $method->name) && $method->getNumberOfParameters() === 1)
+ || (preg_match('#^(get|create)[A-Z]#', $method->name) && $method->getNumberOfParameters() === 0)
+ )) {
+ throw new Nette\InvalidArgumentException(sprintf(
+ "Service '%s': Method %s::%s() does not meet the requirements: is create(\$name), get(\$name), create*() or get*() and is non-static.",
+ $this->getName(),
+ $interface,
+ $method->name,
+ ));
+ }
+
+ if ($method->getNumberOfParameters() === 0) {
+ Nette\DI\Helpers::ensureClassType(
+ Nette\Utils\Type::fromReflection($method),
+ "return type of $interface::$method->name()",
+ allowNullable: true,
+ );
+ }
+ }
+
+ return parent::setType($interface);
+ }
+
+
+ public function getImplement(): ?string
+ {
+ return $this->getType();
+ }
+
+
+ public function setReferences(array $references): static
+ {
+ $this->references = [];
+ foreach ($references as $name => $ref) {
+ $this->references[$name] = str_starts_with($ref, '@')
+ ? new Reference(substr($ref, 1))
+ : Reference::fromType($ref);
+ }
+
+ return $this;
+ }
+
+
+ /** @return Reference[] */
+ public function getReferences(): array
+ {
+ return $this->references;
+ }
+
+
+ public function setTagged(?string $tagged): static
+ {
+ $this->tagged = $tagged;
+ return $this;
+ }
+
+
+ public function getTagged(): ?string
+ {
+ return $this->tagged;
+ }
+
+
+ public function resolveType(Nette\DI\Resolver $resolver): void
+ {
+ }
+
+
+ public function complete(Nette\DI\Resolver $resolver): void
+ {
+ if ($this->tagged !== null) {
+ $this->references = [];
+ foreach ($resolver->getContainerBuilder()->findByTag($this->tagged) as $name => $tag) {
+ if (isset($this->references[$tag])) {
+ trigger_error(sprintf(
+ "Service '%s': duplicated tag '%s' with value '%s'.",
+ $this->getName(),
+ $this->tagged,
+ $tag,
+ ));
+ }
+
+ $this->references[$tag] = new Reference($name);
+ }
+ }
+
+ foreach ($this->references as $name => $ref) {
+ $this->references[$name] = $resolver->normalizeReference($ref);
+ }
+ }
+
+
+ public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGenerator $generator): void
+ {
+ $class = (new Nette\PhpGenerator\ClassType)
+ ->addImplement($this->getType());
+
+ $class->addMethod('__construct')
+ ->addPromotedParameter('container')
+ ->setPrivate()
+ ->setType($generator->getClassName());
+
+ foreach ((new \ReflectionClass($this->getType()))->getMethods() as $rm) {
+ preg_match('#^(get|create)(.*)#', $rm->name, $m);
+ $name = lcfirst($m[2]);
+ $nullable = $rm->getReturnType()->allowsNull();
+
+ $methodInner = $class->addMethod($rm->name)
+ ->setReturnType((string) Nette\Utils\Type::fromReflection($rm));
+
+ if (!$name) {
+ $class->addProperty('mapping', array_map(fn($item) => $item->getValue(), $this->references))
+ ->setPrivate();
+
+ $methodInner->setBody(<<<'XX'
+ if (!isset($this->mapping[$name])) {
+
+ XX . "\t" . ($nullable ? 'return null;' : 'throw new Nette\DI\MissingServiceException("Service \'$name\' is not defined.");') . <<<'XX'
+
+ }
+ return $this->container->
+ XX . $m[1] . 'Service($this->mapping[$name]);')
+ ->addParameter('name');
+
+ } elseif (isset($this->references[$name])) {
+ $ref = $this->references[$name]->getValue();
+ if ($m[1] === 'get') {
+ $methodInner->setBody('return $this->container->getService(?);', [$ref]);
+ } else {
+ $methodInner->setBody('return $this->container->?();', [Nette\DI\Container::getMethodName($ref)]);
+ }
+ } else {
+ $methodInner->setBody($nullable ? 'return null;' : 'throw new Nette\DI\MissingServiceException("Service is not defined.");');
+ }
+ }
+
+ $method->setBody('return new class ($this) ' . $class . ';');
+ }
+}
diff --git a/vendor/nette/di/src/DI/Definitions/Reference.php b/vendor/nette/di/src/DI/Definitions/Reference.php
new file mode 100644
index 0000000..25625de
--- /dev/null
+++ b/vendor/nette/di/src/DI/Definitions/Reference.php
@@ -0,0 +1,64 @@
+value = $value;
+ }
+
+
+ public function getValue(): string
+ {
+ return $this->value;
+ }
+
+
+ public function isName(): bool
+ {
+ return !str_contains($this->value, '\\') && $this->value !== self::Self;
+ }
+
+
+ public function isType(): bool
+ {
+ return str_contains($this->value, '\\');
+ }
+
+
+ public function isSelf(): bool
+ {
+ return $this->value === self::Self;
+ }
+}
diff --git a/vendor/nette/di/src/DI/Definitions/ServiceDefinition.php b/vendor/nette/di/src/DI/Definitions/ServiceDefinition.php
new file mode 100644
index 0000000..ff934c2
--- /dev/null
+++ b/vendor/nette/di/src/DI/Definitions/ServiceDefinition.php
@@ -0,0 +1,228 @@
+creator = new Statement(null);
+ }
+
+
+ public function setType(?string $type): static
+ {
+ return parent::setType($type);
+ }
+
+
+ /**
+ * Alias for setCreator()
+ */
+ public function setFactory(string|array|Definition|Reference|Statement $factory, array $args = []): static
+ {
+ return $this->setCreator($factory, $args);
+ }
+
+
+ /**
+ * Alias for getCreator()
+ */
+ public function getFactory(): Statement
+ {
+ return $this->getCreator();
+ }
+
+
+ public function setCreator(string|array|Definition|Reference|Statement $creator, array $args = []): static
+ {
+ $this->creator = $creator instanceof Statement
+ ? $creator
+ : new Statement($creator, $args);
+ return $this;
+ }
+
+
+ public function getCreator(): Statement
+ {
+ return $this->creator;
+ }
+
+
+ public function getEntity(): string|array|Definition|Reference|null
+ {
+ return $this->creator->getEntity();
+ }
+
+
+ public function setArguments(array $args = []): static
+ {
+ $this->creator->arguments = $args;
+ return $this;
+ }
+
+
+ public function setArgument($key, $value): static
+ {
+ $this->creator->arguments[$key] = $value;
+ return $this;
+ }
+
+
+ /**
+ * @param Statement[] $setup
+ */
+ public function setSetup(array $setup): static
+ {
+ foreach ($setup as &$entity) {
+ if (!$entity instanceof Statement) {
+ throw new Nette\InvalidArgumentException('Argument must be Nette\DI\Definitions\Statement[].');
+ }
+ $entity = $this->prependSelf($entity);
+ }
+
+ $this->setup = $setup;
+ return $this;
+ }
+
+
+ /** @return Statement[] */
+ public function getSetup(): array
+ {
+ return $this->setup;
+ }
+
+
+ public function addSetup(string|array|Definition|Reference|Statement $entity, array $args = []): static
+ {
+ $entity = $entity instanceof Statement
+ ? $entity
+ : new Statement($entity, $args);
+ $this->setup[] = $this->prependSelf($entity);
+ return $this;
+ }
+
+
+ public function resolveType(Nette\DI\Resolver $resolver): void
+ {
+ if (!$this->getEntity()) {
+ if (!$this->getType()) {
+ throw new ServiceCreationException('Factory and type are missing in definition of service.');
+ }
+
+ $this->setCreator($this->getType(), $this->creator->arguments ?? []);
+
+ } elseif (!$this->getType()) {
+ $type = $resolver->resolveEntityType($this->creator);
+ if (!$type) {
+ throw new ServiceCreationException('Unknown service type, specify it or declare return type of factory method.');
+ }
+
+ $this->setType($type);
+ $resolver->addDependency(new \ReflectionClass($type));
+ }
+
+ // auto-disable autowiring for aliases
+ if ($this->getAutowired() === true && $this->getEntity() instanceof Reference) {
+ $this->setAutowired(false);
+ }
+ }
+
+
+ public function complete(Nette\DI\Resolver $resolver): void
+ {
+ $entity = $this->creator->getEntity();
+ if ($entity instanceof Reference && !$this->creator->arguments && !$this->setup) {
+ $ref = $resolver->normalizeReference($entity);
+ $this->setCreator([new Reference(Nette\DI\ContainerBuilder::ThisContainer), 'getService'], [$ref->getValue()]);
+ }
+
+ $this->creator = $resolver->completeStatement($this->creator);
+
+ foreach ($this->setup as &$setup) {
+ $setup = $resolver->completeStatement($setup, true);
+ }
+ }
+
+
+ private function prependSelf(Statement $setup): Statement
+ {
+ return is_string($setup->getEntity()) && strpbrk($setup->getEntity(), ':@?\\') === false
+ ? new Statement([new Reference(Reference::Self), $setup->getEntity()], $setup->arguments)
+ : $setup;
+ }
+
+
+ public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGenerator $generator): void
+ {
+ $lines = [];
+ foreach ([$this->creator, ...$this->setup] as $stmt) {
+ $lines[] = $generator->formatStatement($stmt) . ";\n";
+ }
+
+ if ($this->canBeLazy() && !preg_grep('#(?:func_get_arg|func_num_args)#i', $lines)) { // latteFactory workaround
+ $class = $this->creator->getEntity();
+ $lines[0] = (new \ReflectionClass($class))->hasMethod('__construct')
+ ? $generator->formatPhp("\$service->__construct(...?:);\n", [$this->creator->arguments])
+ : '';
+ $method->setBody("return new ReflectionClass($class::class)->newLazyGhost(function (\$service) {\n"
+ . Strings::indent(implode('', $lines))
+ . '});');
+
+ } elseif (count($lines) === 1) {
+ $method->setBody('return ' . $lines[0]);
+
+ } else {
+ $method->setBody('$service = ' . implode('', $lines) . 'return $service;');
+ }
+ }
+
+
+ private function canBeLazy(): bool
+ {
+ return $this->lazy
+ && is_string($class = $this->creator->getEntity())
+ && ($this->creator->arguments || $this->setup)
+ && ($ancestor = ($tmp = class_parents($class)) ? array_pop($tmp) : $class)
+ && !(new \ReflectionClass($ancestor))->isInternal();
+ }
+
+
+ public function __clone()
+ {
+ parent::__clone();
+ $this->creator = unserialize(serialize($this->creator));
+ $this->setup = unserialize(serialize($this->setup));
+ }
+}
+
+
+class_exists(Nette\DI\ServiceDefinition::class);
diff --git a/vendor/nette/di/src/DI/Definitions/Statement.php b/vendor/nette/di/src/DI/Definitions/Statement.php
new file mode 100644
index 0000000..cd80f6d
--- /dev/null
+++ b/vendor/nette/di/src/DI/Definitions/Statement.php
@@ -0,0 +1,68 @@
+entity = $entity;
+ $this->arguments = $arguments;
+ }
+
+
+ public function getEntity(): string|array|Definition|Reference|null
+ {
+ return $this->entity;
+ }
+}
+
+
+class_exists(Nette\DI\Statement::class);
diff --git a/vendor/nette/di/src/DI/DependencyChecker.php b/vendor/nette/di/src/DI/DependencyChecker.php
new file mode 100644
index 0000000..94eb9fd
--- /dev/null
+++ b/vendor/nette/di/src/DI/DependencyChecker.php
@@ -0,0 +1,189 @@
+ */
+ private array $dependencies = [];
+
+
+ /**
+ * Adds dependencies to the list.
+ */
+ public function add(array $deps): static
+ {
+ $this->dependencies = array_merge($this->dependencies, $deps);
+ return $this;
+ }
+
+
+ /**
+ * Exports dependencies.
+ */
+ public function export(): array
+ {
+ $files = $phpFiles = $classes = $functions = [];
+ foreach ($this->dependencies as $dep) {
+ if (is_string($dep)) {
+ $files[] = $dep;
+
+ } elseif ($dep instanceof ReflectionClass) {
+ if (empty($classes[$name = $dep->name])) {
+ $all = [$name] + class_parents($name) + class_implements($name);
+ foreach ($all as &$item) {
+ $all += class_uses($item);
+ $phpFiles[] = (new ReflectionClass($item))->getFileName();
+ $classes[$item] = true;
+ }
+ }
+ } elseif ($dep instanceof \ReflectionFunctionAbstract) {
+ $phpFiles[] = $dep->getFileName();
+ $functions[] = rtrim(Reflection::toString($dep), '()');
+
+ } else {
+ throw new Nette\InvalidStateException(sprintf('Unexpected dependency %s', get_debug_type($dep)));
+ }
+ }
+
+ $classes = array_keys($classes);
+ $functions = array_unique($functions, SORT_REGULAR);
+ $hash = self::calculateHash($classes, $functions);
+ $files = @array_map('filemtime', array_combine($files, $files)); // @ - file may not exist
+ $phpFiles = @array_map('filemtime', array_combine($phpFiles, $phpFiles)); // @ - file may not exist
+ return [self::Version, $files, $phpFiles, $classes, $functions, $hash];
+ }
+
+
+ /**
+ * Are dependencies expired?
+ */
+ public static function isExpired(
+ int $version,
+ array $files,
+ array &$phpFiles,
+ array $classes,
+ array $functions,
+ string $hash,
+ ): bool
+ {
+ try {
+ $currentFiles = @array_map('filemtime', array_combine($tmp = array_keys($files), $tmp)); // @ - files may not exist
+ $origPhpFiles = $phpFiles;
+ $phpFiles = @array_map('filemtime', array_combine($tmp = array_keys($phpFiles), $tmp)); // @ - files may not exist
+ return $version !== self::Version
+ || $files !== $currentFiles
+ || ($phpFiles !== $origPhpFiles && $hash !== self::calculateHash($classes, $functions));
+ } catch (\ReflectionException) {
+ return true;
+ }
+ }
+
+
+ private static function calculateHash(array $classes, array $functions): string
+ {
+ $hash = [];
+ foreach ($classes as $name) {
+ $class = new ReflectionClass($name);
+ $hash[] = [
+ $name,
+ Reflection::getUseStatements($class),
+ $class->isAbstract(),
+ get_parent_class($name),
+ class_implements($name),
+ class_uses($name),
+ ];
+
+ foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) {
+ if ($prop->getDeclaringClass() == $class) { // intentionally ==
+ $hash[] = [
+ $name,
+ $prop->name,
+ $prop->getDocComment(),
+ (string) $prop->getType(),
+ count($prop->getAttributes(Attributes\Inject::class)),
+ ];
+ }
+ }
+
+ foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
+ if ($method->getDeclaringClass() == $class) { // intentionally ==
+ $hash[] = [
+ $name,
+ $method->name,
+ $method->getDocComment(),
+ self::hashParameters($method),
+ (string) $method->getReturnType(),
+ ];
+ }
+ }
+ }
+
+ $flip = array_flip($classes);
+ foreach ($functions as $name) {
+ if (str_contains($name, '::')) {
+ $method = PHP_VERSION_ID < 80300
+ ? new ReflectionMethod($name)
+ : ReflectionMethod::createFromMethodName($name);
+ $class = $method->getDeclaringClass();
+ if (isset($flip[$class->name])) {
+ continue;
+ }
+
+ $uses = Reflection::getUseStatements($class);
+ } else {
+ $method = new \ReflectionFunction($name);
+ $uses = null;
+ }
+
+ $hash[] = [
+ $name,
+ $uses,
+ $method->getDocComment(),
+ self::hashParameters($method),
+ (string) $method->getReturnType(),
+ ];
+ }
+
+ return hash('xxh128', serialize($hash));
+ }
+
+
+ private static function hashParameters(\ReflectionFunctionAbstract $method): array
+ {
+ $res = [];
+ foreach ($method->getParameters() as $param) {
+ $res[] = [
+ $param->name,
+ (string) $param->getType(),
+ $param->isVariadic(),
+ $param->isDefaultValueAvailable()
+ ? is_object($tmp = Reflection::getParameterDefaultValue($param)) ? ['object' => $tmp::class] : ['value' => $tmp]
+ : null,
+ ];
+ }
+
+ return $res;
+ }
+}
diff --git a/vendor/nette/di/src/DI/DynamicParameter.php b/vendor/nette/di/src/DI/DynamicParameter.php
new file mode 100644
index 0000000..8c3ae48
--- /dev/null
+++ b/vendor/nette/di/src/DI/DynamicParameter.php
@@ -0,0 +1,20 @@
+debugMode = $debugMode;
+ $this->time = microtime(true);
+
+ $this->config = new class {
+ public ?bool $debugger = null;
+
+ /** @var string[] */
+ public array $excluded = [];
+ public ?string $parentClass = null;
+ public object $export;
+ public bool $lazy = false;
+ };
+ $this->config->export = new class {
+ public bool $parameters = true;
+
+ /** @var string[]|bool|null */
+ public array|bool|null $tags = true;
+
+ /** @var string[]|bool|null */
+ public array|bool|null $types = true;
+ };
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ $builder = $this->getContainerBuilder();
+ $builder->addExcludedClasses($this->config->excluded);
+ }
+
+
+ public function beforeCompile(): void
+ {
+ if ($this->config->lazy && PHP_VERSION_ID >= 80400) {
+ $builder = $this->getContainerBuilder();
+ foreach ($builder->getDefinitions() as $def) {
+ if ($def instanceof ServiceDefinition) {
+ $def->lazy ??= true;
+ }
+ }
+ }
+ }
+
+
+ public function afterCompile(Nette\PhpGenerator\ClassType $class): void
+ {
+ if ($this->config->parentClass) {
+ $class->setExtends($this->config->parentClass);
+ }
+
+ $this->restrictParameters($class);
+ $this->restrictTags($class);
+ $this->restrictTypes($class);
+
+ if (
+ $this->debugMode &&
+ ($this->config->debugger ?? $this->getContainerBuilder()->getByType(Tracy\Bar::class))
+ ) {
+ $this->enableTracyIntegration();
+ }
+ }
+
+
+ private function restrictParameters(Nette\PhpGenerator\ClassType $class): void
+ {
+ if (!$this->config->export->parameters) {
+ $class->removeMethod('getParameters');
+ $class->removeMethod('getStaticParameters');
+ }
+ }
+
+
+ private function restrictTags(Nette\PhpGenerator\ClassType $class): void
+ {
+ $option = $this->config->export->tags;
+ if ($option === true) {
+ } elseif ($option === false) {
+ $class->removeProperty('tags');
+ } elseif ($prop = $class->getProperties()['tags'] ?? null) {
+ $prop->setValue(array_intersect_key($prop->getValue(), $this->exportedTags + array_flip((array) $option)));
+ }
+ }
+
+
+ private function restrictTypes(Nette\PhpGenerator\ClassType $class): void
+ {
+ $option = $this->config->export->types;
+ if ($option === true) {
+ return;
+ }
+
+ $prop = $class->getProperty('wiring');
+ $prop->setValue(array_intersect_key(
+ $prop->getValue(),
+ $this->exportedTypes + (is_array($option) ? array_flip($option) : []),
+ ));
+ }
+
+
+ private function enableTracyIntegration(): void
+ {
+ Nette\Bridges\DITracy\ContainerPanel::$compilationTime = $this->time;
+ $this->initialization->addBody($this->getContainerBuilder()->formatPhp('?;', [
+ new Nette\DI\Definitions\Statement(
+ '@Tracy\Bar::addPanel',
+ [new Nette\DI\Definitions\Statement(Nette\Bridges\DITracy\ContainerPanel::class)],
+ ),
+ ]));
+ }
+}
diff --git a/vendor/nette/di/src/DI/Extensions/DecoratorExtension.php b/vendor/nette/di/src/DI/Extensions/DecoratorExtension.php
new file mode 100644
index 0000000..0725d80
--- /dev/null
+++ b/vendor/nette/di/src/DI/Extensions/DecoratorExtension.php
@@ -0,0 +1,87 @@
+ Expect::list(),
+ 'tags' => Expect::array(),
+ 'inject' => Expect::bool(),
+ ]),
+ );
+ }
+
+
+ public function beforeCompile(): void
+ {
+ $this->getContainerBuilder()->resolve();
+ foreach ($this->config as $type => $info) {
+ if (!class_exists($type) && !interface_exists($type)) {
+ throw new Nette\DI\InvalidConfigurationException(sprintf("Decorated class '%s' not found.", $type));
+ }
+
+ if ($info->inject !== null) {
+ $info->tags[InjectExtension::TagInject] = $info->inject;
+ }
+
+ $this->addSetups($type, Nette\DI\Helpers::filterArguments($info->setup));
+ $this->addTags($type, $info->tags);
+ }
+ }
+
+
+ public function addSetups(string $type, array $setups): void
+ {
+ foreach ($this->findByType($type) as $def) {
+ if ($def instanceof Definitions\FactoryDefinition) {
+ $def = $def->getResultDefinition();
+ }
+
+ foreach ($setups as $setup) {
+ if (is_array($setup)) {
+ $setup = new Definitions\Statement(key($setup), array_values($setup));
+ }
+
+ $def->addSetup($setup);
+ }
+ }
+ }
+
+
+ public function addTags(string $type, array $tags): void
+ {
+ $tags = Nette\Utils\Arrays::normalize($tags, filling: true);
+ foreach ($this->findByType($type) as $def) {
+ $def->setTags($def->getTags() + $tags);
+ }
+ }
+
+
+ private function findByType(string $type): array
+ {
+ return array_filter(
+ $this->getContainerBuilder()->getDefinitions(),
+ fn(Definitions\Definition $def): bool => is_a($def->getType(), $type, true)
+ || ($def instanceof Definitions\FactoryDefinition && is_a($def->getResultType(), $type, allow_string: true)),
+ );
+ }
+}
diff --git a/vendor/nette/di/src/DI/Extensions/DefinitionSchema.php b/vendor/nette/di/src/DI/Extensions/DefinitionSchema.php
new file mode 100644
index 0000000..487ddec
--- /dev/null
+++ b/vendor/nette/di/src/DI/Extensions/DefinitionSchema.php
@@ -0,0 +1,232 @@
+builder = $builder;
+ }
+
+
+ public function complete($def, Context $context)
+ {
+ if ($def === [false]) {
+ return (object) $def;
+ }
+
+ if (Helpers::takeParent($def)) {
+ $def['reset']['all'] = true;
+ }
+
+ foreach (['arguments', 'setup', 'tags'] as $k) {
+ if (isset($def[$k]) && Helpers::takeParent($def[$k])) {
+ $def['reset'][$k] = true;
+ }
+ }
+
+ $type = $this->sniffType(end($context->path), $def);
+ $def = $this->getSchema($type)->complete($def, $context);
+ if ($def) {
+ $def->defType = $type;
+ }
+
+ return $def;
+ }
+
+
+ public function merge($def, $base)
+ {
+ if (!empty($def['alteration'])) {
+ unset($def['alteration']);
+ }
+
+ return Nette\Schema\Helpers::merge($def, $base);
+ }
+
+
+ /**
+ * Normalizes configuration of service definitions.
+ */
+ public function normalize($def, Context $context)
+ {
+ if ($def === null || $def === false) {
+ return (array) $def;
+
+ } elseif (is_string($def) && interface_exists($def)) {
+ return ['implement' => $def];
+
+ } elseif ($def instanceof Statement && is_string($def->getEntity()) && interface_exists($def->getEntity())) {
+ $res = ['implement' => $def->getEntity()];
+ if (array_keys($def->arguments) === ['tagged']) {
+ $res += $def->arguments;
+ } elseif (array_keys($def->arguments) === [0]) {
+ $res['create'] = $def->arguments[0];
+ } elseif ($def->arguments) {
+ $res['references'] = $def->arguments;
+ }
+
+ return $res;
+
+ } elseif (!is_array($def) || isset($def[0], $def[1])) {
+ return ['create' => $def];
+
+ } else {
+ // back compatibility
+ if (isset($def['factory']) && !isset($def['create'])) {
+ $def['create'] = $def['factory'];
+ unset($def['factory']);
+ }
+ if (isset($def['class']) && !isset($def['type']) && !isset($def['imported'])) {
+ $def[isset($def['create']) ? 'type' : 'create'] = $def['class'];
+ unset($def['class']);
+ }
+
+ return $def;
+ }
+ }
+
+
+ public function completeDefault(Context $context)
+ {
+ }
+
+
+ private function sniffType($key, array $def): string
+ {
+ if (is_string($key)) {
+ $name = preg_match('#^@[\w\\\\]+$#D', $key)
+ ? $this->builder->getByType(substr($key, 1))
+ : $key;
+
+ if ($name && $this->builder->hasDefinition($name)) {
+ return get_class($this->builder->getDefinition($name));
+ }
+ }
+
+ if (isset($def['implement'], $def['references']) || isset($def['implement'], $def['tagged'])) {
+ return Definitions\LocatorDefinition::class;
+
+ } elseif (isset($def['implement'])) {
+ return method_exists($def['implement'], 'create')
+ ? Definitions\FactoryDefinition::class
+ : Definitions\AccessorDefinition::class;
+
+ } elseif (isset($def['imported'])) {
+ return Definitions\ImportedDefinition::class;
+
+ } elseif (!$def) {
+ throw new Nette\DI\InvalidConfigurationException("Service '$key': Empty definition.");
+
+ } else {
+ return Definitions\ServiceDefinition::class;
+ }
+ }
+
+
+ private static function getSchema(string $type): Schema
+ {
+ static $cache;
+ $cache = $cache ?: [
+ Definitions\ServiceDefinition::class => self::getServiceSchema(),
+ Definitions\AccessorDefinition::class => self::getAccessorSchema(),
+ Definitions\FactoryDefinition::class => self::getFactorySchema(),
+ Definitions\LocatorDefinition::class => self::getLocatorSchema(),
+ Definitions\ImportedDefinition::class => self::getImportedSchema(),
+ ];
+ return $cache[$type];
+ }
+
+
+ private static function getServiceSchema(): Schema
+ {
+ return Expect::structure([
+ 'type' => Expect::type('string'),
+ 'create' => Expect::type('callable|Nette\DI\Definitions\Statement|Nette\DI\Definitions\Reference'),
+ 'arguments' => Expect::array(),
+ 'setup' => Expect::listOf('callable|Nette\DI\Definitions\Statement|array:1'),
+ 'inject' => Expect::bool(),
+ 'autowired' => Expect::type('bool|string|array'),
+ 'tags' => Expect::array(),
+ 'reset' => Expect::array(),
+ 'alteration' => Expect::bool(),
+ 'lazy' => Expect::bool(),
+ ]);
+ }
+
+
+ private static function getAccessorSchema(): Schema
+ {
+ return Expect::structure([
+ 'type' => Expect::string(),
+ 'implement' => Expect::string(),
+ 'create' => Expect::type('callable|Nette\DI\Definitions\Statement'),
+ 'autowired' => Expect::type('bool|string|array'),
+ 'tags' => Expect::array(),
+ ]);
+ }
+
+
+ private static function getFactorySchema(): Schema
+ {
+ return Expect::structure([
+ 'type' => Expect::string(),
+ 'create' => Expect::type('callable|Nette\DI\Definitions\Statement'),
+ 'implement' => Expect::string(),
+ 'arguments' => Expect::array(),
+ 'setup' => Expect::listOf('callable|Nette\DI\Definitions\Statement|array:1'),
+ 'references' => Expect::array(),
+ 'tagged' => Expect::string(),
+ 'inject' => Expect::bool(),
+ 'autowired' => Expect::type('bool|string|array'),
+ 'tags' => Expect::array(),
+ 'reset' => Expect::array(),
+ ]);
+ }
+
+
+ private static function getLocatorSchema(): Schema
+ {
+ return Expect::structure([
+ 'implement' => Expect::string(),
+ 'references' => Expect::array(),
+ 'tagged' => Expect::string(),
+ 'autowired' => Expect::type('bool|string|array'),
+ 'tags' => Expect::array(),
+ ]);
+ }
+
+
+ private static function getImportedSchema(): Schema
+ {
+ return Expect::structure([
+ 'type' => Expect::string(),
+ 'imported' => Expect::bool(),
+ 'autowired' => Expect::type('bool|string|array'),
+ 'tags' => Expect::array(),
+ ]);
+ }
+}
diff --git a/vendor/nette/di/src/DI/Extensions/ExtensionsExtension.php b/vendor/nette/di/src/DI/Extensions/ExtensionsExtension.php
new file mode 100644
index 0000000..591ad4f
--- /dev/null
+++ b/vendor/nette/di/src/DI/Extensions/ExtensionsExtension.php
@@ -0,0 +1,48 @@
+getConfig() as $name => $class) {
+ if (is_int($name)) {
+ $name = null;
+ }
+
+ $args = [];
+ if ($class instanceof Nette\DI\Definitions\Statement) {
+ [$class, $args] = [$class->getEntity(), $class->arguments];
+ }
+
+ if (!is_a($class, Nette\DI\CompilerExtension::class, allow_string: true)) {
+ throw new Nette\DI\InvalidConfigurationException(sprintf(
+ "Extension '%s' not found or is not Nette\\DI\\CompilerExtension descendant.",
+ $class,
+ ));
+ }
+
+ $this->compiler->addExtension($name, (new \ReflectionClass($class))->newInstanceArgs($args));
+ }
+ }
+}
diff --git a/vendor/nette/di/src/DI/Extensions/InjectExtension.php b/vendor/nette/di/src/DI/Extensions/InjectExtension.php
new file mode 100644
index 0000000..4c40b30
--- /dev/null
+++ b/vendor/nette/di/src/DI/Extensions/InjectExtension.php
@@ -0,0 +1,172 @@
+getContainerBuilder()->getDefinitions() as $def) {
+ if ($def->getTag(self::TagInject)) {
+ $def = $def instanceof Definitions\FactoryDefinition
+ ? $def->getResultDefinition()
+ : $def;
+ if ($def instanceof Definitions\ServiceDefinition) {
+ $this->updateDefinition($def);
+ }
+ }
+ }
+ }
+
+
+ private function updateDefinition(Definitions\ServiceDefinition $def): void
+ {
+ $resolvedType = (new DI\Resolver($this->getContainerBuilder()))->resolveEntityType($def->getCreator());
+ $class = is_subclass_of($resolvedType, $def->getType())
+ ? $resolvedType
+ : $def->getType();
+ $setups = $def->getSetup();
+
+ foreach (self::getInjectProperties($class) as $property => $type) {
+ $builder = $this->getContainerBuilder();
+ $inject = new Definitions\Statement(['@self', '$' . $property], [Definitions\Reference::fromType((string) $type)]);
+ foreach ($setups as $key => $setup) {
+ if ($setup->getEntity() == $inject->getEntity()) { // intentionally ==
+ $inject = $setup;
+ $builder = null;
+ unset($setups[$key]);
+ }
+ }
+
+ if ($builder) {
+ self::checkType($class, $property, $type, $builder);
+ }
+ array_unshift($setups, $inject);
+ }
+
+ foreach (array_reverse(self::getInjectMethods($class)) as $method) {
+ $inject = new Definitions\Statement(['@self', $method]);
+ foreach ($setups as $key => $setup) {
+ if ($setup->getEntity() == $inject->getEntity()) { // intentionally ==
+ $inject = $setup;
+ unset($setups[$key]);
+ }
+ }
+
+ array_unshift($setups, $inject);
+ }
+
+ $def->setSetup($setups);
+ }
+
+
+ /**
+ * Generates list of inject methods.
+ * @internal
+ */
+ public static function getInjectMethods(string $class): array
+ {
+ $classes = [];
+ foreach (get_class_methods($class) as $name) {
+ if (str_starts_with($name, 'inject')) {
+ $classes[$name] = (new \ReflectionMethod($class, $name))->getDeclaringClass()->name;
+ }
+ }
+
+ $methods = array_keys($classes);
+ uksort($classes, fn(string $a, string $b): int => $classes[$a] === $classes[$b]
+ ? array_search($a, $methods, strict: true) <=> array_search($b, $methods, strict: true)
+ : (is_a($classes[$a], $classes[$b], allow_string: true) ? 1 : -1));
+ return array_keys($classes);
+ }
+
+
+ /**
+ * Generates list of properties with annotation @inject.
+ * @internal
+ */
+ public static function getInjectProperties(string $class): array
+ {
+ $res = [];
+ foreach ((new \ReflectionClass($class))->getProperties() as $rp) {
+ $hasAttr = $rp->getAttributes(DI\Attributes\Inject::class);
+ if ($hasAttr || DI\Helpers::parseAnnotation($rp, 'inject') !== null) {
+ if (!$rp->isPublic() || $rp->isStatic() || $rp->isReadOnly()) {
+ throw new Nette\InvalidStateException(sprintf('Property %s for injection must not be static, readonly and must be public.', Reflection::toString($rp)));
+ }
+
+ $type = Nette\Utils\Type::fromReflection($rp);
+ if (!$type && !$hasAttr && ($annotation = DI\Helpers::parseAnnotation($rp, 'var'))) {
+ $annotation = Reflection::expandClassName($annotation, Reflection::getPropertyDeclaringClass($rp));
+ $type = Nette\Utils\Type::fromString($annotation);
+ }
+
+ $res[$rp->getName()] = DI\Helpers::ensureClassType($type, 'type of property ' . Reflection::toString($rp));
+ }
+ }
+
+ ksort($res);
+ return $res;
+ }
+
+
+ /**
+ * Calls all methods starting with "inject" using autowiring.
+ */
+ public static function callInjects(DI\Container $container, object $service): void
+ {
+ foreach (self::getInjectMethods($service::class) as $method) {
+ $container->callMethod([$service, $method]);
+ }
+
+ foreach (self::getInjectProperties($service::class) as $property => $type) {
+ self::checkType($service, $property, $type, $container);
+ $service->$property = $container->getByType($type);
+ }
+ }
+
+
+ private static function checkType(
+ object|string $class,
+ string $name,
+ ?string $type,
+ DI\Container|DI\ContainerBuilder $container,
+ ): void
+ {
+ if (!$container->getByType($type, throw: false)) {
+ throw new Nette\DI\MissingServiceException(sprintf(
+ 'Service of type %s required by %s not found. Did you add it to configuration file?',
+ $type,
+ Reflection::toString(new \ReflectionProperty($class, $name)),
+ ));
+ }
+ }
+}
diff --git a/vendor/nette/di/src/DI/Extensions/ParametersExtension.php b/vendor/nette/di/src/DI/Extensions/ParametersExtension.php
new file mode 100644
index 0000000..144554d
--- /dev/null
+++ b/vendor/nette/di/src/DI/Extensions/ParametersExtension.php
@@ -0,0 +1,102 @@
+compilerConfig = &$compilerConfig;
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ $builder = $this->getContainerBuilder();
+ $params = $this->config;
+ foreach ($this->dynamicParams as $key) {
+ $params[$key] = new DynamicParameter('$this->getParameter(' . var_export($key, true) . ')');
+ }
+
+ $builder->parameters = Helpers::expand($params, $params, recursive: true);
+ $this->compilerConfig = Helpers::expand($this->compilerConfig, $builder->parameters);
+ }
+
+
+ public function afterCompile(Nette\PhpGenerator\ClassType $class): void
+ {
+ $builder = $this->getContainerBuilder();
+ $dynamicParams = array_fill_keys($this->dynamicParams, true);
+ foreach ($builder->parameters as $key => $value) {
+ $value = [$value];
+ array_walk_recursive($value, function ($val) use (&$dynamicParams, $key): void {
+ if ($val instanceof DynamicParameter) {
+ $dynamicParams[$key] ??= true;
+ } elseif ($val instanceof Nette\DI\Definitions\Statement) {
+ $dynamicParams[$key] = false;
+ }
+ });
+ }
+
+ $manipulator = new Nette\PhpGenerator\ClassManipulator($class);
+ $manipulator->inheritMethod('getStaticParameters')
+ ->addBody('return ?;', [array_diff_key($builder->parameters, $dynamicParams)]);
+
+ if (!$dynamicParams) {
+ return;
+ }
+
+ $resolver = new Nette\DI\Resolver($builder);
+ $generator = new Nette\DI\PhpGenerator($builder);
+ $method = $manipulator->inheritMethod('getDynamicParameter');
+ $method->addBody('return match($key) {');
+ foreach ($dynamicParams as $key => $foo) {
+ $value = Helpers::expand($this->config[$key] ?? null, $builder->parameters);
+ try {
+ $value = $generator->convertArguments($resolver->completeArguments(Helpers::filterArguments([$value])))[0];
+ $method->addBody("\t? => ?,", [$key, $value]);
+ } catch (Nette\DI\ServiceCreationException $e) {
+ $method->addBody("\t? => throw new Nette\\DI\\ServiceCreationException(?),", [$key, $e->getMessage()]);
+ }
+ }
+ $method->addBody("\tdefault => parent::getDynamicParameter(\$key),\n};");
+
+ if ($preload = array_keys($dynamicParams, true, true)) {
+ $method = $manipulator->inheritMethod('getParameters');
+ $method->addBody('array_map($this->getParameter(...), ?);', [$preload]);
+ $method->addBody('return parent::getParameters();');
+ }
+
+ foreach ($this->dynamicValidators as [$param, $expected, $path]) {
+ if ($param instanceof DynamicParameter) {
+ $this->initialization->addBody(
+ 'Nette\Utils\Validators::assert(?, ?, ?);',
+ [$param, $expected, "dynamic parameter used in '" . implode("\u{a0}›\u{a0}", $path) . "'"],
+ );
+ }
+ }
+ }
+}
diff --git a/vendor/nette/di/src/DI/Extensions/SearchExtension.php b/vendor/nette/di/src/DI/Extensions/SearchExtension.php
new file mode 100644
index 0000000..eb87253
--- /dev/null
+++ b/vendor/nette/di/src/DI/Extensions/SearchExtension.php
@@ -0,0 +1,159 @@
+tempDir = $tempDir;
+ }
+
+
+ public function getConfigSchema(): Nette\Schema\Schema
+ {
+ return Expect::arrayOf(
+ Expect::structure([
+ 'in' => Expect::string()->required(),
+ 'files' => Expect::anyOf(Expect::listOf('string'), Expect::string()->castTo('array'))->default([]),
+ 'classes' => Expect::anyOf(Expect::listOf('string'), Expect::string()->castTo('array'))->default([]),
+ 'extends' => Expect::anyOf(Expect::listOf('string'), Expect::string()->castTo('array'))->default([]),
+ 'implements' => Expect::anyOf(Expect::listOf('string'), Expect::string()->castTo('array'))->default([]),
+ 'exclude' => Expect::structure([
+ 'files' => Expect::anyOf(Expect::listOf('string'), Expect::string()->castTo('array'))->default([]),
+ 'classes' => Expect::anyOf(Expect::listOf('string'), Expect::string()->castTo('array'))->default([]),
+ 'extends' => Expect::anyOf(Expect::listOf('string'), Expect::string()->castTo('array'))->default([]),
+ 'implements' => Expect::anyOf(Expect::listOf('string'), Expect::string()->castTo('array'))->default([]),
+ ]),
+ 'tags' => Expect::array(),
+ ]),
+ )->before(fn($val) => is_string($val['in'] ?? null)
+ ? ['default' => $val]
+ : $val);
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ foreach (array_filter($this->config) as $name => $batch) {
+ if (!is_dir($batch->in)) {
+ throw new Nette\DI\InvalidConfigurationException(sprintf(
+ "Option '%s\u{a0}›\u{a0}%s\u{a0}›\u{a0}in' must be valid directory name, '%s' given.",
+ $this->name,
+ $name,
+ $batch->in,
+ ));
+ }
+
+ foreach ($this->findClasses($batch) as $class) {
+ $this->classes[$class] = array_merge($this->classes[$class] ?? [], $batch->tags);
+ }
+ }
+ }
+
+
+ public function findClasses(\stdClass $config): array
+ {
+ $exclude = $config->exclude;
+ $robot = new RobotLoader;
+ $robot->setTempDirectory($this->tempDir);
+ $robot->addDirectory($config->in);
+ $robot->acceptFiles = $config->files ?: ['*.php'];
+ $robot->ignoreDirs = array_merge($robot->ignoreDirs, $exclude->files);
+ $robot->reportParseErrors(false);
+ $robot->refresh();
+ $classes = array_unique(array_keys($robot->getIndexedClasses()));
+
+ $acceptRE = self::buildNameRegexp($config->classes);
+ $rejectRE = self::buildNameRegexp($exclude->classes);
+ $acceptParent = array_merge($config->extends, $config->implements);
+ $rejectParent = array_merge($exclude->extends, $exclude->implements);
+
+ $found = [];
+ foreach ($classes as $class) {
+ if (!class_exists($class) && !interface_exists($class) && !trait_exists($class)) {
+ throw new Nette\InvalidStateException(sprintf(
+ 'Class %s was found, but it cannot be loaded by autoloading.',
+ $class,
+ ));
+ }
+
+ $rc = new \ReflectionClass($class);
+ if (
+ ($rc->isInstantiable()
+ ||
+ ($rc->isInterface()
+ && count($methods = $rc->getMethods()) === 1
+ && in_array($methods[0]->name, ['get', 'create'], true))
+ )
+ && (!$acceptRE || preg_match($acceptRE, $rc->name))
+ && (!$rejectRE || !preg_match($rejectRE, $rc->name))
+ && (!$acceptParent || Arrays::some($acceptParent, fn($nm) => $rc->isSubclassOf($nm)))
+ && (!$rejectParent || Arrays::every($rejectParent, fn($nm) => !$rc->isSubclassOf($nm)))
+ ) {
+ $found[] = $rc->name;
+ }
+ }
+
+ return $found;
+ }
+
+
+ public function beforeCompile(): void
+ {
+ $builder = $this->getContainerBuilder();
+
+ foreach ($this->classes as $class => $foo) {
+ if ($builder->findByType($class)) {
+ unset($this->classes[$class]);
+ }
+ }
+
+ foreach ($this->classes as $class => $tags) {
+ if (class_exists($class)) {
+ $def = $builder->addDefinition(null)->setType($class);
+ } elseif (method_exists($class, 'create')) {
+ $def = $builder->addFactoryDefinition(null)->setImplement($class);
+ } else {
+ $def = $builder->addAccessorDefinition(null)->setImplement($class);
+ }
+ $def->setTags(Arrays::normalize($tags, filling: true));
+ }
+ }
+
+
+ private static function buildNameRegexp(array $masks): ?string
+ {
+ $res = [];
+ foreach ($masks as $mask) {
+ $mask = (str_contains($mask, '\\') ? '' : '**\\') . $mask;
+ $mask = preg_quote($mask, '#');
+ $mask = str_replace('\*\*\\\\', '(.*\\\\)?', $mask);
+ $mask = str_replace('\\\\\*\*', '(\\\\.*)?', $mask);
+ $mask = str_replace('\*', '\w*', $mask);
+ $res[] = $mask;
+ }
+
+ return $res ? '#^(' . implode('|', $res) . ')$#i' : null;
+ }
+}
diff --git a/vendor/nette/di/src/DI/Extensions/ServicesExtension.php b/vendor/nette/di/src/DI/Extensions/ServicesExtension.php
new file mode 100644
index 0000000..075cf54
--- /dev/null
+++ b/vendor/nette/di/src/DI/Extensions/ServicesExtension.php
@@ -0,0 +1,260 @@
+getContainerBuilder()));
+ }
+
+
+ public function loadConfiguration(): void
+ {
+ $this->loadDefinitions($this->config);
+ }
+
+
+ /**
+ * Loads list of service definitions.
+ */
+ public function loadDefinitions(array $config): void
+ {
+ foreach ($config as $key => $defConfig) {
+ $this->loadDefinition($this->convertKeyToName($key), $defConfig);
+ }
+ }
+
+
+ /**
+ * Loads service definition from normalized configuration.
+ */
+ private function loadDefinition(?string $name, \stdClass $config): void
+ {
+ try {
+ if ((array) $config === [false]) {
+ $this->getContainerBuilder()->removeDefinition($name);
+ return;
+ } elseif (!empty($config->alteration) && !$this->getContainerBuilder()->hasDefinition($name)) {
+ throw new Nette\DI\InvalidConfigurationException('missing original definition for alteration.');
+ }
+
+ $def = $this->retrieveDefinition($name, $config);
+
+ $methods = [
+ Definitions\ServiceDefinition::class => 'updateServiceDefinition',
+ Definitions\AccessorDefinition::class => 'updateAccessorDefinition',
+ Definitions\FactoryDefinition::class => 'updateFactoryDefinition',
+ Definitions\LocatorDefinition::class => 'updateLocatorDefinition',
+ Definitions\ImportedDefinition::class => 'updateImportedDefinition',
+ ];
+ $this->{$methods[$config->defType]}($def, $config);
+ $this->updateDefinition($def, $config);
+ } catch (\Throwable $e) {
+ throw new Nette\DI\InvalidConfigurationException(($name ? "Service '$name': " : '') . $e->getMessage(), 0, $e);
+ }
+ }
+
+
+ /**
+ * Updates service definition according to normalized configuration.
+ */
+ private function updateServiceDefinition(Definitions\ServiceDefinition $definition, \stdClass $config): void
+ {
+ if ($config->create) {
+ $definition->setCreator(Helpers::filterArguments([$config->create])[0]);
+ $definition->setType(null);
+ }
+
+ if ($config->type) {
+ $definition->setType($config->type);
+ }
+
+ if ($config->arguments) {
+ $arguments = Helpers::filterArguments($config->arguments);
+ if (empty($config->reset['arguments']) && !Nette\Utils\Arrays::isList($arguments)) {
+ $arguments = array_replace($definition->getCreator()->arguments, $arguments);
+ }
+
+ $definition->setArguments($arguments);
+ }
+
+ if (isset($config->setup)) {
+ if (!empty($config->reset['setup'])) {
+ $definition->setSetup([]);
+ }
+
+ foreach (Helpers::filterArguments($config->setup) as $setup) {
+ if (is_array($setup)) {
+ $setup = new Statement(key($setup), array_values($setup));
+ }
+
+ $definition->addSetup($setup);
+ }
+ }
+
+ if (isset($config->inject)) {
+ $definition->addTag(InjectExtension::TagInject, $config->inject);
+ }
+
+ if (isset($config->lazy)) {
+ $definition->lazy = $config->lazy;
+ }
+ }
+
+
+ private function updateAccessorDefinition(Definitions\AccessorDefinition $definition, \stdClass $config): void
+ {
+ if (isset($config->implement)) {
+ $definition->setImplement($config->implement);
+ }
+
+ if ($ref = $config->create ?? $config->type ?? null) {
+ $definition->setReference($ref);
+ }
+ }
+
+
+ private function updateFactoryDefinition(Definitions\FactoryDefinition $definition, \stdClass $config): void
+ {
+ $resultDef = $definition->getResultDefinition();
+
+ if (isset($config->implement)) {
+ $definition->setImplement($config->implement);
+ $definition->setAutowired();
+ }
+
+ if ($config->create) {
+ $resultDef->setCreator(Helpers::filterArguments([$config->create])[0]);
+ }
+
+ if ($config->type) {
+ $resultDef->setCreator($config->type);
+ }
+
+ if ($config->arguments) {
+ $arguments = Helpers::filterArguments($config->arguments);
+ if (empty($config->reset['arguments']) && !Nette\Utils\Arrays::isList($arguments)) {
+ $arguments = array_replace($resultDef->getCreator()->arguments, $arguments);
+ }
+
+ $resultDef->setArguments($arguments);
+ }
+
+ if (isset($config->setup)) {
+ if (!empty($config->reset['setup'])) {
+ $resultDef->setSetup([]);
+ }
+
+ foreach (Helpers::filterArguments($config->setup) as $setup) {
+ if (is_array($setup)) {
+ $setup = new Statement(key($setup), array_values($setup));
+ }
+
+ $resultDef->addSetup($setup);
+ }
+ }
+
+ if (isset($config->inject)) {
+ $definition->addTag(InjectExtension::TagInject, $config->inject);
+ }
+ }
+
+
+ private function updateLocatorDefinition(Definitions\LocatorDefinition $definition, \stdClass $config): void
+ {
+ if (isset($config->implement)) {
+ $definition->setImplement($config->implement);
+ }
+
+ if (isset($config->references)) {
+ foreach ($config->references as $name => $reference) {
+ if ($reference instanceof Statement) {
+ $config->references[$name] = '@' . $this->getContainerBuilder()
+ ->addDefinition(null)
+ ->setFactory($reference)
+ ->setAutowired(false)
+ ->getName();
+ }
+ }
+
+ $definition->setReferences($config->references);
+ }
+
+ if (isset($config->tagged)) {
+ $definition->setTagged($config->tagged);
+ }
+ }
+
+
+ private function updateImportedDefinition(Definitions\ImportedDefinition $definition, \stdClass $config): void
+ {
+ if ($config->type) {
+ $definition->setType($config->type);
+ }
+ }
+
+
+ private function updateDefinition(Definitions\Definition $definition, \stdClass $config): void
+ {
+ if (isset($config->autowired)) {
+ $definition->setAutowired($config->autowired);
+ }
+
+ if (isset($config->tags)) {
+ if (!empty($config->reset['tags'])) {
+ $definition->setTags([]);
+ }
+
+ foreach ($config->tags as $tag => $attrs) {
+ if (is_int($tag) && is_string($attrs)) {
+ $definition->addTag($attrs);
+ } else {
+ $definition->addTag($tag, $attrs);
+ }
+ }
+ }
+ }
+
+
+ private function convertKeyToName($key): ?string
+ {
+ if (is_int($key)) {
+ return null;
+ } elseif (preg_match('#^@[\w\\\\]+$#D', $key)) {
+ return $this->getContainerBuilder()->getByType(substr($key, 1), throw: true);
+ }
+
+ return $key;
+ }
+
+
+ private function retrieveDefinition(?string $name, \stdClass $config): Definitions\Definition
+ {
+ $builder = $this->getContainerBuilder();
+ if (!empty($config->reset['all'])) {
+ $builder->removeDefinition($name);
+ }
+
+ return $name && $builder->hasDefinition($name)
+ ? $builder->getDefinition($name)
+ : $builder->addDefinition($name, new $config->defType);
+ }
+}
diff --git a/vendor/nette/di/src/DI/Helpers.php b/vendor/nette/di/src/DI/Helpers.php
new file mode 100644
index 0000000..610239b
--- /dev/null
+++ b/vendor/nette/di/src/DI/Helpers.php
@@ -0,0 +1,285 @@
+ $val) {
+ $res[self::expand($key, $params, $recursive)] = self::expand($val, $params, $recursive);
+ }
+ return $res;
+
+ } elseif ($var instanceof Statement) {
+ return new Statement(
+ self::expand($var->getEntity(), $params, $recursive),
+ self::expand($var->arguments, $params, $recursive),
+ );
+
+ } elseif ($var === '%parameters%' && !array_key_exists('parameters', $params)) {
+ trigger_error('%parameters% is deprecated, use @container::getParameters()', E_USER_DEPRECATED);
+ return $recursive
+ ? self::expand($params, $params, $recursive)
+ : $params;
+
+ } elseif (is_string($var)) {
+ $recursive = is_array($recursive) ? $recursive : ($recursive ? [] : null);
+ return self::expandString($var, $params, $recursive);
+
+ } else {
+ return $var;
+ }
+ }
+
+
+ /**
+ * Expands %placeholders% in string
+ * @throws Nette\InvalidArgumentException
+ */
+ private static function expandString(
+ string $string,
+ array $params,
+ ?array $recursive,
+ bool $onlyString = false,
+ ): mixed
+ {
+ $parts = preg_split('#%([\w.-]*)%#i', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
+ $res = [];
+ $dynamic = false;
+ foreach ($parts as $n => $part) {
+ if ($n % 2 === 0) {
+ $res[] = $part;
+ } elseif ($part === '') {
+ $res[] = '%';
+ } else {
+ $res[] = $val = self::expandParameter($part, $params, $recursive, $onlyString);
+ if (strlen($part) + 2 === strlen($string)) {
+ return $val;
+ } elseif ($val instanceof DynamicParameter || $val instanceof Statement) {
+ $dynamic = true;
+ } elseif (!is_scalar($val)) {
+ throw new Nette\InvalidArgumentException(sprintf("Unable to concatenate non-scalar parameter '%s' into '%s'.", $part, $string));
+ }
+ }
+ }
+
+ return $dynamic
+ ? new Statement('::implode', [$res])
+ : implode('', $res);
+ }
+
+
+ private static function expandParameter(
+ string $parameter,
+ array $params,
+ ?array $recursive,
+ bool $onlyString,
+ ): mixed
+ {
+ $val = $params;
+ $path = [];
+ $keys = explode('.', $parameter);
+ while (($key = $path[] = array_shift($keys)) !== null) {
+ if (is_array($val) && array_key_exists($key, $val)) {
+ $val = $val[$key];
+ $fullExpand = !$onlyString && !$keys; // last
+ if (is_array($recursive) && ($fullExpand || is_string($val))) {
+ $pathStr = implode('.', $path);
+ if (isset($recursive[$pathStr])) {
+ throw new Nette\InvalidArgumentException('Circular reference detected for parameters: %' . implode('%, %', array_keys($recursive)) . '%');
+ }
+ $val = $fullExpand
+ ? self::expand($val, $params, $recursive + [$pathStr => 1])
+ : self::expandString($val, $params, $recursive + [$pathStr => 1], true);
+ }
+ } elseif ($val instanceof DynamicParameter) {
+ $val = new DynamicParameter($val . '[' . var_export($key, true) . ']');
+ } elseif ($val instanceof Statement) {
+ $val = new Statement('(?)[?]', [$val, $key]);
+ } else {
+ throw new Nette\InvalidArgumentException(sprintf("Missing parameter '%s'.", $parameter));
+ }
+ }
+ return $val;
+ }
+
+
+ /**
+ * Escapes '%' and '@'
+ */
+ public static function escape(mixed $value): mixed
+ {
+ if (is_array($value)) {
+ $res = [];
+ foreach ($value as $key => $val) {
+ $key = is_string($key) ? str_replace('%', '%%', $key) : $key;
+ $res[$key] = self::escape($val);
+ }
+
+ return $res;
+ } elseif (is_string($value)) {
+ return preg_replace('#^@|%#', '$0$0', $value);
+ }
+
+ return $value;
+ }
+
+
+ /**
+ * Process constants recursively.
+ */
+ public static function filterArguments(array $args): array
+ {
+ foreach ($args as $k => $v) {
+ if (is_string($v) && preg_match('#^@[\w\\\\]+$#D', $v)) {
+ $args[$k] = new Reference(substr($v, 1));
+ } elseif (is_array($v)) {
+ $args[$k] = self::filterArguments($v);
+ } elseif ($v instanceof Statement) {
+ [$tmp] = self::filterArguments([$v->getEntity()]);
+ $args[$k] = new Statement($tmp, self::filterArguments($v->arguments));
+ }
+ }
+
+ return $args;
+ }
+
+
+ /**
+ * Replaces @extension with real extension name in service definition.
+ */
+ public static function prefixServiceName(mixed $config, string $namespace): mixed
+ {
+ if (is_string($config)) {
+ if (strncmp($config, '@extension.', 10) === 0) {
+ $config = '@' . $namespace . '.' . substr($config, 11);
+ }
+ } elseif ($config instanceof Reference) {
+ if (strncmp($config->getValue(), 'extension.', 9) === 0) {
+ $config = new Reference($namespace . '.' . substr($config->getValue(), 10));
+ }
+ } elseif ($config instanceof Statement) {
+ return new Statement(
+ self::prefixServiceName($config->getEntity(), $namespace),
+ self::prefixServiceName($config->arguments, $namespace),
+ );
+ } elseif (is_array($config)) {
+ foreach ($config as &$val) {
+ $val = self::prefixServiceName($val, $namespace);
+ }
+ }
+
+ return $config;
+ }
+
+
+ /**
+ * Returns an annotation value.
+ */
+ public static function parseAnnotation(\Reflector $ref, string $name): ?string
+ {
+ if (!Reflection::areCommentsAvailable()) {
+ throw new Nette\InvalidStateException('You have to enable phpDoc comments in opcode cache.');
+ }
+
+ $re = '#[\s*]@' . preg_quote($name, '#') . '(?=\s|$)(?:[ \t]+([^@\s]\S*))?#';
+ if ($ref->getDocComment() && preg_match($re, trim($ref->getDocComment(), '/*'), $m)) {
+ return $m[1] ?? '';
+ }
+
+ return null;
+ }
+
+
+ public static function getReturnTypeAnnotation(\ReflectionFunctionAbstract $func): ?Type
+ {
+ $type = preg_replace('#[|\s].*#', '', (string) self::parseAnnotation($func, 'return'));
+ if (!$type || $type === 'object' || $type === 'mixed') {
+ return null;
+ } elseif ($func instanceof \ReflectionMethod) {
+ $type = $type === '$this' ? 'static' : $type;
+ $type = Reflection::expandClassName($type, $func->getDeclaringClass());
+ }
+
+ return Type::fromString($type);
+ }
+
+
+ public static function ensureClassType(?Type $type, string $hint, bool $allowNullable = false): string
+ {
+ if (!$type) {
+ throw new ServiceCreationException(sprintf('%s is not declared.', ucfirst($hint)));
+ } elseif (!$type->isClass() || (!$allowNullable && $type->allows('null'))) {
+ throw new ServiceCreationException(sprintf("%s is expected to not be %sbuilt-in/complex, '%s' given.", ucfirst($hint), $allowNullable ? '' : 'nullable/', $type));
+ }
+
+ $class = $type->getSingleName();
+ if (!class_exists($class) && !interface_exists($class)) {
+ throw new ServiceCreationException(sprintf("Class '%s' not found.\nCheck the %s.", $class, $hint));
+ }
+
+ return $class;
+ }
+
+
+ public static function normalizeClass(string $type): string
+ {
+ return class_exists($type) || interface_exists($type)
+ ? (new \ReflectionClass($type))->name
+ : $type;
+ }
+
+
+ /**
+ * Non data-loss type conversion.
+ * @throws Nette\InvalidStateException
+ */
+ public static function convertType(mixed $value, string $type): mixed
+ {
+ if (is_scalar($value)) {
+ $norm = ($value === false ? '0' : (string) $value);
+ if ($type === 'float') {
+ $norm = preg_replace('#\.0*$#D', '', $norm);
+ }
+
+ $orig = $norm;
+ settype($norm, $type);
+ if ($orig === ($norm === false ? '0' : (string) $norm)) {
+ return $norm;
+ }
+ }
+
+ throw new Nette\InvalidStateException(sprintf(
+ 'Cannot convert %s to %s.',
+ is_scalar($value) ? "'$value'" : get_debug_type($value),
+ $type,
+ ));
+ }
+}
diff --git a/vendor/nette/di/src/DI/PhpGenerator.php b/vendor/nette/di/src/DI/PhpGenerator.php
new file mode 100644
index 0000000..b5176c4
--- /dev/null
+++ b/vendor/nette/di/src/DI/PhpGenerator.php
@@ -0,0 +1,202 @@
+builder = $builder;
+ }
+
+
+ /**
+ * Generates PHP classes. First class is the container.
+ */
+ public function generate(string $className): Php\ClassType
+ {
+ $this->className = $className;
+ $class = new Php\ClassType($this->className);
+ $class->setExtends(Container::class);
+ $manipulator = new Php\ClassManipulator($class);
+ $manipulator->inheritMethod('__construct')
+ ->addBody('parent::__construct($params);');
+
+ foreach ($this->builder->exportMeta() as $key => $value) {
+ $manipulator->inheritProperty($key)
+ ->setComment(null)
+ ->setValue($value);
+ }
+
+ $definitions = $this->builder->getDefinitions();
+ ksort($definitions);
+
+ foreach ($definitions as $def) {
+ $class->addMember($this->generateMethod($def));
+ }
+
+ $class->getMethod(Container::getMethodName(ContainerBuilder::ThisContainer))
+ ->setBody('return $this;');
+
+ $manipulator->inheritMethod('initialize');
+
+ return $class;
+ }
+
+
+ public function toString(Php\ClassType $class): string
+ {
+ return <<<'XX'
+ /** @noinspection PhpParamsInspection,PhpMethodMayBeStaticInspection */
+
+ declare(strict_types=1);
+
+
+ XX . $class->__toString();
+ }
+
+
+ public function addInitialization(Php\ClassType $class, CompilerExtension $extension): void
+ {
+ $closure = $extension->getInitialization();
+ if ($closure->getBody()) {
+ $class->getMethod('initialize')
+ ->addBody('// ' . $extension->prefix(''))
+ ->addBody("($closure)();");
+ }
+ }
+
+
+ public function generateMethod(Definitions\Definition $def): Php\Method
+ {
+ $name = $def->getName();
+ try {
+ $method = new Php\Method(Container::getMethodName($name));
+ $method->setPublic();
+ $method->setReturnType($def->getType());
+ $def->generateMethod($method, $this);
+ return $method;
+
+ } catch (\Throwable $e) {
+ throw new ServiceCreationException("Service '$name': " . $e->getMessage(), 0, $e);
+ }
+ }
+
+
+ /**
+ * Formats PHP code for class instantiating, function calling or property setting in PHP.
+ */
+ public function formatStatement(Statement $statement): string
+ {
+ $entity = $statement->getEntity();
+ $arguments = $statement->arguments;
+
+ switch (true) {
+ case is_string($entity) && str_contains($entity, '?'): // PHP literal
+ return $this->formatPhp($entity, $arguments);
+
+ case is_string($entity): // create class
+ return $arguments
+ ? $this->formatPhp("new $entity(...?:)", [$arguments])
+ : $this->formatPhp("new $entity", []);
+
+ case is_array($entity):
+ switch (true) {
+ case $entity[1][0] === '$': // property getter, setter or appender
+ $name = substr($entity[1], 1);
+ if ($append = (str_ends_with($name, '[]'))) {
+ $name = substr($name, 0, -2);
+ }
+
+ $prop = $entity[0] instanceof Reference
+ ? $this->formatPhp('?->?', [$entity[0], $name])
+ : $this->formatPhp('?::$?', [$entity[0], $name]);
+ return $arguments
+ ? $this->formatPhp(($append ? '?[]' : '?') . ' = ?', [new Php\Literal($prop), $arguments[0]])
+ : $prop;
+
+ case $entity[0] instanceof Statement:
+ $inner = $this->formatPhp('?', [$entity[0]]);
+ if (str_starts_with($inner, 'new ')) {
+ $inner = "($inner)";
+ }
+
+ return $this->formatPhp('?->?(...?:)', [new Php\Literal($inner), $entity[1], $arguments]);
+
+ case $entity[0] instanceof Reference:
+ return $this->formatPhp('?->?(...?:)', [$entity[0], $entity[1], $arguments]);
+
+ case $entity[0] === '': // function call
+ return $this->formatPhp('?(...?:)', [new Php\Literal($entity[1]), $arguments]);
+
+ case is_string($entity[0]): // static method call
+ return $this->formatPhp('?::?(...?:)', [new Php\Literal($entity[0]), $entity[1], $arguments]);
+ }
+ }
+
+ throw new Nette\InvalidStateException;
+ }
+
+
+ /**
+ * Formats PHP statement.
+ * @internal
+ */
+ public function formatPhp(string $statement, array $args): string
+ {
+ return (new Php\Dumper)->format($statement, ...$this->convertArguments($args));
+ }
+
+
+ public function convertArguments(array $args): array
+ {
+ array_walk_recursive($args, function (&$val): void {
+ if ($val instanceof Statement) {
+ $val = new Php\Literal($this->formatStatement($val));
+
+ } elseif ($val instanceof Reference) {
+ $name = $val->getValue();
+ if ($val->isSelf()) {
+ $val = new Php\Literal('$service');
+ } elseif ($name === ContainerBuilder::ThisContainer) {
+ $val = new Php\Literal('$this');
+ } else {
+ $val = ContainerBuilder::literal('$this->getService(?)', [$name]);
+ }
+ } elseif (
+ is_object($val)
+ && !$val instanceof Php\Literal && !$val instanceof \DateTimeInterface
+ && (new \ReflectionObject($val))->getProperties(\ReflectionProperty::IS_PRIVATE | \ReflectionProperty::IS_PROTECTED)
+ ) {
+ trigger_error(sprintf('Nette DI: suspicious dumping of objects %s when generating the container', $val::class));
+ }
+ });
+ return $args;
+ }
+
+
+ public function getClassName(): ?string
+ {
+ return $this->className;
+ }
+}
diff --git a/vendor/nette/di/src/DI/Resolver.php b/vendor/nette/di/src/DI/Resolver.php
new file mode 100644
index 0000000..a1e5944
--- /dev/null
+++ b/vendor/nette/di/src/DI/Resolver.php
@@ -0,0 +1,663 @@
+builder = $builder;
+ $this->recursive = new \SplObjectStorage;
+ }
+
+
+ public function getContainerBuilder(): ContainerBuilder
+ {
+ return $this->builder;
+ }
+
+
+ public function resolveDefinition(Definition $def): void
+ {
+ if ($this->recursive->contains($def)) {
+ $names = array_map(fn($item) => $item->getName(), iterator_to_array($this->recursive));
+ throw new ServiceCreationException(sprintf('Circular reference detected for services: %s.', implode(', ', $names)));
+ }
+
+ try {
+ $this->recursive->attach($def);
+
+ $def->resolveType($this);
+
+ if (!$def->getType()) {
+ throw new ServiceCreationException('Type of service is unknown.');
+ }
+ } catch (\Throwable $e) {
+ throw $this->completeException($e, $def);
+
+ } finally {
+ $this->recursive->detach($def);
+ }
+ }
+
+
+ public function resolveReferenceType(Reference $ref): ?string
+ {
+ if ($ref->isSelf()) {
+ return $this->currentServiceType;
+ } elseif ($ref->isType()) {
+ return ltrim($ref->getValue(), '\\');
+ }
+
+ $def = $this->resolveReference($ref);
+ if (!$def->getType()) {
+ $this->resolveDefinition($def);
+ }
+
+ return $def->getType();
+ }
+
+
+ public function resolveEntityType(Statement $statement): ?string
+ {
+ $entity = $this->normalizeEntity($statement);
+
+ if ($statement->arguments === self::getFirstClassCallable()) {
+ return \Closure::class;
+
+ } elseif (is_array($entity)) {
+ if ($entity[0] instanceof Reference || $entity[0] instanceof Statement) {
+ $entity[0] = $this->resolveEntityType($entity[0] instanceof Statement ? $entity[0] : new Statement($entity[0]));
+ if (!$entity[0]) {
+ return null;
+ }
+ }
+
+ try {
+ $reflection = Callback::toReflection($entity[0] === '' ? $entity[1] : $entity);
+ assert($reflection instanceof \ReflectionMethod || $reflection instanceof \ReflectionFunction);
+ $refClass = $reflection instanceof \ReflectionMethod
+ ? $reflection->getDeclaringClass()
+ : null;
+ } catch (\ReflectionException $e) {
+ $refClass = $reflection = null;
+ }
+
+ if (isset($e) || ($refClass && (!$reflection->isPublic()
+ || ($refClass->isTrait() && !$reflection->isStatic())
+ ))) {
+ throw new ServiceCreationException(sprintf('Method %s() is not callable.', Callback::toString($entity)), 0, $e ?? null);
+ }
+
+ $this->addDependency($reflection);
+
+ $type = Nette\Utils\Type::fromReflection($reflection) ?? ($annotation = Helpers::getReturnTypeAnnotation($reflection));
+ if ($type && !in_array($type->getSingleName(), ['object', 'mixed'], strict: true)) {
+ if (isset($annotation)) {
+ trigger_error('Annotation @return should be replaced with native return type at ' . Callback::toString($entity), E_USER_DEPRECATED);
+ }
+
+ return Helpers::ensureClassType(
+ $type,
+ sprintf('return type of %s()', Callback::toString($entity)),
+ allowNullable: true,
+ );
+ }
+
+ return null;
+
+ } elseif ($entity instanceof Reference) { // alias or factory
+ return $this->resolveReferenceType($entity);
+
+ } elseif (is_string($entity)) { // class
+ if (!class_exists($entity)) {
+ throw new ServiceCreationException(sprintf(
+ interface_exists($entity)
+ ? "Interface %s can not be used as 'create' or 'factory', did you mean 'implement'?"
+ : "Class '%s' not found.",
+ $entity,
+ ));
+ }
+
+ return $entity;
+ }
+
+ return null;
+ }
+
+
+ public function completeDefinition(Definition $def): void
+ {
+ $this->currentService = in_array($def, $this->builder->getDefinitions(), strict: true)
+ ? $def
+ : null;
+ $this->currentServiceType = $def->getType();
+ $this->currentServiceAllowed = false;
+
+ try {
+ $def->complete($this);
+
+ $this->addDependency(new \ReflectionClass($def->getType()));
+
+ } catch (\Throwable $e) {
+ throw $this->completeException($e, $def);
+
+ } finally {
+ $this->currentService = $this->currentServiceType = null;
+ }
+ }
+
+
+ public function completeStatement(Statement $statement, bool $currentServiceAllowed = false): Statement
+ {
+ $this->currentServiceAllowed = $currentServiceAllowed;
+ $entity = $this->normalizeEntity($statement);
+ $arguments = $this->convertReferences($statement->arguments);
+ $getter = fn(string $type, bool $single) => $single
+ ? $this->getByType($type)
+ : array_values(array_filter($this->builder->findAutowired($type), fn($obj) => $obj !== $this->currentService));
+
+ switch (true) {
+ case $statement->arguments === self::getFirstClassCallable():
+ if (!is_array($entity) || !PhpHelpers::isIdentifier($entity[1])) {
+ throw new ServiceCreationException(sprintf('Cannot create closure for %s(...)', $entity));
+ }
+ if ($entity[0] instanceof Statement) {
+ $entity[0] = $this->completeStatement($entity[0], $this->currentServiceAllowed);
+ }
+ break;
+
+ case is_string($entity) && str_contains($entity, '?'): // PHP literal
+ break;
+
+ case $entity === 'not':
+ if (count($arguments) !== 1) {
+ throw new ServiceCreationException(sprintf('Function %s() expects 1 parameter, %s given.', $entity, count($arguments)));
+ }
+
+ $entity = ['', '!'];
+ break;
+
+ case $entity === 'bool':
+ case $entity === 'int':
+ case $entity === 'float':
+ case $entity === 'string':
+ if (count($arguments) !== 1) {
+ throw new ServiceCreationException(sprintf('Function %s() expects 1 parameter, %s given.', $entity, count($arguments)));
+ }
+
+ $arguments = [$arguments[0], $entity];
+ $entity = [Helpers::class, 'convertType'];
+ break;
+
+ case is_string($entity): // create class
+ if (!class_exists($entity)) {
+ throw new ServiceCreationException(sprintf("Class '%s' not found.", $entity));
+ } elseif ((new \ReflectionClass($entity))->isAbstract()) {
+ throw new ServiceCreationException(sprintf('Class %s is abstract.', $entity));
+ } elseif (($rm = (new \ReflectionClass($entity))->getConstructor()) !== null && !$rm->isPublic()) {
+ throw new ServiceCreationException(sprintf('Class %s has %s constructor.', $entity, $rm->isProtected() ? 'protected' : 'private'));
+ } elseif ($constructor = (new \ReflectionClass($entity))->getConstructor()) {
+ $arguments = self::autowireArguments($constructor, $arguments, $getter);
+ $this->addDependency($constructor);
+ } elseif ($arguments) {
+ throw new ServiceCreationException(sprintf(
+ 'Unable to pass arguments, class %s has no constructor.',
+ $entity,
+ ));
+ }
+
+ break;
+
+ case $entity instanceof Reference:
+ if ($arguments) {
+ $e = $this->completeException(new ServiceCreationException(sprintf('Parameters were passed to reference @%s, although references cannot have any parameters.', $entity->getValue())), $this->currentService);
+ trigger_error($e->getMessage(), E_USER_DEPRECATED);
+ }
+ $entity = [new Reference(ContainerBuilder::ThisContainer), Container::getMethodName($entity->getValue())];
+ break;
+
+ case is_array($entity):
+ if (!preg_match('#^\$?(\\\\?' . PhpHelpers::ReIdentifier . ')+(\[\])?$#D', $entity[1])) {
+ throw new ServiceCreationException(sprintf(
+ "Expected function, method or property name, '%s' given.",
+ $entity[1],
+ ));
+ }
+
+ switch (true) {
+ case $entity[0] === '': // function call
+ if (!function_exists($entity[1])) {
+ throw new ServiceCreationException(sprintf("Function %s doesn't exist.", $entity[1]));
+ }
+
+ $rf = new \ReflectionFunction($entity[1]);
+ $arguments = self::autowireArguments($rf, $arguments, $getter);
+ $this->addDependency($rf);
+ break;
+
+ case $entity[0] instanceof Statement:
+ $entity[0] = $this->completeStatement($entity[0], $this->currentServiceAllowed);
+ // break omitted
+
+ case is_string($entity[0]): // static method call
+ case $entity[0] instanceof Reference:
+ if ($entity[1][0] === '$') { // property getter, setter or appender
+ Validators::assert($arguments, 'list:0..1', "setup arguments for '" . Callback::toString($entity) . "'");
+ if (!$arguments && str_ends_with($entity[1], '[]')) {
+ throw new ServiceCreationException(sprintf('Missing argument for %s.', $entity[1]));
+ }
+ } elseif (
+ $type = $entity[0] instanceof Reference
+ ? $this->resolveReferenceType($entity[0])
+ : $this->resolveEntityType($entity[0] instanceof Statement ? $entity[0] : new Statement($entity[0]))
+ ) {
+ $rc = new \ReflectionClass($type);
+ if ($rc->hasMethod($entity[1])) {
+ $rm = $rc->getMethod($entity[1]);
+ if (!$rm->isPublic()) {
+ throw new ServiceCreationException(sprintf('%s::%s() is not callable.', $type, $entity[1]));
+ }
+
+ $arguments = self::autowireArguments($rm, $arguments, $getter);
+ $this->addDependency($rm);
+ }
+ }
+ }
+ }
+
+ try {
+ $arguments = $this->completeArguments($arguments);
+ } catch (ServiceCreationException $e) {
+ if (!str_contains($e->getMessage(), ' (used in')) {
+ $e->setMessage($e->getMessage() . " (used in {$this->entityToString($entity)})");
+ }
+
+ throw $e;
+ }
+
+ return new Statement($entity, $arguments);
+ }
+
+
+ public function completeArguments(array $arguments): array
+ {
+ array_walk_recursive($arguments, function (&$val): void {
+ if ($val instanceof Statement) {
+ $entity = $val->getEntity();
+ if ($entity === 'typed' || $entity === 'tagged') {
+ $services = [];
+ $current = $this->currentService?->getName();
+ foreach ($val->arguments as $argument) {
+ foreach ($entity === 'tagged' ? $this->builder->findByTag($argument) : $this->builder->findAutowired($argument) as $name => $foo) {
+ if ($name !== $current) {
+ $services[] = new Reference($name);
+ }
+ }
+ }
+
+ $val = $this->completeArguments($services);
+ } else {
+ $val = $this->completeStatement($val, $this->currentServiceAllowed);
+ }
+ } elseif ($val instanceof Definition || $val instanceof Reference) {
+ $val = $this->normalizeEntity(new Statement($val));
+ }
+ });
+ return $arguments;
+ }
+
+
+ /** Returns literal, Class, Reference, [Class, member], [, globalFunc], [Reference, member], [Statement, member] */
+ private function normalizeEntity(Statement $statement): string|array|Reference|null
+ {
+ $entity = $statement->getEntity();
+ if (is_array($entity)) {
+ $item = &$entity[0];
+ } else {
+ $item = &$entity;
+ }
+
+ if ($item instanceof Definition) {
+ if ($this->builder->getDefinition($item->getName()) !== $item) {
+ throw new ServiceCreationException(sprintf("Service '%s' does not match the expected service.", $item->getName()));
+
+ }
+ $item = new Reference($item->getName());
+ }
+
+ if ($item instanceof Reference) {
+ $item = $this->normalizeReference($item);
+ }
+
+ return $entity;
+ }
+
+
+ /**
+ * Normalizes reference to 'self' or named reference (or leaves it typed if it is not possible during resolving) and checks existence of service.
+ */
+ public function normalizeReference(Reference $ref): Reference
+ {
+ $service = $ref->getValue();
+ if ($ref->isSelf()) {
+ return $ref;
+ } elseif ($ref->isName()) {
+ if (!$this->builder->hasDefinition($service)) {
+ throw new ServiceCreationException(sprintf("Reference to missing service '%s'.", $service));
+ }
+
+ return $this->currentService && $service === $this->currentService->getName()
+ ? new Reference(Reference::Self)
+ : $ref;
+ }
+
+ try {
+ return $this->getByType($service);
+ } catch (NotAllowedDuringResolvingException) {
+ return new Reference($service);
+ }
+ }
+
+
+ public function resolveReference(Reference $ref): Definition
+ {
+ return $ref->isSelf()
+ ? $this->currentService
+ : $this->builder->getDefinition($ref->getValue());
+ }
+
+
+ /**
+ * Returns named reference to service resolved by type (or 'self' reference for local-autowiring).
+ * @throws ServiceCreationException when multiple found
+ * @throws MissingServiceException when not found
+ */
+ public function getByType(string $type): Reference
+ {
+ if (
+ $this->currentService
+ && $this->currentServiceAllowed
+ && is_a($this->currentServiceType, $type, allow_string: true)
+ ) {
+ return new Reference(Reference::Self);
+ }
+
+ $name = $this->builder->getByType($type, throw: true);
+ if (
+ !$this->currentServiceAllowed
+ && $this->currentService === $this->builder->getDefinition($name)
+ ) {
+ throw new MissingServiceException;
+ }
+
+ return new Reference($name);
+ }
+
+
+ /**
+ * Adds item to the list of dependencies.
+ */
+ public function addDependency(\ReflectionClass|\ReflectionFunctionAbstract|string $dep): static
+ {
+ $this->builder->addDependency($dep);
+ return $this;
+ }
+
+
+ private function completeException(\Throwable $e, Definition $def): ServiceCreationException
+ {
+ if ($e instanceof ServiceCreationException && str_starts_with($e->getMessage(), "Service '")) {
+ return $e;
+ }
+
+ $name = $def->getName();
+ $type = $def->getType();
+ if ($name && !ctype_digit($name)) {
+ $message = "Service '$name'" . ($type ? " (type of $type)" : '') . ': ';
+ } elseif ($type) {
+ $message = "Service of type $type: ";
+ } elseif ($def instanceof Definitions\ServiceDefinition && $def->getEntity()) {
+ $message = 'Service (' . $this->entityToString($def->getEntity()) . '): ';
+ } else {
+ $message = '';
+ }
+
+ $message .= $type
+ ? str_replace("$type::", preg_replace('~.*\\\\~', '', $type) . '::', $e->getMessage())
+ : $e->getMessage();
+
+ return $e instanceof ServiceCreationException
+ ? $e->setMessage($message)
+ : new ServiceCreationException($message, 0, $e);
+ }
+
+
+ private function entityToString($entity): string
+ {
+ $referenceToText = fn(Reference $ref): string => $ref->isSelf() && $this->currentService
+ ? '@' . $this->currentService->getName()
+ : '@' . $ref->getValue();
+ if (is_string($entity)) {
+ return $entity . '::__construct()';
+ } elseif ($entity instanceof Reference) {
+ $entity = $referenceToText($entity);
+ } elseif (is_array($entity)) {
+ if (!str_contains($entity[1], '$')) {
+ $entity[1] .= '()';
+ }
+
+ if ($entity[0] instanceof Reference) {
+ $entity[0] = $referenceToText($entity[0]);
+ } elseif (!is_string($entity[0])) {
+ return $entity[1];
+ }
+
+ return implode('::', $entity);
+ }
+
+ return (string) $entity;
+ }
+
+
+ private function convertReferences(array $arguments): array
+ {
+ array_walk_recursive($arguments, function (&$val): void {
+ if (is_string($val) && strlen($val) > 1 && $val[0] === '@' && $val[1] !== '@') {
+ $pair = explode('::', substr($val, 1), 2);
+ if (!isset($pair[1])) { // @service
+ $val = new Reference($pair[0]);
+ } elseif (preg_match('#^[A-Z][a-zA-Z0-9_]*$#D', $pair[1])) { // @service::CONSTANT
+ $val = ContainerBuilder::literal($this->resolveReferenceType(new Reference($pair[0])) . '::' . $pair[1]);
+ } else { // @service::property
+ $val = new Statement([new Reference($pair[0]), '$' . $pair[1]]);
+ }
+ } elseif (is_string($val) && str_starts_with($val, '@@')) { // escaped text @@
+ $val = substr($val, 1);
+ }
+ });
+ return $arguments;
+ }
+
+
+ /**
+ * Add missing arguments using autowiring.
+ * @param (callable(string, bool): (object|object[]|null)) $getter
+ * @throws ServiceCreationException
+ */
+ public static function autowireArguments(
+ \ReflectionFunctionAbstract $method,
+ array $arguments,
+ callable $getter,
+ ): array
+ {
+ $useName = false;
+ $num = -1;
+ $res = [];
+
+ foreach ($method->getParameters() as $num => $param) {
+ $paramName = $param->name;
+
+ if ($param->isVariadic()) {
+ if ($useName && Arrays::some($arguments, fn($val, $key) => is_int($key))) {
+ throw new ServiceCreationException(sprintf(
+ 'Cannot use positional argument after named or omitted argument in %s.',
+ Reflection::toString($param),
+ ));
+
+ } elseif (array_key_exists($paramName, $arguments)) {
+ if (!is_array($arguments[$paramName])) {
+ throw new ServiceCreationException(sprintf(
+ 'Parameter %s must be array, %s given.',
+ Reflection::toString($param),
+ gettype($arguments[$paramName]),
+ ));
+ }
+
+ $res = array_merge($res, $arguments[$paramName]);
+ unset($arguments[$paramName]);
+
+ } else {
+ $res = array_merge($res, $arguments);
+ $arguments = [];
+ }
+
+ } elseif (array_key_exists($key = $paramName, $arguments) || array_key_exists($key = $num, $arguments)) {
+ $val = $arguments[$key];
+ $res[$useName ? $paramName : $num] = is_scalar($val) && $param->getAttributes(\SensitiveParameter::class)
+ ? ContainerBuilder::literal('/*sensitive{*/?/*}*/', [$val])
+ : $val;
+ unset($arguments[$key], $arguments[$num]); // unset $num to enable overwriting in configuration
+
+ } elseif (($aw = self::autowireArgument($param, $getter)) !== null) {
+ $res[$useName ? $paramName : $num] = $aw;
+
+ } else {
+ $useName = true; // is optional
+ }
+ }
+
+ // extra parameters
+ while (!$useName && array_key_exists(++$num, $arguments)) {
+ $res[$num] = $arguments[$num];
+ unset($arguments[$num]);
+ }
+
+ if ($arguments) {
+ throw new ServiceCreationException(sprintf(
+ 'Unable to pass specified arguments to %s.',
+ Reflection::toString($method),
+ ));
+ }
+
+ return $res;
+ }
+
+
+ /**
+ * Resolves missing argument using autowiring.
+ * @param (callable(string, bool): (object|object[]|null)) $getter
+ * @throws ServiceCreationException
+ */
+ private static function autowireArgument(\ReflectionParameter $parameter, callable $getter): mixed
+ {
+ $desc = Reflection::toString($parameter);
+ $type = Nette\Utils\Type::fromReflection($parameter);
+
+ if ($type?->isClass()) {
+ $class = $type->getSingleName();
+ try {
+ $res = $getter($class, true);
+ } catch (MissingServiceException) {
+ $res = null;
+ } catch (ServiceCreationException $e) {
+ throw new ServiceCreationException("{$e->getMessage()} (required by $desc)", 0, $e);
+ }
+
+ if ($res !== null || $parameter->isOptional()) {
+ return $res;
+ } elseif (class_exists($class) || interface_exists($class)) {
+ throw new ServiceCreationException(sprintf(
+ 'Service of type %s required by %s not found. Did you add it to configuration file?',
+ $class,
+ $desc,
+ ));
+ } else {
+ throw new ServiceCreationException(sprintf(
+ "Class '%s' required by %s not found. Check the parameter type and 'use' statements.",
+ $class,
+ $desc,
+ ));
+ }
+
+ } elseif ($itemType = self::isArrayOf($parameter, $type)) {
+ return $getter($itemType, false);
+
+ } elseif ($parameter->isOptional()) {
+ return null;
+
+ } else {
+ throw new ServiceCreationException(sprintf(
+ 'Parameter %s has %s, so its value must be specified.',
+ $desc,
+ $type && !$type->isSimple() ? 'complex type and no default value' : 'no class type or default value',
+ ));
+ }
+ }
+
+
+ private static function isArrayOf(\ReflectionParameter $parameter, ?Nette\Utils\Type $type): ?string
+ {
+ $method = $parameter->getDeclaringFunction();
+ return $method instanceof \ReflectionMethod
+ && $type?->getSingleName() === 'array'
+ && preg_match(
+ '#@param[ \t]+(?|([\w\\\\]+)\[\]|list<([\w\\\\]+)>|array)[ \t]+\$' . $parameter->name . '#',
+ (string) $method->getDocComment(),
+ $m,
+ )
+ && ($itemType = Reflection::expandClassName($m[1], $method->getDeclaringClass()))
+ && (class_exists($itemType) || interface_exists($itemType))
+ ? $itemType
+ : null;
+ }
+
+
+ /** @internal */
+ public static function getFirstClassCallable(): array
+ {
+ static $x = [new Nette\PhpGenerator\Literal('...')];
+ return $x;
+ }
+}
diff --git a/vendor/nette/di/src/DI/exceptions.php b/vendor/nette/di/src/DI/exceptions.php
new file mode 100644
index 0000000..83fcb52
--- /dev/null
+++ b/vendor/nette/di/src/DI/exceptions.php
@@ -0,0 +1,49 @@
+message = $message;
+ return $this;
+ }
+}
+
+
+/**
+ * Not allowed when container is resolving.
+ */
+class NotAllowedDuringResolvingException extends Nette\InvalidStateException
+{
+}
+
+
+/**
+ * Error in configuration.
+ */
+class InvalidConfigurationException extends Nette\InvalidStateException
+{
+}
diff --git a/vendor/nette/di/src/compatibility.php b/vendor/nette/di/src/compatibility.php
new file mode 100644
index 0000000..f0a0e53
--- /dev/null
+++ b/vendor/nette/di/src/compatibility.php
@@ -0,0 +1,39 @@
+ '@|Nette\Utils\ArrayHash']));
+override(new \Nette\Forms\Container, map(['' => 'Nette\Forms\Controls\BaseControl']));
diff --git a/vendor/nette/forms/composer.json b/vendor/nette/forms/composer.json
new file mode 100644
index 0000000..919069a
--- /dev/null
+++ b/vendor/nette/forms/composer.json
@@ -0,0 +1,50 @@
+{
+ "name": "nette/forms",
+ "description": "📝 Nette Forms: generating, validating and processing secure forms in PHP. Handy API, fully customizable, server & client side validation and mature design.",
+ "keywords": ["nette", "forms", "validation", "csrf", "javascript", "bootstrap"],
+ "homepage": "https://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.1 - 8.4",
+ "nette/component-model": "^3.1",
+ "nette/http": "^3.3",
+ "nette/utils": "^4.0.4"
+ },
+ "require-dev": {
+ "nette/application": "^3.0",
+ "nette/di": "^3.0",
+ "nette/tester": "^2.5.2",
+ "latte/latte": "^2.10.2 || ^3.0.12",
+ "tracy/tracy": "^2.9",
+ "phpstan/phpstan-nette": "^1"
+ },
+ "conflict": {
+ "latte/latte": ">=3.0.0 <3.0.12 || >=3.1"
+ },
+ "suggest": {
+ "ext-intl": "to use date/time controls"
+ },
+ "autoload": {
+ "classmap": ["src/"]
+ },
+ "minimum-stability": "dev",
+ "scripts": {
+ "phpstan": "phpstan analyse",
+ "tester": "tester tests -s"
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ }
+}
diff --git a/vendor/nette/forms/eslint.config.js b/vendor/nette/forms/eslint.config.js
new file mode 100644
index 0000000..a1b94f6
--- /dev/null
+++ b/vendor/nette/forms/eslint.config.js
@@ -0,0 +1,53 @@
+import globals from 'globals';
+import pluginJs from '@eslint/js';
+import stylistic from '@stylistic/eslint-plugin';
+import tseslint from 'typescript-eslint';
+
+export default [
+ {
+ ignores: [
+ '*/', '!src/', '!tests/',
+ '**/netteForms*.*',
+ ],
+ },
+
+ pluginJs.configs.recommended,
+ ...tseslint.configs.recommended,
+
+ stylistic.configs.customize({
+ indent: 'tab',
+ braceStyle: '1tbs',
+ arrowParens: true,
+ semi: true,
+ jsx: false,
+ }),
+
+ {
+ languageOptions: {
+ ecmaVersion: 'latest',
+ globals: {
+ ...globals.browser,
+ ...globals.jasmine,
+ ...globals.amd,
+ ...globals.commonjs,
+ Nette: 'readable',
+ Tracy: 'writeable',
+ },
+ },
+ plugins: {
+ '@stylistic': stylistic,
+ },
+ rules: {
+ '@stylistic/no-multiple-empty-lines': ['error', { max: 2, maxEOF: 0 }],
+ '@stylistic/new-parens': ['error', 'never'],
+ '@stylistic/padded-blocks': 'off',
+ '@typescript-eslint/no-explicit-any': 'off',
+ 'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
+ 'prefer-arrow-callback': 'error',
+ 'arrow-body-style': 'error',
+ 'eqeqeq': ['error', 'always', { null: 'ignore' }],
+ 'no-var': 'error',
+ 'prefer-const': 'off',
+ },
+ },
+];
diff --git a/vendor/nette/forms/examples/assets/logo.png b/vendor/nette/forms/examples/assets/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..c687118daf018d8cffe3f5622e4e58c45aacd767
GIT binary patch
literal 1346
zcmV-I1-<%-P)Px(s7XXYRCwC#SlN=?ItVpr
z7cKk$|281d=E*}+x9?k2Q!}1p1QHyU?(6zbE9aVD$Q$^|%C!>ElkU6$1TEfQw^reb
z$vMOV1Nbxr=-b9>EQsiM1^PYk#YN5*#;QPi0pE-l4&Ca-Ol1Jy_hK5xrWaqp7Z>2$
zi|((y*omuxRo3AQdB<<_Or_;T#u=a!SW2mHJaln>FmVH>%I_hjl;V=e#E1*QrK`uI
z=1&+G5ja5pOt*G`R(b^47hxT}HpverE=RjULS5#MOcadNh^)7h+-(cfT@Vj|)Kr}N
z@S=AFSV{yAT4hL`XNsbOOu-!sbHWp7a!hDusbl4?*U2QT;MP8TvIMJdL1$@%fxx|t
z{Qx+&8G@P$c9M}1Q#jPq8&z!SBamGmVF;PG`LZv7gOSInnG9iPX?|vk;JmhaBTrk?
z*T`<=*h$!VeeSz~6e?#xdl+D0yBCMpye>zV6bYxp=hG*{a1_&`*(s<3fD)SXgV(hK
zf=KPcd7Gi*%144K0k%Rk>O>-@qy@SMUu=lxt*!0AC}td|6+1c$jX(hNo?(V50+~>W
zB%IFeei}P%FbwDb>|&gN@Nqa;yuVScd6j}^SiqP@zDT-M37S%4?=F4OkxC&A;wQ`M
z6*A;wFVkFi!gQ{h(n7FcOZ!=sjRcEvdc+cD0o!US7dhH0EbY9((4d~DL#vf^Wai!y
zdOC0rR4#AE0_*`~25!s=ZC29?uU2-=FdMLpVTc#lkut=*)vCJtl-aYi63l{67rLW!
zu@ZL};{rE;H23it15Yc5v8BJw+}A7^^*?MbVpVnUO%L@3qIpn?vYcfai-$4z?Bx~N
z8`6h_mK%Iu>8SVa{zP|{JRq6)nxMFxg+~A#o?1|fkrND`{0fY_UeWCA@_Vjx<
z8nj=|%0JO_3I&+M&Zt6%8q3k1H-i)1*uh%I-L0J6qh}}Wal@Mn!NGObn#sLdoKrG)
zNj`Sz8951{DNNNZch2mze%hVXsq+J1`(=xWYgR$3oIa%|Td8S*i%$tr37Fv#m!ou*
zNMj__NdXtafE+la0c5Hv=&TV^g;BCOYJG5;3BgIlEn^#Z2%tBSZQ#ls+YpsHM5=B)
z_FX>**#F}*&%gC={rSfdUh`><%JYd}{hOx<=a0M?Vl=mkh$Ro#6F5Ibf#=n&LGeD(
zKu3Qhul+pF@Yv_eYsrU<-8ed;twN5N4iYs&1^&g&v$zhqz&@;+q|tYNMlPV?X!%5O?4&m(d{31
z#4HZyK9`4l8XMmM@e?SK_^EPRk}X+dpg!ts)brHjc}BN6m^O|H|)?MDsf&Zm_iVotbC+lZQSUwtfjP01~D&N+x9QX8-^I07*qoM6N<$
Ef_3zng8%>k
literal 0
HcmV?d00001
diff --git a/vendor/nette/forms/examples/assets/style.css b/vendor/nette/forms/examples/assets/style.css
new file mode 100644
index 0000000..e31f88b
--- /dev/null
+++ b/vendor/nette/forms/examples/assets/style.css
@@ -0,0 +1,72 @@
+/** common style for Nette examples */
+
+html {
+ font: 16px/1.5 sans-serif;
+ border-top: 4.7em solid #F4EBDB;
+}
+
+body {
+ max-width: 990px;
+ margin: -4.7em auto 0;
+ background: white;
+ color: #333;
+}
+
+h1 {
+ font-size: 1.9em;
+ margin: .5em 0 1.5em;
+ background: url(logo.png) right center no-repeat;
+ color: #7A7772;
+ text-shadow: 1px 1px 0 white;
+}
+
+fieldset {
+ padding: .2em 1em 1em;
+ margin: .5em 0;
+ background: #E4F1FC;
+ border: 1px solid #B2D1EB;
+}
+
+textarea,
+select,
+input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="image"]):not([type="range"]) {
+ padding: .3em .5em;
+ color: black;
+ background: white;
+ border: 1px solid silver;
+}
+
+.has-error textarea,
+.has-error select,
+.has-error input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="image"]):not([type="range"]) {
+ border-color: #E22;
+}
+
+select {
+ padding-right: .3em;
+}
+
+input[type="submit"] {
+ font-size: 120%;
+}
+
+th {
+ width: 10em;
+ text-align: right;
+ font-weight: normal;
+}
+
+.required label {
+ font-weight: bold;
+}
+
+.error {
+ color: #E22;
+ font-weight: bold;
+ margin-left: 1em;
+}
+
+footer a {
+ font-size: 70%;
+ color: gray;
+}
diff --git a/vendor/nette/forms/examples/basic-example.php b/vendor/nette/forms/examples/basic-example.php
new file mode 100644
index 0000000..b7074fb
--- /dev/null
+++ b/vendor/nette/forms/examples/basic-example.php
@@ -0,0 +1,132 @@
+addGroup('Personal data')
+ ->setOption('description', 'We value your privacy and we ensure that the information you give to us will not be shared to other entities.');
+
+$form->addText('name', 'Your name:')
+ ->setRequired('Enter your name');
+
+$form->addText('age', 'Your age:')
+ ->setRequired('Enter your age')
+ ->addRule($form::Integer, 'Age must be numeric value')
+ ->addRule($form::Range, 'Age must be in range from %d to %d', [10, 100]);
+
+$form->addRadioList('gender', 'Your gender:', [
+ 'm' => 'male',
+ 'f' => 'female',
+]);
+
+$form->addCheckboxList('colors', 'Favorite colors:', [
+ 'r' => 'red',
+ 'g' => 'green',
+ 'b' => 'blue',
+]);
+
+$form->addEmail('email', 'Email:')
+ ->setEmptyValue('@');
+
+
+// group Shipping address
+$form->addGroup('Shipping address')
+ ->setOption('embedNext', true);
+
+$form->addCheckbox('send', 'Ship to address')
+ ->addCondition($form::Filled) // conditional rule: if is checkbox checked...
+ ->toggle('sendBox'); // toggle div #sendBox
+
+
+// subgroup
+$form->addGroup()
+ ->setOption('container', Html::el('div')->id('sendBox'));
+
+$form->addText('street', 'Street:');
+
+$form->addText('city', 'City:')
+ ->addConditionOn($form['send'], $form::Filled)
+ ->setRequired('Enter your shipping address');
+
+$countries = [
+ 'World' => [
+ 'bu' => 'Buranda',
+ 'qu' => 'Qumran',
+ 'st' => 'Saint Georges Island',
+ ],
+ '?' => 'other',
+];
+$form->addSelect('country', 'Country:', $countries)
+ ->setPrompt('Select your country')
+ ->addConditionOn($form['send'], $form::Filled)
+ ->setRequired('Select your country');
+
+
+// group Your account
+$form->addGroup('Your account');
+
+$form->addPassword('password', 'Choose password:')
+ ->setRequired('Choose your password')
+ ->addRule($form::MinLength, 'The password is too short: it must be at least %d characters', 3);
+
+$form->addPassword('password2', 'Reenter password:')
+ ->setRequired('Reenter your password')
+ ->addRule($form::Equal, 'Passwords do not match', $form['password']);
+
+$form->addUpload('avatar', 'Picture:')
+ ->addRule($form::Image, 'Uploaded file is not image');
+
+$form->addHidden('userid');
+
+$form->addTextArea('note', 'Comment:');
+
+// group for buttons
+$form->addGroup();
+
+$form->addSubmit('submit', 'Send');
+
+
+$form->setDefaults([
+ 'name' => 'John Doe',
+ 'userid' => 231,
+]);
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues(), [Dumper::COLLAPSE => false]);
+ exit;
+}
+
+
+?>
+
+
+Nette Forms basic example
+
+
+
+Nette Forms basic example
+
+render() ?>
+
+
diff --git a/vendor/nette/forms/examples/bootstrap4-rendering.php b/vendor/nette/forms/examples/bootstrap4-rendering.php
new file mode 100644
index 0000000..8abd4a1
--- /dev/null
+++ b/vendor/nette/forms/examples/bootstrap4-rendering.php
@@ -0,0 +1,107 @@
+getRenderer();
+ $renderer->wrappers['controls']['container'] = null;
+ $renderer->wrappers['pair']['container'] = 'div class="form-group row"';
+ $renderer->wrappers['label']['container'] = 'div class="col-sm-3 col-form-label"';
+ $renderer->wrappers['control']['container'] = 'div class=col-sm-9';
+ $renderer->wrappers['control']['description'] = 'span class=form-text';
+ $renderer->wrappers['control']['errorcontainer'] = 'span class=invalid-feedback';
+ $renderer->wrappers['control']['.error'] = 'is-invalid';
+ $renderer->wrappers['error']['container'] = 'div class="alert alert-danger"';
+
+ foreach ($form->getControls() as $control) {
+ $type = $control->getOption('type');
+ if ($type === 'button') {
+ $control->getControlPrototype()->addClass(empty($usedPrimary) ? 'btn btn-primary' : 'btn btn-secondary');
+ $usedPrimary = true;
+
+ } elseif (in_array($type, ['text', 'textarea', 'select', 'datetime'], true)) {
+ $control->getControlPrototype()->addClass('form-control');
+
+ } elseif ($type === 'file') {
+ $control->getControlPrototype()->addClass('form-control-file');
+
+ } elseif (in_array($type, ['checkbox', 'radio'], true)) {
+ if ($control instanceof Nette\Forms\Controls\Checkbox) {
+ $control->getLabelPrototype()->addClass('form-check-label');
+ } else {
+ $control->getItemLabelPrototype()->addClass('form-check-label');
+ }
+ $control->getControlPrototype()->addClass('form-check-input');
+ $control->getContainerPrototype()->setName('div')->addClass('form-check');
+ }
+ }
+}
+
+
+$form = new Form;
+$form->onRender[] = 'makeBootstrap4';
+
+$form->addGroup('Personal data');
+$form->addText('name', 'Your name')
+ ->setRequired('Enter your name');
+
+$form->addRadioList('gender', 'Your gender', [
+ 'male', 'female',
+]);
+
+$form->addCheckboxList('colors', 'Favorite colors', [
+ 'red', 'green', 'blue',
+]);
+
+$form->addSelect('country', 'Country', [
+ 'Buranda', 'Qumran', 'Saint Georges Island',
+]);
+
+$form->addCheckbox('send', 'Ship to address');
+
+$form->addGroup('Your account');
+$form->addPassword('password', 'Choose password');
+$form->addUpload('avatar', 'Picture');
+$form->addTextArea('note', 'Comment');
+
+$form->addGroup();
+$form->addSubmit('submit', 'Send');
+$form->addSubmit('cancel', 'Cancel');
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+
+?>
+
+
+Nette Forms & Bootstrap v4 rendering example
+
+
+
+
+
Nette Forms & Bootstrap v4 rendering example
+
+ render() ?>
+
diff --git a/vendor/nette/forms/examples/bootstrap5-rendering.php b/vendor/nette/forms/examples/bootstrap5-rendering.php
new file mode 100644
index 0000000..5c1a845
--- /dev/null
+++ b/vendor/nette/forms/examples/bootstrap5-rendering.php
@@ -0,0 +1,112 @@
+getRenderer();
+ $renderer->wrappers['controls']['container'] = null;
+ $renderer->wrappers['pair']['container'] = 'div class="mb-3 row"';
+ $renderer->wrappers['label']['container'] = 'div class="col-sm-3 col-form-label"';
+ $renderer->wrappers['control']['container'] = 'div class=col-sm-9';
+ $renderer->wrappers['control']['description'] = 'span class=form-text';
+ $renderer->wrappers['control']['errorcontainer'] = 'span class=invalid-feedback';
+ $renderer->wrappers['control']['.error'] = 'is-invalid';
+ $renderer->wrappers['error']['container'] = 'div class="alert alert-danger"';
+
+ foreach ($form->getControls() as $control) {
+ $type = $control->getOption('type');
+ if ($type === 'button') {
+ $control->getControlPrototype()->addClass(empty($usedPrimary) ? 'btn btn-primary' : 'btn btn-secondary');
+ $usedPrimary = true;
+
+ } elseif (in_array($type, ['text', 'textarea', 'select', 'datetime', 'file'], true)) {
+ $control->getControlPrototype()->addClass('form-control');
+
+ } elseif (in_array($type, ['checkbox', 'radio'], true)) {
+ if ($control instanceof Nette\Forms\Controls\Checkbox) {
+ $control->getLabelPrototype()->addClass('form-check-label');
+ } else {
+ $control->getItemLabelPrototype()->addClass('form-check-label');
+ }
+ $control->getControlPrototype()->addClass('form-check-input');
+ $control->getContainerPrototype()->setName('div')->addClass('form-check');
+
+ } elseif ($type === 'color') {
+ $control->getControlPrototype()->addClass('form-control form-control-color');
+ }
+ }
+}
+
+
+$form = new Form;
+$form->onRender[] = 'makeBootstrap5';
+
+$form->addGroup('Personal data');
+$form->addText('name', 'Your name')
+ ->setRequired('Enter your name')
+ ->setOption('description', 'Name and surname');
+
+$form->addDate('birth', 'Date of birth');
+
+$form->addRadioList('gender', 'Your gender', [
+ 'male', 'female',
+]);
+
+$form->addCheckboxList('colors', 'Favorite colors', [
+ 'red', 'green', 'blue',
+]);
+
+$form->addSelect('country', 'Country', [
+ 'Buranda', 'Qumran', 'Saint Georges Island',
+]);
+
+$form->addCheckbox('send', 'Ship to address');
+
+$form->addColor('color', 'Favourite colour');
+
+$form->addGroup('Your account');
+$form->addPassword('password', 'Choose password');
+$form->addUpload('avatar', 'Picture');
+$form->addTextArea('note', 'Comment');
+
+$form->addGroup();
+$form->addSubmit('submit', 'Send');
+$form->addSubmit('cancel', 'Cancel');
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+
+?>
+
+
+Nette Forms & Bootstrap v5 rendering example
+
+
+
+
+
Nette Forms & Bootstrap v5 rendering example
+
+ render() ?>
+
diff --git a/vendor/nette/forms/examples/containers.php b/vendor/nette/forms/examples/containers.php
new file mode 100644
index 0000000..b75a4c4
--- /dev/null
+++ b/vendor/nette/forms/examples/containers.php
@@ -0,0 +1,64 @@
+addGroup('First person');
+
+$first = $form->addContainer('first');
+$first->addText('name', 'Your name:');
+$first->addText('email', 'Email:');
+$first->addText('street', 'Street:');
+$first->addText('city', 'City:');
+
+// group Second person
+$form->addGroup('Second person');
+
+$second = $form->addContainer('second');
+$second->addText('name', 'Your name:');
+$second->addText('email', 'Email:');
+$second->addText('street', 'Street:');
+$second->addText('city', 'City:');
+
+// group for button
+$form->addGroup();
+
+$form->addSubmit('submit', 'Send');
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+
+?>
+
+
+Nette Forms containers example
+
+
+Nette Forms containers example
+
+render() ?>
+
+
diff --git a/vendor/nette/forms/examples/custom-control.php b/vendor/nette/forms/examples/custom-control.php
new file mode 100644
index 0000000..84f3373
--- /dev/null
+++ b/vendor/nette/forms/examples/custom-control.php
@@ -0,0 +1,137 @@
+addRule(self::validateDate(...), 'Date is invalid.');
+ }
+
+
+ public function setValue($value)
+ {
+ if ($value === null) {
+ $this->day = $this->month = $this->year = '';
+ } else {
+ $date = Nette\Utils\DateTime::from($value);
+ $this->day = $date->format('j');
+ $this->month = $date->format('n');
+ $this->year = $date->format('Y');
+ }
+ return $this;
+ }
+
+
+ public function getValue(): ?DateTimeImmutable
+ {
+ return self::validateDate($this)
+ ? (new DateTimeImmutable)->setDate((int) $this->year, (int) $this->month, (int) $this->day)->setTime(0, 0)
+ : null;
+ }
+
+
+ public function isFilled(): bool
+ {
+ return $this->day !== '' || $this->year !== '';
+ }
+
+
+ public function loadHttpData(): void
+ {
+ $this->day = $this->getHttpData(Form::DataLine, '[day]');
+ $this->month = $this->getHttpData(Form::DataLine, '[month]');
+ $this->year = $this->getHttpData(Form::DataLine, '[year]');
+ }
+
+
+ /**
+ * Generates control's HTML element.
+ */
+ public function getControl()
+ {
+ $name = $this->getHtmlName();
+ return Html::el('input', [
+ 'name' => $name . '[day]',
+ 'id' => $this->getHtmlId(),
+ 'value' => $this->day,
+ 'type' => 'number',
+ 'min' => 1,
+ 'max' => 31,
+ 'data-nette-rules' => Helpers::exportRules($this->getRules()) ?: null,
+ ])
+
+ . Helpers::createSelectBox(
+ [1 => 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
+ [],
+ $this->month,
+ )->name($name . '[month]')
+
+ . Html::el('input', [
+ 'name' => $name . '[year]',
+ 'value' => $this->year,
+ 'type' => 'number',
+ ]);
+ }
+
+
+ public static function validateDate(Nette\Forms\Control $control): bool
+ {
+ return ctype_digit($control->day)
+ && ctype_digit($control->month)
+ && ctype_digit($control->year)
+ && checkdate((int) $control->month, (int) $control->day, (int) $control->year);
+ }
+}
+
+
+Tracy\Debugger::enable();
+
+$form = new Form;
+
+$form['date'] = new DateInput('Date:');
+$form['date']->setDefaultValue(new DateTime);
+
+$form->addSubmit('submit', 'Send');
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Tracy\Dumper::dump($form->getValues());
+ exit;
+}
+
+
+?>
+
+
+Nette Forms custom control example
+
+
+
+Nette Forms custom control example
+
+render() ?>
+
+
diff --git a/vendor/nette/forms/examples/custom-rendering.php b/vendor/nette/forms/examples/custom-rendering.php
new file mode 100644
index 0000000..360333b
--- /dev/null
+++ b/vendor/nette/forms/examples/custom-rendering.php
@@ -0,0 +1,127 @@
+getRenderer();
+$renderer->wrappers['form']['container'] = Html::el('div')->id('form');
+$renderer->wrappers['group']['container'] = null;
+$renderer->wrappers['group']['label'] = 'h3';
+$renderer->wrappers['pair']['container'] = null;
+$renderer->wrappers['controls']['container'] = 'dl';
+$renderer->wrappers['control']['container'] = 'dd';
+$renderer->wrappers['control']['.odd'] = 'odd';
+$renderer->wrappers['label']['container'] = 'dt';
+$renderer->wrappers['label']['suffix'] = ':';
+$renderer->wrappers['control']['requiredsuffix'] = " \u{2022}";
+
+
+$form->addGroup('Personal data');
+$form->addText('name', 'Your name')
+ ->setRequired('Enter your name');
+
+$form->addRadioList('gender', 'Your gender', [
+ 'm' => Html::el('span', 'male')->style('color: #248bd3'),
+ 'f' => Html::el('span', 'female')->style('color: #e948d4'),
+]);
+
+$form->addSelect('country', 'Country', [
+ 'Buranda', 'Qumran', 'Saint Georges Island',
+]);
+
+$form->addCheckbox('send', 'Ship to address');
+
+$form->addGroup('Your account');
+$form->addPassword('password', 'Choose password');
+$form->addUpload('avatar', 'Picture');
+$form->addTextArea('note', 'Comment');
+
+$form->addGroup();
+$form->addSubmit('submit', 'Send');
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+
+?>
+
+
+Nette Forms custom rendering example
+
+
+
+
+
+Nette Forms custom rendering example
+
+render() ?>
+
+
diff --git a/vendor/nette/forms/examples/custom-validator.php b/vendor/nette/forms/examples/custom-validator.php
new file mode 100644
index 0000000..ff733fc
--- /dev/null
+++ b/vendor/nette/forms/examples/custom-validator.php
@@ -0,0 +1,64 @@
+value % $arg === 0;
+ }
+}
+
+
+$form = new Form;
+
+$form->addText('num1', 'Multiple of 8:')
+ ->setDefaultValue(5)
+ ->addRule('MyValidators::divisibilityValidator', 'First number must be %d multiple', 8);
+
+$form->addSubmit('submit', 'Send');
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+
+?>
+
+
+Nette Forms custom validator example
+
+
+
+
+
+Nette Forms custom validator example
+
+render() ?>
+
+
diff --git a/vendor/nette/forms/examples/html5.php b/vendor/nette/forms/examples/html5.php
new file mode 100644
index 0000000..eb1a4d4
--- /dev/null
+++ b/vendor/nette/forms/examples/html5.php
@@ -0,0 +1,63 @@
+addGroup();
+
+$form->addText('query', 'Search:')
+ ->setHtmlType('search')
+ ->setHtmlAttribute('autofocus');
+
+$form->addInteger('count', 'Number of results:')
+ ->setDefaultValue(10)
+ ->addRule($form::Range, 'Must be in range from %d to %d', [1, 100]);
+
+$form->addFloat('precision', 'Precision:')
+ ->setHtmlType('range')
+ ->setDefaultValue(50)
+ ->addRule($form::Range, 'Precision must be in range from %d to %d', [0, 100]);
+
+$form->addEmail('email', 'Send to email:')
+ ->setHtmlAttribute('autocomplete', 'off')
+ ->setHtmlAttribute('placeholder', 'Optional, but Recommended');
+
+$form->addSubmit('submit', 'Send');
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+
+?>
+
+
+Nette Forms and HTML5
+
+
+
+Nette Forms and HTML5
+
+render() ?>
+
+
diff --git a/vendor/nette/forms/examples/latte.php b/vendor/nette/forms/examples/latte.php
new file mode 100644
index 0000000..07c2fa1
--- /dev/null
+++ b/vendor/nette/forms/examples/latte.php
@@ -0,0 +1,62 @@
+addText('name', 'Your name')
+ ->setRequired('Enter your name')
+ ->setOption('description', 'Name and surname');
+
+$form->addDate('birth', 'Date of birth');
+
+$form->addRadioList('gender', 'Your gender', [
+ 'male', 'female',
+]);
+
+$form->addCheckboxList('colors', 'Favorite colors', [
+ 'red', 'green', 'blue',
+]);
+
+$form->addSelect('country', 'Country', [
+ 'Buranda', 'Qumran', 'Saint Georges Island',
+]);
+
+$form->addCheckbox('send', 'Ship to address');
+
+$form->addColor('color', 'Favourite colour');
+
+$form->addPassword('password', 'Choose password');
+$form->addUpload('avatar', 'Picture');
+$form->addTextArea('note', 'Comment');
+
+$form->addSubmit('submit', 'Send');
+$form->addSubmit('cancel', 'Cancel');
+
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+$latte = new Latte\Engine;
+$latte->addExtension(new Nette\Bridges\FormsLatte\FormsExtension);
+
+$latte->render(__DIR__ . '/latte/page.latte', ['form' => $form]);
diff --git a/vendor/nette/forms/examples/latte/form-bootstrap5.latte b/vendor/nette/forms/examples/latte/form-bootstrap5.latte
new file mode 100644
index 0000000..6d7bcae
--- /dev/null
+++ b/vendor/nette/forms/examples/latte/form-bootstrap5.latte
@@ -0,0 +1,66 @@
+{* Generic form template for Bootstrap v5 *}
+
+{define bootstrap-form, $name}
+
+{/define}
+
+
+{define local controls, array $controls}
+ {* Loop over form controls and render each one *}
+
+
+ {* Label for the control *}
+
{label $control /}
+
+
+ {include control $control}
+ {if $control->getOption(type) === button}
+ {while $iterator->nextValue?->getOption(type) === button}
+ {input $iterator->nextValue class => "btn btn-secondary"}
+ {do $iterator->next()}
+ {/while}
+ {/if}
+
+ {* Display control-level errors or descriptions, if present *}
+ {$control->error}
+ {$control->getOption(description)}
+
+
+{/define}
+
+
+{define local control, Nette\Forms\Controls\BaseControl $control}
+ {* Conditionally render controls based on their type with appropriate Bootstrap classes *}
+ {if $control->getOption(type) in [text, select, textarea, datetime, file]}
+ {input $control class => form-control}
+
+ {elseif $control->getOption(type) === button}
+ {input $control class => "btn btn-primary"}
+
+ {elseif $control->getOption(type) in [checkbox, radio]}
+ {var $items = $control instanceof Nette\Forms\Controls\Checkbox ? [''] : $control->getItems()}
+
+ {input $control:$key class => form-check-input}{label $control:$key class => form-check-label /}
+
+
+ {elseif $control->getOption(type) === color}
+ {input $control class => "form-control form-control-color"}
+
+ {else}
+ {input $control}
+ {/if}
+{/define}
diff --git a/vendor/nette/forms/examples/latte/form.latte b/vendor/nette/forms/examples/latte/form.latte
new file mode 100644
index 0000000..f0230cd
--- /dev/null
+++ b/vendor/nette/forms/examples/latte/form.latte
@@ -0,0 +1,37 @@
+{* Generic form template *}
+
+{define form, $name}
+
+{/define}
+
+
+{define local controls, array $controls}
+ {* Loop over form controls and render each one *}
+
+
+
+ {label $control /}
+
+
+ {input $control}
+
+ {$control->getOption(description)}
+ {$control->error}
+
+
+
+{/define}
diff --git a/vendor/nette/forms/examples/latte/page.latte b/vendor/nette/forms/examples/latte/page.latte
new file mode 100644
index 0000000..f55ad5d
--- /dev/null
+++ b/vendor/nette/forms/examples/latte/page.latte
@@ -0,0 +1,19 @@
+{import 'form-bootstrap5.latte'}
+
+
+
+
+
+ Nette Forms rendering using Latte
+
+
+
+
+
+
+
Nette Forms & Bootstrap v5 rendering example
+
+ {include bootstrap-form, $form}
+
+
+
diff --git a/vendor/nette/forms/examples/live-validation.php b/vendor/nette/forms/examples/live-validation.php
new file mode 100644
index 0000000..63cf434
--- /dev/null
+++ b/vendor/nette/forms/examples/live-validation.php
@@ -0,0 +1,106 @@
+addText('name', 'Your name:')
+ ->setRequired('Enter your name');
+
+$form->addText('age', 'Your age:')
+ ->setRequired('Enter your age')
+ ->addRule($form::Integer, 'Age must be numeric value')
+ ->addRule($form::Range, 'Age must be in range from %d to %d', [10, 100]);
+
+$form->addPassword('password', 'Choose password:')
+ ->setRequired('Choose your password')
+ ->addRule($form::MinLength, 'The password is too short: it must be at least %d characters', 3);
+
+$form->addPassword('password2', 'Reenter password:')
+ ->setRequired('Reenter your password')
+ ->addRule($form::Equal, 'Passwords do not match', $form['password']);
+
+$form->addSubmit('submit', 'Send');
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+$renderer = $form->getRenderer();
+$renderer->wrappers['pair']['.error'] = 'has-error';
+
+?>
+
+
+Nette Forms live validation example
+
+
+
+
+
+
+Nette Forms live validation example
+
+render() ?>
+
+
diff --git a/vendor/nette/forms/examples/localization.ini b/vendor/nette/forms/examples/localization.ini
new file mode 100644
index 0000000..f03ef27
--- /dev/null
+++ b/vendor/nette/forms/examples/localization.ini
@@ -0,0 +1,12 @@
+Personal data = Osobní údaje
+Your name: = Jméno:
+Enter your name = Zadejte jméno
+Your age: = Věk:
+Enter your age = Zadejte váš věk
+Age must be numeric value = Věk musí být číslo
+Age must be in range from %d to %d = Věk musí být v rozmezí %d až %d
+Country: = Země:
+Select your country = Vyberte zemi
+World = Svět
+other = jiná
+Send = Odeslat
diff --git a/vendor/nette/forms/examples/localization.php b/vendor/nette/forms/examples/localization.php
new file mode 100644
index 0000000..bfa4b5c
--- /dev/null
+++ b/vendor/nette/forms/examples/localization.php
@@ -0,0 +1,89 @@
+table = $table;
+ }
+
+
+ /**
+ * Translates the given string.
+ */
+ public function translate($message, ...$parameters): string
+ {
+ return $this->table[$message] ?? $message;
+ }
+}
+
+
+$form = new Form;
+
+$translator = new MyTranslator(parse_ini_file(__DIR__ . '/localization.ini'));
+$form->setTranslator($translator);
+
+$form->addGroup('Personal data');
+$form->addText('name', 'Your name:')
+ ->setRequired('Enter your name');
+
+$form->addText('age', 'Your age:')
+ ->setRequired('Enter your age')
+ ->addRule($form::Integer, 'Age must be numeric value')
+ ->addRule($form::Range, 'Age must be in range from %d to %d', [10, 100]);
+
+$countries = [
+ 'World' => [
+ 'bu' => 'Buranda',
+ 'qu' => 'Qumran',
+ 'st' => 'Saint Georges Island',
+ ],
+ '?' => 'other',
+];
+$form->addSelect('country', 'Country:', $countries)
+ ->setPrompt('Select your country');
+
+$form->addSubmit('submit', 'Send');
+
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+
+?>
+
+
+Nette Forms localization example
+
+
+
+Nette Forms localization example
+
+render() ?>
+
+
diff --git a/vendor/nette/forms/examples/manual-rendering.php b/vendor/nette/forms/examples/manual-rendering.php
new file mode 100644
index 0000000..1a02e17
--- /dev/null
+++ b/vendor/nette/forms/examples/manual-rendering.php
@@ -0,0 +1,95 @@
+addText('name')
+ ->setRequired('Enter your name');
+
+$form->addText('age')
+ ->setRequired('Enter your age');
+
+$form->addRadioList('gender', null, [
+ 'm' => 'male',
+ 'f' => 'female',
+]);
+
+$form->addEmail('email');
+
+$form->addSubmit('submit');
+
+if ($form->isSuccess()) {
+ echo 'Form was submitted and successfully validated ';
+ Dumper::dump($form->getValues());
+ exit;
+}
+
+
+?>
+
+
+
+
+ Nette Forms manual form rendering
+
+
+
+
+
+ Nette Forms manual form rendering
+
+ render('begin') ?>
+
+ errors): ?>
+
+ errors as $error): ?>
+
+
+
+
+
+
+ Personal data
+
+
+ getLabel('Your name:') ?>
+ control->cols(35) ?> error ?>
+
+
+ getLabel('Your age:') ?>
+ control->cols(5) ?> error ?>
+
+
+ getLabel('Your gender:') ?>
+ control ?> error ?>
+
+
+ getLabel('Email:') ?>
+ control->cols(35) ?> error ?>
+
+
+
+
+
+ getControl('Send') ?>
+
+
+ render('end'); ?>
+
+
diff --git a/vendor/nette/forms/license.md b/vendor/nette/forms/license.md
new file mode 100644
index 0000000..cf741bd
--- /dev/null
+++ b/vendor/nette/forms/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/nette/forms/package.json b/vendor/nette/forms/package.json
new file mode 100644
index 0000000..ce66366
--- /dev/null
+++ b/vendor/nette/forms/package.json
@@ -0,0 +1,31 @@
+{
+ "type": "module",
+ "devDependencies": {
+ "@eslint/js": "^9.8.0",
+ "@rollup/plugin-json": "^6.1.0",
+ "@rollup/plugin-node-resolve": "^15.2.3",
+ "@rollup/plugin-terser": "^0.4.4",
+ "@rollup/plugin-typescript": "^11.1.6",
+ "@stylistic/eslint-plugin": "^2.1.0",
+ "eslint": "^9.8.0",
+ "globals": "^15.3.0",
+ "jasmine": "^5.1.0",
+ "jasmine-core": "^5.1.1",
+ "karma": "^6.4.2",
+ "karma-chrome-launcher": "^3.2.0",
+ "karma-jasmine": "^5.1.0",
+ "rollup": "^4.18.0",
+ "rollup-plugin-dts": "^6.1.1",
+ "terser": "^5.31.0",
+ "typescript": "^5.5.4",
+ "typescript-eslint": "^8.0.0"
+ },
+ "scripts": {
+ "typecheck": "tsc -noemit",
+ "lint": "eslint",
+ "lint:fix": "eslint --fix",
+ "test": "karma start tests/netteForms/karma.conf.ts",
+ "build": "rollup -c",
+ "postbuild": "npm run test"
+ }
+}
diff --git a/vendor/nette/forms/readme.md b/vendor/nette/forms/readme.md
new file mode 100644
index 0000000..630329e
--- /dev/null
+++ b/vendor/nette/forms/readme.md
@@ -0,0 +1,93 @@
+Nette Forms: greatly facilitates web forms
+==========================================
+
+[](https://packagist.org/packages/nette/forms)
+[](https://github.com/nette/forms/actions)
+[](https://coveralls.io/github/nette/forms?branch=v3.2)
+[](https://github.com/nette/forms/releases)
+[](https://github.com/nette/forms/blob/master/license.md)
+
+
+Introduction
+------------
+
+Nette\Forms greatly facilitates creating and processing web forms. What it can really do?
+
+- validate sent data both client-side (JavaScript) and server-side
+- provide high level of security
+- multiple render modes
+- translations, i18n
+
+Why should you bother setting up framework for a simple web form? You won't have to take care about routine tasks such as writing two validation scripts (client and server) and your code will be safe against security breaches.
+
+Nette Framework puts a great effort to be safe and since forms are the most common user input, Nette forms are as good as impenetrable. All is maintained dynamically and transparently, nothing has to be set manually. Well known vulnerabilities such as Cross Site Scripting (XSS) and Cross-Site Request Forgery (CSRF) are filtered, as well as special control characters. All inputs are checked for UTF-8 validity. Every multiple-choice, select box and similar are checked for forged values upon validating. Sounds good? Let's try it out.
+
+Documentation can be found on the [website](https://doc.nette.org/forms).
+
+
+[Support Me](https://github.com/sponsors/dg)
+--------------------------------------------
+
+Do you like Nette Forms? Are you looking forward to the new features?
+
+[](https://github.com/sponsors/dg)
+
+Thank you!
+
+
+Installation
+------------
+
+The recommended way to install is via Composer:
+
+```
+composer require nette/forms
+```
+
+It requires PHP version 8.1 and supports PHP up to 8.4.
+
+
+Client-side support can be installed with npm or yarn:
+
+```
+npm install nette-forms
+```
+
+Usage
+-----
+
+Let's create a simple registration form:
+
+```php
+use Nette\Forms\Form;
+
+$form = new Form;
+
+$form->addText('name', 'Name:');
+$form->addPassword('password', 'Password:');
+$form->addSubmit('send', 'Register');
+
+echo $form; // renders the form
+```
+Though we mentioned validation, yet our form has none. Let's fix it. We require users to tell us their name, so we should call a `setRequired()` method, which optional argument is an error message to show, if user does not fill his name in:
+
+```php
+$form->addText('name', 'Name:')
+ ->setRequired('Please fill your name.');
+```
+
+Try submitting a form without the name - you will keep seeing this message until you meet the validation rules. All that is left for us is setting up JavaScript rules. Luckily it's a piece of cake. We only have to link `netteForms.js`, which is located at `/client-side/forms` in the distribution package.
+
+```html
+
+```
+
+Nette Framework adds `required` class to all mandatory elements. Adding the following style will turn label of *name* input to red.
+
+```html
+
+```
+
+[Continue…](https://doc.nette.org/en/forms).
diff --git a/vendor/nette/forms/rollup.config.js b/vendor/nette/forms/rollup.config.js
new file mode 100644
index 0000000..8a36975
--- /dev/null
+++ b/vendor/nette/forms/rollup.config.js
@@ -0,0 +1,78 @@
+import json from '@rollup/plugin-json';
+import { nodeResolve } from '@rollup/plugin-node-resolve';
+import typescript from '@rollup/plugin-typescript';
+import terser from '@rollup/plugin-terser';
+import dts from 'rollup-plugin-dts';
+
+
+// adds a header and calls initOnLoad() in the browser
+function fix() {
+ return {
+ renderChunk(code) {
+ code = `/*!
+ * NetteForms - simple form validation.
+ *
+ * This file is part of the Nette Framework (https://nette.org)
+ * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
+ */
+`
+ + code;
+ code = code.replace('global.Nette = factory()', 'global.Nette?.noInit ? (global.Nette = factory()) : (global.Nette = factory()).initOnLoad()');
+ code = code.replace(/\/\*\*.*\* \*\//s, '');
+ return code;
+ },
+ };
+}
+
+function spaces2tabs() {
+ return {
+ renderChunk(code) {
+ return code.replaceAll(' ', '\t');
+ },
+ };
+}
+
+
+export default [
+ {
+ input: 'src/assets/index.umd.ts',
+ output: [
+ {
+ format: 'umd',
+ name: 'Nette',
+ dir: 'src/assets',
+ entryFileNames: 'netteForms.js',
+ generatedCode: 'es2015',
+ },
+ {
+ format: 'umd',
+ name: 'Nette',
+ dir: 'src/assets',
+ entryFileNames: 'netteForms.min.js',
+ generatedCode: 'es2015',
+ plugins: [
+ terser(),
+ ],
+ },
+ ],
+ plugins: [
+ json(),
+ nodeResolve(),
+ typescript(),
+ fix(),
+ spaces2tabs(),
+ ],
+ },
+
+ {
+ input: 'src/assets/index.umd.ts',
+ output: [{
+ file: 'src/assets/netteForms.d.ts',
+ format: 'es',
+ }],
+ plugins: [
+ dts(),
+ spaces2tabs(),
+ ],
+ },
+];
diff --git a/vendor/nette/forms/src/Bridges/FormsDI/FormsExtension.php b/vendor/nette/forms/src/Bridges/FormsDI/FormsExtension.php
new file mode 100644
index 0000000..b06ca67
--- /dev/null
+++ b/vendor/nette/forms/src/Bridges/FormsDI/FormsExtension.php
@@ -0,0 +1,43 @@
+config = new class {
+ /** @var string[] */
+ public array $messages = [];
+ };
+ }
+
+
+ public function afterCompile(Nette\PhpGenerator\ClassType $class): void
+ {
+ $initialize = $this->initialization ?? $class->getMethod('initialize');
+
+ foreach ($this->config->messages as $name => $text) {
+ if (defined('Nette\Forms\Form::' . $name)) {
+ $initialize->addBody('Nette\Forms\Validator::$messages[Nette\Forms\Form::?] = ?;', [$name, $text]);
+ } elseif (defined($name)) {
+ $initialize->addBody('Nette\Forms\Validator::$messages[' . $name . '] = ?;', [$text]);
+ } else {
+ throw new Nette\InvalidArgumentException('Constant Nette\Forms\Form::' . $name . ' or constant ' . $name . ' does not exist.');
+ }
+ }
+ }
+}
diff --git a/vendor/nette/forms/src/Bridges/FormsLatte/FormMacros.php b/vendor/nette/forms/src/Bridges/FormsLatte/FormMacros.php
new file mode 100644
index 0000000..18c889a
--- /dev/null
+++ b/vendor/nette/forms/src/Bridges/FormsLatte/FormMacros.php
@@ -0,0 +1,330 @@
+addMacro('form', [$me, 'macroForm'], 'echo Nette\Bridges\FormsLatte\Runtime::renderFormEnd(array_pop($this->global->formsStack));');
+ $me->addMacro('formContext', [$me, 'macroFormContext'], 'array_pop($this->global->formsStack);');
+ $me->addMacro('formContainer', [$me, 'macroFormContainer'], 'array_pop($this->global->formsStack); $formContainer = end($this->global->formsStack)');
+ $me->addMacro('label', [$me, 'macroLabel'], [$me, 'macroLabelEnd'], null, self::AUTO_EMPTY);
+ $me->addMacro('input', [$me, 'macroInput']);
+ $me->addMacro('name', [$me, 'macroName'], [$me, 'macroNameEnd'], [$me, 'macroNameAttr']);
+ $me->addMacro('inputError', [$me, 'macroInputError']);
+ $me->addMacro('formPrint', [$me, 'macroFormPrint']);
+ $me->addMacro('formClassPrint', [$me, 'macroFormPrint']);
+ }
+
+
+ /********************* macros ****************d*g**/
+
+
+ /**
+ * {form ...}
+ */
+ public function macroForm(MacroNode $node, PhpWriter $writer)
+ {
+ if ($node->modifiers) {
+ throw new CompileException('Modifiers are not allowed in ' . $node->getNotation());
+ }
+
+ if ($node->prefix) {
+ throw new CompileException('Did you mean
+';
+
+echo '';
+
+foreach ($panels as $panel) {
+ $content = $panel->panel ? ($panel->panel . "\n" . $icons) : '';
+ $class = 'tracy-panel ' . ($type === 'ajax' ? '' : 'tracy-panel-persist') . ' tracy-panel-' . $type; ?>
+
'>
';
+echo '
';
diff --git a/vendor/tracy/tracy/src/Tracy/Bar/panels/dumps.panel.phtml b/vendor/tracy/tracy/src/Tracy/Bar/panels/dumps.panel.phtml
new file mode 100644
index 0000000..28c146c
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Bar/panels/dumps.panel.phtml
@@ -0,0 +1,29 @@
+
+
+
+Dumps
+
+
+
+
+
= Helpers::escapeHtml($item['title']) ?>
+
+
+ = $item['dump'] ?>
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/Bar/panels/dumps.tab.phtml b/vendor/tracy/tracy/src/Tracy/Bar/panels/dumps.tab.phtml
new file mode 100644
index 0000000..12e0e0b
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Bar/panels/dumps.tab.phtml
@@ -0,0 +1,13 @@
+
+
+dumps
diff --git a/vendor/tracy/tracy/src/Tracy/Bar/panels/errors.panel.phtml b/vendor/tracy/tracy/src/Tracy/Bar/panels/errors.panel.phtml
new file mode 100644
index 0000000..96883dd
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Bar/panels/errors.panel.phtml
@@ -0,0 +1,20 @@
+
+Warnings
+
+
+
+ $count): [$file, $line, $message] = explode('|', $item, 3) ?>
+
+ = $count ? "$count\xC3\x97" : '' ?>
+ = Helpers::escapeHtml($message), ' in ', Helpers::editorLink($file, (int) $line) ?>
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/Bar/panels/errors.tab.phtml b/vendor/tracy/tracy/src/Tracy/Bar/panels/errors.tab.phtml
new file mode 100644
index 0000000..70b0a53
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Bar/panels/errors.tab.phtml
@@ -0,0 +1,25 @@
+
+
+
+
+= $sum = array_sum($data), $sum > 1 ? ' warnings' : ' warning' ?>
+
diff --git a/vendor/tracy/tracy/src/Tracy/Bar/panels/info.panel.phtml b/vendor/tracy/tracy/src/Tracy/Bar/panels/info.panel.phtml
new file mode 100644
index 0000000..3f6af5d
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Bar/panels/info.panel.phtml
@@ -0,0 +1,125 @@
+cpuUsage) && $this->time) {
+ foreach (getrusage() as $key => $val) {
+ $this->cpuUsage[$key] -= $val;
+ }
+ $userUsage = -round(($this->cpuUsage['ru_utime.tv_sec'] * 1e6 + $this->cpuUsage['ru_utime.tv_usec']) / $this->time / 10000);
+ $systemUsage = -round(($this->cpuUsage['ru_stime.tv_sec'] * 1e6 + $this->cpuUsage['ru_stime.tv_usec']) / $this->time / 10000);
+}
+
+$countClasses = function (array $list): int {
+ return count(array_filter($list, function (string $name): bool {
+ return (new \ReflectionClass($name))->isUserDefined();
+ }));
+};
+
+$ipFormatter = static function (?string $ip): ?string {
+ if ($ip === '127.0.0.1' || $ip === '::1') {
+ $ip .= ' (localhost)';
+ }
+ return $ip;
+};
+
+$opcache = function_exists('opcache_get_status') ? @opcache_get_status() : null; // @ can be restricted
+$cachedFiles = isset($opcache['scripts']) ? array_intersect(array_keys($opcache['scripts']), get_included_files()) : [];
+$jit = $opcache['jit'] ?? null;
+
+$info = [
+ 'Execution time' => number_format($this->time * 1000, 1, '.', "\u{202f}") . "\u{202f}ms",
+ 'CPU usage user + system' => isset($userUsage) ? (int) $userUsage . "\u{202f}% + " . (int) $systemUsage . "\u{202f}%" : null,
+ 'Peak of allocated memory' => number_format(memory_get_peak_usage() / 1000000, 2, '.', "\u{202f}") . "\u{202f}MB",
+ 'Included files' => count(get_included_files()),
+ 'Classes + interfaces + traits' => $countClasses(get_declared_classes()) . ' + '
+ . $countClasses(get_declared_interfaces()) . ' + ' . $countClasses(get_declared_traits()),
+ 'OPcache' => $opcache ? round(count($cachedFiles) * 100 / count(get_included_files())) . "\u{202f}% cached" : '–',
+ 'JIT' => empty($jit['buffer_size']) ? '–' : round(($jit['buffer_size'] - $jit['buffer_free']) / $jit['buffer_size'] * 100) . "\u{202f}% used",
+ 'Your IP' => $ipFormatter($_SERVER['REMOTE_ADDR'] ?? null),
+ 'Server IP' => $ipFormatter($_SERVER['SERVER_ADDR'] ?? null),
+ 'HTTP method / response code' => isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] . ' / ' . http_response_code() : null,
+ 'PHP' => PHP_VERSION . ' ' . (PHP_ZTS ? 'TS' : 'NTS'),
+ 'Xdebug' => extension_loaded('xdebug') ? phpversion('xdebug') . ' (' . implode(', ', xdebug_info('mode')) . ')' : null,
+ 'Tracy' => Debugger::Version,
+ 'Server' => $_SERVER['SERVER_SOFTWARE'] ?? null,
+];
+
+$info = array_map('strval', array_filter($info + (array) $this->data));
+
+$packages = $devPackages = [];
+if (class_exists('Composer\Autoload\ClassLoader', autoload: false)) {
+ $baseDir = (function () {
+ @include dirname((new \ReflectionClass('Composer\Autoload\ClassLoader'))->getFileName()) . '/autoload_psr4.php'; // @ may not exist
+ return $baseDir;
+ })();
+ $composer = @json_decode((string) file_get_contents($baseDir . '/composer.lock')); // @ may not exist or be valid
+ [$packages, $devPackages] = [(array) @$composer->packages, (array) @$composer->{'packages-dev'}]; // @ keys may not exist
+ foreach ([&$packages, &$devPackages] as &$items) {
+ array_walk($items, function ($package) {
+ $package->hash = $package->source->reference ?? $package->dist->reference ?? null;
+ }, $items);
+ usort($items, function ($a, $b): int { return $a->name <=> $b->name; });
+ }
+}
+
+?>
+
+
+System info
+
+
+
+
+ $val): ?>
+
+ 25): ?>
+ = Helpers::escapeHtml($key) ?> = Helpers::escapeHtml($val) ?>
+
+ = Helpers::escapeHtml($key) ?> = Helpers::escapeHtml($val) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ = Helpers::escapeHtml($package->name) ?> = Helpers::escapeHtml($package->version . (strpos($package->version, 'dev') !== false && $package->hash ? ' #' . substr($package->hash, 0, 4) : '')) ?>
+
+
+
+
+
+
Dev Packages
+
+
+ = Helpers::escapeHtml($package->name) ?> = Helpers::escapeHtml($package->version . (strpos($package->version, 'dev') !== false && $package->hash ? ' #' . substr($package->hash, 0, 4) : '')) ?>
+
+
+
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/Bar/panels/info.tab.phtml b/vendor/tracy/tracy/src/Tracy/Bar/panels/info.tab.phtml
new file mode 100644
index 0000000..1e8c4da
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Bar/panels/info.tab.phtml
@@ -0,0 +1,15 @@
+time = microtime(true) - Debugger::$time;
+
+?>
+
+
+= number_format($this->time * 1000, 1, '.', "\u{202f}") ?> ms
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php b/vendor/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php
new file mode 100644
index 0000000..0a30592
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/BlueScreen.php
@@ -0,0 +1,502 @@
+ */
+ private \WeakMap $fibers;
+
+
+ public function __construct()
+ {
+ $this->collapsePaths = preg_match('#(.+/vendor)/tracy/tracy/src/Tracy/BlueScreen$#', strtr(__DIR__, '\\', '/'), $m)
+ ? [$m[1] . '/tracy', $m[1] . '/nette', $m[1] . '/latte']
+ : [dirname(__DIR__)];
+ $this->fileGenerators[] = [self::class, 'generateNewPhpFileContents'];
+ $this->fibers = new \WeakMap;
+ }
+
+
+ /**
+ * Add custom panel as function (?\Throwable $e): ?array
+ * @return static
+ */
+ public function addPanel(callable $panel): self
+ {
+ if (!in_array($panel, $this->panels, true)) {
+ $this->panels[] = $panel;
+ }
+
+ return $this;
+ }
+
+
+ /**
+ * Add action.
+ * @return static
+ */
+ public function addAction(callable $action): self
+ {
+ $this->actions[] = $action;
+ return $this;
+ }
+
+
+ /**
+ * Add new file generator.
+ * @param callable(string): ?string $generator
+ * @return static
+ */
+ public function addFileGenerator(callable $generator): self
+ {
+ $this->fileGenerators[] = $generator;
+ return $this;
+ }
+
+
+ public function addFiber(\Fiber|\Generator $fiber): static
+ {
+ $this->fibers[$fiber] = true;
+ return $this;
+ }
+
+
+ /**
+ * Renders blue screen.
+ */
+ public function render(\Throwable $exception): void
+ {
+ if (!headers_sent()) {
+ header('Content-Type: text/html; charset=UTF-8');
+ }
+
+ $this->renderTemplate($exception, __DIR__ . '/assets/page.phtml');
+ }
+
+
+ /** @internal */
+ public function renderToAjax(\Throwable $exception, DeferredContent $defer): void
+ {
+ $defer->addSetup('Tracy.BlueScreen.loadAjax', Helpers::capture(fn() => $this->renderTemplate($exception, __DIR__ . '/assets/content.phtml')));
+ }
+
+
+ /**
+ * Renders blue screen to file (if file exists, it will not be overwritten).
+ */
+ public function renderToFile(\Throwable $exception, string $file): bool
+ {
+ if ($handle = @fopen($file, 'x')) {
+ ob_start(); // double buffer prevents sending HTTP headers in some PHP
+ ob_start(function ($buffer) use ($handle): void { fwrite($handle, $buffer); }, 4096);
+ $this->renderTemplate($exception, __DIR__ . '/assets/page.phtml', toScreen: false);
+ ob_end_flush();
+ ob_end_clean();
+ fclose($handle);
+ return true;
+ }
+
+ return false;
+ }
+
+
+ private function renderTemplate(\Throwable $exception, string $template, bool $toScreen = true): void
+ {
+ [$generators, $fibers] = $this->findGeneratorsAndFibers($exception);
+ $headersSent = headers_sent($headersFile, $headersLine);
+ $obStatus = Debugger::$obStatus;
+ $showEnvironment = $this->showEnvironment && (!str_contains($exception->getMessage(), 'Allowed memory size'));
+ $info = array_filter($this->info);
+ $source = Helpers::getSource();
+ $title = $exception instanceof \ErrorException
+ ? Helpers::errorTypeToString($exception->getSeverity())
+ : get_debug_type($exception);
+ $lastError = $exception instanceof \ErrorException || $exception instanceof \Error
+ ? null
+ : error_get_last();
+
+ if (function_exists('apache_request_headers')) {
+ $httpHeaders = apache_request_headers();
+ } else {
+ $httpHeaders = array_filter($_SERVER, fn($k) => strncmp($k, 'HTTP_', 5) === 0, ARRAY_FILTER_USE_KEY);
+ $httpHeaders = array_combine(array_map(fn($k) => strtolower(strtr(substr($k, 5), '_', '-')), array_keys($httpHeaders)), $httpHeaders);
+ }
+
+ $snapshot = &$this->snapshot;
+ $snapshot = [];
+ $dump = $this->getDumper();
+
+ $css = array_map('file_get_contents', array_merge([
+ __DIR__ . '/../assets/reset.css',
+ __DIR__ . '/assets/bluescreen.css',
+ __DIR__ . '/../assets/toggle.css',
+ __DIR__ . '/../assets/table-sort.css',
+ __DIR__ . '/../assets/tabs.css',
+ __DIR__ . '/../Dumper/assets/dumper-light.css',
+ ], Debugger::$customCssFiles));
+ $css = Helpers::minifyCss(implode('', $css));
+
+ $nonceAttr = $toScreen ? Helpers::getNonceAttr() : null;
+ $actions = $toScreen ? $this->renderActions($exception) : [];
+
+ require $template;
+ }
+
+
+ /**
+ * @return \stdClass[]
+ */
+ private function renderPanels(?\Throwable $ex): array
+ {
+ $obLevel = ob_get_level();
+ $res = [];
+ foreach ($this->panels as $callback) {
+ try {
+ $panel = $callback($ex);
+ if (empty($panel['tab']) || empty($panel['panel'])) {
+ continue;
+ }
+
+ $res[] = (object) $panel;
+ continue;
+ } catch (\Throwable $e) {
+ }
+
+ while (ob_get_level() > $obLevel) { // restore ob-level if broken
+ ob_end_clean();
+ }
+
+ is_callable($callback, true, $name);
+ $res[] = (object) [
+ 'tab' => "Error in panel $name",
+ 'panel' => nl2br(Helpers::escapeHtml($e)),
+ ];
+ }
+
+ return $res;
+ }
+
+
+ /**
+ * @return array[]
+ */
+ private function renderActions(\Throwable $ex): array
+ {
+ $actions = [];
+ foreach ($this->actions as $callback) {
+ $action = $callback($ex);
+ if (!empty($action['link']) && !empty($action['label'])) {
+ $actions[] = $action;
+ }
+ }
+
+ if (
+ property_exists($ex, 'tracyAction')
+ && !empty($ex->tracyAction['link'])
+ && !empty($ex->tracyAction['label'])
+ ) {
+ $actions[] = $ex->tracyAction;
+ }
+
+ if (preg_match('# ([\'"])(\w{3,}(?:\\\\\w{2,})+)\1#i', $ex->getMessage(), $m)) {
+ $class = $m[2];
+ if (
+ !class_exists($class, false) && !interface_exists($class, false) && !trait_exists($class, false)
+ && ($file = Helpers::guessClassFile($class)) && !@is_file($file) // @ - may trigger error
+ ) {
+ [$content, $line] = $this->generateNewFileContents($file, $class);
+ $actions[] = [
+ 'link' => Helpers::editorUri($file, $line, 'create', '', $content),
+ 'label' => 'create class',
+ ];
+ }
+ }
+
+ if (preg_match('# ([\'"])((?:/|[a-z]:[/\\\\])\w[^\'"]+\.\w{2,5})\1#i', $ex->getMessage(), $m)) {
+ $file = $m[2];
+ if (@is_file($file)) { // @ - may trigger error
+ $label = 'open';
+ $content = '';
+ $line = 1;
+ } else {
+ $label = 'create';
+ [$content, $line] = $this->generateNewFileContents($file);
+ }
+
+ $actions[] = [
+ 'link' => Helpers::editorUri($file, $line, $label, '', $content),
+ 'label' => $label . ' file',
+ ];
+ }
+
+ $query = ($ex instanceof \ErrorException ? '' : get_debug_type($ex) . ' ')
+ . preg_replace('#\'.*\'|".*"#Us', '', $ex->getMessage());
+ $actions[] = [
+ 'link' => 'https://www.google.com/search?sourceid=tracy&q=' . urlencode($query),
+ 'label' => 'search',
+ 'external' => true,
+ ];
+
+ if (
+ $ex instanceof \ErrorException
+ && !empty($ex->skippable)
+ && preg_match('#^https?://#', $source = Helpers::getSource())
+ ) {
+ $actions[] = [
+ 'link' => $source . (strpos($source, '?') ? '&' : '?') . '_tracy_skip_error',
+ 'label' => 'skip error',
+ ];
+ }
+
+ return $actions;
+ }
+
+
+ /**
+ * Returns syntax highlighted source code.
+ */
+ public static function highlightFile(
+ string $file,
+ int $line,
+ int $lines = 15,
+ bool $php = true,
+ int $column = 0,
+ ): ?string
+ {
+ $source = @file_get_contents($file); // @ file may not exist
+ if ($source === false) {
+ return null;
+ }
+
+ $source = $php
+ ? CodeHighlighter::highlightPhp($source, $line, $column)
+ : '' . CodeHighlighter::highlightLine(htmlspecialchars($source, ENT_IGNORE, 'UTF-8'), $line, $column) . '
';
+
+ if ($editor = Helpers::editorUri($file, $line)) {
+ $source = substr_replace($source, ' title="Ctrl-Click to open in editor" data-tracy-href="' . Helpers::escapeHtml($editor) . '"', 4, 0);
+ }
+
+ return $source;
+ }
+
+
+ /**
+ * Returns syntax highlighted source code.
+ */
+ public static function highlightPhp(string $source, int $line, int $lines = 15, int $column = 0): string
+ {
+ return CodeHighlighter::highlightPhp($source, $line, $column);
+ }
+
+
+ /**
+ * Returns highlighted line in HTML code.
+ */
+ public static function highlightLine(string $html, int $line, int $lines = 15, int $column = 0): string
+ {
+ return CodeHighlighter::highlightLine($html, $line, $column);
+ }
+
+
+ /**
+ * Should a file be collapsed in stack trace?
+ * @internal
+ */
+ public function isCollapsed(string $file): bool
+ {
+ $file = strtr($file, '\\', '/') . '/';
+ foreach ($this->collapsePaths as $path) {
+ $path = strtr($path, '\\', '/') . '/';
+ if (strncmp($file, $path, strlen($path)) === 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ /** @internal */
+ public function getDumper(): \Closure
+ {
+ return fn($v, $k = null): string => Dumper::toHtml($v, [
+ Dumper::DEPTH => $this->maxDepth,
+ Dumper::TRUNCATE => $this->maxLength,
+ Dumper::ITEMS => $this->maxItems,
+ Dumper::SNAPSHOT => &$this->snapshot,
+ Dumper::LOCATION => Dumper::LOCATION_CLASS,
+ Dumper::SCRUBBER => $this->scrubber,
+ Dumper::KEYS_TO_HIDE => $this->keysToHide,
+ ], $k);
+ }
+
+
+ public function formatMessage(\Throwable $exception): string
+ {
+ $msg = Helpers::encodeString(trim((string) $exception->getMessage()), self::MaxMessageLength, showWhitespaces: false);
+
+ // highlight 'string'
+ $msg = preg_replace(
+ '#\'\S(?:[^\']|\\\\\')*\S\'|"\S(?:[^"]|\\\\")*\S"#',
+ '$0 ',
+ $msg,
+ );
+
+ // clickable class & methods
+ $msg = preg_replace_callback(
+ '#(\w+\\\\[\w\\\\]+\w)(?:::(\w+))?#',
+ function ($m) {
+ if (isset($m[2]) && method_exists($m[1], $m[2])) {
+ $r = new \ReflectionMethod($m[1], $m[2]);
+ } elseif (class_exists($m[1], false) || interface_exists($m[1], false)) {
+ $r = new \ReflectionClass($m[1]);
+ }
+
+ if (empty($r) || !$r->getFileName()) {
+ return $m[0];
+ }
+
+ return '' . $m[0] . ' ';
+ },
+ $msg,
+ );
+
+ // clickable file name
+ $msg = preg_replace_callback(
+ '#([\w\\\\/.:-]+\.(?:php|phpt|phtml|latte|neon))(?|:(\d+)| on line (\d+))?#',
+ fn($m) => @is_file($m[1]) // @ - may trigger error
+ ? '' . $m[0] . ' '
+ : $m[0],
+ $msg,
+ );
+
+ return $msg;
+ }
+
+
+ private function renderPhpInfo(): void
+ {
+ ob_start();
+ @phpinfo(INFO_LICENSE); // @ phpinfo may be disabled
+ $license = ob_get_clean();
+ ob_start();
+ @phpinfo(INFO_CONFIGURATION | INFO_MODULES); // @ phpinfo may be disabled
+ $info = ob_get_clean();
+
+ if (!str_contains($license, '', Helpers::escapeHtml($info), '';
+ } else {
+ $info = str_replace('|.+\z| |Configuration #s', '', $info);
+ }
+ }
+
+
+ /** @internal */
+ private function generateNewFileContents(string $file, ?string $class = null): array
+ {
+ foreach (array_reverse($this->fileGenerators) as $generator) {
+ $content = $generator($file, $class);
+ if ($content !== null) {
+ $line = 1;
+ $pos = strpos($content, '$END$');
+ if ($pos !== false) {
+ $content = substr_replace($content, '', $pos, 5);
+ $line = substr_count($content, "\n", 0, $pos) + 1;
+ }
+
+ return [$content, $line];
+ }
+ }
+
+ return ['', 1];
+ }
+
+
+ /** @internal */
+ public static function generateNewPhpFileContents(string $file, ?string $class = null): ?string
+ {
+ if (substr($file, -4) !== '.php') {
+ return null;
+ }
+
+ $res = "isStarted() && !$obj->isTerminated()) {
+ $fibers[spl_object_id($obj)] = $obj;
+ }
+ };
+
+ foreach ($this->fibers as $k => $v) {
+ $add($k);
+ }
+
+ Helpers::traverseValue($object, $add);
+ return [$generators, $fibers];
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/CodeHighlighter.php b/vendor/tracy/tracy/src/Tracy/BlueScreen/CodeHighlighter.php
new file mode 100644
index 0000000..fb5ae0f
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/CodeHighlighter.php
@@ -0,0 +1,139 @@
+]*>#', function ($m) use (&$openTags, &$closeTags) {
+ if ($m[0][1] === '/') {
+ array_pop($openTags);
+ array_shift($closeTags);
+ } else {
+ $openTags[] = $m[0];
+ array_unshift($closeTags, "$m[1]>");
+ }
+ }, $lines[$n]);
+
+ if ($n === $line) {
+ $s = strip_tags($lines[$n]);
+ if ($column) {
+ $s = preg_replace(
+ '#((?:&.*?;|[^&]){' . ($column - 1) . '})(&.*?;|.)#u',
+ '\1\2 ',
+ $s . ' ',
+ 1,
+ );
+ }
+ $out .= sprintf("%{$numWidth}s: %s \n%s", $n, $s, implode('', $openTags));
+ } else {
+ $out .= sprintf("%{$numWidth}s: %s\n", $n, $lines[$n]);
+ }
+ }
+
+ $out .= implode('', $closeTags);
+ return $out;
+ }
+
+
+ /**
+ * Returns syntax highlighted source code.
+ */
+ public static function highlightPhp(string $code, int $line, int $column = 0): string
+ {
+ $html = self::highlightPhpCode($code);
+ $html = self::highlightLine($html, $line, $column);
+ return "$html
";
+ }
+
+
+ private static function highlightPhpCode(string $code): string
+ {
+ $code = str_replace("\r\n", "\n", $code);
+ $code = preg_replace('#(__halt_compiler\s*\(\)\s*;).*#is', '$1', $code);
+ $code = rtrim($code);
+ $code = preg_replace('#/\*sensitive\{\*/.*?/\*\}\*/#s', Dumper\Describer::HiddenValue, $code);
+
+ $last = $out = '';
+ foreach (\PhpToken::tokenize($code) as $token) {
+ $next = match ($token->id) {
+ T_COMMENT, T_DOC_COMMENT, T_INLINE_HTML => 'tracy-code-comment',
+ T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, T_CLOSE_TAG, T_LINE, T_FILE, T_DIR, T_TRAIT_C, T_METHOD_C, T_FUNC_C, T_NS_C, T_CLASS_C,
+ T_STRING, T_NAME_FULLY_QUALIFIED, T_NAME_QUALIFIED, T_NAME_RELATIVE => '',
+ T_LNUMBER, T_DNUMBER => 'tracy-dump-number',
+ T_VARIABLE => 'tracy-code-var',
+ T_ENCAPSED_AND_WHITESPACE, T_CONSTANT_ENCAPSED_STRING => 'tracy-dump-string',
+ T_WHITESPACE => $last,
+ default => 'tracy-code-keyword',
+ };
+
+ if ($last !== $next) {
+ if ($last !== '') {
+ $out .= '';
+ }
+ $last = $next;
+ if ($last !== '') {
+ $out .= "";
+ }
+ }
+
+ $out .= strtr($token->text, ['<' => '<', '>' => '>', '&' => '&', "\t" => ' ']);
+ }
+ if ($last !== '') {
+ $out .= ' ';
+ }
+ return $out;
+ }
+
+
+ /**
+ * Returns syntax highlighted source code to Terminal.
+ */
+ public static function highlightPhpCli(string $code, int $line, int $column = 0): string
+ {
+ return Helpers::htmlToAnsi(
+ self::highlightPhp($code, $line, $column),
+ [
+ 'string' => '1;32',
+ 'number' => '1;32',
+ 'code-comment' => '1;30',
+ 'code-keyword' => '1;37',
+ 'code-var' => '1;36',
+ 'line' => '1;30',
+ 'line-highlight' => "1;37m\e[41",
+ ],
+ );
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.css b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.css
new file mode 100644
index 0000000..bbe86c9
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.css
@@ -0,0 +1,422 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+html.tracy-bs-visible,
+html.tracy-bs-visible body {
+ display: block;
+ overflow: auto;
+}
+
+#tracy-bs {
+ font: 9pt/1.5 Verdana, sans-serif;
+ background: white;
+ color: #333;
+ position: absolute;
+ z-index: 20000;
+ left: 0;
+ top: 0;
+ width: 100%;
+ text-align: left;
+}
+
+#tracy-bs a {
+ text-decoration: none;
+ color: #328ADC;
+ padding: 0 4px;
+ margin: 0 -4px;
+}
+
+#tracy-bs a + a {
+ margin-left: 0;
+}
+
+#tracy-bs a:hover,
+#tracy-bs a:focus {
+ color: #085AA3;
+}
+
+#tracy-bs-toggle {
+ position: absolute;
+ right: .5em;
+ top: .5em;
+ text-decoration: none;
+ background: #CD1818;
+ color: white !important;
+ padding: 3px;
+}
+
+#tracy-bs-toggle.tracy-collapsed {
+ position: fixed;
+}
+
+.tracy-bs-main {
+ display: flex;
+ flex-direction: column;
+ padding-bottom: 80vh;
+}
+
+.tracy-bs-main.tracy-collapsed {
+ display: none;
+}
+
+#tracy-bs :where(:is(
+ h1, h2, h3, h4, h5, h6,
+ p,
+ ol, ul, dl,
+ pre, table, hr,
+ .tracy-section-panel,
+ .tracy-pane
+):not(:first-child)) {
+ margin-top: var(--tracy-space);
+}
+
+#tracy-bs h1 {
+ font-size: 15pt;
+ font-weight: normal;
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, .3);
+}
+
+#tracy-bs h1 span {
+ white-space: pre-wrap;
+}
+
+#tracy-bs h2 {
+ font-size: 14pt;
+ font-weight: normal;
+}
+
+#tracy-bs h3 {
+ font-size: 10pt;
+ font-weight: bold;
+}
+
+#tracy-bs pre,
+#tracy-bs code,
+#tracy-bs table {
+ font: 9pt/1.5 Consolas, monospace !important;
+}
+
+#tracy-bs pre,
+#tracy-bs table {
+ background: #FDF5CE;
+ padding: .4em .7em;
+ border: 2px solid #ffffffa6;
+ box-shadow: 1px 2px 6px #00000005;
+ overflow: auto;
+}
+
+#tracy-bs table pre {
+ padding: 0;
+ margin: 0;
+ border: none;
+ box-shadow: none;
+}
+
+#tracy-bs table {
+ border-collapse: collapse;
+ width: 100%;
+}
+
+#tracy-bs td,
+#tracy-bs th {
+ vertical-align: top;
+ text-align: left;
+ padding: 2px 6px;
+ border: 1px solid #e6dfbf;
+}
+
+#tracy-bs th {
+ font-weight: bold;
+}
+
+#tracy-bs tr > :first-child {
+ width: 20%;
+}
+
+#tracy-bs tr:nth-child(2n),
+#tracy-bs tr:nth-child(2n) pre {
+ background-color: #F7F0CB;
+}
+
+#tracy-bs .tracy-footer--sticky {
+ position: fixed;
+ width: 100%;
+ bottom: 0;
+}
+
+#tracy-bs footer ul {
+ font-size: 7pt;
+ padding: var(--tracy-space);
+ margin: var(--tracy-space) 0 0;
+ color: #777;
+ background: #F6F5F3;
+ border-top: 1px solid #DDD;
+ list-style: none;
+}
+
+#tracy-bs .tracy-footer-logo {
+ position: relative;
+}
+
+#tracy-bs .tracy-footer-logo a {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ width: 100px;
+ height: 50px;
+ background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAAAUBAMAAAD/1DctAAAAMFBMVEWupZzj39rEvbTy8O3X0sz9/PvGwLu8tavQysHq6OS0rKP5+Pbd2dT29fPMxbzPx8DKErMJAAAACXBIWXMAAAsTAAALEwEAmpwYAAACGUlEQVQoFX3TQWgTQRQA0MWLIJJDYehBTykhG5ERTx56K1u8eEhCYtomE7x5L4iLh0ViF7egewuFFqSIYE6hIHsIYQ6CQSg9CDKn4QsNCRlB59C74J/ZNHW1+An5+bOPyf6/s46oz2P+A0yIeZZ2ieEHi6TOnLKTxvWq+b52mxlVO3xnM1s7xLX1504XQH65OnW2dBqn7cCkYsFsfYsWpyY/2salmFTpEyzeR8zosYqMdiPDXdyU52K1wgEa/SjGpdEwUAxqvRfckQCDOyFearsEHe2grvkh/cFAHKvdtI3lcVceKQIOFpv+FOZaNPQBwJZLPp+hfrvT5JZXaUFsR8zqQc9qSgAharkfS5M/5F6nGJJAtXq/eLr3ucZpHccSxOOIPaQhtHohpCH2Xu6rLmQ0djnr4/+J3C6v+AW8/XWYxwYNdlhWj/P5fPSTQwVr0T9lGxdaBCqErNZaqYnEwbkjEB3NasGF3lPdrHa1nnxNOMgj0+neePUPjd2v/qVvUv29ifvc19huQ48qwXShy/9o8o3OSk0cs37mOFd0Ydgvsf/oZEnPVtggfd66lORn9mDyyzXU13SRtH2L6aR5T/snGAcZPfAXz5J1YlJWBEuxdMYqQecpBrlM49xAbmqyHA+xlA1FxBtqT2xmJoNXZlIt74ZBLeJ9ZGDqByNI7p543idzJ23vXEv7IgnsxiS+eNtwNbFdLq7+Bi4wQ0I4SVb9AAAAAElFTkSuQmCC') no-repeat;
+ opacity: .6;
+ padding: 0;
+ margin: 0;
+}
+
+#tracy-bs .tracy-footer-logo a:hover,
+#tracy-bs .tracy-footer-logo a:focus {
+ opacity: 1;
+ transition: opacity 0.1s;
+}
+
+
+#tracy-bs .tracy-section {
+ padding: var(--tracy-space);
+}
+
+#tracy-bs .tracy-section-panel {
+ background: #5040200E;
+ padding: var(--tracy-space);
+ border-radius: 8px;
+ box-shadow: inset 1px 1px 0px 0 #00000005;
+ overflow: hidden;
+}
+
+#tracy-bs .outer, /* deprecated */
+#tracy-bs .tracy-pane {
+ overflow: auto;
+}
+
+#tracy-bs.tracy-mac .tracy-pane {
+ padding-bottom: 12px;
+}
+
+
+/* header */
+#tracy-bs .tracy-section--error {
+ background: #CD1818;
+ color: white;
+}
+
+#tracy-bs .tracy-section--error p,
+#tracy-bs .tracy-section--error h1 {
+ font-size: 13pt;
+ color: white;
+}
+
+#tracy-bs .tracy-section--error::selection,
+#tracy-bs .tracy-section--error ::selection {
+ color: black !important;
+ background: #FDF5CE !important;
+}
+
+#tracy-bs .tracy-section--error h1 a {
+ color: #ffefa1 !important;
+}
+
+#tracy-bs .tracy-section--error span span {
+ font-size: 80%;
+ color: rgba(255, 255, 255, 0.5);
+ text-shadow: none;
+}
+
+#tracy-bs .tracy-section--error a.tracy-action {
+ color: white !important;
+ opacity: 0;
+ font-size: .7em;
+ border-bottom: none !important;
+}
+
+#tracy-bs .tracy-section--error:hover a.tracy-action {
+ opacity: .6;
+}
+
+#tracy-bs .tracy-section--error a.tracy-action:hover {
+ opacity: 1;
+}
+
+#tracy-bs .tracy-section--error i {
+ color: #ffefa1;
+ font-style: normal;
+}
+
+#tracy-bs .tracy-section--error:has(.tracy-caused) {
+ border-radius: 0 0 0 8px;
+ overflow: hidden;
+}
+
+#tracy-bs .tracy-caused {
+ margin: var(--tracy-space) calc(-1 * var(--tracy-space)) calc(-1 * var(--tracy-space));
+ padding: .3em var(--tracy-space);
+ background: #df8075;
+ white-space: nowrap;
+}
+
+#tracy-bs .tracy-caused a {
+ color: white;
+}
+
+
+
+/* source code */
+#tracy-bs pre.tracy-code > div {
+ min-width: 100%;
+ float: left;
+ white-space: pre;
+}
+
+#tracy-bs .tracy-code-comment {
+ color: rgba(0, 0, 0, 0.5);
+ font-style: italic;
+}
+
+#tracy-bs .tracy-code-keyword {
+ color: #D24;
+ font-weight: bold;
+}
+
+#tracy-bs .tracy-code-var {
+ font-weight: bold;
+}
+
+#tracy-bs .tracy-line-highlight {
+ background: #CD1818;
+ color: white;
+ font-weight: bold;
+ font-style: normal;
+ display: block;
+ padding: 0 1ch;
+ margin: 0 -1ch -1lh;
+}
+
+#tracy-bs .tracy-column-highlight {
+ display: inline-block;
+ backdrop-filter: grayscale(1);
+ margin: 0 -1px;
+ padding: 0 1px;
+}
+
+#tracy-bs .tracy-line {
+ color: #9F9C7F;
+ font-weight: normal;
+ font-style: normal;
+}
+
+#tracy-bs a.tracy-editor {
+ color: inherit;
+ border-bottom: 1px dotted rgba(0, 0, 0, .3);
+ border-radius: 3px;
+}
+
+#tracy-bs a.tracy-editor:hover {
+ background: #0001;
+}
+
+#tracy-bs span[data-tracy-href] {
+ border-bottom: 1px dotted rgba(0, 0, 0, .3);
+}
+
+#tracy-bs .tracy-dump-whitespace {
+ color: #0003;
+}
+
+#tracy-bs .tracy-callstack {
+ display: grid;
+ overflow: auto;
+ grid-template-columns: max-content 1fr;
+ row-gap: calc(.5 * var(--tracy-space));
+}
+
+#tracy-bs .tracy-callstack-file {
+ text-align: right;
+ padding-right: var(--tracy-space);
+ white-space: nowrap;
+}
+
+#tracy-bs .tracy-callstack-callee {
+ white-space: nowrap;
+}
+
+#tracy-bs .tracy-callstack-additional {
+ grid-column-start: 1;
+ grid-column-end: 3;
+}
+
+#tracy-bs .tracy-callstack-args tr:first-child > * {
+ position: relative;
+}
+
+#tracy-bs .tracy-callstack-args tr:first-child td:before {
+ position: absolute;
+ right: .3em;
+ content: 'may not be true';
+ opacity: .4;
+}
+
+#tracy-bs .tracy-panel-fadein {
+ animation: tracy-panel-fadein .12s ease;
+}
+
+@keyframes tracy-panel-fadein {
+ 0% {
+ opacity: 0;
+ }
+}
+
+#tracy-bs .tracy-section--causedby {
+ flex-direction: column;
+ padding: 0;
+}
+
+#tracy-bs .tracy-section--causedby:not(.tracy-collapsed) {
+ display: flex;
+}
+
+#tracy-bs .tracy-section--causedby .tracy-section--error {
+ background: #cd1818a6;
+}
+
+#tracy-bs .tracy-section--error + .tracy-section--stack {
+ margin-top: calc(1.5 * var(--tracy-space));
+}
+
+
+/* tabs */
+#tracy-bs .tracy-tab-bar {
+ display: flex;
+ list-style: none;
+ padding-left: 0;
+ margin: 0;
+ width: 100%;
+ font-size: 110%;
+ column-gap: var(--tracy-space);
+}
+
+#tracy-bs .tracy-tab-bar a {
+ display: block;
+ padding: calc(.5 * var(--tracy-space)) var(--tracy-space);
+ margin: 0;
+ height: 100%;
+ box-sizing: border-box;
+ border-radius: 5px 5px 0 0;
+ text-decoration: none;
+ transition: all 0.1s;
+}
+
+#tracy-bs .tracy-tab-bar > .tracy-active a {
+ background: white;
+}
+
+#tracy-bs .tracy-tab-panel {
+ border-top: 2px solid white;
+ padding-top: var(--tracy-space);
+ overflow: auto;
+}
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.js b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.js
new file mode 100644
index 0000000..c69cd5c
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/bluescreen.js
@@ -0,0 +1,76 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+class BlueScreen {
+ static init(ajax) {
+ BlueScreen.globalInit();
+
+ let blueScreen = document.getElementById('tracy-bs');
+
+ document.documentElement.classList.add('tracy-bs-visible');
+ if (navigator.platform.indexOf('Mac') > -1) {
+ blueScreen.classList.add('tracy-mac');
+ }
+
+ blueScreen.addEventListener('tracy-toggle', (e) => {
+ if (e.target.matches('#tracy-bs-toggle')) { // blue screen toggle
+ document.documentElement.classList.toggle('tracy-bs-visible', !e.detail.collapsed);
+
+ } else if (!e.target.matches('.tracy-dump *') && e.detail.originalEvent) { // panel toggle
+ e.detail.relatedTarget.classList.toggle('tracy-panel-fadein', !e.detail.collapsed);
+ }
+ });
+
+ if (!ajax) {
+ document.body.appendChild(blueScreen);
+ let id = location.href + document.querySelector('.tracy-section--error').textContent;
+ Tracy.Toggle.persist(blueScreen, sessionStorage.getItem('tracy-toggles-bskey') === id);
+ sessionStorage.setItem('tracy-toggles-bskey', id);
+ }
+
+ (new ResizeObserver(stickyFooter)).observe(blueScreen);
+
+ if (document.documentElement.classList.contains('tracy-bs-visible')) {
+ window.scrollTo(0, 0);
+ }
+ }
+
+
+ static globalInit() {
+ // enables toggling via ESC
+ document.addEventListener('keyup', (e) => {
+ if (e.keyCode === 27 && !e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey) { // ESC
+ Tracy.Toggle.toggle(document.getElementById('tracy-bs-toggle'));
+ }
+ });
+
+ Tracy.TableSort.init();
+ Tracy.Tabs.init();
+
+ window.addEventListener('scroll', stickyFooter);
+
+ BlueScreen.globalInit = function () {};
+ }
+
+
+ static loadAjax(content) {
+ let ajaxBs = document.getElementById('tracy-bs');
+ if (ajaxBs) {
+ ajaxBs.remove();
+ }
+ document.body.insertAdjacentHTML('beforeend', content);
+ ajaxBs = document.getElementById('tracy-bs');
+ Tracy.Dumper.init(ajaxBs);
+ BlueScreen.init(true);
+ }
+}
+
+function stickyFooter() {
+ let footer = document.querySelector('#tracy-bs footer');
+ footer.classList.toggle('tracy-footer--sticky', false); // to measure footer.offsetTop
+ footer.classList.toggle('tracy-footer--sticky', footer.offsetHeight + footer.offsetTop - window.innerHeight - document.documentElement.scrollTop < 0);
+}
+
+let Tracy = window.Tracy = window.Tracy || {};
+Tracy.BlueScreen = Tracy.BlueScreen || BlueScreen;
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/content.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/content.phtml
new file mode 100644
index 0000000..107b6a0
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/content.phtml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+renderPanels(null) as $panel): ?>
+bottom)) { $bottomPanels[] = $panel; continue; } ?>
+collapsed) || $panel->collapsed ? ' tracy-collapsed' : ''; ?>
+
+
+
+
+ = $panel->panel ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = $panel->panel ?>
+
+
+
+
+
+
+ >
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/page.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/page.phtml
new file mode 100644
index 0000000..a6846dc
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/page.phtml
@@ -0,0 +1,57 @@
+getCode() ? ' #' . $exception->getCode() : '';
+$chain = Helpers::getExceptionChain($exception);
+?>
+
+
+
+
+
+
+ = Helpers::escapeHtml($title . ': ' . $exception->getMessage() . $code) ?>
+
+ 1): ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-cli.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-cli.phtml
new file mode 100644
index 0000000..6d06e40
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-cli.phtml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
Process ID = Helpers::escapeHtml(getmypid()) ?>
+
+
php= Helpers::escapeHtml($tmp[1]) ?>
+
+
+
+
Arguments
+
+
+ $v): ?>
+ = Helpers::escapeHtml($k) ?> = $dump($v, $k) ?>
+
+
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-environment.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-environment.phtml
new file mode 100644
index 0000000..866ec89
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-environment.phtml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $v): ?>
+ = Helpers::escapeHtml($k) ?> = $dump($v, $k) ?>
+
+
+
+
+
+
+
+
+
+ $v): ?>
+ = Helpers::escapeHtml($k) ?> = $k === '__NF' ? 'Nette Session ' : $dump($v, $k) ?>
+
+
+
+
+
+
+
Nette Session
+
+
+ $v): ?>
+ = Helpers::escapeHtml($k) ?> = $dump($v, $k) ?>
+
+
+
+
+
+
+
+
+
+
+
+
+ $v): ?>
+ = Helpers::escapeHtml($k) ?> = $dump($v, $k) ?>
+
+
+
+
+
+
+
+ renderPhpInfo() ?>
+
+
+
+
+
+
+ = Dumper::toHtml($obStatus, [Dumper::COLLAPSE_COUNT => 10]) ?>
+
+
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-causedBy.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-causedBy.phtml
new file mode 100644
index 0000000..8807bf0
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-causedBy.phtml
@@ -0,0 +1,29 @@
+getPrevious();
+if (!$ex || in_array($ex, $exceptions, true)) {
+ return;
+}
+$exceptions[] = $ex;
+?>
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-exception.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-exception.phtml
new file mode 100644
index 0000000..104edd4
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception-exception.phtml
@@ -0,0 +1,21 @@
+
+
+
+
+ = $dump($ex) ?>
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception.phtml
new file mode 100644
index 0000000..fba0627
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-exception.phtml
@@ -0,0 +1,72 @@
+
+
+
+renderPanels($ex) as $panel): ?>
+
+
+
+
+ = $panel->panel ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-header.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-header.phtml
new file mode 100644
index 0000000..f4ab19f
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-header.phtml
@@ -0,0 +1,35 @@
+getSeverity())
+ : get_debug_type($ex);
+$code = $ex->getCode() ? ' #' . $ex->getCode() : '';
+
+?>
+
+ getMessage()): ?>= Helpers::escapeHtml($title . $code) ?>
+
+
+
+
+ getPrevious()): ?>
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-http.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-http.phtml
new file mode 100644
index 0000000..000ef1a
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-http.phtml
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $v): ?>
+ = Helpers::escapeHtml($k) ?> = $dump($v, $k) ?>
+
+
+
+
+
+
+
$_GET
+
+
empty
+
+
+
+ $v): ?>
+ = Helpers::escapeHtml($k) ?> = $dump($v, $k) ?>
+
+
+
+
+
+
+
+
+
+
$_POST
+
empty
+
+
POST (preview)
+ = $dump($post) ?>
+
+
+
$_POST
+
+
+ $v): ?>
+ = Helpers::escapeHtml($k) ?> = $dump($v, $k) ?>
+
+
+
+
+
+
+
$_COOKIE
+
+
empty
+
+
+
+ $v): ?>
+ = Helpers::escapeHtml($k) ?> = $dump($v, $k) ?>
+
+
+
+
+
+
+
+
+
Code: = Helpers::escapeHtml(http_response_code()) ?>
+
+
+
+
+ = Helpers::escapeHtml($s[0]) ?> = $dump(trim($s[1]), $s[0]) ?>
+
+
+
+
+
no headers
+
+
+
+
+
Headers have been sent, output started at = Helpers::editorLink($headersFile, $headersLine) ?> source
+
= BlueScreen::highlightFile($headersFile, $headersLine) ?>
+
+
Headers have been sent
+
+
Headers were not sent at the time the exception was thrown
+
+
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-lastMutedError.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-lastMutedError.phtml
new file mode 100644
index 0000000..a4f79f7
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-lastMutedError.phtml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
= Helpers::errorTypeToString($lastError['type']) ?>: = Helpers::escapeHtml($lastError['message']) ?>
+
Note: the last muted error may have nothing to do with the thrown exception.
+
+
+
= Helpers::editorLink($lastError['file'], $lastError['line']) ?>
+
= BlueScreen::highlightFile($lastError['file'], $lastError['line']) ?>
+
+
inner-code
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml
new file mode 100644
index 0000000..74b3744
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-callStack.phtml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+ $row): ?>
+
+
+
+
+ = Helpers::editorLink($row['file'], $row['line']) ?>
+
+ inner-code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = BlueScreen::highlightFile(...$sourceOriginal) ?>
+
+
+
+ = BlueScreen::highlightFile($sourceMapped['file'], $sourceMapped['line'], php: false) ?>
+
+
+
+
+ = BlueScreen::highlightFile(...$sourceOriginal) ?>
+
+
+
+
+
+getParameters();
+ } catch (\Exception) {
+ $params = [];
+ }
+ foreach ($row['args'] as $k => $v) {
+ $argName = isset($params[$k]) && !$params[$k]->isVariadic() ? $params[$k]->name : $k;
+ echo '', Helpers::escapeHtml((is_string($argName) ? '$' : '#') . $argName), ' ';
+ echo $dump($v, (string) $argName);
+ echo " \n";
+ }
+?>
+
+
+
+
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-exception.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-exception.phtml
new file mode 100644
index 0000000..7f578cc
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-exception.phtml
@@ -0,0 +1,38 @@
+getTrace();
+if (in_array($stack[0]['class'] ?? null, [DevelopmentStrategy::class, ProductionStrategy::class], true)) {
+ array_shift($stack);
+}
+if (($stack[0]['class'] ?? null) === Debugger::class && in_array($stack[0]['function'], ['shutdownHandler', 'errorHandler'], true)) {
+ array_shift($stack);
+}
+
+$expanded = null;
+if (
+ (!$ex instanceof \ErrorException || in_array($ex->getSeverity(), [E_USER_NOTICE, E_USER_WARNING, E_USER_DEPRECATED], true))
+ && $this->isCollapsed($ex->getFile())
+) {
+ foreach ($stack as $key => $row) {
+ if (isset($row['file']) && !$this->isCollapsed($row['file'])) {
+ $expanded = $key;
+ break;
+ }
+ }
+}
+
+$file = $ex->getFile();
+$line = $ex->getLine();
+
+require __DIR__ . '/section-stack-sourceFile.phtml';
+require __DIR__ . '/section-stack-callStack.phtml';
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-fiber.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-fiber.phtml
new file mode 100644
index 0000000..4427be8
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-fiber.phtml
@@ -0,0 +1,16 @@
+getTrace();
+$expanded = 0;
+
+require __DIR__ . '/section-stack-callStack.phtml';
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-generator.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-generator.phtml
new file mode 100644
index 0000000..60aa6fc
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-generator.phtml
@@ -0,0 +1,21 @@
+getTrace();
+$expanded = null;
+$execGenerator = $ref->getExecutingGenerator();
+$refExec = new \ReflectionGenerator($execGenerator);
+$file = $refExec->getExecutingFile();
+$line = $refExec->getExecutingLine();
+
+require __DIR__ . '/section-stack-sourceFile.phtml';
+require __DIR__ . '/section-stack-callStack.phtml';
diff --git a/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml
new file mode 100644
index 0000000..492a526
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/BlueScreen/assets/section-stack-sourceFile.phtml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
File: = Helpers::editorLink(...$sourceOriginal) ?>
+ = BlueScreen::highlightFile(...$sourceOriginal) ?>
+
+
+
+
File: = Helpers::editorLink($sourceMapped['file'], $sourceMapped['line']) ?>
+ = BlueScreen::highlightFile($sourceMapped['file'], $sourceMapped['line'], php: false) ?>
+
+
+
+
+
File: = Helpers::editorLink($file, $line) ?>
+
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/Debugger/Debugger.php b/vendor/tracy/tracy/src/Tracy/Debugger/Debugger.php
new file mode 100644
index 0000000..e0c1522
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Debugger/Debugger.php
@@ -0,0 +1,616 @@
+initialize();
+ self::dispatch();
+
+ if (self::$enabled) {
+ return;
+ }
+
+ register_shutdown_function([self::class, 'shutdownHandler']);
+ set_exception_handler(function (\Throwable $e) {
+ self::exceptionHandler($e);
+ exit(255);
+ });
+ set_error_handler([self::class, 'errorHandler']);
+
+ foreach ([
+ 'Bar/Bar',
+ 'Bar/DefaultBarPanel',
+ 'BlueScreen/BlueScreen',
+ 'BlueScreen/CodeHighlighter',
+ 'Dumper/Describer',
+ 'Dumper/Dumper',
+ 'Dumper/Exposer',
+ 'Dumper/Renderer',
+ 'Dumper/Value',
+ 'Logger/Logger',
+ 'Session/SessionStorage',
+ 'Session/FileSession',
+ 'Session/NativeSession',
+ 'Helpers',
+ ] as $path) {
+ require_once dirname(__DIR__) . "/$path.php";
+ }
+
+ self::$enabled = true;
+ }
+
+
+ public static function dispatch(): void
+ {
+ if (
+ !Helpers::isCli()
+ && self::getStrategy()->sendAssets()
+ ) {
+ self::$showBar = false;
+ exit;
+ }
+ }
+
+
+ /**
+ * Renders loading
+
+
+
+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 | Tracy is unable to log error.
+
+
+
+
diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Describer.php b/vendor/tracy/tracy/src/Tracy/Dumper/Describer.php
new file mode 100644
index 0000000..f0c017b
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Dumper/Describer.php
@@ -0,0 +1,360 @@
+ */
+ public array $resourceExposers = [];
+
+ /** @var array */
+ public array $objectExposers = [];
+
+ /** @var array */
+ public array $enumProperties = [];
+
+ /** @var (int|\stdClass)[] */
+ public array $references = [];
+
+
+ public function describe(mixed $var): \stdClass
+ {
+ uksort($this->objectExposers, fn($a, $b): int => $b === '' || (class_exists($a, false) && is_subclass_of($a, $b)) ? -1 : 1);
+
+ try {
+ return (object) [
+ 'value' => $this->describeVar($var),
+ 'snapshot' => $this->snapshot,
+ 'location' => $this->location ? self::findLocation() : null,
+ ];
+
+ } finally {
+ $free = [[], []];
+ $this->snapshot = &$free[0];
+ $this->references = &$free[1];
+ }
+ }
+
+
+ private function describeVar(mixed $var, int $depth = 0, ?int $refId = null): mixed
+ {
+ if ($var === null || is_bool($var)) {
+ return $var;
+ }
+
+ $m = 'describe' . explode(' ', gettype($var))[0];
+ return $this->$m($var, $depth, $refId);
+ }
+
+
+ private function describeInteger(int $num): Value|int
+ {
+ return $num <= self::JsSafeInteger && $num >= -self::JsSafeInteger
+ ? $num
+ : new Value(Value::TypeNumber, "$num");
+ }
+
+
+ private function describeDouble(float $num): Value|float
+ {
+ if (!is_finite($num)) {
+ return new Value(Value::TypeNumber, (string) $num);
+ }
+
+ $js = json_encode($num);
+ return strpos($js, '.')
+ ? $num
+ : new Value(Value::TypeNumber, "$js.0"); // to distinct int and float in JS
+ }
+
+
+ private function describeString(string $s, int $depth = 0): Value|string
+ {
+ $encoded = Helpers::encodeString($s, $depth ? $this->maxLength : null);
+ if ($encoded === $s) {
+ return $encoded;
+ } elseif (Helpers::isUtf8($s)) {
+ return new Value(Value::TypeStringHtml, $encoded, Helpers::utf8Length($s));
+ } else {
+ return new Value(Value::TypeBinaryHtml, $encoded, strlen($s));
+ }
+ }
+
+
+ private function describeArray(array $arr, int $depth = 0, ?int $refId = null): Value|array
+ {
+ if ($refId) {
+ $res = new Value(Value::TypeRef, 'p' . $refId);
+ $value = &$this->snapshot[$res->value];
+ if ($value && $value->depth <= $depth) {
+ return $res;
+ }
+
+ $value = new Value(Value::TypeArray);
+ $value->id = $res->value;
+ $value->depth = $depth;
+ if ($this->maxDepth && $depth >= $this->maxDepth) {
+ $value->length = count($arr);
+ return $res;
+ } elseif ($depth && $this->maxItems && count($arr) > $this->maxItems) {
+ $value->length = count($arr);
+ $arr = array_slice($arr, 0, $this->maxItems, preserve_keys: true);
+ }
+
+ $items = &$value->items;
+
+ } elseif ($arr && $this->maxDepth && $depth >= $this->maxDepth) {
+ return new Value(Value::TypeArray, null, count($arr));
+
+ } elseif ($depth && $this->maxItems && count($arr) > $this->maxItems) {
+ $res = new Value(Value::TypeArray, null, count($arr));
+ $res->depth = $depth;
+ $items = &$res->items;
+ $arr = array_slice($arr, 0, $this->maxItems, preserve_keys: true);
+ }
+
+ $items = [];
+ foreach ($arr as $k => $v) {
+ $refId = $this->getReferenceId($arr, $k);
+ $items[] = [
+ $this->describeVar($k, $depth + 1),
+ $this->isSensitive((string) $k, $v)
+ ? new Value(Value::TypeText, self::hideValue($v))
+ : $this->describeVar($v, $depth + 1, $refId),
+ ] + ($refId ? [2 => $refId] : []);
+ }
+
+ return $res ?? $items;
+ }
+
+
+ private function describeObject(object $obj, int $depth = 0): Value
+ {
+ $id = spl_object_id($obj);
+ $value = &$this->snapshot[$id];
+ if ($value && $value->depth <= $depth) {
+ return new Value(Value::TypeRef, $id);
+ }
+
+ $value = new Value(Value::TypeObject, get_debug_type($obj));
+ $value->id = $id;
+ $value->depth = $depth;
+ $value->holder = $obj; // to be not released by garbage collector in collecting mode
+ if ($this->location) {
+ $rc = $obj instanceof \Closure
+ ? new \ReflectionFunction($obj)
+ : new \ReflectionClass($obj);
+ if ($rc->getFileName() && ($editor = Helpers::editorUri($rc->getFileName(), $rc->getStartLine()))) {
+ $value->editor = (object) ['file' => $rc->getFileName(), 'line' => $rc->getStartLine(), 'url' => $editor];
+ }
+ }
+
+ if ($this->maxDepth && $depth < $this->maxDepth) {
+ $value->items = [];
+ $props = $this->exposeObject($obj, $value);
+ foreach ($props ?? [] as $k => $v) {
+ $this->addPropertyTo($value, (string) $k, $v, Value::PropertyVirtual, $this->getReferenceId($props, $k));
+ }
+ }
+
+ return new Value(Value::TypeRef, $id);
+ }
+
+
+ /**
+ * @param resource $resource
+ */
+ private function describeResource($resource, int $depth = 0): Value
+ {
+ $id = 'r' . (int) $resource;
+ $value = &$this->snapshot[$id];
+ if (!$value) {
+ $type = is_resource($resource) ? get_resource_type($resource) : 'closed';
+ $value = new Value(Value::TypeResource, $type . ' resource');
+ $value->id = $id;
+ $value->depth = $depth;
+ $value->items = [];
+ if (isset($this->resourceExposers[$type])) {
+ foreach (($this->resourceExposers[$type])($resource) as $k => $v) {
+ $value->items[] = [htmlspecialchars($k), $this->describeVar($v, $depth + 1)];
+ }
+ }
+ }
+
+ return new Value(Value::TypeRef, $id);
+ }
+
+
+ public function describeKey(string $key): Value|string
+ {
+ if (preg_match('#^[\w!\#$%&*+./;<>?@^{|}~-]{1,50}$#D', $key) && !preg_match('#^(true|false|null)$#iD', $key)) {
+ return $key;
+ }
+
+ $value = $this->describeString($key);
+ return is_string($value) // ensure result is Value
+ ? new Value(Value::TypeStringHtml, $key, Helpers::utf8Length($key))
+ : $value;
+ }
+
+
+ public function addPropertyTo(
+ Value $value,
+ string $k,
+ mixed $v,
+ int $type = Value::PropertyVirtual,
+ ?int $refId = null,
+ ?string $class = null,
+ ?Value $described = null,
+ ): void
+ {
+ if ($value->depth && $this->maxItems && count($value->items ?? []) >= $this->maxItems) {
+ $value->length = ($value->length ?? count($value->items)) + 1;
+ return;
+ }
+
+ $class ??= $value->value;
+ $value->items[] = [
+ $this->describeKey($k),
+ $type !== Value::PropertyVirtual && $this->isSensitive($k, $v, $class)
+ ? new Value(Value::TypeText, self::hideValue($v))
+ : ($described ?? $this->describeVar($v, $value->depth + 1, $refId)),
+ $type === Value::PropertyPrivate ? $class : $type,
+ ] + ($refId ? [3 => $refId] : []);
+ }
+
+
+ private function exposeObject(object $obj, Value $value): ?array
+ {
+ foreach ($this->objectExposers as $type => $dumper) {
+ if (!$type || $obj instanceof $type) {
+ return $dumper($obj, $value, $this);
+ }
+ }
+
+ if ($this->debugInfo && method_exists($obj, '__debugInfo')) {
+ return $obj->__debugInfo();
+ }
+
+ Exposer::exposeObject($obj, $value, $this);
+ return null;
+ }
+
+
+ private function isSensitive(string $key, mixed $val, ?string $class = null): bool
+ {
+ return $val instanceof \SensitiveParameterValue
+ || ($this->scrubber !== null && ($this->scrubber)($key, $val, $class))
+ || isset($this->keysToHide[strtolower($key)])
+ || isset($this->keysToHide[strtolower($class . '::$' . $key)]);
+ }
+
+
+ private static function hideValue(mixed $val): string
+ {
+ if ($val instanceof \SensitiveParameterValue) {
+ $val = $val->getValue();
+ }
+
+ return self::HiddenValue . ' (' . get_debug_type($val) . ')';
+ }
+
+
+ public function describeEnumProperty(string $class, string $property, mixed $value): ?Value
+ {
+ [$set, $constants] = $this->enumProperties["$class::$property"] ?? null;
+ if (!is_int($value)
+ || !$constants
+ || !($constants = Helpers::decomposeFlags($value, $set, $constants))
+ ) {
+ return null;
+ }
+
+ $constants = array_map(fn(string $const): string => str_replace("$class::", 'self::', $const), $constants);
+ return new Value(Value::TypeNumber, implode(' | ', $constants) . " ($value)");
+ }
+
+
+ public function getReferenceId(array $arr, string|int $key): ?int
+ {
+ return ($rr = \ReflectionReference::fromArrayElement($arr, $key))
+ ? ($this->references[$rr->getId()] ??= count($this->references) + 1)
+ : null;
+ }
+
+
+ /**
+ * Finds the location where dump was called. Returns [file, line, code]
+ */
+ private static function findLocation(): ?array
+ {
+ foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $item) {
+ if (isset($item['class']) && ($item['class'] === self::class || $item['class'] === Tracy\Dumper::class)) {
+ $location = $item;
+ continue;
+ } elseif (isset($item['function'])) {
+ try {
+ $reflection = isset($item['class'])
+ ? new \ReflectionMethod($item['class'], $item['function'])
+ : new \ReflectionFunction($item['function']);
+ if (
+ $reflection->isInternal()
+ || preg_match('#\s@tracySkipLocation\s#', (string) $reflection->getDocComment())
+ ) {
+ $location = $item;
+ continue;
+ }
+ } catch (\ReflectionException) {
+ }
+ }
+
+ break;
+ }
+
+ if (isset($location['file'], $location['line']) && @is_file($location['file'])) { // @ - may trigger error
+ $lines = file($location['file']);
+ $line = $lines[$location['line'] - 1];
+ return [
+ $location['file'],
+ $location['line'],
+ trim(preg_match('#\w*dump(er::\w+)?\(.*\)#i', $line, $m) ? $m[0] : $line),
+ ];
+ }
+
+ return null;
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Dumper.php b/vendor/tracy/tracy/src/Tracy/Dumper/Dumper.php
new file mode 100644
index 0000000..49ca5ca
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Dumper/Dumper.php
@@ -0,0 +1,254 @@
+ '1;33',
+ 'null' => '1;33',
+ 'number' => '1;32',
+ 'string' => '1;36',
+ 'array' => '1;31',
+ 'public' => '1;37',
+ 'protected' => '1;37',
+ 'private' => '1;37',
+ 'dynamic' => '1;37',
+ 'virtual' => '1;37',
+ 'object' => '1;31',
+ 'resource' => '1;37',
+ 'indent' => '1;30',
+ ];
+
+ public static array $resources = [
+ 'stream' => 'stream_get_meta_data',
+ 'stream-context' => 'stream_context_get_options',
+ 'curl' => 'curl_getinfo',
+ ];
+
+ public static array $objectExporters = [
+ \Closure::class => [Exposer::class, 'exposeClosure'],
+ \UnitEnum::class => [Exposer::class, 'exposeEnum'],
+ \ArrayObject::class => [Exposer::class, 'exposeArrayObject'],
+ \SplFileInfo::class => [Exposer::class, 'exposeSplFileInfo'],
+ \SplObjectStorage::class => [Exposer::class, 'exposeSplObjectStorage'],
+ \__PHP_Incomplete_Class::class => [Exposer::class, 'exposePhpIncompleteClass'],
+ \Generator::class => [Exposer::class, 'exposeGenerator'],
+ \Fiber::class => [Exposer::class, 'exposeFiber'],
+ \DOMNode::class => [Exposer::class, 'exposeDOMNode'],
+ \DOMNodeList::class => [Exposer::class, 'exposeDOMNodeList'],
+ \DOMNamedNodeMap::class => [Exposer::class, 'exposeDOMNodeList'],
+ Ds\Collection::class => [Exposer::class, 'exposeDsCollection'],
+ Ds\Map::class => [Exposer::class, 'exposeDsMap'],
+ \WeakMap::class => [Exposer::class, 'exposeWeakMap'],
+ ];
+
+ /** @var array */
+ private static array $enumProperties = [];
+
+ private Describer $describer;
+ private Renderer $renderer;
+
+
+ /**
+ * Dumps variable to the output.
+ */
+ public static function dump(mixed $var, array $options = []): mixed
+ {
+ if (Helpers::isCli()) {
+ $useColors = self::$terminalColors && Helpers::detectColors();
+ $dumper = new self($options);
+ fwrite(STDOUT, $dumper->asTerminal($var, $useColors ? self::$terminalColors : []));
+
+ } elseif (Helpers::isHtmlMode()) {
+ $options[self::LOCATION] ??= true;
+ self::renderAssets();
+ echo self::toHtml($var, $options);
+
+ } else {
+ echo self::toText($var, $options);
+ }
+
+ return $var;
+ }
+
+
+ /**
+ * Dumps variable to HTML.
+ */
+ public static function toHtml(mixed $var, array $options = [], mixed $key = null): string
+ {
+ return (new self($options))->asHtml($var, $key);
+ }
+
+
+ /**
+ * Dumps variable to plain text.
+ */
+ public static function toText(mixed $var, array $options = []): string
+ {
+ return (new self($options))->asTerminal($var);
+ }
+
+
+ /**
+ * Dumps variable to x-terminal.
+ */
+ public static function toTerminal(mixed $var, array $options = []): string
+ {
+ return (new self($options))->asTerminal($var, self::$terminalColors);
+ }
+
+
+ /**
+ * Renders \n";
+ }
+ }
+
+
+ private function __construct(array $options = [])
+ {
+ $location = $options[self::LOCATION] ?? 0;
+ $location = $location === true ? ~0 : (int) $location;
+
+ $describer = $this->describer = new Describer;
+ $describer->maxDepth = (int) ($options[self::DEPTH] ?? $describer->maxDepth);
+ $describer->maxLength = (int) ($options[self::TRUNCATE] ?? $describer->maxLength);
+ $describer->maxItems = (int) ($options[self::ITEMS] ?? $describer->maxItems);
+ $describer->debugInfo = (bool) ($options[self::DEBUGINFO] ?? $describer->debugInfo);
+ $describer->scrubber = $options[self::SCRUBBER] ?? $describer->scrubber;
+ $describer->keysToHide = array_flip(array_map('strtolower', $options[self::KEYS_TO_HIDE] ?? []));
+ $describer->resourceExposers = ($options['resourceExporters'] ?? []) + self::$resources;
+ $describer->objectExposers = ($options[self::OBJECT_EXPORTERS] ?? []) + self::$objectExporters;
+ $describer->enumProperties = self::$enumProperties;
+ $describer->location = (bool) $location;
+ if ($options[self::LIVE] ?? false) {
+ $tmp = &self::$liveSnapshot;
+ } elseif (isset($options[self::SNAPSHOT])) {
+ $tmp = &$options[self::SNAPSHOT];
+ }
+
+ if (isset($tmp)) {
+ $tmp[0] ??= [];
+ $tmp[1] ??= [];
+ $describer->snapshot = &$tmp[0];
+ $describer->references = &$tmp[1];
+ }
+
+ $renderer = $this->renderer = new Renderer;
+ $renderer->collapseTop = $options[self::COLLAPSE] ?? $renderer->collapseTop;
+ $renderer->collapseSub = $options[self::COLLAPSE_COUNT] ?? $renderer->collapseSub;
+ $renderer->collectingMode = isset($options[self::SNAPSHOT]) || !empty($options[self::LIVE]);
+ $renderer->lazy = $renderer->collectingMode
+ ? true
+ : ($options[self::LAZY] ?? $renderer->lazy);
+ $renderer->sourceLocation = !(~$location & self::LOCATION_SOURCE);
+ $renderer->classLocation = !(~$location & self::LOCATION_CLASS);
+ $renderer->theme = ($options[self::THEME] ?? $renderer->theme) ?: null;
+ $renderer->hash = $options[self::HASH] ?? true;
+ }
+
+
+ /**
+ * Dumps variable to HTML.
+ */
+ private function asHtml(mixed $var, mixed $key = null): string
+ {
+ if ($key === null) {
+ $model = $this->describer->describe($var);
+ } else {
+ $model = $this->describer->describe([$key => $var]);
+ $model->value = $model->value[0][1];
+ }
+
+ return $this->renderer->renderAsHtml($model);
+ }
+
+
+ /**
+ * Dumps variable to x-terminal.
+ */
+ private function asTerminal(mixed $var, array $colors = []): string
+ {
+ $model = $this->describer->describe($var);
+ return $this->renderer->renderAsText($model, $colors);
+ }
+
+
+ public static function formatSnapshotAttribute(array &$snapshot): string
+ {
+ $res = "'" . Renderer::jsonEncode($snapshot[0] ?? []) . "'";
+ $snapshot = [];
+ return $res;
+ }
+
+
+ public static function addEnumProperty(string $class, string $property, array $constants, bool $set = false): void
+ {
+ self::$enumProperties["$class::$property"] = [$set, $constants];
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Exposer.php b/vendor/tracy/tracy/src/Tracy/Dumper/Exposer.php
new file mode 100644
index 0000000..aaa87bb
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Dumper/Exposer.php
@@ -0,0 +1,277 @@
+ $v) {
+ $describer->addPropertyTo($value, (string) $k, $v);
+ }
+
+ foreach (array_diff_key($values, $props) as $k => $v) {
+ $describer->addPropertyTo(
+ $value,
+ (string) $k,
+ $v,
+ Value::PropertyDynamic,
+ $describer->getReferenceId($values, $k),
+ );
+ }
+
+ foreach ($props as $k => [$name, $class, $type]) {
+ if (array_key_exists($k, $values)) {
+ $describer->addPropertyTo(
+ $value,
+ $name,
+ $values[$k],
+ $type,
+ $describer->getReferenceId($values, $k),
+ $class,
+ $describer->describeEnumProperty($class, $name, $values[$k]),
+ );
+ } else {
+ $describer->addPropertyTo(
+ $value,
+ $name,
+ null,
+ $type,
+ class: $class,
+ described: new Value(Value::TypeText, 'unset'),
+ );
+ }
+ }
+ }
+
+
+ private static function getProperties(string $class): array
+ {
+ static $cache;
+ if (isset($cache[$class])) {
+ return $cache[$class];
+ }
+
+ $rc = new \ReflectionClass($class);
+ $parentProps = $rc->getParentClass() ? self::getProperties($rc->getParentClass()->getName()) : [];
+ $props = [];
+
+ foreach ($rc->getProperties() as $prop) {
+ $name = $prop->getName();
+ if ($prop->isStatic() || $prop->getDeclaringClass()->getName() !== $class) {
+ // nothing
+ } elseif ($prop->isPrivate()) {
+ $props["\x00" . $class . "\x00" . $name] = [$name, $class, Value::PropertyPrivate];
+ } elseif ($prop->isProtected()) {
+ $props["\x00*\x00" . $name] = [$name, $class, Value::PropertyProtected];
+ } else {
+ $props[$name] = [$name, $class, Value::PropertyPublic];
+ unset($parentProps["\x00*\x00" . $name]);
+ }
+ }
+
+ return $cache[$class] = $props + $parentProps;
+ }
+
+
+ public static function exposeClosure(\Closure $obj, Value $value, Describer $describer): void
+ {
+ $rc = new \ReflectionFunction($obj);
+ if ($describer->location) {
+ $describer->addPropertyTo($value, 'file', $rc->getFileName() . ':' . $rc->getStartLine());
+ }
+
+ $params = [];
+ foreach ($rc->getParameters() as $param) {
+ $params[] = '$' . $param->getName();
+ }
+
+ $value->value .= '(' . implode(', ', $params) . ')';
+
+ $uses = [];
+ $useValue = new Value(Value::TypeObject);
+ $useValue->depth = $value->depth + 1;
+ foreach ($rc->getStaticVariables() as $name => $v) {
+ $uses[] = '$' . $name;
+ $describer->addPropertyTo($useValue, '$' . $name, $v);
+ }
+
+ if ($uses) {
+ $useValue->value = implode(', ', $uses);
+ $useValue->collapsed = true;
+ $describer->addPropertyTo($value, 'use', null, described: $useValue);
+ }
+ }
+
+
+ public static function exposeEnum(\UnitEnum $enum, Value $value, Describer $describer): void
+ {
+ $value->value = $enum::class . '::' . $enum->name;
+ if ($enum instanceof \BackedEnum) {
+ $describer->addPropertyTo($value, 'value', $enum->value);
+ $value->collapsed = true;
+ }
+ }
+
+
+ public static function exposeArrayObject(\ArrayObject $obj, Value $value, Describer $describer): void
+ {
+ $flags = $obj->getFlags();
+ $obj->setFlags(\ArrayObject::STD_PROP_LIST);
+ self::exposeObject($obj, $value, $describer);
+ $obj->setFlags($flags);
+ $describer->addPropertyTo($value, 'storage', $obj->getArrayCopy(), Value::PropertyPrivate, null, \ArrayObject::class);
+ $value->value .= ' (' . count($obj) . ')';
+ }
+
+
+ public static function exposeDOMNode(\DOMNode $obj, Value $value, Describer $describer): void
+ {
+ $props = preg_match_all('#^\s*\[([^\]]+)\] =>#m', print_r($obj, return: true), $tmp) ? $tmp[1] : [];
+ sort($props);
+ foreach ($props as $p) {
+ $describer->addPropertyTo($value, $p, @$obj->$p, Value::PropertyPublic); // @ some props may be deprecated
+ }
+ }
+
+
+ public static function exposeDOMNodeList(
+ \DOMNodeList|\DOMNamedNodeMap $obj,
+ Value $value,
+ Describer $describer,
+ ): void
+ {
+ $describer->addPropertyTo($value, 'length', $obj->length, Value::PropertyPublic);
+ $describer->addPropertyTo($value, 'items', iterator_to_array($obj));
+ }
+
+
+ public static function exposeGenerator(\Generator $gen, Value $value, Describer $describer): void
+ {
+ try {
+ $r = new \ReflectionGenerator($gen);
+ $describer->addPropertyTo($value, 'file', $r->getExecutingFile() . ':' . $r->getExecutingLine());
+ $describer->addPropertyTo($value, 'this', $r->getThis());
+ } catch (\ReflectionException) {
+ $value->value = $gen::class . ' (terminated)';
+ }
+ }
+
+
+ public static function exposeFiber(\Fiber $fiber, Value $value, Describer $describer): void
+ {
+ if ($fiber->isTerminated()) {
+ $value->value = $fiber::class . ' (terminated)';
+ } elseif (!$fiber->isStarted()) {
+ $value->value = $fiber::class . ' (not started)';
+ } else {
+ $r = new \ReflectionFiber($fiber);
+ $describer->addPropertyTo($value, 'file', $r->getExecutingFile() . ':' . $r->getExecutingLine());
+ $describer->addPropertyTo($value, 'callable', $r->getCallable());
+ }
+ }
+
+
+ public static function exposeSplFileInfo(\SplFileInfo $obj): array
+ {
+ return ['path' => $obj->getPathname()];
+ }
+
+
+ public static function exposeSplObjectStorage(\SplObjectStorage $obj, Value $value, Describer $describer): void
+ {
+ $value->value .= ' (' . count($obj) . ')';
+ foreach (clone $obj as $v) {
+ $pair = new Value(Value::TypeObject, '');
+ $pair->depth = $value->depth + 1;
+ $describer->addPropertyTo($pair, 'key', $v);
+ $describer->addPropertyTo($pair, 'value', $obj[$v]);
+ $describer->addPropertyTo($value, '', null, described: $pair);
+ $value->items[array_key_last($value->items)][0] = '';
+ }
+ }
+
+
+ public static function exposeWeakMap(\WeakMap $obj, Value $value, Describer $describer): void
+ {
+ $value->value .= ' (' . count($obj) . ')';
+ foreach ($obj as $k => $v) {
+ $pair = new Value(Value::TypeObject, '');
+ $pair->depth = $value->depth + 1;
+ $describer->addPropertyTo($pair, 'key', $k);
+ $describer->addPropertyTo($pair, 'value', $v);
+ $describer->addPropertyTo($value, '', null, described: $pair);
+ $value->items[array_key_last($value->items)][0] = '';
+ }
+ }
+
+
+ public static function exposePhpIncompleteClass(
+ \__PHP_Incomplete_Class $obj,
+ Value $value,
+ Describer $describer,
+ ): void
+ {
+ $values = get_mangled_object_vars($obj);
+ $class = $values['__PHP_Incomplete_Class_Name'];
+ unset($values['__PHP_Incomplete_Class_Name']);
+ foreach ($values as $k => $v) {
+ $refId = $describer->getReferenceId($values, $k);
+ if (isset($k[0]) && $k[0] === "\x00") {
+ $info = explode("\00", $k);
+ $k = end($info);
+ $type = $info[1] === '*' ? Value::PropertyProtected : Value::PropertyPrivate;
+ $decl = $type === Value::PropertyPrivate ? $info[1] : null;
+ } else {
+ $type = Value::PropertyPublic;
+ $k = (string) $k;
+ $decl = null;
+ }
+
+ $describer->addPropertyTo($value, $k, $v, $type, $refId, $decl);
+ }
+
+ $value->value = $class . ' (Incomplete Class)';
+ }
+
+
+ public static function exposeDsCollection(
+ Ds\Collection $obj,
+ Value $value,
+ Describer $describer,
+ ): void
+ {
+ foreach (clone $obj as $k => $v) {
+ $describer->addPropertyTo($value, (string) $k, $v);
+ }
+ }
+
+
+ public static function exposeDsMap(
+ Ds\Map $obj,
+ Value $value,
+ Describer $describer,
+ ): void
+ {
+ $i = 0;
+ foreach ($obj as $k => $v) {
+ $describer->addPropertyTo($value, (string) $i++, new Ds\Pair($k, $v));
+ }
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Renderer.php b/vendor/tracy/tracy/src/Tracy/Dumper/Renderer.php
new file mode 100644
index 0000000..edcff74
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Dumper/Renderer.php
@@ -0,0 +1,424 @@
+value;
+ $this->snapshot = $model->snapshot;
+
+ if ($this->lazy === false) { // no lazy-loading
+ $html = $this->renderVar($value);
+ $json = $snapshot = null;
+
+ } elseif ($this->lazy && (is_array($value) && $value || is_object($value))) { // full lazy-loading
+ $html = '';
+ $snapshot = $this->collectingMode ? null : $this->snapshot;
+ $json = $value;
+
+ } else { // lazy-loading of collapsed parts
+ $html = $this->renderVar($value);
+ $snapshot = $this->snapshotSelection;
+ $json = null;
+ }
+ } finally {
+ $this->parents = $this->snapshot = $this->above = [];
+ $this->snapshotSelection = null;
+ }
+
+ $location = null;
+ if ($model->location && $this->sourceLocation) {
+ [$file, $line, $code] = $model->location;
+ $uri = Helpers::editorUri($file, $line);
+ $location = Helpers::formatHtml(
+ '',
+ $uri ?? '#',
+ $file,
+ $line,
+ $uri ? "\nClick to open in editor" : '',
+ ) . Helpers::encodeString($code, 50) . " 📍 ";
+ }
+
+ return ' 100 ? "\n" : '')
+ . '>'
+ . $location
+ . $html
+ . " \n";
+ }
+
+
+ public function renderAsText(\stdClass $model, array $colors = []): string
+ {
+ try {
+ $this->snapshot = $model->snapshot;
+ $this->lazy = false;
+ $s = $this->renderVar($model->value);
+ } finally {
+ $this->parents = $this->snapshot = $this->above = [];
+ }
+
+ $s = $colors ? Helpers::htmlToAnsi($s, $colors) : Helpers::htmlToText($s);
+ $s = str_replace('…', '...', $s);
+ $s .= substr($s, -1) === "\n" ? '' : "\n";
+
+ if ($this->sourceLocation && ([$file, $line] = $model->location)) {
+ $s .= "in $file:$line\n";
+ }
+
+ return $s;
+ }
+
+
+ private function renderVar(mixed $value, int $depth = 0, string|int|null $keyType = null): string
+ {
+ return match (true) {
+ $value === null => 'null ',
+ is_bool($value) => '' . ($value ? 'true' : 'false') . ' ',
+ is_int($value) => '' . $value . ' ',
+ is_float($value) => '' . self::jsonEncode($value) . ' ',
+ is_string($value) => $this->renderString($value, $depth, $keyType),
+ is_array($value), $value->type === Value::TypeArray => $this->renderArray($value, $depth),
+ $value->type === Value::TypeRef => $this->renderVar($this->snapshot[$value->value], $depth, $keyType),
+ $value->type === Value::TypeObject => $this->renderObject($value, $depth),
+ $value->type === Value::TypeNumber => '' . Helpers::escapeHtml($value->value) . ' ',
+ $value->type === Value::TypeText => '' . Helpers::escapeHtml($value->value) . ' ',
+ $value->type === Value::TypeStringHtml, $value->type === Value::TypeBinaryHtml => $this->renderString($value, $depth, $keyType),
+ $value->type === Value::TypeResource => $this->renderResource($value, $depth),
+ default => throw new \Exception('Unknown type'),
+ };
+ }
+
+
+ private function renderString(string|Value $str, int $depth, string|int|null $keyType): string
+ {
+ if ($keyType === self::TypeArrayKey) {
+ $indent = ' ' . str_repeat('| ', $depth - 1) . ' ';
+ return ''
+ . "' "
+ . (is_string($str) ? Helpers::escapeHtml($str) : str_replace("\n", "\n" . $indent, $str->value))
+ . "' "
+ . ' ';
+
+ } elseif ($keyType !== null) {
+ $classes = [
+ Value::PropertyPublic => 'tracy-dump-public',
+ Value::PropertyProtected => 'tracy-dump-protected',
+ Value::PropertyDynamic => 'tracy-dump-dynamic',
+ Value::PropertyVirtual => 'tracy-dump-virtual',
+ ];
+ $indent = ' ' . str_repeat('| ', $depth - 1) . ' ';
+ $title = is_string($keyType)
+ ? ' title="declared in ' . Helpers::escapeHtml($keyType) . '"'
+ : null;
+ return ''
+ . (is_string($str)
+ ? Helpers::escapeHtml($str)
+ : "' " . str_replace("\n", "\n" . $indent, $str->value) . "' ")
+ . ' ';
+
+ } elseif (is_string($str)) {
+ $len = Helpers::utf8Length($str);
+ return ' 1 ? ' title="' . $len . ' characters"' : '')
+ . '>'
+ . "' "
+ . Helpers::escapeHtml($str)
+ . "' "
+ . ' ';
+
+ } else {
+ $unit = $str->type === Value::TypeStringHtml ? 'characters' : 'bytes';
+ $count = substr_count($str->value, "\n");
+ if ($count) {
+ $collapsed = $indent1 = $toggle = null;
+ $indent = ' ';
+ if ($depth) {
+ $collapsed = $count >= $this->collapseSub;
+ $indent1 = ' ' . str_repeat('| ', $depth) . ' ';
+ $indent = ' ' . str_repeat('| ', $depth) . ' ';
+ $toggle = 'string ' . "\n";
+ }
+
+ return $toggle
+ . ''
+ . $indent1
+ . '' "
+ . str_replace("\n", "\n" . $indent, $str->value)
+ . "' "
+ . ($depth ? "\n" : '')
+ . '
';
+ }
+
+ return 'length > 1 ? " title=\"{$str->length} $unit\"" : '')
+ . '>'
+ . "' "
+ . $str->value
+ . "' "
+ . ' ';
+ }
+ }
+
+
+ private function renderArray(array|Value $array, int $depth): string
+ {
+ $out = 'array (';
+
+ if (is_array($array)) {
+ $items = $array;
+ $count = count($items);
+ $out .= $count . ')';
+ } elseif ($array->items === null) {
+ return $out . $array->length . ') …';
+ } else {
+ $items = $array->items;
+ $count = $array->length ?? count($items);
+ $out .= $count . ')';
+ if ($array->id && isset($this->parents[$array->id])) {
+ return $out . ' RECURSION ';
+
+ } elseif ($array->id && ($array->depth < $depth || isset($this->above[$array->id]))) {
+ if ($this->lazy !== false) {
+ $ref = new Value(Value::TypeRef, $array->id);
+ $this->copySnapshot($ref);
+ return '" . $out . ' ';
+
+ } elseif ($this->hash) {
+ return $out . (isset($this->above[$array->id]) ? ' see above ' : ' see below ');
+ }
+ }
+ }
+
+ if (!$count) {
+ return $out;
+ }
+
+ $collapsed = $depth
+ ? ($this->lazy === false || $depth === 1 ? $count >= $this->collapseSub : true)
+ : (is_int($this->collapseTop) ? $count >= $this->collapseTop : $this->collapseTop);
+
+ $span = 'lazy !== false) {
+ $array = isset($array->id) ? new Value(Value::TypeRef, $array->id) : $array;
+ $this->copySnapshot($array);
+ return $span . " data-tracy-dump='" . self::jsonEncode($array) . "'>" . $out . ' ';
+ }
+
+ $out = $span . '>' . $out . "\n" . '';
+ $indent = ' ' . str_repeat('| ', $depth) . ' ';
+ $this->parents[$array->id ?? null] = $this->above[$array->id ?? null] = true;
+
+ foreach ($items as $info) {
+ [$k, $v, $ref] = $info + [2 => null];
+ $out .= $indent
+ . $this->renderVar($k, $depth + 1, self::TypeArrayKey)
+ . ' => '
+ . ($ref && $this->hash ? '&' . $ref . ' ' : '')
+ . ($tmp = $this->renderVar($v, $depth + 1))
+ . (substr($tmp, -6) === '
' ? '' : "\n");
+ }
+
+ if ($count > count($items)) {
+ $out .= $indent . "…\n";
+ }
+
+ unset($this->parents[$array->id ?? null]);
+ return $out . '';
+ }
+
+
+ private function renderObject(Value $object, int $depth): string
+ {
+ $editorAttributes = '';
+ if ($this->classLocation && $object->editor) {
+ $editorAttributes = Helpers::formatHtml(
+ ' title="Declared in file % on line %%%" data-tracy-href="%"',
+ $object->editor->file,
+ $object->editor->line,
+ $object->editor->url ? "\nCtrl-Click to open in editor" : '',
+ "\nAlt-Click to expand/collapse all child nodes",
+ $object->editor->url,
+ );
+ }
+
+ $pos = strrpos($object->value, '\\');
+ $out = ''
+ . ($pos
+ ? Helpers::escapeHtml(substr($object->value, 0, $pos + 1)) . '' . Helpers::escapeHtml(substr($object->value, $pos + 1)) . ' '
+ : Helpers::escapeHtml($object->value))
+ . ' '
+ . ($object->id && $this->hash ? ' #' . $object->id . ' ' : '');
+
+ if ($object->items === null) {
+ return $out . ' …';
+
+ } elseif (!$object->items) {
+ return $out;
+
+ } elseif ($object->id && isset($this->parents[$object->id])) {
+ return $out . ' RECURSION ';
+
+ } elseif ($object->id && ($object->depth < $depth || isset($this->above[$object->id]))) {
+ if ($this->lazy !== false) {
+ $ref = new Value(Value::TypeRef, $object->id);
+ $this->copySnapshot($ref);
+ return '" . $out . ' ';
+
+ } elseif ($this->hash) {
+ return $out . (isset($this->above[$object->id]) ? ' see above ' : ' see below ');
+ }
+ }
+
+ $collapsed = $object->collapsed ?? ($depth
+ ? ($this->lazy === false || $depth === 1 ? count($object->items) >= $this->collapseSub : true)
+ : (is_int($this->collapseTop) ? count($object->items) >= $this->collapseTop : $this->collapseTop));
+
+ $span = 'lazy !== false) {
+ $value = $object->id ? new Value(Value::TypeRef, $object->id) : $object;
+ $this->copySnapshot($value);
+ return $span . " data-tracy-dump='" . self::jsonEncode($value) . "'>" . $out . ' ';
+ }
+
+ $out = $span . '>' . $out . "\n" . '';
+ $indent = ' ' . str_repeat('| ', $depth) . ' ';
+ $this->parents[$object->id] = $this->above[$object->id] = true;
+
+ foreach ($object->items as $info) {
+ [$k, $v, $type, $ref] = $info + [2 => Value::PropertyVirtual, null];
+ $out .= $indent
+ . $this->renderVar($k, $depth + 1, $type)
+ . ': '
+ . ($ref && $this->hash ? '&' . $ref . ' ' : '')
+ . ($tmp = $this->renderVar($v, $depth + 1))
+ . (substr($tmp, -6) === '
' ? '' : "\n");
+ }
+
+ if ($object->length > count($object->items)) {
+ $out .= $indent . "…\n";
+ }
+
+ unset($this->parents[$object->id]);
+ return $out . '';
+ }
+
+
+ private function renderResource(Value $resource, int $depth): string
+ {
+ $out = '' . Helpers::escapeHtml($resource->value) . ' '
+ . ($this->hash ? '@' . substr($resource->id, 1) . ' ' : '');
+
+ if (!$resource->items) {
+ return $out;
+
+ } elseif (isset($this->above[$resource->id])) {
+ if ($this->lazy !== false) {
+ $ref = new Value(Value::TypeRef, $resource->id);
+ $this->copySnapshot($ref);
+ return '" . $out . ' ';
+ }
+
+ return $out . ' see above ';
+
+ } else {
+ $this->above[$resource->id] = true;
+ $out = "$out \n";
+ foreach ($resource->items as [$k, $v]) {
+ $out .= ' ' . str_repeat('| ', $depth) . ' '
+ . $this->renderVar($k, $depth + 1, Value::PropertyVirtual)
+ . ': '
+ . ($tmp = $this->renderVar($v, $depth + 1))
+ . (substr($tmp, -6) === '
' ? '' : "\n");
+ }
+
+ return $out . '';
+ }
+ }
+
+
+ private function copySnapshot(mixed $value): void
+ {
+ if ($this->collectingMode) {
+ return;
+ }
+
+ if ($this->snapshotSelection === null) {
+ $this->snapshotSelection = [];
+ }
+
+ if (is_array($value)) {
+ foreach ($value as [, $v]) {
+ $this->copySnapshot($v);
+ }
+ } elseif ($value instanceof Value && $value->type === Value::TypeRef) {
+ if (!isset($this->snapshotSelection[$value->value])) {
+ $ref = $this->snapshotSelection[$value->value] = $this->snapshot[$value->value];
+ $this->copySnapshot($ref);
+ }
+ } elseif ($value instanceof Value && $value->items) {
+ foreach ($value->items as [, $v]) {
+ $this->copySnapshot($v);
+ }
+ }
+ }
+
+
+ public static function jsonEncode(mixed $value): string
+ {
+ $old = @ini_set('serialize_precision', '-1'); // @ may be disabled
+ try {
+ return json_encode($value, JSON_HEX_APOS | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
+ } finally {
+ if ($old !== false) {
+ ini_set('serialize_precision', $old);
+ }
+ }
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/Value.php b/vendor/tracy/tracy/src/Tracy/Dumper/Value.php
new file mode 100644
index 0000000..5fa6e44
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Dumper/Value.php
@@ -0,0 +1,65 @@
+type = $type;
+ $this->value = $value;
+ $this->length = $length;
+ }
+
+
+ public function jsonSerialize(): array
+ {
+ $res = [$this->type => $this->value];
+ foreach (['length', 'editor', 'items', 'collapsed'] as $k) {
+ if ($this->$k !== null) {
+ $res[$k] = $this->$k;
+ }
+ }
+
+ return $res;
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-dark.css b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-dark.css
new file mode 100644
index 0000000..8346d72
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-dark.css
@@ -0,0 +1,145 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+.tracy-dump.tracy-dark {
+ text-align: left;
+ color: #f8f8f2;
+ background: #29292e;
+ border-radius: 4px;
+ padding: var(--tracy-space);
+ margin: var(--tracy-space) 0;
+ word-break: break-all;
+ white-space: pre-wrap;
+}
+
+.tracy-dump.tracy-dark div {
+ padding-left: 2.5ex;
+}
+
+.tracy-dump.tracy-dark div div {
+ border-left: 1px solid rgba(255, 255, 255, .1);
+ margin-left: .5ex;
+}
+
+.tracy-dump.tracy-dark div div:hover {
+ border-left-color: rgba(255, 255, 255, .25);
+}
+
+.tracy-dark .tracy-dump-location {
+ color: silver;
+ font-size: 80%;
+ text-decoration: none;
+ background: none;
+ opacity: .5;
+ float: right;
+ cursor: pointer;
+}
+
+.tracy-dark .tracy-dump-location:hover,
+.tracy-dark .tracy-dump-location:focus {
+ opacity: 1;
+}
+
+.tracy-dark .tracy-dump-array,
+.tracy-dark .tracy-dump-object {
+ color: #f69c2e;
+ user-select: text;
+}
+
+.tracy-dark .tracy-dump-string {
+ color: #3cdfef;
+ white-space: break-spaces;
+}
+
+.tracy-dark div.tracy-dump-string {
+ position: relative;
+ padding-left: 3.5ex;
+}
+
+.tracy-dark .tracy-dump-lq {
+ margin-left: calc(-1ex - 1px);
+}
+
+.tracy-dark div.tracy-dump-string:before {
+ content: '';
+ position: absolute;
+ left: calc(3ex - 1px);
+ top: 1.5em;
+ bottom: 0;
+ border-left: 1px solid rgba(255, 255, 255, .1);
+}
+
+.tracy-dark .tracy-dump-virtual span,
+.tracy-dark .tracy-dump-dynamic span,
+.tracy-dark .tracy-dump-string span {
+ color: rgba(255, 255, 255, 0.5);
+}
+
+.tracy-dark .tracy-dump-virtual i,
+.tracy-dark .tracy-dump-dynamic i,
+.tracy-dark .tracy-dump-string i {
+ font-size: 80%;
+ font-style: normal;
+ color: rgba(255, 255, 255, 0.5);
+ user-select: none;
+}
+
+.tracy-dark .tracy-dump-number {
+ color: #77d285;
+}
+
+.tracy-dark .tracy-dump-null,
+.tracy-dark .tracy-dump-bool {
+ color: #f3cb44;
+}
+
+.tracy-dark .tracy-dump-virtual {
+ font-style: italic;
+}
+
+.tracy-dark .tracy-dump-public::after {
+ content: ' pub';
+}
+
+.tracy-dark .tracy-dump-protected::after {
+ content: ' pro';
+}
+
+.tracy-dark .tracy-dump-private::after {
+ content: ' pri';
+}
+
+.tracy-dark .tracy-dump-public::after,
+.tracy-dark .tracy-dump-protected::after,
+.tracy-dark .tracy-dump-private::after,
+.tracy-dark .tracy-dump-hash {
+ font-size: 85%;
+ color: rgba(255, 255, 255, 0.35);
+}
+
+.tracy-dark .tracy-dump-indent {
+ display: none;
+}
+
+.tracy-dark .tracy-dump-highlight {
+ background: #C22;
+ color: white;
+ border-radius: 2px;
+ padding: 0 2px;
+ margin: 0 -2px;
+}
+
+span[data-tracy-href] {
+ border-bottom: 1px dotted rgba(255, 255, 255, .2);
+}
+
+.tracy-dark .tracy-dump-flash {
+ animation: tracy-dump-flash .2s ease;
+}
+
+@keyframes tracy-dump-flash {
+ 0% {
+ background: #c0c0c033;
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-light.css b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-light.css
new file mode 100644
index 0000000..fb86592
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper-light.css
@@ -0,0 +1,145 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+.tracy-dump.tracy-light {
+ text-align: left;
+ color: #444;
+ background: #fdf9e2;
+ border-radius: 4px;
+ padding: var(--tracy-space);
+ margin: var(--tracy-space) 0;
+ word-break: break-all;
+ white-space: pre-wrap;
+}
+
+.tracy-dump.tracy-light div {
+ padding-left: 2.5ex;
+}
+
+.tracy-dump.tracy-light div div {
+ border-left: 1px solid rgba(0, 0, 0, .1);
+ margin-left: .5ex;
+}
+
+.tracy-dump.tracy-light div div:hover {
+ border-left-color: rgba(0, 0, 0, .25);
+}
+
+.tracy-light .tracy-dump-location {
+ color: gray;
+ font-size: 80%;
+ text-decoration: none;
+ background: none;
+ opacity: .5;
+ float: right;
+ cursor: pointer;
+}
+
+.tracy-light .tracy-dump-location:hover,
+.tracy-light .tracy-dump-location:focus {
+ opacity: 1;
+}
+
+.tracy-light .tracy-dump-array,
+.tracy-light .tracy-dump-object {
+ color: #C22;
+ user-select: text;
+}
+
+.tracy-light .tracy-dump-string {
+ color: #35D;
+ white-space: break-spaces;
+}
+
+.tracy-light div.tracy-dump-string {
+ position: relative;
+ padding-left: 3.5ex;
+}
+
+.tracy-light .tracy-dump-lq {
+ margin-left: calc(-1ex - 1px);
+}
+
+.tracy-light div.tracy-dump-string:before {
+ content: '';
+ position: absolute;
+ left: calc(3ex - 1px);
+ top: 1.5em;
+ bottom: 0;
+ border-left: 1px solid rgba(0, 0, 0, .1);
+}
+
+.tracy-light .tracy-dump-virtual span,
+.tracy-light .tracy-dump-dynamic span,
+.tracy-light .tracy-dump-string span {
+ color: rgba(0, 0, 0, 0.5);
+}
+
+.tracy-light .tracy-dump-virtual i,
+.tracy-light .tracy-dump-dynamic i,
+.tracy-light .tracy-dump-string i {
+ font-size: 80%;
+ font-style: normal;
+ color: rgba(0, 0, 0, 0.5);
+ user-select: none;
+}
+
+.tracy-light .tracy-dump-number {
+ color: #090;
+}
+
+.tracy-light .tracy-dump-null,
+.tracy-light .tracy-dump-bool {
+ color: #850;
+}
+
+.tracy-light .tracy-dump-virtual {
+ font-style: italic;
+}
+
+.tracy-light .tracy-dump-public::after {
+ content: ' pub';
+}
+
+.tracy-light .tracy-dump-protected::after {
+ content: ' pro';
+}
+
+.tracy-light .tracy-dump-private::after {
+ content: ' pri';
+}
+
+.tracy-light .tracy-dump-public::after,
+.tracy-light .tracy-dump-protected::after,
+.tracy-light .tracy-dump-private::after,
+.tracy-light .tracy-dump-hash {
+ font-size: 85%;
+ color: rgba(0, 0, 0, 0.35);
+}
+
+.tracy-light .tracy-dump-indent {
+ display: none;
+}
+
+.tracy-light .tracy-dump-highlight {
+ background: #C22;
+ color: white;
+ border-radius: 2px;
+ padding: 0 2px;
+ margin: 0 -2px;
+}
+
+span[data-tracy-href] {
+ border-bottom: 1px dotted rgba(0, 0, 0, .2);
+}
+
+.tracy-light .tracy-dump-flash {
+ animation: tracy-dump-flash .2s ease;
+}
+
+@keyframes tracy-dump-flash {
+ 0% {
+ background: #c0c0c033;
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper.js b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper.js
new file mode 100644
index 0000000..81417ad
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Dumper/assets/dumper.js
@@ -0,0 +1,392 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+const
+ COLLAPSE_COUNT = 7,
+ COLLAPSE_COUNT_TOP = 14,
+ TYPE_ARRAY = 'a',
+ TYPE_OBJECT = 'o',
+ TYPE_RESOURCE = 'r',
+ PROP_VIRTUAL = 4,
+ PROP_PRIVATE = 2;
+
+const
+ HINT_CTRL = 'Ctrl-Click to open in editor',
+ HINT_ALT = 'Alt-Click to expand/collapse all child nodes';
+
+class Dumper {
+ static init(context) {
+ // full lazy
+ (context || document).querySelectorAll('[data-tracy-snapshot][data-tracy-dump]').forEach((pre) => { //
+ let snapshot = JSON.parse(pre.getAttribute('data-tracy-snapshot'));
+ pre.removeAttribute('data-tracy-snapshot');
+ pre.appendChild(build(JSON.parse(pre.getAttribute('data-tracy-dump')), snapshot, pre.classList.contains('tracy-collapsed')));
+ pre.removeAttribute('data-tracy-dump');
+ pre.classList.remove('tracy-collapsed');
+ });
+
+ // snapshots
+ (context || document).querySelectorAll('meta[itemprop=tracy-snapshot]').forEach((meta) => {
+ let snapshot = JSON.parse(meta.getAttribute('content'));
+ meta.parentElement.querySelectorAll('[data-tracy-dump]').forEach((pre) => { //
+ if (pre.closest('[data-tracy-snapshot]')) { // ignore unrelated
+ return;
+ }
+ pre.appendChild(build(JSON.parse(pre.getAttribute('data-tracy-dump')), snapshot, pre.classList.contains('tracy-collapsed')));
+ pre.removeAttribute('data-tracy-dump');
+ pre.classList.remove('tracy-collapsed');
+ });
+ // must be left for debug bar panel content
+ });
+
+ if (Dumper.inited) {
+ return;
+ }
+ Dumper.inited = true;
+
+ document.documentElement.addEventListener('click', (e) => {
+ let el;
+ // enables & ctrl or cmd key
+ if ((e.ctrlKey || e.metaKey) && (el = e.target.closest('[data-tracy-href]'))) {
+ location.href = el.getAttribute('data-tracy-href');
+ return false;
+ }
+
+ });
+
+ document.documentElement.addEventListener('tracy-beforetoggle', (e) => {
+ let el;
+ // initializes lazy inside
+ if ((el = e.target.closest('[data-tracy-snapshot]'))) {
+ let snapshot = JSON.parse(el.getAttribute('data-tracy-snapshot'));
+ el.removeAttribute('data-tracy-snapshot');
+ el.querySelectorAll('[data-tracy-dump]').forEach((toggler) => {
+ if (!toggler.nextSibling) {
+ toggler.after(document.createTextNode('\n')); // enforce \n after toggler
+ }
+ toggler.nextSibling.after(buildStruct(JSON.parse(toggler.getAttribute('data-tracy-dump')), snapshot, toggler, true, []));
+ toggler.removeAttribute('data-tracy-dump');
+ });
+ }
+ });
+
+ document.documentElement.addEventListener('tracy-toggle', (e) => {
+ if (!e.target.matches('.tracy-dump *')) {
+ return;
+ }
+
+ let cont = e.detail.relatedTarget;
+ let origE = e.detail.originalEvent;
+
+ if (origE && origE.usedIds) { // triggered by expandChild()
+ toggleChildren(cont, origE.usedIds);
+ return;
+
+ } else if (origE && origE.altKey && cont.querySelector('.tracy-toggle')) { // triggered by alt key
+ if (e.detail.collapsed) { // reopen
+ e.target.classList.toggle('tracy-collapsed', false);
+ cont.classList.toggle('tracy-collapsed', false);
+ e.detail.collapsed = false;
+ }
+
+ let expand = e.target.tracyAltExpand = !e.target.tracyAltExpand;
+ toggleChildren(cont, expand ? {} : false);
+ }
+
+ cont.classList.toggle('tracy-dump-flash', !e.detail.collapsed);
+ });
+
+ document.documentElement.addEventListener('animationend', (e) => {
+ if (e.animationName === 'tracy-dump-flash') {
+ e.target.classList.toggle('tracy-dump-flash', false);
+ }
+ });
+
+ document.addEventListener('mouseover', (e) => {
+ if (!e.target.matches('.tracy-dump *')) {
+ return;
+ }
+
+ let el;
+
+ if (e.target.matches('.tracy-dump-hash') && (el = e.target.closest('tracy-div'))) {
+ el.querySelectorAll('.tracy-dump-hash').forEach((el) => {
+ if (el.textContent === e.target.textContent) {
+ el.classList.add('tracy-dump-highlight');
+ }
+ });
+ return;
+ }
+
+ if ((el = e.target.closest('.tracy-toggle')) && !el.title) {
+ el.title = HINT_ALT;
+ }
+ });
+
+ document.addEventListener('mouseout', (e) => {
+ if (e.target.matches('.tracy-dump-hash')) {
+ document.querySelectorAll('.tracy-dump-hash.tracy-dump-highlight').forEach((el) => {
+ el.classList.remove('tracy-dump-highlight');
+ });
+ }
+ });
+
+ Tracy.Toggle.init();
+ }
+}
+
+
+function build(data, repository, collapsed, parentIds, keyType) {
+ let id, type = data === null ? 'null' : typeof data,
+ collapseCount = collapsed === null ? COLLAPSE_COUNT : COLLAPSE_COUNT_TOP;
+
+ if (type === 'null' || type === 'number' || type === 'boolean') {
+ return createEl(null, null, [
+ createEl(
+ 'span',
+ { class: 'tracy-dump-' + type.replace('ean', '') },
+ [data + ''],
+ ),
+ ]);
+
+ } else if (type === 'string') {
+ data = {
+ string: data.replace(/&/g, '&').replace(/\' ' + s + '\' ' },
+ ),
+ ]);
+
+ } else if (keyType !== undefined) {
+ if (type !== 'string') {
+ s = '\' ' + s + '\' ';
+ }
+
+ const classes = [
+ 'tracy-dump-public',
+ 'tracy-dump-protected',
+ 'tracy-dump-private',
+ 'tracy-dump-dynamic',
+ 'tracy-dump-virtual',
+ ];
+ return createEl(null, null, [
+ createEl(
+ 'span',
+ {
+ class: classes[typeof keyType === 'string' ? PROP_PRIVATE : keyType],
+ title: typeof keyType === 'string' ? 'declared in ' + keyType : null,
+ },
+ { html: s },
+ ),
+ ]);
+ }
+
+ let count = (s.match(/\n/g) || []).length;
+ if (count) {
+ let collapsed = count >= COLLAPSE_COUNT;
+ return createEl(null, null, [
+ createEl('span', { class: collapsed ? 'tracy-toggle tracy-collapsed' : 'tracy-toggle' }, ['string']),
+ '\n',
+ createEl(
+ 'div',
+ {
+ class: 'tracy-dump-string' + (collapsed ? ' tracy-collapsed' : ''),
+ title: data.length + (data.bin ? ' bytes' : ' characters'),
+ },
+ { html: '\' ' + s + '\' ' },
+ ),
+ ]);
+ }
+
+ return createEl(null, null, [
+ createEl(
+ 'span',
+ {
+ class: 'tracy-dump-string',
+ title: data.length + (data.bin ? ' bytes' : ' characters'),
+ },
+ { html: '\' ' + s + '\' ' },
+ ),
+ ]);
+
+ } else if (data.number) {
+ return createEl(null, null, [
+ createEl('span', { class: 'tracy-dump-number' }, [data.number]),
+ ]);
+
+ } else if (data.text !== undefined) {
+ return createEl(null, null, [
+ createEl('span', { class: 'tracy-dump-virtual' }, [data.text]),
+ ]);
+
+ } else { // object || resource || array
+ let pos, nameEl;
+ nameEl = data.object && (pos = data.object.lastIndexOf('\\')) > 0
+ ? [data.object.substr(0, pos + 1), createEl('b', null, [data.object.substr(pos + 1)])]
+ : [data.object || data.resource];
+
+ let span = data.array !== undefined
+ ? [
+ createEl('span', { class: 'tracy-dump-array' }, ['array']),
+ ' (' + (data.length || data.items.length) + ')',
+ ]
+ : [
+ createEl('span', {
+ 'class': data.object ? 'tracy-dump-object' : 'tracy-dump-resource',
+ 'title': data.editor ? 'Declared in file ' + data.editor.file + ' on line ' + data.editor.line + (data.editor.url ? '\n' + HINT_CTRL : '') + '\n' + HINT_ALT : null,
+ 'data-tracy-href': data.editor ? data.editor.url : null,
+ }, nameEl),
+ ...(id ? [' ', createEl('span', { class: 'tracy-dump-hash' }, [data.resource ? '@' + id.substr(1) : '#' + id])] : []),
+ ];
+
+ parentIds = parentIds ? parentIds.slice() : [];
+ let recursive = id && parentIds.indexOf(id) > -1;
+ parentIds.push(id);
+
+ if (recursive || !data.items || !data.items.length) {
+ span.push(recursive ? ' RECURSION' : (!data.items || data.items.length ? ' …' : ''));
+ return createEl(null, null, span);
+ }
+
+ collapsed = collapsed === true || data.collapsed || (data.items && data.items.length >= collapseCount);
+ let toggle = createEl('span', { class: collapsed ? 'tracy-toggle tracy-collapsed' : 'tracy-toggle' }, span);
+
+ return createEl(null, null, [
+ toggle,
+ '\n',
+ buildStruct(data, repository, toggle, collapsed, parentIds),
+ ]);
+ }
+}
+
+
+function buildStruct(data, repository, toggle, collapsed, parentIds) {
+ if (Array.isArray(data)) {
+ data = { items: data };
+
+ } else if (data.ref) {
+ parentIds = parentIds.slice();
+ parentIds.push(data.ref);
+ data = repository[data.ref];
+ }
+
+ let cut = data.items && data.length > data.items.length;
+ let type = data.object ? TYPE_OBJECT : data.resource ? TYPE_RESOURCE : TYPE_ARRAY;
+ let div = createEl('div', { class: collapsed ? 'tracy-collapsed' : null });
+
+ if (collapsed) {
+ let handler;
+ toggle.addEventListener('tracy-toggle', handler = function () {
+ toggle.removeEventListener('tracy-toggle', handler);
+ createItems(div, data.items, type, repository, parentIds, null);
+ if (cut) {
+ createEl(div, null, ['…\n']);
+ }
+ });
+ } else {
+ createItems(div, data.items, type, repository, parentIds, true);
+ if (cut) {
+ createEl(div, null, ['…\n']);
+ }
+ }
+
+ return div;
+}
+
+
+function createEl(el, attrs, content) {
+ if (!(el instanceof Node)) {
+ el = el ? document.createElement(el) : document.createDocumentFragment();
+ }
+ for (let id in attrs || {}) {
+ if (attrs[id] !== null) {
+ el.setAttribute(id, attrs[id]);
+ }
+ }
+
+ if (content && content.html !== undefined) {
+ el.innerHTML = content.html;
+ return el;
+ }
+
+ content = content || [];
+ el.append(...content.filter((child) => (child !== null)));
+ return el;
+}
+
+
+function createItems(el, items, type, repository, parentIds, collapsed) {
+ let key, val, vis, ref, i, tmp;
+
+ for (i = 0; i < items.length; i++) {
+ if (type === TYPE_ARRAY) {
+ [key, val, ref] = items[i];
+ } else {
+ [key, val, vis = PROP_VIRTUAL, ref] = items[i];
+ }
+
+ createEl(el, null, [
+ build(key, null, null, null, type === TYPE_ARRAY ? TYPE_ARRAY : vis),
+ type === TYPE_ARRAY ? ' => ' : ': ',
+ ...(ref ? [createEl('span', { class: 'tracy-dump-hash' }, ['&' + ref]), ' '] : []),
+ tmp = build(val, repository, collapsed, parentIds),
+ tmp.lastElementChild.tagName === 'DIV' ? '' : '\n',
+ ]);
+ }
+}
+
+
+function toggleChildren(cont, usedIds) {
+ let hashEl, id;
+
+ cont.querySelectorAll(':scope > .tracy-toggle').forEach((el) => {
+ hashEl = (el.querySelector('.tracy-dump-hash') || el.previousElementSibling);
+ id = hashEl && hashEl.matches('.tracy-dump-hash') ? hashEl.textContent : null;
+
+ if (!usedIds || (id && usedIds[id])) {
+ Tracy.Toggle.toggle(el, false);
+ } else {
+ usedIds[id] = true;
+ Tracy.Toggle.toggle(el, true, { usedIds: usedIds });
+ }
+ });
+}
+
+
+function UnknownEntityException() {}
+
+
+let Tracy = window.Tracy = window.Tracy || {};
+Tracy.Dumper = Tracy.Dumper || Dumper;
+
+function init() {
+ Tracy.Dumper.init();
+}
+
+if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', init);
+} else {
+ init();
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Helpers.php b/vendor/tracy/tracy/src/Tracy/Helpers.php
new file mode 100644
index 0000000..a47d36e
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Helpers.php
@@ -0,0 +1,646 @@
+%% %',
+ $editor,
+ $origFile . ($line ? ":$line" : ''),
+ rtrim(dirname($file), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR,
+ basename($file),
+ $line ? ":$line" : '',
+ );
+ } else {
+ return self::formatHtml('% ', $file . ($line ? ":$line" : ''));
+ }
+ }
+
+
+ /**
+ * Returns link to editor.
+ */
+ public static function editorUri(
+ string $file,
+ ?int $line = null,
+ string $action = 'open',
+ string $search = '',
+ string $replace = '',
+ ): ?string
+ {
+ if (Debugger::$editor && $file && ($action === 'create' || @is_file($file))) { // @ - may trigger error
+ $file = strtr($file, '/', DIRECTORY_SEPARATOR);
+ $file = strtr($file, Debugger::$editorMapping);
+ $search = str_replace("\n", PHP_EOL, $search);
+ $replace = str_replace("\n", PHP_EOL, $replace);
+ return strtr(Debugger::$editor, [
+ '%action' => $action,
+ '%file' => rawurlencode($file),
+ '%line' => $line ?: 1,
+ '%search' => rawurlencode($search),
+ '%replace' => rawurlencode($replace),
+ ]);
+ }
+
+ return null;
+ }
+
+
+ public static function formatHtml(string $mask): string
+ {
+ $args = func_get_args();
+ return preg_replace_callback('#%#', function () use (&$args, &$count): string {
+ return str_replace("\n", '
', self::escapeHtml($args[++$count]));
+ }, $mask);
+ }
+
+
+ public static function escapeHtml(mixed $s): string
+ {
+ return htmlspecialchars((string) $s, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8');
+ }
+
+
+ public static function htmlToText(string $s): string
+ {
+ return htmlspecialchars_decode(strip_tags($s), ENT_QUOTES | ENT_HTML5);
+ }
+
+
+ public static function findTrace(array $trace, array|string $method, ?int &$index = null): ?array
+ {
+ $m = is_array($method) ? $method : explode('::', $method);
+ foreach ($trace as $i => $item) {
+ if (
+ isset($item['function'])
+ && $item['function'] === end($m)
+ && isset($item['class']) === isset($m[1])
+ && (!isset($item['class']) || $m[0] === '*' || is_a($item['class'], $m[0], allow_string: true))
+ ) {
+ $index = $i;
+ return $item;
+ }
+ }
+
+ return null;
+ }
+
+
+ /** @internal */
+ public static function errorTypeToString(int $type): string
+ {
+ $types = [
+ E_ERROR => 'Fatal Error',
+ E_USER_ERROR => 'User Error',
+ E_RECOVERABLE_ERROR => 'Recoverable Error',
+ E_CORE_ERROR => 'Core Error',
+ E_COMPILE_ERROR => 'Compile Error',
+ E_PARSE => 'Parse Error',
+ E_WARNING => 'Warning',
+ E_CORE_WARNING => 'Core Warning',
+ E_COMPILE_WARNING => 'Compile Warning',
+ E_USER_WARNING => 'User Warning',
+ E_NOTICE => 'Notice',
+ E_USER_NOTICE => 'User Notice',
+ E_DEPRECATED => 'Deprecated',
+ E_USER_DEPRECATED => 'User Deprecated',
+ ];
+ return $types[$type] ?? 'Unknown error';
+ }
+
+
+ /** @internal */
+ public static function getSource(): string
+ {
+ if (self::isCli()) {
+ return 'CLI (PID: ' . getmypid() . ')'
+ . (isset($_SERVER['argv']) ? ': ' . implode(' ', array_map([self::class, 'escapeArg'], $_SERVER['argv'])) : '');
+
+ } elseif (isset($_SERVER['REQUEST_URI'])) {
+ return (!empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'off') ? 'https://' : 'http://')
+ . ($_SERVER['HTTP_HOST'] ?? '')
+ . $_SERVER['REQUEST_URI'];
+
+ } else {
+ return PHP_SAPI;
+ }
+ }
+
+
+ /** @internal */
+ public static function improveException(\Throwable $e): void
+ {
+ $message = $e->getMessage();
+ if (
+ !($e instanceof \Error || $e instanceof \ErrorException)
+ || str_contains($e->getMessage(), 'did you mean')
+ ) {
+ // do nothing
+ } elseif (preg_match('~Argument #(\d+)(?: \(\$\w+\))? must be of type callable, (.+ given)~', $message, $m)) {
+ $arg = $e->getTrace()[0]['args'][$m[1] - 1] ?? null;
+ if (is_string($arg) && str_contains($arg, '::')) {
+ $arg = explode('::', $arg, 2);
+ }
+ if (!is_callable($arg, syntax_only: true)) {
+ // do nothing
+ } elseif (is_array($arg) && is_string($arg[0]) && !class_exists($arg[0]) && !trait_exists($arg[0])) {
+ $message = str_replace($m[2], "but class '$arg[0]' does not exist", $message);
+ } elseif (is_array($arg) && !method_exists($arg[0], $arg[1])) {
+ $hint = self::getSuggestion(get_class_methods($arg[0]) ?: [], $arg[1]);
+ $class = is_object($arg[0]) ? get_class($arg[0]) : $arg[0];
+ $message = str_replace($m[2], "but method $class::$arg[1]() does not exist" . ($hint ? " (did you mean $hint?)" : ''), $message);
+ } elseif (is_string($arg) && !function_exists($arg)) {
+ $funcs = array_merge(get_defined_functions()['internal'], get_defined_functions()['user']);
+ $hint = self::getSuggestion($funcs, $arg);
+ $message = str_replace($m[2], "but function '$arg' does not exist" . ($hint ? " (did you mean $hint?)" : ''), $message);
+ }
+
+ } elseif (preg_match('#^Call to undefined function (\S+\\\\)?(\w+)\(#', $message, $m)) {
+ $funcs = array_merge(get_defined_functions()['internal'], get_defined_functions()['user']);
+ if ($hint = self::getSuggestion($funcs, $m[1] . $m[2]) ?: self::getSuggestion($funcs, $m[2])) {
+ $message = "Call to undefined function $m[2](), did you mean $hint()?";
+ $replace = ["$m[2](", "$hint("];
+ }
+
+ } elseif (preg_match('#^Call to undefined method ([\w\\\\]+)::(\w+)#', $message, $m)) {
+ if ($hint = self::getSuggestion(get_class_methods($m[1]) ?: [], $m[2])) {
+ $message .= ", did you mean $hint()?";
+ $replace = ["$m[2](", "$hint("];
+ }
+
+ } elseif (preg_match('#^Undefined property: ([\w\\\\]+)::\$(\w+)#', $message, $m)) {
+ $rc = new \ReflectionClass($m[1]);
+ $items = array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), fn($prop) => !$prop->isStatic());
+ if ($hint = self::getSuggestion($items, $m[2])) {
+ $message .= ", did you mean $$hint?";
+ $replace = ["->$m[2]", "->$hint"];
+ }
+
+ } elseif (preg_match('#^Access to undeclared static property:? ([\w\\\\]+)::\$(\w+)#', $message, $m)) {
+ $rc = new \ReflectionClass($m[1]);
+ $items = array_filter($rc->getProperties(\ReflectionProperty::IS_STATIC), fn($prop) => $prop->isPublic());
+ if ($hint = self::getSuggestion($items, $m[2])) {
+ $message .= ", did you mean $$hint?";
+ $replace = ["::$$m[2]", "::$$hint"];
+ }
+ }
+
+ if ($message !== $e->getMessage()) {
+ $ref = new \ReflectionProperty($e, 'message');
+ $ref->setAccessible(true);
+ $ref->setValue($e, $message);
+ }
+
+ if (isset($replace)) {
+ $loc = Debugger::mapSource($e->getFile(), $e->getLine()) ?? ['file' => $e->getFile(), 'line' => $e->getLine()];
+ @$e->tracyAction = [ // dynamic properties are deprecated since PHP 8.2
+ 'link' => self::editorUri($loc['file'], $loc['line'], 'fix', $replace[0], $replace[1]),
+ 'label' => 'fix it',
+ ];
+ }
+ }
+
+
+ /** @internal */
+ public static function improveError(string $message): string
+ {
+ if (preg_match('#^Undefined property: ([\w\\\\]+)::\$(\w+)#', $message, $m)) {
+ $rc = new \ReflectionClass($m[1]);
+ $items = array_filter($rc->getProperties(\ReflectionProperty::IS_PUBLIC), fn($prop) => !$prop->isStatic());
+ $hint = self::getSuggestion($items, $m[2]);
+ return $hint ? $message . ", did you mean $$hint?" : $message;
+ }
+
+ return $message;
+ }
+
+
+ /** @internal */
+ public static function guessClassFile(string $class): ?string
+ {
+ $segments = explode('\\', $class);
+ $res = null;
+ $max = 0;
+ foreach (get_declared_classes() as $class) {
+ $parts = explode('\\', $class);
+ foreach ($parts as $i => $part) {
+ if ($part !== ($segments[$i] ?? null)) {
+ break;
+ }
+ }
+
+ if ($i > $max && $i < count($segments) && ($file = (new \ReflectionClass($class))->getFileName())) {
+ $max = $i;
+ $res = array_merge(array_slice(explode(DIRECTORY_SEPARATOR, $file), 0, $i - count($parts)), array_slice($segments, $i));
+ $res = implode(DIRECTORY_SEPARATOR, $res) . '.php';
+ }
+ }
+
+ return $res;
+ }
+
+
+ /**
+ * Finds the best suggestion.
+ * @internal
+ */
+ public static function getSuggestion(array $items, string $value): ?string
+ {
+ $best = null;
+ $min = (strlen($value) / 4 + 1) * 10 + .1;
+ $items = array_map(fn($item) => $item instanceof \Reflector ? $item->getName() : (string) $item, $items);
+ foreach (array_unique($items) as $item) {
+ if (($len = levenshtein($item, $value, 10, 11, 10)) > 0 && $len < $min) {
+ $min = $len;
+ $best = $item;
+ }
+ }
+
+ return $best;
+ }
+
+
+ /** @internal */
+ public static function isHtmlMode(): bool
+ {
+ return empty($_SERVER['HTTP_X_REQUESTED_WITH'])
+ && empty($_SERVER['HTTP_X_TRACY_AJAX'])
+ && isset($_SERVER['HTTP_HOST'])
+ && !self::isCli()
+ && !preg_match('#^Content-Type: *+(?!text/html)#im', implode("\n", headers_list()));
+ }
+
+
+ /** @internal */
+ public static function isAjax(): bool
+ {
+ return isset($_SERVER['HTTP_X_TRACY_AJAX']) && preg_match('#^\w{10,15}$#D', $_SERVER['HTTP_X_TRACY_AJAX']);
+ }
+
+
+ /** @internal */
+ public static function isRedirect(): bool
+ {
+ return (bool) preg_match('#^Location:#im', implode("\n", headers_list()));
+ }
+
+
+ /** @internal */
+ public static function createId(): string
+ {
+ return bin2hex(random_bytes(5));
+ }
+
+
+ /** @internal */
+ public static function isCli(): bool
+ {
+ return PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg';
+ }
+
+
+ /** @internal */
+ public static function getNonceAttr(): string
+ {
+ return preg_match('#^Content-Security-Policy(?:-Report-Only)?:.*\sscript-src\s+(?:[^;]+\s)?\'nonce-([\w+/]+=*)\'#mi', implode("\n", headers_list()), $m)
+ ? ' nonce="' . self::escapeHtml($m[1]) . '"'
+ : '';
+ }
+
+
+ /**
+ * Escape a string to be used as a shell argument.
+ */
+ private static function escapeArg(string $s): string
+ {
+ if (preg_match('#^[a-z0-9._=/:-]+$#Di', $s)) {
+ return $s;
+ }
+
+ return defined('PHP_WINDOWS_VERSION_BUILD')
+ ? '"' . str_replace('"', '""', $s) . '"'
+ : escapeshellarg($s);
+ }
+
+
+ /**
+ * Captures PHP output into a string.
+ */
+ public static function capture(callable $func): string
+ {
+ ob_start(fn() => null);
+ try {
+ $func();
+ return ob_get_clean();
+ } catch (\Throwable $e) {
+ ob_end_clean();
+ throw $e;
+ }
+ }
+
+
+ /** @internal */
+ public static function encodeString(string $s, ?int $maxLength = null, bool $showWhitespaces = true): string
+ {
+ $utf8 = self::isUtf8($s);
+ $len = $utf8 ? self::utf8Length($s) : strlen($s);
+ return $maxLength && $len > $maxLength + 20
+ ? self::doEncodeString(self::truncateString($s, $maxLength, $utf8), $utf8, $showWhitespaces)
+ . ' … '
+ . self::doEncodeString(self::truncateString($s, -10, $utf8), $utf8, $showWhitespaces)
+ : self::doEncodeString($s, $utf8, $showWhitespaces);
+ }
+
+
+ private static function doEncodeString(string $s, bool $utf8, bool $showWhitespaces): string
+ {
+ $specials = [
+ true => [
+ "\r" => '\r ',
+ "\n" => "\\n \n",
+ "\t" => '\t ',
+ "\e" => '\e ',
+ '<' => '<',
+ '&' => '&',
+ ],
+ false => [
+ "\r" => "\r",
+ "\n" => "\n",
+ "\t" => "\t",
+ "\e" => '\e ',
+ '<' => '<',
+ '&' => '&',
+ ],
+ ];
+ $special = $specials[$showWhitespaces];
+ $s = preg_replace_callback(
+ $utf8 ? '#[\p{C}<&]#u' : '#[\x00-\x1F\x7F-\xFF<&]#',
+ fn($m) => $special[$m[0]] ?? (strlen($m[0]) === 1
+ ? '\x' . str_pad(strtoupper(dechex(ord($m[0]))), 2, '0', STR_PAD_LEFT) . ' '
+ : '\u{' . strtoupper(ltrim(dechex(self::utf8Ord($m[0])), '0')) . '} '),
+ $s,
+ );
+ $s = str_replace('', '', $s);
+ $s = preg_replace('~\n$~D', '', $s);
+ return $s;
+ }
+
+
+ private static function utf8Ord(string $c): int
+ {
+ $ord0 = ord($c[0]);
+ if ($ord0 < 0x80) {
+ return $ord0;
+ } elseif ($ord0 < 0xE0) {
+ return ($ord0 << 6) + ord($c[1]) - 0x3080;
+ } elseif ($ord0 < 0xF0) {
+ return ($ord0 << 12) + (ord($c[1]) << 6) + ord($c[2]) - 0xE2080;
+ } else {
+ return ($ord0 << 18) + (ord($c[1]) << 12) + (ord($c[2]) << 6) + ord($c[3]) - 0x3C82080;
+ }
+ }
+
+
+ /** @internal */
+ public static function utf8Length(string $s): int
+ {
+ return match (true) {
+ extension_loaded('mbstring') => mb_strlen($s, 'UTF-8'),
+ extension_loaded('iconv') => iconv_strlen($s, 'UTF-8'),
+ default => strlen(@utf8_decode($s)), // deprecated
+ };
+ }
+
+
+ /** @internal */
+ public static function isUtf8(string $s): bool
+ {
+ return (bool) preg_match('##u', $s);
+ }
+
+
+ /** @internal */
+ public static function truncateString(string $s, int $len, bool $utf8): string
+ {
+ if (!$utf8) {
+ return $len < 0 ? substr($s, $len) : substr($s, 0, $len);
+ } elseif (function_exists('mb_substr')) {
+ return $len < 0
+ ? mb_substr($s, $len, -$len, 'UTF-8')
+ : mb_substr($s, 0, $len, 'UTF-8');
+ } else {
+ $len < 0
+ ? preg_match('#.{0,' . -$len . '}\z#us', $s, $m)
+ : preg_match("#^.{0,$len}#us", $s, $m);
+ return $m[0];
+ }
+ }
+
+
+ /** @internal */
+ public static function htmlToAnsi(string $s, array $colors): string
+ {
+ $stack = ['0'];
+ $s = preg_replace_callback(
+ '#<\w+(?: class=["\']tracy-(?:dump-)?([\w-]+)["\'])?[^>]*>|\w+>#',
+ function ($m) use ($colors, &$stack): string {
+ if ($m[0][1] === '/') {
+ array_pop($stack);
+ } else {
+ $stack[] = isset($m[1], $colors[$m[1]]) ? $colors[$m[1]] : '0';
+ }
+ return "\e[" . end($stack) . 'm';
+ },
+ $s,
+ );
+ $s = preg_replace('/\e\[0m( *)(?=\e)/', '$1', $s);
+ $s = self::htmlToText($s);
+ return $s;
+ }
+
+
+ /** @internal */
+ public static function minifyJs(string $s): string
+ {
+ // author: Jakub Vrana https://php.vrana.cz/minifikace-javascriptu.php
+ $last = '';
+ return preg_replace_callback(
+ <<<'XX'
+ (
+ (?:
+ (^|[-+\([{}=,:;!%^&*|?~]|/(?![/*])|return|throw) # context before regexp
+ (?:\s|//[^\n]*+\n|/\*(?:[^*]|\*(?!/))*+\*/)* # optional space
+ (/(?![/*])(?:\\[^\n]|[^[\n/\\]|\[(?:\\[^\n]|[^]])++)+/) # regexp
+ |(^
+ |'(?:\\.|[^\n'\\])*'
+ |"(?:\\.|[^\n"\\])*"
+ |([0-9A-Za-z_$]+)
+ |([-+]+)
+ |.
+ )
+ )(?:\s|//[^\n]*+\n|/\*(?:[^*]|\*(?!/))*+\*/)* # optional space
+ ())sx
+ XX,
+ function ($match) use (&$last) {
+ [, $context, $regexp, $result, $word, $operator] = $match;
+ if ($word !== '') {
+ $result = ($last === 'word' ? ' ' : ($last === 'return' ? ' ' : '')) . $result;
+ $last = ($word === 'return' || $word === 'throw' || $word === 'break' ? 'return' : 'word');
+ } elseif ($operator) {
+ $result = ($last === $operator[0] ? ' ' : '') . $result;
+ $last = $operator[0];
+ } else {
+ if ($regexp) {
+ $result = $context . ($context === '/' ? ' ' : '') . $regexp;
+ }
+
+ $last = '';
+ }
+
+ return $result;
+ },
+ $s . "\n",
+ );
+ }
+
+
+ /** @internal */
+ public static function minifyCss(string $s): string
+ {
+ $last = '';
+ return preg_replace_callback(
+ <<<'XX'
+ (
+ (^
+ |'(?:\\.|[^\n'\\])*'
+ |"(?:\\.|[^\n"\\])*"
+ |([0-9A-Za-z_*#.%:()[\]-]+)
+ |.
+ )(?:\s|/\*(?:[^*]|\*(?!/))*+\*/)* # optional space
+ ())sx
+ XX,
+ function ($match) use (&$last) {
+ [, $result, $word] = $match;
+ if ($last === ';') {
+ $result = $result === '}' ? '}' : ';' . $result;
+ $last = '';
+ }
+
+ if ($word !== '') {
+ $result = ($last === 'word' ? ' ' : '') . $result;
+ $last = 'word';
+ } elseif ($result === ';') {
+ $last = ';';
+ $result = '';
+ } else {
+ $last = '';
+ }
+
+ return $result;
+ },
+ $s . "\n",
+ );
+ }
+
+
+ public static function detectColors(): bool
+ {
+ return self::isCli()
+ && getenv('NO_COLOR') === false // https://no-color.org
+ && (getenv('FORCE_COLOR')
+ || (function_exists('sapi_windows_vt100_support')
+ ? sapi_windows_vt100_support(STDOUT)
+ : @stream_isatty(STDOUT)) // @ may trigger error 'cannot cast a filtered stream on this system'
+ );
+ }
+
+
+ public static function getExceptionChain(\Throwable $ex): array
+ {
+ $res = [$ex];
+ while (($ex = $ex->getPrevious()) && !in_array($ex, $res, true)) {
+ $res[] = $ex;
+ }
+
+ return $res;
+ }
+
+
+ public static function traverseValue(mixed $val, callable $callback, array &$skip = [], ?string $refId = null): void
+ {
+ if (is_object($val)) {
+ $id = spl_object_id($val);
+ if (!isset($skip[$id])) {
+ $skip[$id] = true;
+ $callback($val);
+ self::traverseValue((array) $val, $callback, $skip);
+ }
+
+ } elseif (is_array($val)) {
+ if ($refId) {
+ if (isset($skip[$refId])) {
+ return;
+ }
+ $skip[$refId] = true;
+ }
+
+ foreach ($val as $k => $v) {
+ $refId = \ReflectionReference::fromArrayElement($val, $k)?->getId();
+ self::traverseValue($v, $callback, $skip, $refId);
+ }
+ }
+ }
+
+
+ /** @internal */
+ public static function decomposeFlags(int $flags, bool $set, array $constants): ?array
+ {
+ $res = null;
+ foreach ($constants as $constant) {
+ if (defined($constant)) {
+ $v = constant($constant);
+ if ($set) {
+ if ($v && ($flags & $v) === $v) {
+ $res[] = $constant;
+ $flags &= ~$v;
+ }
+ } elseif ($flags === $v) {
+ return [$constant];
+ }
+ }
+ }
+
+ if ($flags && $res && $set) {
+ $res[] = (string) $flags;
+ }
+ return $res;
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Logger/ILogger.php b/vendor/tracy/tracy/src/Tracy/Logger/ILogger.php
new file mode 100644
index 0000000..de32dab
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Logger/ILogger.php
@@ -0,0 +1,27 @@
+directory = $directory;
+ $this->email = $email;
+ $this->blueScreen = $blueScreen;
+ $this->mailer = [$this, 'defaultMailer'];
+ }
+
+
+ /**
+ * Logs message or exception to file and sends email notification.
+ * For levels ERROR, EXCEPTION and CRITICAL it sends email.
+ * @return string|null logged error filename
+ */
+ public function log(mixed $message, string $level = self::INFO)
+ {
+ if (!$this->directory) {
+ throw new \LogicException('Logging directory is not specified.');
+ } elseif (!is_dir($this->directory)) {
+ throw new \RuntimeException("Logging directory '$this->directory' is not found or is not directory.");
+ }
+
+ $exceptionFile = $message instanceof \Throwable
+ ? $this->getExceptionFile($message, $level)
+ : null;
+ $line = static::formatLogLine($message, $exceptionFile);
+ $file = $this->directory . '/' . strtolower($level ?: self::INFO) . '.log';
+
+ if (!@file_put_contents($file, $line . PHP_EOL, FILE_APPEND | LOCK_EX)) { // @ is escalated to exception
+ throw new \RuntimeException("Unable to write to log file '$file'. Is directory writable?");
+ }
+
+ if ($exceptionFile) {
+ $this->logException($message, $exceptionFile);
+ }
+
+ if (in_array($level, [self::ERROR, self::EXCEPTION, self::CRITICAL], true)) {
+ $this->sendEmail($message);
+ }
+
+ return $exceptionFile;
+ }
+
+
+ /**
+ * @param mixed $message
+ */
+ public static function formatMessage($message): string
+ {
+ if ($message instanceof \Throwable) {
+ foreach (Helpers::getExceptionChain($message) as $exception) {
+ $tmp[] = ($exception instanceof \ErrorException
+ ? Helpers::errorTypeToString($exception->getSeverity()) . ': ' . $exception->getMessage()
+ : get_debug_type($exception) . ': ' . $exception->getMessage() . ($exception->getCode() ? ' #' . $exception->getCode() : '')
+ ) . ' in ' . $exception->getFile() . ':' . $exception->getLine();
+ }
+
+ $message = implode("\ncaused by ", $tmp);
+
+ } elseif (!is_string($message)) {
+ $message = Dumper::toText($message);
+ }
+
+ return trim($message);
+ }
+
+
+ /**
+ * @param mixed $message
+ */
+ public static function formatLogLine($message, ?string $exceptionFile = null): string
+ {
+ return implode(' ', [
+ date('[Y-m-d H-i-s]'),
+ preg_replace('#\s*\r?\n\s*#', ' ', static::formatMessage($message)),
+ ' @ ' . Helpers::getSource(),
+ $exceptionFile ? ' @@ ' . basename($exceptionFile) : null,
+ ]);
+ }
+
+
+ public function getExceptionFile(\Throwable $exception, string $level = self::EXCEPTION): string
+ {
+ foreach (Helpers::getExceptionChain($exception) as $exception) {
+ $data[] = [
+ $exception::class, $exception->getMessage(), $exception->getCode(), $exception->getFile(), $exception->getLine(),
+ array_map(function (array $item): array {
+ unset($item['args']);
+ return $item;
+ }, $exception->getTrace()),
+ ];
+ }
+
+ $hash = substr(md5(serialize($data)), 0, 10);
+ $dir = strtr($this->directory . '/', '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR);
+ foreach (new \DirectoryIterator($this->directory) as $file) {
+ if (strpos($file->getBasename(), $hash)) {
+ return $dir . $file;
+ }
+ }
+
+ return $dir . $level . '--' . date('Y-m-d--H-i') . "--$hash.html";
+ }
+
+
+ /**
+ * Logs exception to the file if file doesn't exist.
+ * @return string logged error filename
+ */
+ protected function logException(\Throwable $exception, ?string $file = null): string
+ {
+ $file = $file ?: $this->getExceptionFile($exception);
+ $bs = $this->blueScreen ?: new BlueScreen;
+ $bs->renderToFile($exception, $file);
+ return $file;
+ }
+
+
+ /**
+ * @param mixed $message
+ */
+ protected function sendEmail($message): void
+ {
+ $snooze = is_numeric($this->emailSnooze)
+ ? $this->emailSnooze
+ : strtotime($this->emailSnooze) - time();
+
+ if (
+ $this->email
+ && $this->mailer
+ && @filemtime($this->directory . '/email-sent') + $snooze < time() // @ file may not exist
+ && @file_put_contents($this->directory . '/email-sent', 'sent') // @ file may not be writable
+ ) {
+ ($this->mailer)($message, implode(', ', (array) $this->email));
+ }
+ }
+
+
+ /**
+ * Default mailer.
+ * @param mixed $message
+ * @internal
+ */
+ public function defaultMailer($message, string $email): void
+ {
+ $host = preg_replace('#[^\w.-]+#', '', $_SERVER['SERVER_NAME'] ?? php_uname('n'));
+ mail(
+ $email,
+ "PHP: An error occurred on the server $host",
+ static::formatMessage($message) . "\n\nsource: " . Helpers::getSource(),
+ implode("\r\n", [
+ 'From: ' . ($this->fromEmail ?: "noreply@$host"),
+ 'X-Mailer: Tracy',
+ 'Content-Type: text/plain; charset=UTF-8',
+ 'Content-Transfer-Encoding: 8bit',
+ ]),
+ );
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php b/vendor/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php
new file mode 100644
index 0000000..4c8c74c
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/OutputDebugger/OutputDebugger.php
@@ -0,0 +1,83 @@
+start();
+ }
+
+
+ public function start(): void
+ {
+ foreach (get_included_files() as $file) {
+ if (fread(fopen($file, 'r'), 3) === self::BOM) {
+ $this->list[] = [$file, 1, self::BOM];
+ }
+ }
+
+ ob_start([$this, 'handler'], 1);
+ }
+
+
+ /** @internal */
+ public function handler(string $s, int $phase): ?string
+ {
+ $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+ if (isset($trace[0]['file'], $trace[0]['line'])) {
+ $stack = $trace;
+ unset($stack[0]['line'], $stack[0]['args']);
+ $i = count($this->list);
+ if ($i && $this->list[$i - 1][3] === $stack) {
+ $this->list[$i - 1][2] .= $s;
+ } else {
+ $this->list[] = [$trace[0]['file'], $trace[0]['line'], $s, $stack];
+ }
+ }
+
+ return $phase === PHP_OUTPUT_HANDLER_FINAL
+ ? $this->renderHtml()
+ : null;
+ }
+
+
+ private function renderHtml(): string
+ {
+ $res = '';
+ foreach ($this->list as $item) {
+ $stack = [];
+ foreach (array_slice($item[3], 1) as $t) {
+ $t += ['class' => '', 'type' => '', 'function' => ''];
+ $stack[] = "$t[class]$t[type]$t[function]()"
+ . (isset($t['file'], $t['line']) ? ' in ' . basename($t['file']) . ":$t[line]" : '');
+ }
+
+ $res .= ''
+ . Helpers::editorLink($item[0], $item[1]) . ' '
+ . str_replace(self::BOM, 'BOM ', Dumper::toHtml($item[2]))
+ . " \n";
+ }
+
+ return $res . '';
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Session/FileSession.php b/vendor/tracy/tracy/src/Tracy/Session/FileSession.php
new file mode 100644
index 0000000..8aef836
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Session/FileSession.php
@@ -0,0 +1,105 @@
+dir = $dir;
+ }
+
+
+ public function isAvailable(): bool
+ {
+ if (!$this->file) {
+ $this->open();
+ }
+
+ return true;
+ }
+
+
+ private function open(): void
+ {
+ $id = $_COOKIE[$this->cookieName] ?? null;
+ if (
+ !is_string($id)
+ || !preg_match('#^\w{10}\z#i', $id)
+ || !($file = @fopen($path = $this->dir . '/' . self::FilePrefix . $id, 'r+')) // intentionally @
+ ) {
+ $id = Helpers::createId();
+ setcookie($this->cookieName, $id, time() + self::CookieLifetime, '/', '', secure: false, httponly: true);
+
+ $file = @fopen($path = $this->dir . '/' . self::FilePrefix . $id, 'c+'); // intentionally @
+ if ($file === false) {
+ throw new \RuntimeException("Unable to create file '$path'. " . error_get_last()['message']);
+ }
+ }
+
+ if (!@flock($file, LOCK_EX)) { // intentionally @
+ throw new \RuntimeException("Unable to acquire exclusive lock on '$path'. ", error_get_last()['message']);
+ }
+
+ $this->file = $file;
+ $this->data = @unserialize(stream_get_contents($this->file)) ?: []; // @ - file may be empty
+
+ if (mt_rand() / mt_getrandmax() < $this->gcProbability) {
+ $this->clean();
+ }
+ }
+
+
+ public function &getData(): array
+ {
+ return $this->data;
+ }
+
+
+ public function clean(): void
+ {
+ $old = strtotime('-1 week');
+ foreach (glob($this->dir . '/' . self::FilePrefix . '*') as $file) {
+ if (filemtime($file) < $old) {
+ unlink($file);
+ }
+ }
+ }
+
+
+ public function __destruct()
+ {
+ if (!$this->file) {
+ return;
+ }
+
+ ftruncate($this->file, 0);
+ fseek($this->file, 0);
+ fwrite($this->file, serialize($this->data));
+ flock($this->file, LOCK_UN);
+ fclose($this->file);
+ $this->file = null;
+ }
+}
diff --git a/vendor/tracy/tracy/src/Tracy/Session/NativeSession.php b/vendor/tracy/tracy/src/Tracy/Session/NativeSession.php
new file mode 100644
index 0000000..5b6b256
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/Session/NativeSession.php
@@ -0,0 +1,26 @@
+ {
+ let el = e.target;
+ while (el && el !== document) {
+ if (el.tagName === 'A') {
+ const href = el.getAttribute('href');
+ if (href && href.startsWith('editor:')) {
+ el.setAttribute('target', '_blank');
+ }
+ break;
+ }
+ el = el.parentNode;
+ }
+ },
+ true,
+ );
+ }
+}
+
+
+let Tracy = window.Tracy = window.Tracy || {};
+if (!Tracy.helpers) {
+ init();
+ Tracy.helpers = true;
+}
diff --git a/vendor/tracy/tracy/src/Tracy/assets/reset.css b/vendor/tracy/tracy/src/Tracy/assets/reset.css
new file mode 100644
index 0000000..b0a6a6f
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/assets/reset.css
@@ -0,0 +1,386 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+:root {
+ --tracy-space: 16px;
+}
+
+@media (max-width: 600px) {
+ :root {
+ --tracy-space: 8px;
+ }
+}
+
+tracy-div:not(a b),
+tracy-div:not(a b) * {
+ font: inherit;
+ line-height: inherit;
+ color: inherit;
+ background: transparent;
+ margin: 0;
+ padding: 0;
+ border: none;
+ text-align: inherit;
+ list-style: inherit;
+ opacity: 1;
+ border-radius: 0;
+ box-shadow: none;
+ text-shadow: none;
+ box-sizing: border-box;
+ text-decoration: none;
+ text-transform: inherit;
+ white-space: inherit;
+ float: none;
+ clear: none;
+ max-width: initial;
+ min-width: initial;
+ max-height: initial;
+ min-height: initial;
+}
+
+tracy-div:not(a b) *:hover {
+ color: inherit;
+ background: transparent;
+}
+
+tracy-div:not(a b) *:not(svg):not(img):not(table) {
+ width: initial;
+ height: initial;
+}
+
+tracy-div:not(a b):before,
+tracy-div:not(a b):after,
+tracy-div:not(a b) *:before,
+tracy-div:not(a b) *:after {
+ all: unset;
+}
+
+tracy-div:not(a b) b,
+tracy-div:not(a b) strong {
+ font-weight: bold;
+}
+
+tracy-div:not(a b) small {
+ font-size: smaller;
+}
+
+tracy-div:not(a b) i,
+tracy-div:not(a b) em {
+ font-style: italic;
+}
+
+tracy-div:not(a b) big {
+ font-size: larger;
+}
+
+tracy-div:not(a b) small,
+tracy-div:not(a b) sub,
+tracy-div:not(a b) sup {
+ font-size: smaller;
+}
+
+tracy-div:not(a b) ins {
+ text-decoration: underline;
+}
+
+tracy-div:not(a b) del {
+ text-decoration: line-through;
+}
+
+tracy-div:not(a b) table {
+ border-collapse: collapse;
+}
+
+tracy-div:not(a b) pre {
+ font-family: monospace;
+ white-space: pre;
+}
+
+tracy-div:not(a b) code,
+tracy-div:not(a b) kbd,
+tracy-div:not(a b) samp {
+ font-family: monospace;
+}
+
+tracy-div:not(a b) input {
+ background-color: white;
+ padding: 1px;
+ border: 1px solid;
+}
+
+tracy-div:not(a b) textarea {
+ background-color: white;
+ border: 1px solid;
+ padding: 2px;
+ white-space: pre-wrap;
+}
+
+tracy-div:not(a b) select {
+ border: 1px solid;
+ white-space: pre;
+}
+
+tracy-div:not(a b) article,
+tracy-div:not(a b) aside,
+tracy-div:not(a b) details,
+tracy-div:not(a b) div,
+tracy-div:not(a b) figcaption,
+tracy-div:not(a b) footer,
+tracy-div:not(a b) form,
+tracy-div:not(a b) header,
+tracy-div:not(a b) hgroup,
+tracy-div:not(a b) main,
+tracy-div:not(a b) nav,
+tracy-div:not(a b) section,
+tracy-div:not(a b) summary,
+tracy-div:not(a b) pre,
+tracy-div:not(a b) p,
+tracy-div:not(a b) dl,
+tracy-div:not(a b) dd,
+tracy-div:not(a b) dt,
+tracy-div:not(a b) blockquote,
+tracy-div:not(a b) figure,
+tracy-div:not(a b) address,
+tracy-div:not(a b) h1,
+tracy-div:not(a b) h2,
+tracy-div:not(a b) h3,
+tracy-div:not(a b) h4,
+tracy-div:not(a b) h5,
+tracy-div:not(a b) h6,
+tracy-div:not(a b) ul,
+tracy-div:not(a b) ol,
+tracy-div:not(a b) li,
+tracy-div:not(a b) hr {
+ display: block;
+}
+
+tracy-div:not(a b) a,
+tracy-div:not(a b) b,
+tracy-div:not(a b) big,
+tracy-div:not(a b) code,
+tracy-div:not(a b) em,
+tracy-div:not(a b) i,
+tracy-div:not(a b) small,
+tracy-div:not(a b) span,
+tracy-div:not(a b) strong {
+ display: inline;
+}
+
+tracy-div:not(a b) table {
+ display: table;
+}
+
+tracy-div:not(a b) tr {
+ display: table-row;
+}
+
+tracy-div:not(a b) col {
+ display: table-column;
+}
+
+tracy-div:not(a b) colgroup {
+ display: table-column-group;
+}
+
+tracy-div:not(a b) tbody {
+ display: table-row-group;
+}
+
+tracy-div:not(a b) thead {
+ display: table-header-group;
+}
+
+tracy-div:not(a b) tfoot {
+ display: table-footer-group;
+}
+
+tracy-div:not(a b) td {
+ display: table-cell;
+}
+
+tracy-div:not(a b) th {
+ display: table-cell;
+}
+
+
+
+/* TableSort */
+tracy-div:not(a b) .tracy-sortable > :first-child > tr:first-child > * {
+ position: relative;
+}
+
+tracy-div:not(a b) .tracy-sortable > :first-child > tr:first-child > *:hover:before {
+ position: absolute;
+ right: .3em;
+ content: "\21C5";
+ opacity: .4;
+ font-weight: normal;
+}
+
+
+/* dump */
+tracy-div:not(a b) .tracy-dump div {
+ padding-left: 3ex;
+}
+
+tracy-div:not(a b) .tracy-dump div div {
+ border-left: 1px solid rgba(0, 0, 0, .1);
+ margin-left: .5ex;
+}
+
+tracy-div:not(a b) .tracy-dump div div:hover {
+ border-left-color: rgba(0, 0, 0, .25);
+}
+
+tracy-div:not(a b) .tracy-dump {
+ background: #FDF5CE;
+ padding: .4em .7em;
+ border: 1px dotted silver;
+ overflow: auto;
+}
+
+tracy-div:not(a b) table .tracy-dump.tracy-dump { /* overwrite .tracy-dump.tracy-light etc. */
+ padding: 0;
+ margin: 0;
+ border: none;
+}
+
+tracy-div:not(a b) .tracy-dump-location {
+ color: gray;
+ font-size: 80%;
+ text-decoration: none;
+ background: none;
+ opacity: .5;
+ float: right;
+ cursor: pointer;
+}
+
+tracy-div:not(a b) .tracy-dump-location:hover,
+tracy-div:not(a b) .tracy-dump-location:focus {
+ color: gray;
+ background: none;
+ opacity: 1;
+}
+
+tracy-div:not(a b) .tracy-dump-array,
+tracy-div:not(a b) .tracy-dump-object {
+ color: #C22;
+}
+
+tracy-div:not(a b) .tracy-dump-string {
+ color: #35D;
+ white-space: break-spaces;
+}
+
+tracy-div:not(a b) div.tracy-dump-string {
+ position: relative;
+ padding-left: 3.5ex;
+}
+
+tracy-div:not(a b) .tracy-dump-lq {
+ margin-left: calc(-1ex - 1px);
+}
+
+tracy-div:not(a b) div.tracy-dump-string:before {
+ content: '';
+ position: absolute;
+ left: calc(3ex - 1px);
+ top: 1.5em;
+ bottom: 0;
+ border-left: 1px solid rgba(0, 0, 0, .1);
+}
+
+tracy-div:not(a b) .tracy-dump-virtual span,
+tracy-div:not(a b) .tracy-dump-dynamic span,
+tracy-div:not(a b) .tracy-dump-string span {
+ color: rgba(0, 0, 0, 0.5);
+}
+
+tracy-div:not(a b) .tracy-dump-virtual i,
+tracy-div:not(a b) .tracy-dump-dynamic i,
+tracy-div:not(a b) .tracy-dump-string i {
+ font-size: 80%;
+ font-style: normal;
+ color: rgba(0, 0, 0, 0.5);
+ user-select: none;
+}
+
+tracy-div:not(a b) .tracy-dump-number {
+ color: #090;
+}
+
+tracy-div:not(a b) .tracy-dump-null,
+tracy-div:not(a b) .tracy-dump-bool {
+ color: #850;
+}
+
+tracy-div:not(a b) .tracy-dump-virtual {
+ font-style: italic;
+}
+
+tracy-div:not(a b) .tracy-dump-public::after {
+ content: ' pub';
+}
+
+tracy-div:not(a b) .tracy-dump-protected::after {
+ content: ' pro';
+}
+
+tracy-div:not(a b) .tracy-dump-private::after {
+ content: ' pri';
+}
+
+tracy-div:not(a b) .tracy-dump-public::after,
+tracy-div:not(a b) .tracy-dump-protected::after,
+tracy-div:not(a b) .tracy-dump-private::after,
+tracy-div:not(a b) .tracy-dump-hash {
+ font-size: 85%;
+ color: rgba(0, 0, 0, 0.5);
+}
+
+tracy-div:not(a b) .tracy-dump-indent {
+ display: none;
+}
+
+tracy-div:not(a b) .tracy-dump-highlight {
+ background: #C22;
+ color: white;
+ border-radius: 2px;
+ padding: 0 2px;
+ margin: 0 -2px;
+}
+
+tracy-div:not(a b) span[data-tracy-href] {
+ border-bottom: 1px dotted rgba(0, 0, 0, .2);
+}
+
+
+/* toggle */
+tracy-div:not(a b) .tracy-toggle:after {
+ content: '';
+ display: inline-block;
+ vertical-align: middle;
+ line-height: 0;
+ border-top: .6ex solid;
+ border-right: .6ex solid transparent;
+ border-left: .6ex solid transparent;
+ transform: scale(1, 1.5);
+ margin: 0 .2ex 0 .7ex;
+ transition: .1s transform;
+ opacity: .5;
+}
+
+tracy-div:not(a b) .tracy-toggle.tracy-collapsed:after {
+ transform: rotate(-90deg) scale(1, 1.5) translate(.1ex, 0);
+}
+
+
+/* tabs */
+tracy-div:not(a b) .tracy-tab-label {
+ user-select: none;
+}
+
+tracy-div:not(a b) .tracy-tab-panel:not(.tracy-active) {
+ display: none;
+}
diff --git a/vendor/tracy/tracy/src/Tracy/assets/table-sort.css b/vendor/tracy/tracy/src/Tracy/assets/table-sort.css
new file mode 100644
index 0000000..7967a64
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/assets/table-sort.css
@@ -0,0 +1,15 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+.tracy-sortable > :first-child > tr:first-child > * {
+ position: relative;
+}
+
+.tracy-sortable > :first-child > tr:first-child > *:hover:before {
+ position: absolute;
+ right: .3em;
+ content: "\21C5";
+ opacity: .4;
+ font-weight: normal;
+}
diff --git a/vendor/tracy/tracy/src/Tracy/assets/table-sort.js b/vendor/tracy/tracy/src/Tracy/assets/table-sort.js
new file mode 100644
index 0000000..39bae80
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/assets/table-sort.js
@@ -0,0 +1,39 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+// enables
+class TableSort {
+ static init() {
+ document.documentElement.addEventListener('click', (e) => {
+ if ((window.getSelection().type !== 'Range')
+ && e.target.matches('.tracy-sortable > :first-child > tr:first-child *')
+ ) {
+ TableSort.sort(e.target.closest('td,th'));
+ }
+ });
+
+ TableSort.init = function () {};
+ }
+
+ static sort(tcell) {
+ let tbody = tcell.closest('table').tBodies[0];
+ let preserveFirst = !tcell.closest('thead') && !tcell.parentNode.querySelectorAll('td').length;
+ let asc = !(tbody.tracyAsc === tcell.cellIndex);
+ tbody.tracyAsc = asc ? tcell.cellIndex : null;
+ let getText = (cell) => cell ? (cell.getAttribute('data-order') || cell.innerText) : '';
+
+ Array.from(tbody.children)
+ .slice(preserveFirst ? 1 : 0)
+ .sort((a, b) => (function (v1, v2) {
+ return v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2)
+ ? v1 - v2
+ : v1.toString().localeCompare(v2, undefined, { numeric: true, sensitivity: 'base' });
+ }(getText((asc ? a : b).children[tcell.cellIndex]), getText((asc ? b : a).children[tcell.cellIndex]))))
+ .forEach((tr) => { tbody.appendChild(tr); });
+ }
+}
+
+
+let Tracy = window.Tracy = window.Tracy || {};
+Tracy.TableSort = Tracy.TableSort || TableSort;
diff --git a/vendor/tracy/tracy/src/Tracy/assets/tabs.css b/vendor/tracy/tracy/src/Tracy/assets/tabs.css
new file mode 100644
index 0000000..9add853
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/assets/tabs.css
@@ -0,0 +1,11 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+.tracy-tab-label {
+ user-select: none;
+}
+
+.tracy-tab-panel:not(.tracy-active) {
+ display: none;
+}
diff --git a/vendor/tracy/tracy/src/Tracy/assets/tabs.js b/vendor/tracy/tracy/src/Tracy/assets/tabs.js
new file mode 100644
index 0000000..8ec2fe7
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/assets/tabs.js
@@ -0,0 +1,40 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+// enables .tracy-tabs, .tracy-tab-label, .tracy-tab-panel, .tracy-active
+class Tabs {
+ static init() {
+ document.documentElement.addEventListener('click', (e) => {
+ let label, context;
+ if (
+ !e.shiftKey && !e.ctrlKey && !e.metaKey
+ && (label = e.target.closest('.tracy-tab-label'))
+ && (context = e.target.closest('.tracy-tabs'))
+ ) {
+ Tabs.toggle(context, label);
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ }
+ });
+
+ Tabs.init = function () {};
+ }
+
+ static toggle(context, label) {
+ let labels = context.querySelector('.tracy-tab-label').parentNode.querySelectorAll('.tracy-tab-label'),
+ panels = context.querySelector('.tracy-tab-panel').parentNode.querySelectorAll(':scope > .tracy-tab-panel');
+
+ for (let i = 0; i < labels.length; i++) {
+ labels[i].classList.toggle('tracy-active', labels[i] === label);
+ }
+
+ for (let i = 0; i < panels.length; i++) {
+ panels[i].classList.toggle('tracy-active', labels[i] === label);
+ }
+ }
+}
+
+
+let Tracy = window.Tracy = window.Tracy || {};
+Tracy.Tabs = Tracy.Tabs || Tabs;
diff --git a/vendor/tracy/tracy/src/Tracy/assets/toggle.css b/vendor/tracy/tracy/src/Tracy/assets/toggle.css
new file mode 100644
index 0000000..acce8e4
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/assets/toggle.css
@@ -0,0 +1,35 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+.tracy-collapsed {
+ display: none;
+}
+
+.tracy-toggle.tracy-collapsed {
+ display: inline;
+}
+
+.tracy-toggle {
+ cursor: pointer;
+ user-select: none;
+ white-space: nowrap;
+}
+
+.tracy-toggle:after {
+ content: '';
+ display: inline-block;
+ vertical-align: middle;
+ line-height: 0;
+ border-top: .6ex solid;
+ border-right: .6ex solid transparent;
+ border-left: .6ex solid transparent;
+ transform: scale(1, 1.5);
+ margin: 0 .2ex 0 .7ex;
+ transition: .1s transform;
+ opacity: .5;
+}
+
+.tracy-toggle.tracy-collapsed:after {
+ transform: rotate(-90deg) scale(1, 1.5) translate(.1ex, 0);
+}
diff --git a/vendor/tracy/tracy/src/Tracy/assets/toggle.js b/vendor/tracy/tracy/src/Tracy/assets/toggle.js
new file mode 100644
index 0000000..aabefb5
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/assets/toggle.js
@@ -0,0 +1,116 @@
+/**
+ * This file is part of the Tracy (https://tracy.nette.org)
+ */
+
+const MOVE_THRESHOLD = 100;
+
+// enables or toggling
+class Toggle {
+ static init() {
+ let start;
+ document.documentElement.addEventListener('mousedown', (e) => {
+ start = [e.clientX, e.clientY];
+ });
+
+ document.documentElement.addEventListener('click', (e) => {
+ let el;
+ if (
+ !e.shiftKey && !e.ctrlKey && !e.metaKey
+ && (el = e.target.closest('.tracy-toggle'))
+ && Math.pow(start[0] - e.clientX, 2) + Math.pow(start[1] - e.clientY, 2) < MOVE_THRESHOLD
+ ) {
+ Toggle.toggle(el, undefined, e);
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ }
+ });
+ Toggle.init = function () {};
+ }
+
+
+ // changes element visibility
+ static toggle(el, expand, e) {
+ let collapsed = el.classList.contains('tracy-collapsed'),
+ ref = el.getAttribute('data-tracy-ref') || el.getAttribute('href', 2),
+ dest = el;
+
+ if (typeof expand === 'undefined') {
+ expand = collapsed;
+ }
+
+ el.dispatchEvent(new CustomEvent('tracy-beforetoggle', {
+ bubbles: true,
+ detail: { collapsed: !expand, originalEvent: e },
+ }));
+
+ if (!ref || ref === '#') {
+ ref = '+';
+ } else if (ref.substr(0, 1) === '#') {
+ dest = document;
+ }
+ ref = ref.match(/(\^\s*([^+\s]*)\s*)?(\+\s*(\S*)\s*)?(.*)/);
+ dest = ref[1] ? dest.parentNode : dest;
+ dest = ref[2] ? dest.closest(ref[2]) : dest;
+ dest = ref[3] ? Toggle.nextElement(dest.nextElementSibling, ref[4]) : dest;
+ dest = ref[5] ? dest.querySelector(ref[5]) : dest;
+
+ el.classList.toggle('tracy-collapsed', !expand);
+ dest.classList.toggle('tracy-collapsed', !expand);
+
+ el.dispatchEvent(new CustomEvent('tracy-toggle', {
+ bubbles: true,
+ detail: { relatedTarget: dest, collapsed: !expand, originalEvent: e },
+ }));
+ }
+
+
+ // save & restore toggles
+ static persist(baseEl, restore) {
+ let saved = [];
+ baseEl.addEventListener('tracy-toggle', (e) => {
+ if (saved.indexOf(e.target) < 0) {
+ saved.push(e.target);
+ }
+ });
+
+ let toggles = JSON.parse(sessionStorage.getItem('tracy-toggles-' + baseEl.id));
+ if (toggles && restore !== false) {
+ toggles.forEach((item) => {
+ let el = baseEl;
+ for (let i in item.path) {
+ if (!(el = el.children[item.path[i]])) {
+ return;
+ }
+ }
+ if (el.textContent === item.text) {
+ Toggle.toggle(el, item.expand);
+ }
+ });
+ }
+
+ window.addEventListener('pagehide', () => {
+ toggles = saved.map((el) => {
+ let item = { path: [], text: el.textContent, expand: !el.classList.contains('tracy-collapsed') };
+ do {
+ item.path.unshift(Array.from(el.parentNode.children).indexOf(el));
+ el = el.parentNode;
+ } while (el && el !== baseEl);
+ return item;
+ });
+ sessionStorage.setItem('tracy-toggles-' + baseEl.id, JSON.stringify(toggles));
+ });
+ }
+
+
+ // finds next matching element
+ static nextElement(el, selector) {
+ while (el && selector && !el.matches(selector)) {
+ el = el.nextElementSibling;
+ }
+ return el;
+ }
+}
+
+
+let Tracy = window.Tracy = window.Tracy || {};
+Tracy.Toggle = Tracy.Toggle || Toggle;
diff --git a/vendor/tracy/tracy/src/Tracy/functions.php b/vendor/tracy/tracy/src/Tracy/functions.php
new file mode 100644
index 0000000..ab00b0d
--- /dev/null
+++ b/vendor/tracy/tracy/src/Tracy/functions.php
@@ -0,0 +1,46 @@
+setStub("startBuffering();
+foreach ($iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__ . '/../../src', RecursiveDirectoryIterator::SKIP_DOTS)) as $file) {
+ echo "adding: {$iterator->getSubPathname()}\n";
+
+ $s = file_get_contents($file->getPathname());
+ if (!str_contains($s, '@tracySkipLocation')) {
+ $s = php_strip_whitespace($file->getPathname());
+ }
+
+ if ($file->getExtension() === 'js') {
+ $s = compressJs($s);
+
+ } elseif ($file->getExtension() === 'css') {
+ $s = compressCss($s);
+
+ } elseif ($file->getExtension() === 'phtml') {
+ $s = preg_replace_callback('#(<(script|style).*(?)(.*)()#Uis', function ($m): string {
+ [, $begin, $type, $s, $end] = $m;
+
+ if ($s === '' || str_contains($s, '')) {
+ return $m[0];
+
+ } elseif ($type === 'script') {
+ $s = compressJs($s);
+
+ } elseif ($type === 'style') {
+ $s = compressCss($s);
+ }
+
+ return $begin . $s . $end;
+ }, $s);
+
+ } elseif ($file->getExtension() !== 'php') {
+ continue;
+ }
+
+ $phar[$iterator->getSubPathname()] = $s;
+}
+
+$phar->stopBuffering();
+$phar->compressFiles(Phar::GZ);
+
+echo "OK\n";
diff --git a/vendor/tracy/tracy/tools/open-in-editor/linux/install.sh b/vendor/tracy/tracy/tools/open-in-editor/linux/install.sh
new file mode 100644
index 0000000..5a7bfb3
--- /dev/null
+++ b/vendor/tracy/tracy/tools/open-in-editor/linux/install.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# This shell script sets open-editor.sh as handler for editor:// protocol
+
+matches=0
+while read -r line
+do
+ if [ "editor=" == "${line:0:7}" ]; then
+ matches=1
+ break
+ fi
+done < "open-editor.sh"
+
+if [ "$matches" == "0" ]; then
+ echo -e "\e[31;1mError: it seems like you have not set command to run your editor."
+ echo -e "Before install, set variable \`\$editor\` in file \`open-editor.sh\`.\e[0m"
+ exit 1
+fi
+
+# --------------------------------------------------------------
+
+echo "[Desktop Entry]
+Name=Tracy Open Editor
+Exec=tracy-openeditor.sh %u
+Terminal=false
+NoDisplay=true
+Type=Application
+MimeType=x-scheme-handler/editor;" > tracy-openeditor.desktop
+
+chmod +x open-editor.sh
+chmod +x tracy-openeditor.desktop
+
+sudo cp open-editor.sh /usr/bin/tracy-openeditor.sh
+sudo xdg-desktop-menu install tracy-openeditor.desktop
+sudo update-desktop-database
+rm tracy-openeditor.desktop
+
+echo -e "\e[32;1mDone.\e[0m"
diff --git a/vendor/tracy/tracy/tools/open-in-editor/linux/open-editor.sh b/vendor/tracy/tracy/tools/open-in-editor/linux/open-editor.sh
new file mode 100644
index 0000000..69e37be
--- /dev/null
+++ b/vendor/tracy/tracy/tools/open-in-editor/linux/open-editor.sh
@@ -0,0 +1,109 @@
+#!/bin/bash
+declare -A mapping
+
+#
+# Configure your editor by setting the $editor variable:
+#
+
+# Visual Studio Code
+#editor='code --goto "$FILE":"$LINE"'
+# Emacs
+#editor='emacs +$LINE "$FILE"'
+# gVim
+#editor='gvim +$LINE "$FILE"'
+# gEdit
+#editor='gedit +$LINE "$FILE"'
+# Pluma
+#editor='pluma +$LINE "$FILE"'
+# PHPStorm
+# To enable PHPStorm command-line interface, folow this guide: https://www.jetbrains.com/help/phpstorm/working-with-the-ide-features-from-command-line.html
+#editor='phpstorm --line $LINE "$FILE"'
+# VS Codium
+#editor='codium --goto "$FILE":"$LINE"'
+# Visual Studio Code
+#editor='code --goto "$FILE":"$LINE"'
+
+#
+# Optionally configure custom mapping here:
+#
+
+#mapping["/remotepath"]="/localpath"
+#mapping["/mnt/d/"]="d:/"
+
+#
+# Please, do not modify the code below.
+#
+
+# Find and return URI parameter value. Or nothing, if the param is missing.
+# Arguments: 1) URI, 2) Parameter name.
+function get_param {
+ echo "$1" | sed -n -r "s/.*$2=([^&]*).*/\1/ip"
+}
+
+if [[ -z "$editor" ]]; then
+ echo "You need to set the \$editor variable in file '`realpath $0`'"
+ exit
+fi
+
+url=$1
+if [ "${url:0:9}" != "editor://" ]; then
+ exit
+fi
+
+# Parse action and essential data from the URI.
+regex='editor\:\/\/(open|create|fix)\/?\?(.*)'
+action=`echo $url | sed -r "s/$regex/\1/i"`
+uri_params=`echo $url | sed -r "s/$regex/\2/i"`
+
+file=`get_param $uri_params "file"`
+line=`get_param $uri_params "line"`
+search=`get_param $uri_params "search"`
+replace=`get_param $uri_params "replace"`
+
+# Debug?
+#echo "action '$action'"
+#echo "file '$file'"
+#echo "line '$line'"
+#echo "search '$search'"
+#echo "replace '$replace'"
+
+# Convert URI encoded codes to normal characters (e.g. '%2F' => '/').
+printf -v file "${file//%/\\x}"
+# And escape double-quotes.
+file=${file//\"/\\\"}
+
+# Apply custom mapping conversion.
+for path in "${!mapping[@]}"; do
+ file="${file//$path/${mapping[$path]}}"
+done
+
+# Action: Create a file (only if it does not already exist).
+if [ "$action" == "create" ] && [[ ! -f "$file" ]]; then
+ mkdir -p $(dirname "$file")
+ touch "$file"
+ echo $replace > "$file"
+fi
+
+# Action: Fix the file (if the file exists and while creating backup beforehand).
+if [ "$action" == "fix" ]; then
+
+ if [[ ! -f "$file" ]]; then
+ echo "Cannot fix non-existing file '$file'"
+ exit
+ fi
+
+ # Backup the original file.
+ cp $file "$file.bak"
+ # Search and replace in place - only on the specified line.
+ sed -i "${line}s/${search}/${replace}/" $file
+
+fi
+
+# Format the command according to the selected editor.
+command="${editor//\$FILE/$file}"
+command="${command//\$LINE/$line}"
+
+# Debug?
+#echo $command
+
+eval $command
diff --git a/vendor/tracy/tracy/tools/open-in-editor/windows/install.cmd b/vendor/tracy/tracy/tools/open-in-editor/windows/install.cmd
new file mode 100644
index 0000000..d841122
--- /dev/null
+++ b/vendor/tracy/tracy/tools/open-in-editor/windows/install.cmd
@@ -0,0 +1,9 @@
+@echo off
+:: This Windows batch file sets open-editor.js as handler for editor:// protocol
+
+if defined PROCESSOR_ARCHITEW6432 (set reg="%systemroot%\sysnative\reg.exe") else (set reg=reg)
+
+%reg% ADD HKCR\editor /ve /d "URL:editor Protocol" /f
+%reg% ADD HKCR\editor /v "URL Protocol" /d "" /f
+%reg% ADD HKCR\editor\shell\open\command /ve /d "wscript \"%~dp0open-editor.js\" \"%%1\"" /f
+%reg% ADD HKLM\SOFTWARE\Policies\Google\Chrome\URLWhitelist /v "123" /d "editor://*" /f
diff --git a/vendor/tracy/tracy/tools/open-in-editor/windows/open-editor.js b/vendor/tracy/tracy/tools/open-in-editor/windows/open-editor.js
new file mode 100644
index 0000000..ac1093e
--- /dev/null
+++ b/vendor/tracy/tracy/tools/open-in-editor/windows/open-editor.js
@@ -0,0 +1,84 @@
+var settings = {
+
+ // PhpStorm
+ // editor: '"C:\\Program Files\\JetBrains\\PhpStorm 2018.1.2\\bin\\phpstorm64.exe" --line %line% "%file%"',
+ // title: 'PhpStorm',
+
+ // NetBeans
+ // editor: '"C:\\Program Files\\NetBeans 8.1\\bin\\netbeans.exe" "%file%:%line%" --console suppress',
+
+ // Nusphere PHPEd
+ // editor: '"C:\\Program Files\\NuSphere\\PhpED\\phped.exe" "%file%" --line=%line%',
+
+ // SciTE
+ // editor: '"C:\\Program Files\\SciTE\\scite.exe" "-open:%file%" -goto:%line%',
+
+ // EmEditor
+ // editor: '"C:\\Program Files\\EmEditor\\EmEditor.exe" "%file%" /l %line%',
+
+ // PSPad Editor
+ // editor: '"C:\\Program Files\\PSPad editor\\PSPad.exe" -%line% "%file%"',
+
+ // gVim
+ // editor: '"C:\\Program Files\\Vim\\vim73\\gvim.exe" "%file%" +%line%',
+
+ // Sublime Text 2
+ // editor: '"C:\\Program Files\\Sublime Text 2\\sublime_text.exe" "%file%:%line%"',
+
+ // Visual Studio Code / VSCodium
+ // editor: '"C:\\Program Files\\Microsoft VS Code\\Code.exe" --goto "%file%:%line%"',
+
+ mappings: {
+ // '/remotepath': '/localpath'
+ }
+};
+
+
+
+if (!settings.editor) {
+ WScript.Echo('Create variable "settings.editor" in ' + WScript.ScriptFullName);
+ WScript.Quit();
+}
+
+var url = WScript.Arguments(0);
+var match = /^editor:\/\/(open|create|fix)\/?\?file=([^&]+)&line=(\d+)(?:&search=([^&]*)&replace=([^&]*))?/.exec(url);
+if (!match) {
+ WScript.Echo('Unexpected URI ' + url);
+ WScript.Quit();
+}
+for (var i in match) {
+ match[i] = decodeURIComponent(match[i]).replace(/\+/g, ' ');
+}
+
+var action = match[1];
+var file = match[2];
+var line = match[3];
+var search = match[4];
+var replace = match[5];
+
+var shell = new ActiveXObject('WScript.Shell');
+var fileSystem = new ActiveXObject('Scripting.FileSystemObject');
+
+for (var id in settings.mappings) {
+ if (file.indexOf(id) === 0) {
+ file = settings.mappings[id] + file.substr(id.length);
+ break;
+ }
+}
+
+if (action === 'create' && !fileSystem.FileExists(file)) {
+ shell.Run('cmd /c mkdir "' + fileSystem.GetParentFolderName(file) + '"', 0, 1);
+ fileSystem.CreateTextFile(file).Write(replace);
+
+} else if (action === 'fix') {
+ var lines = fileSystem.OpenTextFile(file).ReadAll().split('\n');
+ lines[line-1] = lines[line-1].replace(search, replace);
+ fileSystem.OpenTextFile(file, 2).Write(lines.join('\n'));
+}
+
+var command = settings.editor.replace(/%line%/, line).replace(/%file%/, file);
+shell.Exec(command);
+
+if (settings.title) {
+ shell.AppActivate(settings.title);
+}
diff --git a/www/.htaccess b/www/.htaccess
new file mode 100644
index 0000000..199409c
--- /dev/null
+++ b/www/.htaccess
@@ -0,0 +1,41 @@
+# Apache configuration file (see https://httpd.apache.org/docs/current/mod/quickreference.html)
+
+# Allow access to all resources by default
+Require all granted
+
+# Disable directory listing for security reasons
+
+ Options -Indexes
+
+
+# Enable pretty URLs (removing the need for "index.php" in the URL)
+
+ RewriteEngine On
+
+ # Uncomment the next line if you want to set the base URL for rewrites
+ # RewriteBase /
+
+ # Force usage of HTTPS (secure connection). Uncomment if you have SSL setup.
+ # RewriteCond %{HTTPS} !on
+ # RewriteRule .? https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
+
+ # Permit requests to the '.well-known' directory (used for SSL verification and more)
+ RewriteRule ^\.well-known/.* - [L]
+
+ # Block access to hidden files (starting with a dot) and URLs resembling WordPress admin paths
+ RewriteRule /\.|^\.|^wp-(login|admin|includes|content) - [F]
+
+ # Return 404 for missing files with specific extensions (images, scripts, styles, archives)
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteRule \.(pdf|js|mjs|ico|gif|jpg|jpeg|png|webp|avif|svg|css|rar|zip|7z|tar\.gz|map|eot|ttf|otf|woff|woff2)$ - [L]
+
+ # Front controller pattern - all requests are routed through index.php
+ RewriteCond %{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_FILENAME} !-d
+ RewriteRule . index.php [L]
+
+
+# Enable gzip compression for text files
+
+ AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/json application/xml application/rss+xml image/svg+xml
+
diff --git a/www/favicon.ico b/www/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..b20cfd0f056c1c9d43100f612f4319c66e2adb94
GIT binary patch
literal 2550
zcmcgsdpy=>6#qV`h?U#SZJVg3NgD48bB$?q*(P0BnsTYks)Y)n7Gs6xwl1`?sD@_U
z*mR*3ue;!TGX-%KzT!aoOgA9#8p?H)WL?RL7J%`}#?vCTxIT)jQ5SY=6*49?+
zh&_ole$lYAvxC8Q5iS=MLnsttXlMv`?%ctjEsbHE`WM;pN*(R2gPpQVcsz^BU^|{g
zdOB}*utia3=3%>|9bp}tc@~XfN=iy^4Uf>sN#&@~UN&lzy{)*3spzf3^BSR||YZz~*6I;1wF3`8Euwo$so^QQ+fPxAeUii#5Rap}?}
zI637bDXAWlCQX8umlyQ(DzI){DFgxmGBPq~J0F>ud>9)Wx9
zfgL;esHkY7xZ6lhPR71{g~-j##nPo0;O%`5H*eOUySp2Q4mF^^zn|iS2n`K|hDI$;
zovJ}&<4uS}_n@M34_mgBKvq^3>gwt+H#bLFSs9iuUk*P%KTMxqN_*>}udk1soE*f(
z#nC;_e;ul;
zt8w}?A7jS!QZIBOE2|m`3JTEH))x21tXZ>QWo3op;$o_0Df094;o;#yaal-9OC!E&
zp{go?j7&KuP88z$^;>9YXrMdSVdKV9NJ~poO)8i?c`_KQLVJ5Vi*e)nQB_rs;o(29XHPk%O)EoSARo=m&6HP2wf#l4
zH4*=<7(aeI#SKGEO$`GB1JKmeL|tgHl|
z&&T4$i{a|(iW4VJVAZNs@bU41udgpcLP8K89*&rp7&_}APxI`(?@mKQ1HHYy(9+Vvg9i`L
z)zw8kr-!?D??PU_7j12A;_p^j`9AIG#>|;BVPaweGcz;P)YQPz(vteE0@l{nm@{V%
zN=iy#Z*Nb1a0PSc&P8EiA)K9^k(ZYT7Z(>SS+WFfZf?lV&c@1>E8*$siS+bz>eGGj
z_xGpXNy6^kyRmiaR>a1}A}lNn(b3U}jEsboln`Ub3Nc{<$N329V+>PWBGDrZP)!2^
zgH$uuXI=CzePr8-qdwAy^oBz6>qtwft{!^Z9;%1y^ZT^+>g7P{OXUFj7df)}wRucq
zmlm@v@hbOa8Ko5wENykg4mNL*D*qf~3xUi}fK4-w!qLe|`Yf=;$Q%fcQ2~x_S{3dI
z1exGnPg=`oSp@5O5E7$6zbZYJ`mKgNaD~lBlrvWRaz2EePA_9@`j2`n7s~VV^4Wnj
z`nAb@jO`Kl`fYGqwwdB8k@2B3#Tt)Nf%6LZidBEm%>U
zIp^f3xWHJNw^!P)mp({kCuGbESuBup*#~gvu}K%ttO=2*{sN2{JA-W!z>@{nZxqL{
zh=QL_y(oY&ani$2@YEN_aY*gFm*aH@{||iK?3yQO>z|YV>W4Sqo9I6p5G09PXfCPx
z;&Zb&aX?Vev-kV*{k_d?**5~-RN@c`{2gue-TH}%`ch3}=ROC&rnaYAkVqm}+BD5V
za{pA9-^FlZ;_>*&Z%E=g`&+o(oUB|tP7=3%{UlJbB85M$22KZ{7Oda^FYEk~m9tOZv=@F{=&ov#vg;K8};8MS`EFL7E3`erDkr
Rce72bootWebApplication();
+$application = $container->getByType(Nette\Application\Application::class);
+$application->run();
diff --git a/www/robots.txt b/www/robots.txt
new file mode 100644
index 0000000..e69de29