diff --git a/.gitignore b/.gitignore
index f712bc5..1dda020 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,3 @@
-# ---> Composer
+!.gitignore
composer.phar
-/vendor/
-
-# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
-# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
-# composer.lock
-
+vendor
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..58cd667
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,57 @@
+{
+ "name": "mirzaev/site-wanda",
+ "description": "Site about my friend Wanda Switch",
+ "readme": "README.md",
+ "keywords": [
+ "site",
+ "funny",
+ "love",
+ "friendship"
+ ],
+ "type": "site",
+ "homepage": "https://git.mirzaev.sexy/mirzaev/site-wanda",
+ "license": "WTFPL",
+ "authors": [
+ {
+ "name": "Arsen Mirzaev Tatyano-Muradovich",
+ "email": "arsen@mirzaev.sexy",
+ "homepage": "https://mirzaev.sexy",
+ "role": "Programmer"
+ }
+ ],
+ "support": {
+ "email": "arsen@mirzaev.sexy",
+ "wiki": "https://git.mirzaev.sexy/mirzaev/site-wanda/wiki",
+ "issues": "https://git.mirzaev.sexy/mirzaev/site-wanda/issues"
+ },
+ "funding": [
+ {
+ "type": "funding",
+ "url": "https://fund.mirzaev.sexy"
+ }
+ ],
+ "require": {
+ "php": "~8.1",
+ "ext-sodium": "~8.1",
+ "mirzaev/minimal": "^2.0.x-dev",
+ "mirzaev/accounts": "~1.2.x-dev",
+ "mirzaev/arangodb": "^1.0.0",
+ "mirzaev/vk": "^5.0",
+ "triagens/arangodb": "~3.9.x-dev",
+ "twig/twig": "^3.4",
+ "guzzlehttp/guzzle": "^7.5"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~9.5"
+ },
+ "autoload": {
+ "psr-4": {
+ "mirzaev\\site\\wanda\\": "mirzaev/site/wanda/system"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "mirzaev\\site\\wanda\\tests\\": "mirzaev/site/wanda/tests"
+ }
+ }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..93d837c
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,3051 @@
+{
+ "_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": "851d6a380009568ef88336690be89d68",
+ "packages": [
+ {
+ "name": "guzzlehttp/guzzle",
+ "version": "7.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba",
+ "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.5",
+ "guzzlehttp/psr7": "^1.9 || ^2.4",
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-client": "^1.0",
+ "symfony/deprecation-contracts": "^2.2 || ^3.0"
+ },
+ "provide": {
+ "psr/http-client-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.1",
+ "ext-curl": "*",
+ "php-http/client-integration-tests": "^3.0",
+ "phpunit/phpunit": "^8.5.29 || ^9.5.23",
+ "psr/log": "^1.1 || ^2.0 || ^3.0"
+ },
+ "suggest": {
+ "ext-curl": "Required for CURL handler support",
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ },
+ "branch-alias": {
+ "dev-master": "7.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Jeremy Lindblom",
+ "email": "jeremeamia@gmail.com",
+ "homepage": "https://github.com/jeremeamia"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "psr-18",
+ "psr-7",
+ "rest",
+ "web service"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/guzzle/issues",
+ "source": "https://github.com/guzzle/guzzle/tree/7.5.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-08-28T15:39:27+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "1.5.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "b94b2807d85443f9719887892882d0329d1e2598"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598",
+ "reference": "b94b2807d85443f9719887892882d0329d1e2598",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^4.4 || ^5.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/promises/issues",
+ "source": "https://github.com/guzzle/promises/tree/1.5.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-08-28T14:55:35+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "2.4.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "67c26b443f348a51926030c83481b85718457d3d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d",
+ "reference": "67c26b443f348a51926030c83481b85718457d3d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.0",
+ "ralouphie/getallheaders": "^3.0"
+ },
+ "provide": {
+ "psr/http-factory-implementation": "1.0",
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.1",
+ "http-interop/http-factory-tests": "^0.9",
+ "phpunit/phpunit": "^8.5.29 || ^9.5.23"
+ },
+ "suggest": {
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ },
+ "branch-alias": {
+ "dev-master": "2.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Psr7\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://sagikazarmark.hu"
+ }
+ ],
+ "description": "PSR-7 message implementation that also provides common utility methods",
+ "keywords": [
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/psr7/issues",
+ "source": "https://github.com/guzzle/psr7/tree/2.4.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-10-26T14:07:24+00:00"
+ },
+ {
+ "name": "jasny/error-handler",
+ "version": "v0.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jasny/error-handler.git",
+ "reference": "38e076fc36d86689010081bc2eab96f12d97b0d8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jasny/error-handler/zipball/38e076fc36d86689010081bc2eab96f12d97b0d8",
+ "reference": "38e076fc36d86689010081bc2eab96f12d97b0d8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6.0",
+ "psr/http-message": "^1.0",
+ "psr/log": "^1.0"
+ },
+ "require-dev": {
+ "jasny/http-message": "^1.3",
+ "jasny/php-code-quality": "^2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Jasny\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Arnold Daniels",
+ "email": "arnold@jasny.net",
+ "homepage": "http://www.jasny.net"
+ }
+ ],
+ "description": "Error handler with PSR-7 support",
+ "keywords": [
+ "error handler",
+ "exception handler",
+ "middleware"
+ ],
+ "support": {
+ "issues": "https://github.com/jasny/error-handler/issues",
+ "source": "https://github.com/jasny/error-handler"
+ },
+ "abandoned": true,
+ "time": "2017-01-25T01:27:18+00:00"
+ },
+ {
+ "name": "mirzaev/accounts",
+ "version": "1.2.x-dev",
+ "source": {
+ "type": "git",
+ "url": "https://git.mirzaev.sexy/mirzaev/accounts",
+ "reference": "4d6df00dc9538c99d8eced6deebab55f1af2bf8a"
+ },
+ "require": {
+ "ext-dom": "20031129",
+ "ext-libxml": "~8.1.1",
+ "guzzlehttp/guzzle": "^7.2",
+ "php": "~8.1"
+ },
+ "require-dev": {
+ "phpdocumentor/phpdocumentor": ">=2.9",
+ "phpunit/phpunit": "^9"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "mirzaev\\accounts\\": "mirzaev/accounts/system"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "WTFPL"
+ ],
+ "authors": [
+ {
+ "name": "Arsen Mirzaev Tatyano-Muradovich",
+ "email": "arsen@mirzaev.sexy",
+ "homepage": "https://mirzaev.sexy",
+ "role": "Programmer"
+ }
+ ],
+ "description": "Simple accounts manager",
+ "homepage": "https://git.mirzaev.sexy/mirzaev/accounts",
+ "keywords": [
+ "accounts"
+ ],
+ "support": {
+ "email": "arsen@mirzaev.sexy",
+ "issues": "https://git.mirzaev.sexy/mirzaev/accounts/issues",
+ "wiki": "https://git.mirzaev.sexy/mirzaev/accounts/wiki"
+ },
+ "funding": [
+ {
+ "url": "https://fund.mirzaev.sexy",
+ "type": "funding"
+ }
+ ],
+ "time": "2022-11-05T23:48:10+00:00"
+ },
+ {
+ "name": "mirzaev/arangodb",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://git.mirzaev.sexy/mirzaev/arangodb",
+ "reference": "e7da9978d01d3f8bdef6c74809dfb4eb8989f92c"
+ },
+ "require": {
+ "php": "^8.1",
+ "triagens/arangodb": "~3.8"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "mirzaev\\arangodb\\": "mirzaev/arangodb/system"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "WTFPL"
+ ],
+ "authors": [
+ {
+ "name": "Arsen Mirzaev Tatyano-Muradovich",
+ "email": "arsen@mirzaev.sexy",
+ "homepage": "https://mirzaev.sexy",
+ "role": "Developer"
+ }
+ ],
+ "description": "Simple PHP-framework for ArangoDB",
+ "homepage": "https://git.hood.su/mirzaev/arangodb",
+ "keywords": [
+ "ArangoDb"
+ ],
+ "support": {
+ "email": "arsen@mirzaev.sexy",
+ "issues": "https://git.mirzaev.sexy/mirzaev/arangodb/issues",
+ "wiki": "https://git.mirzaev.sexy/mirzaev/arangodb/manual"
+ },
+ "funding": [
+ {
+ "url": "https://fund.mirzaev.sexy",
+ "type": "funding"
+ }
+ ],
+ "time": "2022-11-06T00:03:56+00:00"
+ },
+ {
+ "name": "mirzaev/minimal",
+ "version": "2.0.x-dev",
+ "source": {
+ "type": "git",
+ "url": "https://git.mirzaev.sexy/mirzaev/minimal",
+ "reference": "1f5685a20d41c1c11742f33138764b835ddd0198"
+ },
+ "require": {
+ "php": "~8.1"
+ },
+ "suggest": {
+ "ext-PDO": "To work with SQL-based databases (MySQL, PostreSQL...)"
+ },
+ "type": "framework",
+ "autoload": {
+ "psr-4": {
+ "mirzaev\\minimal\\": "mirzaev/minimal/system"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "WTFPL"
+ ],
+ "authors": [
+ {
+ "name": "Arsen Mirzaev Tatyano-Muradovich",
+ "email": "arsen@mirzaev.sexy",
+ "homepage": "https://mirzaev.sexy",
+ "role": "Developer"
+ }
+ ],
+ "description": "Lightweight MVC framework that manages only the basic mechanisms, leaving the development of the programmer and not overloading the project",
+ "homepage": "https://git.mirzaev.sexy/mirzaev/minimal",
+ "keywords": [
+ "framework",
+ "mvc"
+ ],
+ "support": {
+ "docs": "https://git.mirzaev.sexy/mirzaev/minimal/wiki",
+ "issues": "https://git.mirzaev.sexy/mirzaev/minimal/issues"
+ },
+ "time": "2022-11-03T06:09:32+00:00"
+ },
+ {
+ "name": "mirzaev/vk",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://git.mirzaev.sexy/mirzaev/vk",
+ "reference": "c61e7a0de5e9fad194725bae26cc30872cc97977"
+ },
+ "require": {
+ "guzzlehttp/guzzle": "^7.5",
+ "jasny/error-handler": "^0.2",
+ "mirzaev/accounts": "^1.2.0",
+ "monolog/monolog": "^1.6",
+ "php": "^8.1",
+ "psr/log": "^1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5"
+ },
+ "suggest": {
+ "ext-sodium": "Can be selected in some conditions to increase security"
+ },
+ "type": "framework",
+ "autoload": {
+ "psr-4": {
+ "mirzaev\\vk\\": "mirzaev/vk/system"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "WTFPL"
+ ],
+ "authors": [
+ {
+ "name": "Arsen Mirzaev Tatyano-Muradovich",
+ "email": "arsen@mirzaev.sexy",
+ "homepage": "https://mirzaev.sexy/mirzaev",
+ "role": "Programmer"
+ }
+ ],
+ "description": "Framework for vk.com API",
+ "homepage": "https://git.mirzaev.sexy/mirzaev/vk",
+ "keywords": [
+ "api",
+ "vk"
+ ],
+ "support": {
+ "docs": "https://git.mirzaev.sexy/mirzaev/vk/wiki",
+ "issues": "https://git.mirzaev.sexy/mirzaev/vk/issues"
+ },
+ "time": "2022-11-13T17:06:52+00:00"
+ },
+ {
+ "name": "monolog/monolog",
+ "version": "1.27.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "904713c5929655dc9b97288b69cfeedad610c9a1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/904713c5929655dc9b97288b69cfeedad610c9a1",
+ "reference": "904713c5929655dc9b97288b69cfeedad610c9a1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0",
+ "psr/log": "~1.0"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0.0"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "^2.4.9 || ^3.0",
+ "doctrine/couchdb": "~1.0@dev",
+ "graylog2/gelf-php": "~1.0",
+ "php-amqplib/php-amqplib": "~2.4",
+ "php-console/php-console": "^3.1.3",
+ "phpstan/phpstan": "^0.12.59",
+ "phpunit/phpunit": "~4.5",
+ "ruflin/elastica": ">=0.90 <3.0",
+ "sentry/sentry": "^0.13",
+ "swiftmailer/swiftmailer": "^5.3|^6.0"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-mongo": "Allow sending log messages to a MongoDB server",
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+ "php-console/php-console": "Allow sending log messages to Google Chrome",
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
+ "sentry/sentry": "Allow sending log messages to a Sentry server"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Monolog\\": "src/Monolog"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "http://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/monolog/issues",
+ "source": "https://github.com/Seldaek/monolog/tree/1.27.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-06-09T08:53:42+00:00"
+ },
+ {
+ "name": "psr/http-client",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-client.git",
+ "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
+ "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0",
+ "psr/http-message": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP clients",
+ "homepage": "https://github.com/php-fig/http-client",
+ "keywords": [
+ "http",
+ "http-client",
+ "psr",
+ "psr-18"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-client/tree/master"
+ },
+ "time": "2020-06-29T06:28:15+00:00"
+ },
+ {
+ "name": "psr/http-factory",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-factory.git",
+ "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
+ "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0.0",
+ "psr/http-message": "^1.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for PSR-7 HTTP message factories",
+ "keywords": [
+ "factory",
+ "http",
+ "message",
+ "psr",
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-factory/tree/master"
+ },
+ "time": "2019-04-30T12:38:16+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-message/tree/master"
+ },
+ "time": "2016-08-06T14:39:51+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/1.1.4"
+ },
+ "time": "2021-05-03T11:20:27+00:00"
+ },
+ {
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/getallheaders.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
+ }
+ ],
+ "description": "A polyfill for getallheaders.",
+ "support": {
+ "issues": "https://github.com/ralouphie/getallheaders/issues",
+ "source": "https://github.com/ralouphie/getallheaders/tree/develop"
+ },
+ "time": "2019-03-08T08:55:37+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918",
+ "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.1-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1"
+ },
+ "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": "2022-02-25T11:15:52+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.27.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
+ "reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-ctype": "*"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.27-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.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": "2022-11-03T14:55:06+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.27.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
+ "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.27-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.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": "2022-11-03T14:55:06+00:00"
+ },
+ {
+ "name": "triagens/arangodb",
+ "version": "3.9.x-dev",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/arangodb/arangodb-php.git",
+ "reference": "21c460dbbd75eb5c066f9abcc3a9adf4487d6e48"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/arangodb/arangodb-php/zipball/21c460dbbd75eb5c066f9abcc3a9adf4487d6e48",
+ "reference": "21c460dbbd75eb5c066f9abcc3a9adf4487d6e48",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-0": {
+ "ArangoDBClient": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Jan Steemann",
+ "homepage": "https://github.com/arangodb/arangodb-php",
+ "role": "Developer"
+ },
+ {
+ "name": "Frank Mayer",
+ "homepage": "https://github.com/arangodb/arangodb-php",
+ "role": "Developer"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/arangodb/arangodb-php/graphs/contributors"
+ }
+ ],
+ "description": "ArangoDB PHP client",
+ "homepage": "https://github.com/arangodb/arangodb-php",
+ "keywords": [
+ "Arango",
+ "ArangoDb",
+ "database",
+ "distributed",
+ "document store",
+ "graph database",
+ "multi-model",
+ "nosql"
+ ],
+ "support": {
+ "issues": "https://github.com/arangodb/arangodb-php/issues",
+ "source": "https://github.com/arangodb/arangodb-php/tree/3.9"
+ },
+ "time": "2022-10-21T15:30:53+00:00"
+ },
+ {
+ "name": "twig/twig",
+ "version": "v3.4.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twigphp/Twig.git",
+ "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58",
+ "reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-mbstring": "^1.3"
+ },
+ "require-dev": {
+ "psr/container": "^1.0",
+ "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Twig\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Twig Team",
+ "role": "Contributors"
+ },
+ {
+ "name": "Armin Ronacher",
+ "email": "armin.ronacher@active-4.com",
+ "role": "Project Founder"
+ }
+ ],
+ "description": "Twig, the flexible, fast, and secure template language for PHP",
+ "homepage": "https://twig.symfony.com",
+ "keywords": [
+ "templating"
+ ],
+ "support": {
+ "issues": "https://github.com/twigphp/Twig/issues",
+ "source": "https://github.com/twigphp/Twig/tree/v3.4.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/twig/twig",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-09-28T08:42:51+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "doctrine/instantiator",
+ "version": "1.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
+ "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^9",
+ "ext-pdo": "*",
+ "ext-phar": "*",
+ "phpbench/phpbench": "^0.16 || ^1",
+ "phpstan/phpstan": "^1.4",
+ "phpstan/phpstan-phpunit": "^1",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "vimeo/psalm": "^4.22"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com",
+ "homepage": "https://ocramius.github.io/"
+ }
+ ],
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+ "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
+ "keywords": [
+ "constructor",
+ "instantiate"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/instantiator/issues",
+ "source": "https://github.com/doctrine/instantiator/tree/1.4.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-03-03T08:28:38+00:00"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614",
+ "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/collections": "<1.6.8",
+ "doctrine/common": "<2.13.3 || >=3,<3.2.2"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.6.8",
+ "doctrine/common": "^2.13.3 || ^3.2.2",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ],
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-03-03T13:19:32+00:00"
+ },
+ {
+ "name": "nikic/php-parser",
+ "version": "v4.15.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/PHP-Parser.git",
+ "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
+ "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": ">=7.0"
+ },
+ "require-dev": {
+ "ircmaxell/php-yacc": "^0.0.7",
+ "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
+ },
+ "bin": [
+ "bin/php-parse"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.9-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpParser\\": "lib/PhpParser"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov"
+ }
+ ],
+ "description": "A PHP parser written in PHP",
+ "keywords": [
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
+ },
+ "time": "2022-11-12T15:38:23+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
+ "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-phar": "*",
+ "ext-xmlwriter": "*",
+ "phar-io/version": "^3.0.1",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "support": {
+ "issues": "https://github.com/phar-io/manifest/issues",
+ "source": "https://github.com/phar-io/manifest/tree/2.0.3"
+ },
+ "time": "2021-07-20T11:28:43+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "support": {
+ "issues": "https://github.com/phar-io/version/issues",
+ "source": "https://github.com/phar-io/version/tree/3.2.1"
+ },
+ "time": "2022-02-21T01:04:05+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "9.2.19",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c77b56b63e3d2031bd8997fcec43c1925ae46559",
+ "reference": "c77b56b63e3d2031bd8997fcec43c1925ae46559",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-xmlwriter": "*",
+ "nikic/php-parser": "^4.14",
+ "php": ">=7.3",
+ "phpunit/php-file-iterator": "^3.0.3",
+ "phpunit/php-text-template": "^2.0.2",
+ "sebastian/code-unit-reverse-lookup": "^2.0.2",
+ "sebastian/complexity": "^2.0",
+ "sebastian/environment": "^5.1.2",
+ "sebastian/lines-of-code": "^1.0.3",
+ "sebastian/version": "^3.0.1",
+ "theseer/tokenizer": "^1.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "suggest": {
+ "ext-pcov": "*",
+ "ext-xdebug": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "9.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.19"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2022-11-18T07:47:47+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "3.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
+ "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2021-12-02T12:48:52+00:00"
+ },
+ {
+ "name": "phpunit/php-invoker",
+ "version": "3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
+ "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
+ "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "ext-pcntl": "*",
+ "phpunit/phpunit": "^9.3"
+ },
+ "suggest": {
+ "ext-pcntl": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Invoke callables with a timeout",
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "keywords": [
+ "process"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T05:58:55+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
+ "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T05:33:50+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "5.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
+ "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:16:10+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "9.5.26",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2",
+ "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.3.1",
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.10.1",
+ "phar-io/manifest": "^2.0.3",
+ "phar-io/version": "^3.0.2",
+ "php": ">=7.3",
+ "phpunit/php-code-coverage": "^9.2.13",
+ "phpunit/php-file-iterator": "^3.0.5",
+ "phpunit/php-invoker": "^3.1.1",
+ "phpunit/php-text-template": "^2.0.3",
+ "phpunit/php-timer": "^5.0.2",
+ "sebastian/cli-parser": "^1.0.1",
+ "sebastian/code-unit": "^1.0.6",
+ "sebastian/comparator": "^4.0.8",
+ "sebastian/diff": "^4.0.3",
+ "sebastian/environment": "^5.1.3",
+ "sebastian/exporter": "^4.0.5",
+ "sebastian/global-state": "^5.0.1",
+ "sebastian/object-enumerator": "^4.0.3",
+ "sebastian/resource-operations": "^3.0.3",
+ "sebastian/type": "^3.2",
+ "sebastian/version": "^3.0.2"
+ },
+ "suggest": {
+ "ext-soap": "*",
+ "ext-xdebug": "*"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "9.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Framework/Assert/Functions.php"
+ ],
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/phpunit/issues",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26"
+ },
+ "funding": [
+ {
+ "url": "https://phpunit.de/sponsors.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-10-28T06:00:21+00:00"
+ },
+ {
+ "name": "sebastian/cli-parser",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/cli-parser.git",
+ "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
+ "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for parsing CLI options",
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T06:08:49+00:00"
+ },
+ {
+ "name": "sebastian/code-unit",
+ "version": "1.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit.git",
+ "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
+ "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/code-unit",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit/issues",
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:08:54+00:00"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
+ "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Looks up which function or method a line of code belongs to",
+ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T05:30:19+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "4.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
+ "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3",
+ "sebastian/diff": "^4.0",
+ "sebastian/exporter": "^4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/comparator/issues",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2022-09-14T12:41:17+00:00"
+ },
+ {
+ "name": "sebastian/complexity",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/complexity.git",
+ "reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
+ "reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^4.7",
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for calculating the complexity of PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/complexity",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/complexity/issues",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T15:52:27+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "4.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
+ "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3",
+ "symfony/process": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:10:38+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "5.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7",
+ "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "suggest": {
+ "ext-posix": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/environment/issues",
+ "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2022-04-03T09:37:03+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "4.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
+ "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3",
+ "sebastian/recursion-context": "^4.0"
+ },
+ "require-dev": {
+ "ext-mbstring": "*",
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/exporter/issues",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2022-09-14T06:03:37+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "5.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2",
+ "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3",
+ "sebastian/object-reflector": "^2.0",
+ "sebastian/recursion-context": "^4.0"
+ },
+ "require-dev": {
+ "ext-dom": "*",
+ "phpunit/phpunit": "^9.3"
+ },
+ "suggest": {
+ "ext-uopz": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/global-state/issues",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2022-02-14T08:28:10+00:00"
+ },
+ {
+ "name": "sebastian/lines-of-code",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/lines-of-code.git",
+ "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
+ "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^4.6",
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for counting the lines of code in PHP source code",
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-11-28T06:42:11+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "4.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
+ "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3",
+ "sebastian/object-reflector": "^2.0",
+ "sebastian/recursion-context": "^4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:12:34+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
+ "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:14:26+00:00"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "4.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
+ "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:17:30+00:00"
+ },
+ {
+ "name": "sebastian/resource-operations",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/resource-operations.git",
+ "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
+ "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides a list of PHP built-in functions that operate on resources",
+ "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
+ "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T06:45:17+00:00"
+ },
+ {
+ "name": "sebastian/type",
+ "version": "3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
+ "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "homepage": "https://github.com/sebastianbergmann/type",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/type/issues",
+ "source": "https://github.com/sebastianbergmann/type/tree/3.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2022-09-12T14:47:03+00:00"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "c6c1022351a901512170118436c764e473f6de8c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
+ "reference": "c6c1022351a901512170118436c764e473f6de8c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/version/issues",
+ "source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T06:39:44+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
+ "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "support": {
+ "issues": "https://github.com/theseer/tokenizer/issues",
+ "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2021-07-28T10:34:58+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": {
+ "mirzaev/minimal": 20,
+ "mirzaev/accounts": 20,
+ "triagens/arangodb": 20
+ },
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {
+ "php": "~8.1",
+ "ext-sodium": "~8.1"
+ },
+ "platform-dev": [],
+ "plugin-api-version": "2.3.0"
+}
diff --git a/mirzaev/site/wanda/system/controllers/core.php b/mirzaev/site/wanda/system/controllers/core.php
new file mode 100644
index 0000000..f5726ef
--- /dev/null
+++ b/mirzaev/site/wanda/system/controllers/core.php
@@ -0,0 +1,58 @@
+
+ */
+class core extends controller
+{
+ /**
+ * Переменные окружения
+ */
+ protected robot $vk;
+
+ /**
+ * Переменные окружения
+ */
+ protected array $variables = [];
+
+ /**
+ * Конструктор
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ // Инициализация ядра моделей (соединение с базой данных...)
+ new models();
+
+ // Инициализация журнала ошибок
+ $this->variables['errors'] = [
+ ];
+
+ // Инициализация препроцессора представления
+ $this->view = new manager;
+ }
+}
diff --git a/mirzaev/site/wanda/system/controllers/error_controller.php b/mirzaev/site/wanda/system/controllers/error_controller.php
new file mode 100644
index 0000000..e6b3f52
--- /dev/null
+++ b/mirzaev/site/wanda/system/controllers/error_controller.php
@@ -0,0 +1,44 @@
+
+ */
+final class error_controller extends core
+{
+ /**
+ * Страница с ошибкой
+ *
+ * @param array $parameters
+ */
+ public function index(array $parameters = []): ?string
+ {
+ // Запись текста ошибки в переменную окружения
+ $this->variables['text'] = $parameters['text'] ?? null;
+
+ if (isset($parameters['code'])) {
+ // Получен код ошибки
+
+ // Запись кода ошибки в переменную окружения
+ $this->variables['code'] = $parameters['code'];
+
+ // Запись кода ответа
+ http_response_code($parameters['code']);
+
+ // Генерация представления
+ return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . 'index.html', $this->variables);
+ }
+
+ // Генерация представления
+ return $this->view->render(DIRECTORY_SEPARATOR . 'errors' . DIRECTORY_SEPARATOR . ($parameters['code'] ?? 'index') . '.html', $this->variables);
+ }
+}
diff --git a/mirzaev/site/wanda/system/controllers/index_controller.php b/mirzaev/site/wanda/system/controllers/index_controller.php
new file mode 100644
index 0000000..2cf792b
--- /dev/null
+++ b/mirzaev/site/wanda/system/controllers/index_controller.php
@@ -0,0 +1,34 @@
+
+ */
+final class index_controller extends core
+{
+ /**
+ * Главная страница
+ *
+ * @param array $parameters Параметры запроса
+ */
+ public function index(array $parameters = []): ?string
+ {
+ // Инициализация загружаемых категорий
+ $this->variables['include'] = [
+ 'head' => ['self'],
+ 'body' => ['self']
+ ];
+
+ // Генерация представления
+ return $this->view->render(DIRECTORY_SEPARATOR . 'index.html', $this->variables);
+ }
+}
diff --git a/mirzaev/site/wanda/system/models/core.php b/mirzaev/site/wanda/system/models/core.php
new file mode 100644
index 0000000..0a57db4
--- /dev/null
+++ b/mirzaev/site/wanda/system/models/core.php
@@ -0,0 +1,143 @@
+
+ */
+class core extends model
+{
+ /**
+ * Коллекция в которой хранятся аккаунты
+ */
+ public const SETTINGS = '../settings/arangodb.php';
+
+ /**
+ * Соединение с базой данных
+ */
+ protected static connection $db;
+
+ public function __construct(connection $db = null)
+ {
+ if (isset($db)) {
+ // Получена инстанция соединения с базой данных
+
+ // Запись и инициализация соединения с базой данных
+ $this->__set('db', $db);
+ } else {
+ // Не получена инстанция соединения с базой данных
+
+ // Инициализация соединения с базой данных по умолчанию
+ $this->__get('db');
+ }
+ }
+
+ /**
+ * Записать свойство
+ *
+ * @param string $name Название
+ * @param mixed $value Значение
+ */
+ public function __set(string $name, mixed $value = null): void
+ {
+ match ($name) {
+ 'db' => (function () use ($value) {
+ if ($this->__isset('db')) {
+ // Свойство уже было инициализировано
+
+ // Выброс исключения (неудача)
+ throw new exception('Запрещено реинициализировать соединение с базой данных ($this->db)', 500);
+ } else {
+ // Свойство ещё не было инициализировано
+
+ if ($value instanceof connection) {
+ // Передано подходящее значение
+
+ // Запись свойства (успех)
+ self::$db = $value;
+ } else {
+ // Передано неподходящее значение
+
+ // Выброс исключения (неудача)
+ throw new exception('Соединение с базой данных ($this->db) должен быть инстанцией mirzaev\arangodb\connection', 500);
+ }
+ }
+ })(),
+ default => parent::__set($name, $value)
+ };
+ }
+
+ /**
+ * Прочитать свойство
+ *
+ * @param string $name Название
+ *
+ * @return mixed Содержимое
+ */
+ public function __get(string $name): mixed
+ {
+ return match ($name) {
+ 'db' => (function () {
+ if (!$this->__isset('db')) {
+ // Свойство не инициализировано
+
+ // Инициализация значения по умолчанию исходя из настроек
+ $this->__set('db', new connection(require static::SETTINGS));
+ }
+
+ return self::$db;
+ })(),
+ default => parent::__get($name)
+ };
+ }
+
+ /**
+ * Проверить свойство на инициализированность
+ *
+ * @param string $name Название
+ */
+ public function __isset(string $name): bool
+ {
+ return match ($name) {
+ default => parent::__isset($name)
+ };
+ }
+
+ /**
+ * Удалить свойство
+ *
+ * @param string $name Название
+ */
+ public function __unset(string $name): void
+ {
+ match ($name) {
+ default => parent::__isset($name)
+ };
+ }
+
+
+ /**
+ * Статический вызов
+ *
+ * @param string $name Название
+ * @param array $arguments Параметры
+ */
+ public static function __callStatic(string $name, array $arguments): mixed
+ {
+ match ($name) {
+ 'db' => (new static)->__get('db'),
+ default => throw new exception("Не найдено свойство или функция: $name", 500)
+ };
+ }
+}
diff --git a/mirzaev/site/wanda/system/public/android-icon-144x144.png b/mirzaev/site/wanda/system/public/android-icon-144x144.png
new file mode 100644
index 0000000..70b045c
Binary files /dev/null and b/mirzaev/site/wanda/system/public/android-icon-144x144.png differ
diff --git a/mirzaev/site/wanda/system/public/android-icon-192x192.png b/mirzaev/site/wanda/system/public/android-icon-192x192.png
new file mode 100644
index 0000000..99250ba
Binary files /dev/null and b/mirzaev/site/wanda/system/public/android-icon-192x192.png differ
diff --git a/mirzaev/site/wanda/system/public/android-icon-36x36.png b/mirzaev/site/wanda/system/public/android-icon-36x36.png
new file mode 100644
index 0000000..45dace0
Binary files /dev/null and b/mirzaev/site/wanda/system/public/android-icon-36x36.png differ
diff --git a/mirzaev/site/wanda/system/public/android-icon-48x48.png b/mirzaev/site/wanda/system/public/android-icon-48x48.png
new file mode 100644
index 0000000..6256bf4
Binary files /dev/null and b/mirzaev/site/wanda/system/public/android-icon-48x48.png differ
diff --git a/mirzaev/site/wanda/system/public/android-icon-72x72.png b/mirzaev/site/wanda/system/public/android-icon-72x72.png
new file mode 100644
index 0000000..73ca800
Binary files /dev/null and b/mirzaev/site/wanda/system/public/android-icon-72x72.png differ
diff --git a/mirzaev/site/wanda/system/public/android-icon-96x96.png b/mirzaev/site/wanda/system/public/android-icon-96x96.png
new file mode 100644
index 0000000..b112033
Binary files /dev/null and b/mirzaev/site/wanda/system/public/android-icon-96x96.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-114x114.png b/mirzaev/site/wanda/system/public/apple-icon-114x114.png
new file mode 100644
index 0000000..1372903
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-114x114.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-120x120.png b/mirzaev/site/wanda/system/public/apple-icon-120x120.png
new file mode 100644
index 0000000..b6654f8
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-120x120.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-144x144.png b/mirzaev/site/wanda/system/public/apple-icon-144x144.png
new file mode 100644
index 0000000..70b045c
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-144x144.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-152x152.png b/mirzaev/site/wanda/system/public/apple-icon-152x152.png
new file mode 100644
index 0000000..ba3c51d
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-152x152.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-180x180.png b/mirzaev/site/wanda/system/public/apple-icon-180x180.png
new file mode 100644
index 0000000..c36d20a
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-180x180.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-57x57.png b/mirzaev/site/wanda/system/public/apple-icon-57x57.png
new file mode 100644
index 0000000..1fb2e5b
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-57x57.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-60x60.png b/mirzaev/site/wanda/system/public/apple-icon-60x60.png
new file mode 100644
index 0000000..fec262e
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-60x60.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-72x72.png b/mirzaev/site/wanda/system/public/apple-icon-72x72.png
new file mode 100644
index 0000000..73ca800
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-72x72.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-76x76.png b/mirzaev/site/wanda/system/public/apple-icon-76x76.png
new file mode 100644
index 0000000..9231d84
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-76x76.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon-precomposed.png b/mirzaev/site/wanda/system/public/apple-icon-precomposed.png
new file mode 100644
index 0000000..4f0f379
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon-precomposed.png differ
diff --git a/mirzaev/site/wanda/system/public/apple-icon.png b/mirzaev/site/wanda/system/public/apple-icon.png
new file mode 100644
index 0000000..4f0f379
Binary files /dev/null and b/mirzaev/site/wanda/system/public/apple-icon.png differ
diff --git a/mirzaev/site/wanda/system/public/browserconfig.xml b/mirzaev/site/wanda/system/public/browserconfig.xml
new file mode 100644
index 0000000..c554148
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/browserconfig.xml
@@ -0,0 +1,2 @@
+
+#ffffff
\ No newline at end of file
diff --git a/mirzaev/site/wanda/system/public/css/main.css b/mirzaev/site/wanda/system/public/css/main.css
new file mode 100644
index 0000000..8c3e2dd
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/css/main.css
@@ -0,0 +1,135 @@
+@import url('/fonts/comissioner.ttf');
+
+* {
+ text-decoration: none;
+ outline : none;
+ border : none;
+ color : var(--text);
+ font-family : 'Commissioner', sans-serif;
+ transition : 0.1s ease-out;
+}
+
+.unselectable {
+ -webkit-touch-callout: none;
+ -webkit-user-select : none;
+ -khtml-user-select : none;
+ -moz-user-select : none;
+ -ms-user-select : none;
+ user-select : none;
+}
+
+a {
+ color: var(--link);
+}
+
+a:hover {
+ color: var(--link-hover);
+}
+
+a:active {
+ color: var(--link-active);
+}
+
+body {
+ height : 100vh;
+ margin : 0;
+ overflow : hidden;
+ display : flex;
+ background: #fff;
+}
+
+aside {
+ z-index : 500;
+ grid-column: 1/ 4;
+ grid-row : 2;
+ overflow : hidden;
+}
+
+header {
+ z-index : 5000;
+ position : absolute;
+ display : flex;
+ flex-direction: column;
+ box-shadow : 2px 0 5px rgba(0, 0, 0, 0.3);
+}
+
+header>menu {
+ margin : unset;
+ padding : 20px;
+ display : flex;
+ flex-direction : column;
+ flex-grow : 1;
+ background-color: var(--background-light-1);
+}
+
+header>#account>button#login {
+ z-index: 1500;
+}
+
+header>menu a {
+ margin-bottom: 8px;
+ display : flex;
+ align-items : center;
+}
+
+header>menu a:last-child {
+ margin-bottom: unset;
+}
+
+header>menu a svg {
+ margin-right: 8px;
+ height : 1.2rem;
+ position : relative;
+}
+
+header>menu a:hover svg {
+ margin-left : -5px;
+ margin-right: 13px;
+}
+
+header>menu a svg path {
+ fill: var(--text);
+}
+
+header>section {
+ background-color: var(--background-light-1);
+}
+
+header :is(button, a[type="button"]) {
+ width : 100%;
+ height : 40px;
+ display : flex;
+ justify-content : center;
+ align-items : center;
+ cursor : pointer;
+ background-color: var(--red);
+ transition : unset;
+}
+
+header button {
+ font-weight : bold;
+ text-transform: uppercase;
+}
+
+header :is(button, a[type="button"]):hover {
+ background-color: var(--red-light);
+}
+
+header :is(button, a[type="button"]):active {
+ background-color: var(--red-dark);
+}
+
+header>nav {
+ margin-top : auto;
+ display : flex;
+ flex-direction: column;
+}
+
+main {
+ z-index: 1000;
+}
+
+footer {
+ z-index : 3000;
+ position: absolute;
+}
diff --git a/mirzaev/site/wanda/system/public/css/valentine.css b/mirzaev/site/wanda/system/public/css/valentine.css
new file mode 100644
index 0000000..26b8dcb
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/css/valentine.css
@@ -0,0 +1,765 @@
+#valentine {
+ width : 100vw;
+ height : 100vh;
+ display : flex;
+ justify-content: center;
+ align-items : center;
+ perspective : 1300px;
+ pointer-events: none;
+}
+
+div {
+ position : absolute;
+ transform-style: preserve-3d;
+}
+
+#chocolate_rains {
+ transform: rotateX(-15deg);
+}
+
+.heart .ring {
+ width : 300px;
+ height : 300px;
+ border-radius: 100%;
+ opacity : 0;
+ border : 1px solid red;
+}
+
+.heart .left {
+ left : -20px;
+ width : 20px;
+ height : 20px;
+ background : #c80000;
+ border-radius : 100%;
+ transform-origin: 100% 0;
+}
+
+.heart .left::before {
+ content : "";
+ position : absolute;
+ top : 10px;
+ width : 20px;
+ height : 25px;
+ background : #c80000;
+ border-radius: 0 0 0 100%;
+}
+
+.heart .right {
+ width : 20px;
+ height : 20px;
+ background : #c80000;
+ border-radius : 100%;
+ transform-origin: 0 0;
+}
+
+.heart .right::before {
+ content : "";
+ position : absolute;
+ top : 10px;
+ width : 20px;
+ height : 25px;
+ background : #c80000;
+ border-radius: 0 0 100% 0;
+}
+
+.heart .movable {
+ opacity: 0;
+}
+
+.heart .reverse {
+ transform: translateY(70px) rotateZ(180deg);
+ opacity : 0.1;
+}
+
+.heart .reverse .left,
+.heart .reverse .right {
+ opacity: 0.5;
+}
+
+.heart:nth-child(1) {
+ transform: translateX(455px) translateZ(-691px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(1) .movable {
+ -webkit-animation: drop 5000ms -2569ms linear infinite;
+ animation : drop 5000ms -2569ms linear infinite;
+}
+
+.heart:nth-child(1) .ring {
+ -webkit-animation: wave 5000ms 1331ms ease-out infinite;
+ animation : wave 5000ms 1331ms ease-out infinite;
+}
+
+.heart:nth-child(1) .inner {
+ -webkit-animation: rotation 2734ms linear infinite;
+ animation : rotation 2734ms linear infinite;
+}
+
+.heart:nth-child(2) {
+ transform: translateX(396px) translateZ(697px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(2) .movable {
+ -webkit-animation: drop 5000ms -742ms linear infinite;
+ animation : drop 5000ms -742ms linear infinite;
+}
+
+.heart:nth-child(2) .ring {
+ -webkit-animation: wave 5000ms 3158ms ease-out infinite;
+ animation : wave 5000ms 3158ms ease-out infinite;
+}
+
+.heart:nth-child(2) .inner {
+ -webkit-animation: rotation 2211ms linear infinite;
+ animation : rotation 2211ms linear infinite;
+}
+
+.heart:nth-child(3) {
+ transform: translateX(266px) translateZ(-436px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(3) .movable {
+ -webkit-animation: drop 5000ms 537ms linear infinite;
+ animation : drop 5000ms 537ms linear infinite;
+}
+
+.heart:nth-child(3) .ring {
+ -webkit-animation: wave 5000ms 4437ms ease-out infinite;
+ animation : wave 5000ms 4437ms ease-out infinite;
+}
+
+.heart:nth-child(3) .inner {
+ -webkit-animation: rotation 3474ms linear infinite;
+ animation : rotation 3474ms linear infinite;
+}
+
+.heart:nth-child(4) {
+ transform: translateX(-329px) translateZ(-563px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(4) .movable {
+ -webkit-animation: drop 5000ms -1846ms linear infinite;
+ animation : drop 5000ms -1846ms linear infinite;
+}
+
+.heart:nth-child(4) .ring {
+ -webkit-animation: wave 5000ms 2054ms ease-out infinite;
+ animation : wave 5000ms 2054ms ease-out infinite;
+}
+
+.heart:nth-child(4) .inner {
+ -webkit-animation: rotation 3278ms linear infinite;
+ animation : rotation 3278ms linear infinite;
+}
+
+.heart:nth-child(5) {
+ transform: translateX(-414px) translateZ(215px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(5) .movable {
+ -webkit-animation: drop 5000ms 1318ms linear infinite;
+ animation : drop 5000ms 1318ms linear infinite;
+}
+
+.heart:nth-child(5) .ring {
+ -webkit-animation: wave 5000ms 5218ms ease-out infinite;
+ animation : wave 5000ms 5218ms ease-out infinite;
+}
+
+.heart:nth-child(5) .inner {
+ -webkit-animation: rotation 2130ms linear infinite;
+ animation : rotation 2130ms linear infinite;
+}
+
+.heart:nth-child(6) {
+ transform: translateX(-445px) translateZ(-614px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(6) .movable {
+ -webkit-animation: drop 5000ms 962ms linear infinite;
+ animation : drop 5000ms 962ms linear infinite;
+}
+
+.heart:nth-child(6) .ring {
+ -webkit-animation: wave 5000ms 4862ms ease-out infinite;
+ animation : wave 5000ms 4862ms ease-out infinite;
+}
+
+.heart:nth-child(6) .inner {
+ -webkit-animation: rotation 3069ms linear infinite;
+ animation : rotation 3069ms linear infinite;
+}
+
+.heart:nth-child(7) {
+ transform: translateX(499px) translateZ(39px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(7) .movable {
+ -webkit-animation: drop 5000ms -2544ms linear infinite;
+ animation : drop 5000ms -2544ms linear infinite;
+}
+
+.heart:nth-child(7) .ring {
+ -webkit-animation: wave 5000ms 1356ms ease-out infinite;
+ animation : wave 5000ms 1356ms ease-out infinite;
+}
+
+.heart:nth-child(7) .inner {
+ -webkit-animation: rotation 4560ms linear infinite;
+ animation : rotation 4560ms linear infinite;
+}
+
+.heart:nth-child(8) {
+ transform: translateX(154px) translateZ(-228px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(8) .movable {
+ -webkit-animation: drop 5000ms 1853ms linear infinite;
+ animation : drop 5000ms 1853ms linear infinite;
+}
+
+.heart:nth-child(8) .ring {
+ -webkit-animation: wave 5000ms 5753ms ease-out infinite;
+ animation : wave 5000ms 5753ms ease-out infinite;
+}
+
+.heart:nth-child(8) .inner {
+ -webkit-animation: rotation 4949ms linear infinite;
+ animation : rotation 4949ms linear infinite;
+}
+
+.heart:nth-child(9) {
+ transform: translateX(-288px) translateZ(-300px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(9) .movable {
+ -webkit-animation: drop 5000ms 883ms linear infinite;
+ animation : drop 5000ms 883ms linear infinite;
+}
+
+.heart:nth-child(9) .ring {
+ -webkit-animation: wave 5000ms 4783ms ease-out infinite;
+ animation : wave 5000ms 4783ms ease-out infinite;
+}
+
+.heart:nth-child(9) .inner {
+ -webkit-animation: rotation 3148ms linear infinite;
+ animation : rotation 3148ms linear infinite;
+}
+
+.heart:nth-child(10) {
+ transform: translateX(274px) translateZ(549px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(10) .movable {
+ -webkit-animation: drop 5000ms -1415ms linear infinite;
+ animation : drop 5000ms -1415ms linear infinite;
+}
+
+.heart:nth-child(10) .ring {
+ -webkit-animation: wave 5000ms 2485ms ease-out infinite;
+ animation : wave 5000ms 2485ms ease-out infinite;
+}
+
+.heart:nth-child(10) .inner {
+ -webkit-animation: rotation 3861ms linear infinite;
+ animation : rotation 3861ms linear infinite;
+}
+
+.heart:nth-child(11) {
+ transform: translateX(142px) translateZ(79px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(11) .movable {
+ -webkit-animation: drop 5000ms 157ms linear infinite;
+ animation : drop 5000ms 157ms linear infinite;
+}
+
+.heart:nth-child(11) .ring {
+ -webkit-animation: wave 5000ms 4057ms ease-out infinite;
+ animation : wave 5000ms 4057ms ease-out infinite;
+}
+
+.heart:nth-child(11) .inner {
+ -webkit-animation: rotation 2800ms linear infinite;
+ animation : rotation 2800ms linear infinite;
+}
+
+.heart:nth-child(12) {
+ transform: translateX(-360px) translateZ(-721px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(12) .movable {
+ -webkit-animation: drop 5000ms -1407ms linear infinite;
+ animation : drop 5000ms -1407ms linear infinite;
+}
+
+.heart:nth-child(12) .ring {
+ -webkit-animation: wave 5000ms 2493ms ease-out infinite;
+ animation : wave 5000ms 2493ms ease-out infinite;
+}
+
+.heart:nth-child(12) .inner {
+ -webkit-animation: rotation 3174ms linear infinite;
+ animation : rotation 3174ms linear infinite;
+}
+
+.heart:nth-child(13) {
+ transform: translateX(27px) translateZ(792px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(13) .movable {
+ -webkit-animation: drop 5000ms -1176ms linear infinite;
+ animation : drop 5000ms -1176ms linear infinite;
+}
+
+.heart:nth-child(13) .ring {
+ -webkit-animation: wave 5000ms 2724ms ease-out infinite;
+ animation : wave 5000ms 2724ms ease-out infinite;
+}
+
+.heart:nth-child(13) .inner {
+ -webkit-animation: rotation 4215ms linear infinite;
+ animation : rotation 4215ms linear infinite;
+}
+
+.heart:nth-child(14) {
+ transform: translateX(278px) translateZ(-694px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(14) .movable {
+ -webkit-animation: drop 5000ms 1363ms linear infinite;
+ animation : drop 5000ms 1363ms linear infinite;
+}
+
+.heart:nth-child(14) .ring {
+ -webkit-animation: wave 5000ms 5263ms ease-out infinite;
+ animation : wave 5000ms 5263ms ease-out infinite;
+}
+
+.heart:nth-child(14) .inner {
+ -webkit-animation: rotation 2320ms linear infinite;
+ animation : rotation 2320ms linear infinite;
+}
+
+.heart:nth-child(15) {
+ transform: translateX(481px) translateZ(366px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(15) .movable {
+ -webkit-animation: drop 5000ms -1590ms linear infinite;
+ animation : drop 5000ms -1590ms linear infinite;
+}
+
+.heart:nth-child(15) .ring {
+ -webkit-animation: wave 5000ms 2310ms ease-out infinite;
+ animation : wave 5000ms 2310ms ease-out infinite;
+}
+
+.heart:nth-child(15) .inner {
+ -webkit-animation: rotation 2371ms linear infinite;
+ animation : rotation 2371ms linear infinite;
+}
+
+.heart:nth-child(16) {
+ transform: translateX(-379px) translateZ(-124px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(16) .movable {
+ -webkit-animation: drop 5000ms -625ms linear infinite;
+ animation : drop 5000ms -625ms linear infinite;
+}
+
+.heart:nth-child(16) .ring {
+ -webkit-animation: wave 5000ms 3275ms ease-out infinite;
+ animation : wave 5000ms 3275ms ease-out infinite;
+}
+
+.heart:nth-child(16) .inner {
+ -webkit-animation: rotation 2053ms linear infinite;
+ animation : rotation 2053ms linear infinite;
+}
+
+.heart:nth-child(17) {
+ transform: translateX(255px) translateZ(-374px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(17) .movable {
+ -webkit-animation: drop 5000ms -90ms linear infinite;
+ animation : drop 5000ms -90ms linear infinite;
+}
+
+.heart:nth-child(17) .ring {
+ -webkit-animation: wave 5000ms 3810ms ease-out infinite;
+ animation : wave 5000ms 3810ms ease-out infinite;
+}
+
+.heart:nth-child(17) .inner {
+ -webkit-animation: rotation 2180ms linear infinite;
+ animation : rotation 2180ms linear infinite;
+}
+
+.heart:nth-child(18) {
+ transform: translateX(-339px) translateZ(419px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(18) .movable {
+ -webkit-animation: drop 5000ms 645ms linear infinite;
+ animation : drop 5000ms 645ms linear infinite;
+}
+
+.heart:nth-child(18) .ring {
+ -webkit-animation: wave 5000ms 4545ms ease-out infinite;
+ animation : wave 5000ms 4545ms ease-out infinite;
+}
+
+.heart:nth-child(18) .inner {
+ -webkit-animation: rotation 2716ms linear infinite;
+ animation : rotation 2716ms linear infinite;
+}
+
+.heart:nth-child(19) {
+ transform: translateX(-102px) translateZ(355px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(19) .movable {
+ -webkit-animation: drop 5000ms -2424ms linear infinite;
+ animation : drop 5000ms -2424ms linear infinite;
+}
+
+.heart:nth-child(19) .ring {
+ -webkit-animation: wave 5000ms 1476ms ease-out infinite;
+ animation : wave 5000ms 1476ms ease-out infinite;
+}
+
+.heart:nth-child(19) .inner {
+ -webkit-animation: rotation 3368ms linear infinite;
+ animation : rotation 3368ms linear infinite;
+}
+
+.heart:nth-child(20) {
+ transform: translateX(-134px) translateZ(714px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(20) .movable {
+ -webkit-animation: drop 5000ms 1537ms linear infinite;
+ animation : drop 5000ms 1537ms linear infinite;
+}
+
+.heart:nth-child(20) .ring {
+ -webkit-animation: wave 5000ms 5437ms ease-out infinite;
+ animation : wave 5000ms 5437ms ease-out infinite;
+}
+
+.heart:nth-child(20) .inner {
+ -webkit-animation: rotation 2578ms linear infinite;
+ animation : rotation 2578ms linear infinite;
+}
+
+.heart:nth-child(21) {
+ transform: translateX(-320px) translateZ(728px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(21) .movable {
+ -webkit-animation: drop 5000ms -606ms linear infinite;
+ animation : drop 5000ms -606ms linear infinite;
+}
+
+.heart:nth-child(21) .ring {
+ -webkit-animation: wave 5000ms 3294ms ease-out infinite;
+ animation : wave 5000ms 3294ms ease-out infinite;
+}
+
+.heart:nth-child(21) .inner {
+ -webkit-animation: rotation 2357ms linear infinite;
+ animation : rotation 2357ms linear infinite;
+}
+
+.heart:nth-child(22) {
+ transform: translateX(261px) translateZ(285px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(22) .movable {
+ -webkit-animation: drop 5000ms 680ms linear infinite;
+ animation : drop 5000ms 680ms linear infinite;
+}
+
+.heart:nth-child(22) .ring {
+ -webkit-animation: wave 5000ms 4580ms ease-out infinite;
+ animation : wave 5000ms 4580ms ease-out infinite;
+}
+
+.heart:nth-child(22) .inner {
+ -webkit-animation: rotation 2295ms linear infinite;
+ animation : rotation 2295ms linear infinite;
+}
+
+.heart:nth-child(23) {
+ transform: translateX(-371px) translateZ(-297px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(23) .movable {
+ -webkit-animation: drop 5000ms -1132ms linear infinite;
+ animation : drop 5000ms -1132ms linear infinite;
+}
+
+.heart:nth-child(23) .ring {
+ -webkit-animation: wave 5000ms 2768ms ease-out infinite;
+ animation : wave 5000ms 2768ms ease-out infinite;
+}
+
+.heart:nth-child(23) .inner {
+ -webkit-animation: rotation 2082ms linear infinite;
+ animation : rotation 2082ms linear infinite;
+}
+
+.heart:nth-child(24) {
+ transform: translateX(-169px) translateZ(663px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(24) .movable {
+ -webkit-animation: drop 5000ms 493ms linear infinite;
+ animation : drop 5000ms 493ms linear infinite;
+}
+
+.heart:nth-child(24) .ring {
+ -webkit-animation: wave 5000ms 4393ms ease-out infinite;
+ animation : wave 5000ms 4393ms ease-out infinite;
+}
+
+.heart:nth-child(24) .inner {
+ -webkit-animation: rotation 4600ms linear infinite;
+ animation : rotation 4600ms linear infinite;
+}
+
+.heart:nth-child(25) {
+ transform: translateX(83px) translateZ(-755px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(25) .movable {
+ -webkit-animation: drop 5000ms 317ms linear infinite;
+ animation : drop 5000ms 317ms linear infinite;
+}
+
+.heart:nth-child(25) .ring {
+ -webkit-animation: wave 5000ms 4217ms ease-out infinite;
+ animation : wave 5000ms 4217ms ease-out infinite;
+}
+
+.heart:nth-child(25) .inner {
+ -webkit-animation: rotation 2607ms linear infinite;
+ animation : rotation 2607ms linear infinite;
+}
+
+.heart:nth-child(26) {
+ transform: translateX(-119px) translateZ(501px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(26) .movable {
+ -webkit-animation: drop 5000ms 1178ms linear infinite;
+ animation : drop 5000ms 1178ms linear infinite;
+}
+
+.heart:nth-child(26) .ring {
+ -webkit-animation: wave 5000ms 5078ms ease-out infinite;
+ animation : wave 5000ms 5078ms ease-out infinite;
+}
+
+.heart:nth-child(26) .inner {
+ -webkit-animation: rotation 2796ms linear infinite;
+ animation : rotation 2796ms linear infinite;
+}
+
+.heart:nth-child(27) {
+ transform: translateX(4px) translateZ(-268px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(27) .movable {
+ -webkit-animation: drop 5000ms -1114ms linear infinite;
+ animation : drop 5000ms -1114ms linear infinite;
+}
+
+.heart:nth-child(27) .ring {
+ -webkit-animation: wave 5000ms 2786ms ease-out infinite;
+ animation : wave 5000ms 2786ms ease-out infinite;
+}
+
+.heart:nth-child(27) .inner {
+ -webkit-animation: rotation 3196ms linear infinite;
+ animation : rotation 3196ms linear infinite;
+}
+
+.heart:nth-child(28) {
+ transform: translateX(48px) translateZ(-611px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(28) .movable {
+ -webkit-animation: drop 5000ms -2925ms linear infinite;
+ animation : drop 5000ms -2925ms linear infinite;
+}
+
+.heart:nth-child(28) .ring {
+ -webkit-animation: wave 5000ms 975ms ease-out infinite;
+ animation : wave 5000ms 975ms ease-out infinite;
+}
+
+.heart:nth-child(28) .inner {
+ -webkit-animation: rotation 2491ms linear infinite;
+ animation : rotation 2491ms linear infinite;
+}
+
+.heart:nth-child(29) {
+ transform: translateX(-463px) translateZ(373px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(29) .movable {
+ -webkit-animation: drop 5000ms 305ms linear infinite;
+ animation : drop 5000ms 305ms linear infinite;
+}
+
+.heart:nth-child(29) .ring {
+ -webkit-animation: wave 5000ms 4205ms ease-out infinite;
+ animation : wave 5000ms 4205ms ease-out infinite;
+}
+
+.heart:nth-child(29) .inner {
+ -webkit-animation: rotation 2700ms linear infinite;
+ animation : rotation 2700ms linear infinite;
+}
+
+.heart:nth-child(30) {
+ transform: translateX(-404px) translateZ(568px) scale3d(0.5, 0.5, 0.5);
+}
+
+.heart:nth-child(30) .movable {
+ -webkit-animation: drop 5000ms -1461ms linear infinite;
+ animation : drop 5000ms -1461ms linear infinite;
+}
+
+.heart:nth-child(30) .ring {
+ -webkit-animation: wave 5000ms 2439ms ease-out infinite;
+ animation : wave 5000ms 2439ms ease-out infinite;
+}
+
+.heart:nth-child(30) .inner {
+ -webkit-animation: rotation 3300ms linear infinite;
+ animation : rotation 3300ms linear infinite;
+}
+
+@-webkit-keyframes blur {
+ 0% {
+ filter: blur(20px) grayscale(150%);
+ }
+
+ 100% {
+ filter: blur(10px) grayscale(50%);
+ }
+}
+
+@keyframes blur {
+ 0% {
+ filter: blur(20px) grayscale(150%);
+ }
+
+ 100% {
+ filter: blur(10px) grayscale(50%);
+ }
+}
+
+@-webkit-keyframes rotation {
+ 0% {
+ transform: rotateY(0deg);
+ }
+
+ 100% {
+ transform: rotateY(360deg);
+ }
+}
+
+@keyframes rotation {
+ 0% {
+ transform: rotateY(0deg);
+ }
+
+ 100% {
+ transform: rotateY(360deg);
+ }
+}
+
+@-webkit-keyframes drop {
+ 0% {
+ transform: translateY(-1000px);
+ opacity : 0;
+ }
+
+ 80% {
+ transform: translateY(0);
+ opacity : 3;
+ }
+
+ 100% {
+ transform: translateY(-40px);
+ opacity : 0;
+ }
+}
+
+@keyframes drop {
+ 0% {
+ transform: translateY(-1000px);
+ opacity : 0;
+ }
+
+ 80% {
+ transform: translateY(0);
+ opacity : 3;
+ }
+
+ 100% {
+ transform: translateY(-40px);
+ opacity : 0;
+ }
+}
+
+@-webkit-keyframes wave {
+ 0% {
+ transform: translate(-50%, -50%) rotateX(90deg) scale(0) translateZ(-37px);
+ opacity : 2;
+ }
+
+ 100% {
+ transform: translate(-50%, -50%) rotateX(90deg) scale(2) translateZ(-37px);
+ opacity : 0;
+ }
+}
+
+@keyframes wave {
+ 0% {
+ transform: translate(-50%, -50%) rotateX(90deg) scale(0) translateZ(-37px);
+ opacity : 2;
+ }
+
+ 100% {
+ transform: translate(-50%, -50%) rotateX(90deg) scale(2) translateZ(-37px);
+ opacity : 0;
+ }
+}
+
+@-webkit-keyframes wing {
+ 0% {
+ transform: rotateY(70deg);
+ }
+
+ 100% {
+ transform: rotateY(0deg);
+ }
+}
+
+@keyframes wing {
+ 0% {
+ transform: rotateY(70deg);
+ }
+
+ 100% {
+ transform: rotateY(0deg);
+ }
+}
diff --git a/mirzaev/site/wanda/system/public/css/wanda.css b/mirzaev/site/wanda/system/public/css/wanda.css
new file mode 100644
index 0000000..151e615
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/css/wanda.css
@@ -0,0 +1,42 @@
+@import url('/fonts/veganstyle.ttf');
+
+a#wanda {
+ margin : auto;
+ font-size : 5em;
+ font-family: 'Vegan Style Personal Use', 'Commissioner', sans-serif;
+ transition : 0.1s ease-in;
+ color : #b35050;
+}
+
+a#wanda:hover {
+ padding-bottom: 30px;
+ color : #c56565;
+}
+
+a#wanda:active {
+ color: #913f3f;
+}
+
+a#wanda::before {
+ z-index : -1000;
+ transform : rotateX(-66deg);
+ content : 'Wanda Switch';
+ position : absolute;
+ margin : auto;
+ padding-left: 0.2em;
+ padding-top : 0.45em;
+ transition : 0.1s ease-in;
+ color : #00000030;
+}
+
+a#wanda:hover::before {
+ padding-left : 0.3em;
+ padding-top : 0.45em;
+ padding-bottom: 30px;
+}
+
+@media (max-width: 600px) {
+ a#wanda {
+ font-size: 2em;
+ }
+}
diff --git a/mirzaev/site/wanda/system/public/favicon-16x16.png b/mirzaev/site/wanda/system/public/favicon-16x16.png
new file mode 100644
index 0000000..c0d1bd6
Binary files /dev/null and b/mirzaev/site/wanda/system/public/favicon-16x16.png differ
diff --git a/mirzaev/site/wanda/system/public/favicon-32x32.png b/mirzaev/site/wanda/system/public/favicon-32x32.png
new file mode 100644
index 0000000..6fe97ed
Binary files /dev/null and b/mirzaev/site/wanda/system/public/favicon-32x32.png differ
diff --git a/mirzaev/site/wanda/system/public/favicon-96x96.png b/mirzaev/site/wanda/system/public/favicon-96x96.png
new file mode 100644
index 0000000..b112033
Binary files /dev/null and b/mirzaev/site/wanda/system/public/favicon-96x96.png differ
diff --git a/mirzaev/site/wanda/system/public/favicon.ico b/mirzaev/site/wanda/system/public/favicon.ico
new file mode 100644
index 0000000..41e76c7
Binary files /dev/null and b/mirzaev/site/wanda/system/public/favicon.ico differ
diff --git a/mirzaev/site/wanda/system/public/fonts/commissioner.ttf b/mirzaev/site/wanda/system/public/fonts/commissioner.ttf
new file mode 100644
index 0000000..08a14a6
Binary files /dev/null and b/mirzaev/site/wanda/system/public/fonts/commissioner.ttf differ
diff --git a/mirzaev/site/wanda/system/public/fonts/veganstyle.ttf b/mirzaev/site/wanda/system/public/fonts/veganstyle.ttf
new file mode 100644
index 0000000..9fdf5c3
Binary files /dev/null and b/mirzaev/site/wanda/system/public/fonts/veganstyle.ttf differ
diff --git a/mirzaev/site/wanda/system/public/images/botnet.svg b/mirzaev/site/wanda/system/public/images/botnet.svg
new file mode 100644
index 0000000..d142a38
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/images/botnet.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mirzaev/site/wanda/system/public/images/keylogger.svg b/mirzaev/site/wanda/system/public/images/keylogger.svg
new file mode 100644
index 0000000..95b18c1
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/images/keylogger.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mirzaev/site/wanda/system/public/images/logo.png b/mirzaev/site/wanda/system/public/images/logo.png
new file mode 100644
index 0000000..ff755e5
Binary files /dev/null and b/mirzaev/site/wanda/system/public/images/logo.png differ
diff --git a/mirzaev/site/wanda/system/public/images/logo_compressed.png b/mirzaev/site/wanda/system/public/images/logo_compressed.png
new file mode 100644
index 0000000..02f6f70
Binary files /dev/null and b/mirzaev/site/wanda/system/public/images/logo_compressed.png differ
diff --git a/mirzaev/site/wanda/system/public/images/logo_red.png b/mirzaev/site/wanda/system/public/images/logo_red.png
new file mode 100644
index 0000000..921128b
Binary files /dev/null and b/mirzaev/site/wanda/system/public/images/logo_red.png differ
diff --git a/mirzaev/site/wanda/system/public/images/logo_red_compressed.png b/mirzaev/site/wanda/system/public/images/logo_red_compressed.png
new file mode 100644
index 0000000..c3ed8a2
Binary files /dev/null and b/mirzaev/site/wanda/system/public/images/logo_red_compressed.png differ
diff --git a/mirzaev/site/wanda/system/public/images/logo_red_white.png b/mirzaev/site/wanda/system/public/images/logo_red_white.png
new file mode 100644
index 0000000..3f8e849
Binary files /dev/null and b/mirzaev/site/wanda/system/public/images/logo_red_white.png differ
diff --git a/mirzaev/site/wanda/system/public/images/logo_red_white_compressed.png b/mirzaev/site/wanda/system/public/images/logo_red_white_compressed.png
new file mode 100644
index 0000000..b9c3f6b
Binary files /dev/null and b/mirzaev/site/wanda/system/public/images/logo_red_white_compressed.png differ
diff --git a/mirzaev/site/wanda/system/public/images/minecraft.svg b/mirzaev/site/wanda/system/public/images/minecraft.svg
new file mode 100644
index 0000000..3a2bd7f
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/images/minecraft.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mirzaev/site/wanda/system/public/images/miner.svg b/mirzaev/site/wanda/system/public/images/miner.svg
new file mode 100644
index 0000000..0d93c82
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/images/miner.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mirzaev/site/wanda/system/public/images/stealer.svg b/mirzaev/site/wanda/system/public/images/stealer.svg
new file mode 100644
index 0000000..6245737
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/images/stealer.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mirzaev/site/wanda/system/public/images/truth.jpg b/mirzaev/site/wanda/system/public/images/truth.jpg
new file mode 100644
index 0000000..961a1d2
Binary files /dev/null and b/mirzaev/site/wanda/system/public/images/truth.jpg differ
diff --git a/mirzaev/site/wanda/system/public/images/wanda.jpg b/mirzaev/site/wanda/system/public/images/wanda.jpg
new file mode 100644
index 0000000..4034bf4
Binary files /dev/null and b/mirzaev/site/wanda/system/public/images/wanda.jpg differ
diff --git a/mirzaev/site/wanda/system/public/images/what.png b/mirzaev/site/wanda/system/public/images/what.png
new file mode 100644
index 0000000..f91d8ab
Binary files /dev/null and b/mirzaev/site/wanda/system/public/images/what.png differ
diff --git a/mirzaev/site/wanda/system/public/index.php b/mirzaev/site/wanda/system/public/index.php
new file mode 100644
index 0000000..c35e67e
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/index.php
@@ -0,0 +1,36 @@
+write('/', 'index', 'index');
+$router->write('/system/hotline', 'hotline', 'index');
+$router->write('/system/graph', 'graph', 'index');
+$router->write('/account/initialization', 'account', 'initialization', 'PUT');
+$router->write('/account/vk/connect', 'account', 'connect');
+$router->write('/account/panel', 'account', 'panel');
+
+// Инициализация ядра
+$core = new core(namespace: __NAMESPACE__, router: $router);
+
+// Обработка запроса
+echo $core->start();
diff --git a/mirzaev/site/wanda/system/public/js/account.js b/mirzaev/site/wanda/system/public/js/account.js
new file mode 100644
index 0000000..ce24849
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/js/account.js
@@ -0,0 +1,26 @@
+"use strict";
+
+class account {
+ static async initialization() {
+ // Запрос
+ return fetch('https://auth.mirzaev.sexy/account/initialization', {
+ method: 'GET'
+ });
+ }
+
+ static authentication() {
+ // Инициализация аккаунта
+ alert(1);
+ this.initialization()
+ .then(
+ (response) => {
+ alert(2);
+ }
+ );
+
+ return true;
+ }
+
+ static deauthentication() {
+ }
+}
diff --git a/mirzaev/site/wanda/system/public/js/graph.js b/mirzaev/site/wanda/system/public/js/graph.js
new file mode 100644
index 0000000..c53fd69
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/js/graph.js
@@ -0,0 +1,1332 @@
+'use strict';
+
+/**
+ * @author Arsen Mirzaev Tatyano-Muradovich
+ */
+class graph {
+ // Оболочка (instanceof HTMLElement)
+ #shell = document.getElementById("graph");
+ get shell() {
+ return this.#shell;
+ }
+
+ // Реестр узлов
+ #nodes = new Set();
+ get nodes() {
+ return this.#nodes;
+ }
+
+ // Реестр соединений
+ #connections = new Set();
+ get connections() {
+ return this.#connections;
+ }
+
+ // Класс узла
+ #node = class node {
+ // Реестр входящих соединений
+ #inputs = new Set();
+ get inputs() {
+ return this.#inputs;
+ }
+
+ // Реестр исходящих соединений
+ #outputs = new Set();
+ get outputs() {
+ return this.#outputs;
+ }
+
+ // Оператор
+ #operator;
+ get operator() {
+ return this.#operator;
+ }
+
+ // HTML-элемент
+ #element;
+ get element() {
+ return this.#element;
+ }
+
+ // Наблюдатель
+ #observer = null;
+ get observer() {
+ return this.#observer;
+ }
+
+ // Реестр запрещённых к изменению параметров
+ #block = new Set(["events"]);
+ get block() {
+ return this.#block;
+ }
+
+ // Диаметр узла
+ #diameter = 100;
+ get diameter() {
+ return this.#diameter;
+ }
+
+ // Степень увеличения диаметра
+ #increase = 0;
+ get increase() {
+ return this.#increase;
+ }
+
+ // Величина степени увеличения диаметра
+ #addition = 12;
+ get addition() {
+ return this.#addition;
+ }
+
+ // Счётчик итераций
+ iteration = 0;
+
+ // Ограничение максимального количества итераций за вызов
+ limit = 3000;
+
+ // Обработка событий
+ actions = {
+ collision: true,
+ pushing: true,
+ pulling: true
+ };
+
+ constructor(operator, data) {
+ // Инициализация ссылки на ядро
+ const _this = this;
+
+ // Инициализация HTML-элемента узла
+ const article = document.createElement("article");
+ article.id = operator.nodes.size;
+ article.classList.add(data.color ?? 'white', "node", "unselectable");
+ if (typeof data.href === "string") {
+ article.href = data.href;
+ }
+
+ // Запись анимации "выделение обводкой" (чтобы не проигрывалась при открытии страницы)
+ article.onmouseenter = fn => {
+ // Запись класса с анимацией
+ article.classList.add('animated');
+ };
+
+ // Инициализация заголовка
+ const title = document.createElement("h4");
+ title.classList.add('title');
+ title.innerText = data.title ?? '';
+
+ // Запись в оболочку
+ article.appendChild(title);
+
+ // Инициализация описания
+ const description = document.createElement("div");
+ description.classList.add('description');
+ if (typeof data.popup === 'string') description.title = data.popup;
+
+ // Запись анимации "выделение обводкой" (чтобы не проигрывалась при открытии страницы)
+ description.onmouseenter = fn => {
+ // Запись класса с анимацией
+ description.classList.add('animated');
+ };
+
+ // Запись блокировки открытия описания в случае, если был перемещён узел
+ title.onmousedown = (onmousedown) => {
+ // Инициализация координат
+ let x = onmousedown.pageX;
+ let y = onmousedown.pageY;
+
+ // Запись события открытия описания
+ title.onclick = (onclick) => {
+ // Отображение описания
+ _this.show();
+
+ // Удаление событий
+ title.onclick = title.onmousemove = null;
+
+ // Реинициализация координат
+ x = onclick.pageX;
+ y = onclick.pageY;
+
+ // Удаление иконки курсора
+ title.style.cursor = null;
+
+ return true;
+ }
+
+ title.onmousemove = (onmousemove) => {
+ // Курсор сдвинут более чем на 15 пикселей?
+ if (Math.abs(x - onmousemove.pageX) > 15 || Math.abs(y - onmousemove.pageY) > 15) {
+ // Запись иконки курсора
+ title.style.cursor = 'grabbing';
+
+ // Запись события для переноса узла
+ title.onclick = (onclick) => {
+ // Удаление событий
+ title.onclick = title.onmousemove = null;
+
+ // Реинициализация координат
+ x = onclick.pageX;
+ y = onclick.pageY;
+
+ // Удаление иконки курсора
+ title.style.cursor = null;
+
+ return false;
+ }
+ } else {
+ // Запись события открытия описания
+ title.onclick = (onclick) => {
+ // Отображение описания
+ _this.show();
+
+ // Удаление событий
+ title.onclick = title.onmousemove = null;
+
+ // Реинициализация координат
+ x = onclick.pageX;
+ y = onclick.pageY;
+
+ // Удаление иконки курсора
+ title.style.cursor = null;
+
+ return true;
+ };
+ }
+ }
+ };
+
+ // Запись в оболочку
+ article.appendChild(description);
+
+ // Инициализация левой фигуры для обёртки текста
+ const left = document.createElement("span");
+ left.classList.add('left', 'wrapper');
+
+ // Запись в описание
+ description.appendChild(left);
+
+ // Инициализация правой фигуры для обёртки текста
+ const right = document.createElement("span");
+ right.classList.add('right', 'wrapper');
+
+ // Запись в описание
+ description.appendChild(right);
+
+ // Инициализация ссылки на источник
+ const a = document.createElement("a");
+ if (typeof data.link === 'object' && typeof data.link.name === 'string') a.innerText = data.link.name;
+ if (typeof data.link === 'object' && typeof data.link.href === 'string') a.href = data.link.href;
+ if (typeof data.link === 'object' && typeof data.link.class === 'object') a.classList.add(...data.link.class);
+ if (typeof data.link === 'object' && typeof data.link.title === 'string') a.title = data.link.title;
+
+ // Блокировка событий браузера (чтобы не мешать переноса узла)
+ a.ondragstart = a.onselectstart = fn => { return false };
+
+ // Запись блокировки перехода по ссылке в случае, если был перемещён узел
+ a.onmousedown = (onmousedown) => {
+ // Инициализация координат
+ let x = onmousedown.pageX;
+ let y = onmousedown.pageY;
+
+ // Запись события открытия описания
+ a.onclick = (onclick) => {
+ // Удаление событий
+ a.onclick = a.onmousemove = null;
+
+ // Реинициализация координат
+ x = onclick.pageX;
+ y = onclick.pageY;
+
+ // Удаление иконки курсора
+ a.style.cursor = null;
+
+ return true;
+ }
+
+ a.onmousemove = (onmousemove) => {
+ // Курсор сдвинут более чем на 15 пикселей?
+ if (Math.abs(x - onmousemove.pageX) > 15 || Math.abs(y - onmousemove.pageY) > 15) {
+ // Запись иконки курсора
+ a.style.cursor = 'grabbing';
+
+ // Запись события для переноса узла
+ a.onclick = (onclick) => {
+ // Удаление событий
+ a.onclick = a.onmousemove = null;
+
+ // Реинициализация координат
+ x = onclick.pageX;
+ y = onclick.pageY;
+
+ // Удаление иконки курсора
+ a.style.cursor = null;
+
+ return false;
+ }
+ } else {
+ // Запись события открытия описания
+ a.onclick = (onclick) => {
+ // Удаление событий
+ a.onclick = a.onmousemove = null;
+
+ // Реинициализация координат
+ x = onclick.pageX;
+ y = onclick.pageY;
+
+ // Удаление иконки курсора
+ a.style.cursor = null;
+
+ return true;
+ };
+ }
+ }
+ };
+
+ // Запись в описание
+ description.appendChild(a);
+
+ // Запись текста в описание
+ const text = document.createElement("p");
+ if (typeof data.description === 'string') text.innerText = data.description;
+
+ // Запись в оболочку
+ description.appendChild(text);
+
+ if (
+ typeof data.cover === "string"
+ ) {
+ // Получено изображение-обложка
+
+ // Инициализация изображения-обложки
+ const cover = document.createElement("img");
+ if (typeof cover.src === 'string') cover.src = data.cover;
+ if (typeof cover.alt === 'string') cover.alt = data.title;
+ cover.classList.add('cover', 'unselectable');
+
+ // Запись в описание
+ description.appendChild(cover);
+ }
+
+ if (
+ typeof data.append === "HTMLCollection" ||
+ typeof data.append === "HTMLElement"
+ ) {
+ // Получены другие HTML-элементы
+
+ // Запись в оболочку
+ article.appendChild(data.append);
+ }
+
+ // Инициализация кнопки закрытия
+ const close = document.createElement('i');
+ close.classList.add('icon', 'close');
+ close.style.display = 'none';
+
+ // Запись блокировки закрытия в случае, если был перемещён узел
+ close.onmousedown = (onmousedown) => {
+ // Инициализация координат
+ let x = onmousedown.pageX;
+ let y = onmousedown.pageY;
+
+ // Запись события открытия описания
+ close.onclick = (onclick) => {
+ // Скрытие описания
+ _this.hide();
+
+ // Удаление событий
+ close.onclick = close.onmousemove = null;
+
+ // Реинициализация координат
+ x = onclick.pageX;
+ y = onclick.pageY;
+
+ // Удаление иконки курсора
+ close.style.cursor = null;
+
+ return true;
+ }
+
+ close.onmousemove = (onmousemove) => {
+ // Курсор сдвинут более чем на 15 пикселей?
+ if (Math.abs(x - onmousemove.pageX) > 15 || Math.abs(y - onmousemove.pageY) > 15) {
+ // Запись иконки курсора
+ close.style.cursor = 'grabbing';
+
+ // Запись события для переноса узла
+ close.onclick = (onclick) => {
+ // Удаление событий
+ close.onclick = close.onmousemove = null;
+
+ // Реинициализация координат
+ x = onclick.pageX;
+ y = onclick.pageY;
+
+ // Удаление иконки курсора
+ close.style.cursor = null;
+
+ return false;
+ }
+ } else {
+ // Запись события открытия описания
+ close.onclick = (onclick) => {
+ // Скрытие описания
+ _this.hide();
+
+ // Удаление событий
+ close.onclick = close.onmousemove = null;
+
+ // Реинициализация координат
+ x = onclick.pageX;
+ y = onclick.pageY;
+
+ // Удаление иконки курсора
+ close.style.cursor = null;
+
+ return true;
+ };
+ }
+ }
+ };
+
+ // Запись в оболочку
+ article.appendChild(close);
+
+ // Запись в документ
+ operator.shell.appendChild(article);
+
+ // Запись диаметра описания в зависимости от размера заголовка (чтобы вмещался)
+ description.style.width = description.style.height = (a.offsetWidth === 0 ? 50 : a.offsetWidth) * 3 + 'px';
+
+ // Запись отступа заголовка (чтобы был по центру описания)
+ a.style.left = description.offsetWidth / 2 - a.offsetWidth / 2 + 'px';
+
+ // Сокрытие описания (выполняется после расчёта размера потому, что иначе размер будет недоступен)
+ description.style.display = "none";
+
+ /**
+ * Показать описание
+ */
+ this.show = () => {
+ // Отображение описания и кнопки закрытия описания
+ description.style.display = close.style.display = null;
+
+ // Сдвиг кнопки закрытия описания
+ close.style.top = close.style.right = -(((description.offsetWidth - article.offsetWidth) / 4) + description.offsetWidth / 8) + 'px';
+
+ // Размер кнопки закрытия описания
+ close.style.scale = 1.3;
+
+ // Прозрачность кнопки закрытия описания (плавное появление)
+ close.style.opacity = 1;
+
+ // Расположение выше остальных узлов
+ article.style.zIndex = close.style.zIndex = 1000;
+ }
+
+ /**
+ * Скрыть описание
+ */
+ this.hide = () => {
+ // Скрытие описания и кнопки закрытия описания
+ description.style.display = close.style.display = 'none';
+
+ // Удаление всех изменённых аттрибутов
+ close.style.top = close.style.right = article.style.zIndex = close.style.zIndex = close.style.scale = close.style.opacity = null;
+ }
+
+ // Запись в свойство
+ this.#element = article;
+
+ // Запись в свойство
+ this.#operator = operator;
+
+ // Инициализация
+ this.init();
+
+ // Перемещение
+ this.move(
+ operator.shell.offsetWidth / 2 -
+ this.#diameter / 2 +
+ (0.5 - Math.random()) * 500,
+ operator.shell.offsetHeight / 2 -
+ this.#diameter / 2 +
+ (0.5 - Math.random()) * 500,
+ true,
+ true,
+ true
+ );
+ }
+
+ init(increase = 0) {
+ // Запись в свойство
+ this.#increase = increase;
+
+ // Инициализация диаметра
+ if (this.#increase !== 0)
+ this.#diameter += this.#addition ** this.#increase;
+
+ // Инициализация размера HTML-элемента
+ this.element.style.width = this.element.style.height =
+ this.#diameter + "px";
+
+ // Инициализация описания
+ const description = this.element.getElementsByClassName('description')[0];
+
+ // Запись отступа описания (чтобы был по центру узла)
+ description.style.display = null;
+ description.style.marginLeft = description.style.marginTop = (this.element.offsetWidth - description.offsetWidth) / 2 + 'px';
+ description.style.display = 'none';
+
+ // Инициализация ссылки на ядро
+ const _this = this;
+
+ // Инициализация наблюдателя
+ this.#observer = new MutationObserver(function (mutations) {
+ for (const mutation of mutations) {
+ if (mutation.type === "attributes") {
+ // Перехвачено изменение аттрибута
+
+ // Запись параметра в инстанцию бегущей строки
+ _this.configure(mutation.attributeName);
+ }
+ }
+ });
+
+ // Активация наблюдения
+ this.observer.observe(this.element, {
+ attributes: true,
+ attributeOldValue: true
+ });
+ }
+
+ move(x, y, collision = false, pushing = false, pulling = false) {
+ // Запись отступов
+ this.element.style.left = x + "px";
+ this.element.style.top = y + "px";
+
+ // Запись аттрибутов с координатами
+ this.element.setAttribute("data-graph-x", x);
+ this.element.setAttribute("data-graph-y", y);
+
+ // Инициализация реестров узлов
+ if (collision === true) collision = new Set();
+ if (pushing === true) pushing = new Set();
+ if (pulling === true) pulling = new Set();
+
+ // Обработка столкновений
+ if (collision && !collision.has(this))
+ this.collision(this.operator.nodes, collision);
+
+ // Инициализация буфера реестра узлов
+ const registry = new Set(this.operator.nodes);
+
+ if (pushing && !pushing.has(this)) {
+ // Активно отталкивание
+
+ // Инициализация счётчика циклов
+ let iterations = 50;
+
+ for (const connection of this.inputs) {
+ // Перебор входящих соединений
+
+ // Ограничение выполнения
+ if (--iterations <= 0) break;
+
+ // Защита от повторной обработки
+ if (pushing.has(connection.from)) continue;
+
+ // Удаление из буфера реестра узлов
+ registry.delete(connection.from);
+
+ // Обработка отталкивания
+ this.pushing(new Set([connection.from]), pushing);
+ }
+
+ // Реинициализация счётчика циклов
+ iterations = 50;
+
+ for (const connection of this.outputs) {
+ // Перебор исходящих соединений
+
+ // Ограничение выполнения
+ if (--iterations <= 0) break;
+
+ // Защита от повторной обработки
+ if (pushing.has(connection.to)) continue;
+
+ // Удаление из буфера реестра узлов
+ registry.delete(connection.to);
+
+ // Обработка отталкивания
+ this.pushing(new Set([connection.to]), pushing);
+ }
+ }
+
+ if (pulling && !pulling.has(this)) {
+ // Активно притягивание
+
+ // Инициализация счётчика циклов
+ let iterations = 50;
+
+ for (const connection of this.inputs) {
+ // Перебор входящих соединений
+
+ // Ограничение выполнения
+ if (--iterations <= 0) break;
+
+ // Защита от повторной обработки
+ if (pulling.has(connection.from)) continue;
+
+ // Удаление из буфера реестра узлов
+ registry.delete(connection.from);
+
+ // Обработка притягивания
+ this.pulling(new Set([connection.from]), pulling);
+ }
+
+ // Реинициализация счётчика циклов
+ iterations = 50;
+
+ for (const connection of this.outputs) {
+ // Перебор входящих соединений
+
+ // Ограничение выполнения
+ if (--iterations <= 0) break;
+
+ // Защита от повторной обработки
+ if (pulling.has(connection.to)) continue;
+
+ // Удаление из буфера реестра узлов
+ registry.delete(connection.to);
+
+ // Обработка притягивания
+ this.pulling(new Set([connection.to]), pulling);
+ }
+ }
+
+ // Обработка отталкивания остальных узлов
+ if (pushing) this.pushing(registry, pushing);
+
+ // Синхронизация местоположения исходящих соединений
+ for (const connection of this.outputs) connection.sync(this);
+
+ // Синхронизация местоположения входящих соединений
+ for (const connection of this.inputs) connection.sync(this);
+ }
+
+ collision(nodes, involved) {
+ // Инициализация буфера реестра узлов
+ const registry = new Set(nodes);
+
+ // Удаление текущего узла из буфера
+ registry.delete(this);
+
+ // Обработка столкновения с узлами
+ for (const node of registry) {
+ // Перебор узлов в реестре
+
+ // Защита от повторной обработки узла
+ if (involved.has(node)) continue;
+
+ // Инициализация вектора между узлами
+ let between;
+
+ // Инициализация ускорения
+ let increase = 0;
+
+ // Инициализация максимального количества итераций
+ let iterations = 30;
+
+ do {
+ // Произошла коллизия (границы кругов перекрылись)
+
+ if (++this.iteration >= this.limit) {
+ // Превышено ограничение по числу итераций
+
+ // Сброс счётчика итераций
+ this.iteration = 0;
+
+ // Конец выполнения
+ break;
+ }
+
+ if (++node.iteration >= node.limit) {
+ // Превышено ограничение по числу итераций
+
+ // Сброс счётчика итераций
+ node.iteration = 0;
+
+ // Конец выполнения
+ break;
+ }
+
+ // Инициализация универсального буфера
+ let buffer;
+
+ // Инициализация координат целевого узла
+ let x1 =
+ (isNaN((buffer = parseInt(node.element.style.left))) ? 0 : buffer) +
+ node.element.offsetWidth / 2;
+ let y1 =
+ (isNaN((buffer = parseInt(node.element.style.top))) ? 0 : buffer) +
+ node.element.offsetHeight / 2;
+
+ // Инициализация координат обрабатываемого узла
+ let x2 =
+ (isNaN((buffer = parseInt(this.element.style.left))) ? 0 : buffer) +
+ this.element.offsetWidth / 2;
+ let y2 =
+ (isNaN((buffer = parseInt(this.element.style.top))) ? 0 : buffer) +
+ this.element.offsetHeight / 2;
+
+ // Реинициализация вектора между узлами
+ between = new Victor(x1 - x2, y1 - y2);
+
+ // Узлы преодолели расстояние столкновения?
+ if (
+ !node.actions.collision ||
+ between.length() > node.diameter / 2 + this.diameter / 2 ||
+ --iterations <= 0
+ )
+ break;
+
+ // Инициализация координат вектора (узла с которым произошло столкновение)
+ let vector = new Victor(x1, y1)
+ .add(new Victor(between.x, between.y).norm().unfloat())
+ .subtract(
+ new Victor(
+ node.element.offsetWidth / 2,
+ node.element.offsetHeight / 2
+ )
+ );
+
+ if (node.actions.collision) {
+ // Активно столкновение узлов
+
+ // Запрещение столкновения, притягивания и отталкивания целевого узла и обрабатываемого узла (другими узлами)
+ node.actions.collision = node.actions.pushing = node.actions.pulling = this.actions.collision = this.actions.pushing = this.actions.pulling = false;
+
+ // Запись узлов в реестр задействованных узлов
+ involved.add(this);
+
+ // Перемещение узла
+ node.move(vector.x, vector.y, involved, involved, involved);
+
+ // Разрешение столкновения, притягивания и отталкивания целевого узла и обрабатываемого узла (другими узлами)
+ node.actions.collision = node.actions.pushing = node.actions.pulling = this.actions.collision = this.actions.pushing = this.actions.pulling = true;
+ }
+
+ // Проверка на столкновение узлов
+ } while (
+ node.actions.collision &&
+ between.length() <= node.diameter / 2 + this.diameter / 2
+ );
+ }
+ }
+
+ pushing(nodes, involved, add) {
+ if (++this.iteration >= this.limit) {
+ // Превышено ограничение по числу итераций
+
+ // Сброс счётчика итераций
+ this.iteration = 0;
+
+ // Отмена выполнения
+ return;
+ }
+
+ // Инициализация буфера реестра узлов
+ const registry = new Set(nodes);
+
+ // Удаление текущего узла из буфера
+ registry.delete(this);
+
+ // Инициализация ссылки на ядро
+ const _this = this;
+
+ // Увеличение дистанции для проверки
+ const distance = 100;
+
+ // Обработка отталкивания узлов
+ for (const node of registry) {
+ // Перебор узлов в буфере реестра
+
+ // Защита от повторной обработки узла
+ if (involved.has(node)) continue;
+
+ // Инициализация вектора между узлами
+ let between;
+
+ // Инициализация максимального количества итераций
+ let iterations = 30;
+
+ function move() {
+ if (++node.iteration >= node.limit) {
+ // Превышено ограничение по числу итераций
+
+ // Сброс счётчика итераций
+ node.iteration = 0;
+
+ // Отмена выполнения
+ return;
+ }
+
+ // Инициализация универсального буфера
+ let buffer;
+
+ // Инициализация координат целевого узла
+ let x1 =
+ (isNaN((buffer = parseInt(node.element.style.left))) ? 0 : buffer) +
+ node.element.offsetWidth / 2;
+ let y1 =
+ (isNaN((buffer = parseInt(node.element.style.top))) ? 0 : buffer) +
+ node.element.offsetHeight / 2;
+
+ // Инициализация координат обрабатываемого узла
+ let x2 =
+ (isNaN((buffer = parseInt(_this.element.style.left)))
+ ? 0
+ : buffer) +
+ _this.element.offsetWidth / 2;
+ let y2 =
+ (isNaN((buffer = parseInt(_this.element.style.top))) ? 0 : buffer) +
+ _this.element.offsetHeight / 2;
+
+ // Реинициализация вектора между узлами
+ between = new Victor(x1 - x2, y1 - y2);
+
+ // Инициализация увеличения
+ let increase =
+ (node.diameter + _this.diameter) /
+ 2 ** (_this.increase + node.increase);
+
+ // Узлы преодолели расстояние отталкивания?
+ if (
+ !node.actions.pushing ||
+ between.length() >
+ (node.diameter + _this.diameter) / 2 +
+ distance +
+ increase +
+ (typeof add === "number" ? add : 0) ||
+ --iterations <= 0
+ )
+ return;
+
+ // Инициализация координат вектора (узла с которым произошло столкновение)
+ let vector = new Victor(x1, y1)
+ .add(new Victor(between.x, between.y).norm().unfloat())
+ .subtract(
+ new Victor(
+ node.element.offsetWidth / 2,
+ node.element.offsetHeight / 2
+ )
+ );
+
+ if (node.actions.pushing) {
+ // Активно притягивание узла
+
+ // Запрещение столкновения, притягивания и отталкивания целевого узла и обрабатываемого узла (другими узлами)
+ node.actions.collision = node.actions.pushing = node.actions.pulling = _this.actions.collision = _this.actions.pushing = _this.actions.pulling = false;
+
+ // Запись узлов в реестр задействованных узлов
+ involved.add(_this);
+
+ // Перемещение узла
+ node.move(vector.x, vector.y, involved, involved, involved);
+
+ // Разрешение столкновения, притягивания и отталкивания целевого узла и обрабатываемого узла (другими узлами)
+ node.actions.collision = node.actions.pushing = node.actions.pulling = _this.actions.collision = _this.actions.pushing = _this.actions.pulling = true;
+ }
+
+ // Проверка расстояния
+ if (
+ node.actions.pushing &&
+ between.length() <=
+ (node.diameter + _this.diameter) / 2 +
+ distance +
+ increase +
+ (typeof add === "number" ? add : 0)
+ )
+ setTimeout(move, between.length() / 100);
+ }
+
+ // Повторная обработка (вход в рекурсию)
+ if (node.actions.pushing) move();
+ }
+ }
+
+ pulling(nodes, involved, add) {
+ // Инициализация буфера реестра узлов
+ const registry = new Set(nodes);
+
+ // Удаление текущего узла из буфера
+ registry.delete(this);
+
+ // Инициализация ссылки на ядро
+ const _this = this;
+
+ // Увеличение дистанции для проверки
+ const distance = 150;
+
+ // Обработка притягивания узлов
+ for (const node of registry) {
+ // Перебор узлов в буфере реестра
+
+ // Защита от повторной обработки узла
+ if (involved.has(node)) continue;
+
+ // Инициализация вектора между узлами
+ let between;
+
+ // Инициализация максимального количества итераций
+ let iterations = 30;
+
+ function move() {
+ if (++_this.iteration >= _this.limit) {
+ // Превышено ограничение по числу итераций
+
+ // Сброс счётчика итераций
+ _this.iteration = 0;
+
+ // Конец выполнения
+ return;
+ }
+
+ if (++node.iteration >= node.limit) {
+ // Превышено ограничение по числу итераций
+
+ // Сброс счётчика итераций
+ node.iteration = 0;
+
+ // Конец выполнения
+ return;
+ }
+
+ // Инициализация универсального буфера
+ let buffer;
+
+ // Инициализация координат целевого узла
+ let x1 =
+ (isNaN((buffer = parseInt(node.element.style.left))) ? 0 : buffer) +
+ node.element.offsetWidth / 2;
+ let y1 =
+ (isNaN((buffer = parseInt(node.element.style.top))) ? 0 : buffer) +
+ node.element.offsetHeight / 2;
+
+ // Инициализация координат обрабатываемого узла
+ let x2 =
+ (isNaN((buffer = parseInt(_this.element.style.left)))
+ ? 0
+ : buffer) +
+ _this.element.offsetWidth / 2;
+ let y2 =
+ (isNaN((buffer = parseInt(_this.element.style.top))) ? 0 : buffer) +
+ _this.element.offsetHeight / 2;
+
+ // Реинициализация вектора между узлами
+ between = new Victor(x1 - x2, y1 - y2);
+
+ // Инициализация увеличения
+ let increase =
+ (node.diameter + _this.diameter) /
+ 2 ** (_this.increase + node.increase);
+
+ // Узлы преодолели расстояние притягивания?
+ if (
+ !node.actions.pulling ||
+ between.length() <=
+ (node.diameter + _this.diameter) / 2 +
+ distance +
+ increase +
+ (typeof add === "number" ? add : 0) ||
+ --iterations <= 0
+ )
+ return;
+
+ // Инициализация координат вектора (узла с которым произошло столкновение)
+ let vector = new Victor(x1, y1)
+ .add(new Victor(between.x, between.y).norm().invert().unfloat())
+ .subtract(
+ new Victor(
+ node.element.offsetWidth / 2,
+ node.element.offsetHeight / 2
+ )
+ );
+
+ if (node.actions.pulling) {
+ // Активно притягивание узлов
+
+ // Запрещение столкновения, притягивания и отталкивания целевого узла и обрабатываемого узла (другими узлами)
+ node.actions.collision = node.actions.pushing = node.actions.pulling = _this.actions.collision = _this.actions.pushing = _this.actions.pulling = false;
+
+ // Запись узлов в реестр задействованных узлов
+ involved.add(_this);
+
+ // Перемещение узла
+ node.move(vector.x, vector.y, involved, involved, involved);
+
+ // Разрешение столкновения, притягивания и отталкивания целевого узла и обрабатываемого узла (другими узлами)
+ node.actions.collision = node.actions.pushing = node.actions.pulling = _this.actions.collision = _this.actions.pushing = _this.actions.pulling = true;
+ }
+
+ if (
+ node.actions.pulling &&
+ between.length() >
+ (node.diameter + _this.diameter) / 2 +
+ distance +
+ increase +
+ (typeof add === "number" ? add : 0)
+ )
+ return setTimeout(
+ move,
+ between.length() / 10 - between.length() / 10
+ );
+ }
+
+ // Повторная обработка (вход в рекурсию)
+ if (node.actions.pulling) move();
+ }
+ }
+
+ configure(attribute) {
+ // Инициализация названия параметра
+ const parameter = (/^data-graph-(\w+)$/.exec(attribute) ?? [, null])[1];
+
+ if (typeof parameter === "string") {
+ // Параметр найден
+
+ // Проверка на разрешение изменения
+ if (this.#block.has(parameter)) return;
+
+ // Инициализация значения параметра
+ const value = this.element.getAttribute(attribute);
+
+ if (typeof value !== undefined || typeof value !== null) {
+ // Найдено значение
+
+ // Запрошено изменение координаты: x
+ if (parameter === "x") this.element.style.left = value + "px";
+
+ // Запрошено изменение координаты: y
+ if (parameter === "y") this.element.style.top = value + "px";
+
+ // Инициализация буфера для временных данных
+ let buffer;
+
+ // Запись параметра
+ this[parameter] = isNaN((buffer = parseFloat(value)))
+ ? value === "true"
+ ? true
+ : value === "false"
+ ? false
+ : value
+ : buffer;
+ }
+ }
+ }
+ };
+
+ // Класс узла
+ get node() {
+ return this.#node;
+ }
+
+ // Класс соединения
+ #connection = class connection {
+ // HTML-элемент
+ #element;
+
+ // HTML-элемент
+ get element() {
+ return this.#element;
+ }
+
+ // Инстанция node от которой начинается соединение
+ #from;
+
+ // Инстанция node от которой начинается соединение
+ get from() {
+ return this.#from;
+ }
+
+ // Инстанция node на которой заканчивается соединение
+ #to;
+
+ // Инстанция node на которой заканчивается соединение
+ get to() {
+ return this.#to;
+ }
+
+ // Оператор
+ #operator;
+
+ // Оператор
+ get operator() {
+ return this.#operator;
+ }
+
+ constructor(operator, from, to) {
+ // Запись свойства
+ this.#operator = operator;
+
+ // Запись свойства
+ this.#from = from;
+
+ // Запись свойства
+ this.#to = to;
+
+ // Инициализация оболочки
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
+ svg.id = operator.connections.size;
+ svg.classList.add("connection");
+ svg.setAttribute("data-from", from.element.id);
+ svg.setAttribute("data-to", to.element.id);
+
+ // Инициализация универсального буфера
+ let buffer;
+
+ // Инициализация оболочки
+ const line = document.createElementNS(
+ "http://www.w3.org/2000/svg",
+ "line"
+ );
+ line.setAttribute(
+ "x1",
+ (isNaN((buffer = parseInt(from.element.style.left))) ? 0 : buffer) +
+ from.element.offsetWidth / 2
+ );
+ line.setAttribute(
+ "y1",
+ (isNaN((buffer = parseInt(from.element.style.top))) ? 0 : buffer) +
+ from.element.offsetHeight / 2
+ );
+ line.setAttribute(
+ "x2",
+ (isNaN((buffer = parseInt(to.element.style.left))) ? 0 : buffer) +
+ to.element.offsetWidth / 2
+ );
+ line.setAttribute(
+ "y2",
+ (isNaN((buffer = parseInt(to.element.style.top))) ? 0 : buffer) +
+ to.element.offsetHeight / 2
+ );
+ line.setAttribute("stroke", "grey");
+ line.setAttribute("stroke-width", "8px");
+
+ // Запись свойства
+ this.#element = svg;
+
+ // Запись в оболочку
+ svg.append(line);
+
+ // Запись в документ
+ operator.shell.appendChild(svg);
+ }
+
+ /**
+ * Синхронизировать местоположение со связанным узлом
+ *
+ * @param {node} node Инстанция узла (связанного с соединением)
+ */
+ sync(node) {
+ // Инициализация названий аттрибутов
+ let x = "x",
+ y = "y";
+
+ if (node === this.from) {
+ // Исходящее соединение
+
+ // Запись названий аттрибутов
+ x += 1;
+ y += 1;
+ } else if (node === this.to) {
+ // Входящее соединение
+
+ // Запись названий аттрибутов
+ x += 2;
+ y += 2;
+ } else return;
+
+ // Инициализация универсального буфера
+ let buffer;
+
+ // Запись отступа (координаты по горизонтали)
+ this.element.children[0].setAttribute(
+ x,
+ (isNaN((buffer = parseInt(node.element.style.left))) ? 0 : buffer) +
+ node.element.offsetWidth / 2
+ );
+
+ // Запись отступа (координаты по вертикали)
+ this.element.children[0].setAttribute(
+ y,
+ (isNaN((buffer = parseInt(node.element.style.top))) ? 0 : buffer) +
+ node.element.offsetHeight / 2
+ );
+ }
+ };
+
+ // Класс соединения
+ get connection() {
+ return this.#connection;
+ }
+
+ #move = true;
+ #camera = true;
+
+ constructor(shell, camera = true) {
+ // Запись оболочки
+ if (shell instanceof HTMLElement) this.#shell = shell;
+
+ // Инициализация ссылки на обрабатываемый объект
+ const _this = this;
+
+ // Перемещение камеры
+ if (camera === true) {
+ this.shell.onmousedown = function (e) {
+ // Начало переноса
+
+ if (_this.#camera) {
+ // Разрешено двигать камеру (оболочку)
+
+ // Инициализация координат
+ const coords = _this.shell.getBoundingClientRect();
+ const x = e.pageX - coords.left + pageXOffset;
+ const y = e.pageY - coords.top + pageYOffset;
+
+ // Инициализация функции переноса полотна
+ function move(onmousemove) {
+ // Запись нового отступа от лева
+ _this.shell.style.left = onmousemove.pageX - x + "px";
+
+ // Запись нового отступа от верха
+ _this.shell.style.top = onmousemove.pageY - y + "px";
+ }
+
+ // Запись слушателя события: "перенос полотна"
+ document.onmousemove = move;
+ }
+
+ // Конец переноса
+ _this.shell.onmouseup = function () {
+ document.onmousemove = null;
+ _this.shell.onmouseup = null;
+ };
+ };
+
+ // Блокировка событий браузера (чтобы не дёргалось)
+ _this.shell.ondragstart = null;
+ }
+ }
+
+ write = function (data = {}) {
+ if (typeof data === "object") {
+ // Получен обязательный входной параметр в правильном типе
+
+ // Инициализация узла
+ const node = new this.node(this, data);
+
+ // Инициализация ссылки на обрабатываемый объект
+ const _this = this;
+
+ // Запрет движения камеры при наведении на узел (чтобы двигать узел)
+ node.element.onmouseover = function (e) {
+ _this.#camera = false;
+ };
+
+ // Снятие запрета движения камеры
+ node.element.onmouseout = function (e) {
+ _this.#camera = true;
+ };
+
+ if (this.#move) {
+ // Разрешено перемещать узлы
+
+ node.element.onmousedown = function (onmousedown) {
+ // Начало переноса
+
+ // Инициализация буфера позиционирования
+ const z = node.element.style.zIndex;
+
+ // Позиционирование над остальными узлами
+ node.element.style.zIndex = 5000;
+
+ if (!_this.#camera) {
+ // Запрещено двигать камеру (оболочку)
+
+ // Инициализация координат
+ const n = node.element.getBoundingClientRect();
+ const s = _this.shell.getBoundingClientRect();
+
+ // Инициализация функции переноса узла
+ function move(onmousemove) {
+ // Запись обработки столкновений и отталкивания
+ node.actions.collision = node.actions.pushing = node.actions.pulling = false;
+
+ // Перемещение
+ node.move(
+ onmousemove.pageX -
+ (onmousedown.pageX - n.left + s.left + pageXOffset),
+ onmousemove.pageY -
+ (onmousedown.pageY - n.top + s.top + pageYOffset),
+ true,
+ true,
+ true
+ );
+ }
+
+ // Запись слушателя события: "перенос узла"
+ document.onmousemove = move;
+ }
+
+ // Конец переноса
+ node.element.onmouseup = function () {
+ // Очистка обработчиков событий
+ document.onmousemove = null;
+ node.element.onmouseup = null;
+
+ // Запись обработки столкновений и отталкивания
+ node.actions.collision = node.actions.pushing = node.actions.pulling = true;
+
+ // Возвращение позиционирования
+ node.element.style.zIndex = z;
+ };
+ };
+
+ // Перещапись событий браузера (чтобы не дёргалось)
+ node.element.ondragstart = null;
+ }
+
+ // Запись в реестр
+ this.nodes.add(node);
+
+ return node;
+ }
+ };
+
+ connect = function (from, to) {
+ if (from instanceof this.node && to instanceof this.node) {
+ // Получены обязательные входные параметры в правильном типе
+
+ // Инициализация соединения
+ const connection = new this.connection(this, from, to);
+
+ // Запись соединений в реестры узлов
+ from.outputs.add(connection);
+ to.inputs.add(connection);
+
+ // Запись в реестр ядра
+ this.connections.add(connection);
+
+ // Реинициализация узла-получателя
+ to.init(1);
+
+ return connection;
+ }
+ };
+}
+
+document.dispatchEvent(
+ new CustomEvent("graph.loaded", {
+ detail: { graph }
+ })
+);
diff --git a/mirzaev/site/wanda/system/public/js/hotline.js b/mirzaev/site/wanda/system/public/js/hotline.js
new file mode 100644
index 0000000..8eddb69
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/js/hotline.js
@@ -0,0 +1,668 @@
+'use strict';
+
+/**
+ * Бегущая строка
+ *
+ * @description
+ * Простой, но мощный класс для создания бегущих строк. Поддерживает
+ * перемещение мышью и прокрутку колесом, полностью настраивается очень гибок
+ * для настроек в CSS и подразумевается, что отлично индексируется поисковыми роботами.
+ * Имеет свой препроцессор, благодаря которому можно создавать бегущие строки
+ * без программирования - с помощью HTML-аттрибутов, а так же возможность
+ * изменять параметры (data-hotline-* аттрибуты) на лету. Есть возможность вызывать
+ * события при выбранных действиях для того, чтобы пользователь имел возможность
+ * дорабатывать функционал без изучения и изменения моего кода
+ *
+ * @example
+ * сonst hotline = new hotline();
+ * hotline.step = '-5';
+ * hotline.start();
+ *
+ * @todo
+ * 1. Бесконечный режим - элементы не удаляются если видны на экране (будут дубликаты)
+ *
+ * @copyright WTFPL
+ * @author Arsen Mirzaev Tatyano-Muradovich
+ */
+class hotline {
+ // Идентификатор
+ #id = 0;
+
+ // Оболочка (instanceof HTMLElement)
+ #shell = document.getElementById("hotline");
+
+ // Инстанция горячей строки
+ #instance = null;
+
+ // Перемещение
+ #transfer = true;
+
+ // Движение
+ #move = true;
+
+ // Наблюдатель
+ #observer = null;
+
+ // Наблюдатель
+ #block = new Set(["events"]);
+
+ // Настраиваемые параметры
+ transfer = null;
+ move = null;
+ delay = 10;
+ step = 1;
+ hover = true;
+ movable = true;
+ sticky = false;
+ wheel = false;
+ delta = null;
+ vertical = false;
+ observe = false;
+ events = new Map([
+ ["start", false],
+ ["stop", false],
+ ["move", false],
+ ["move.block", false],
+ ["move.unblock", false],
+ ["offset", false],
+ ["transfer.start", true],
+ ["transfer.end", true],
+ ["onmousemove", false]
+ ]);
+
+ constructor(id, shell) {
+ // Запись идентификатора
+ if (typeof id === "string" || typeof id === "number") this.#id = id;
+
+ // Запись оболочки
+ if (shell instanceof HTMLElement) this.#shell = shell;
+ }
+
+ start() {
+ if (this.#instance === null) {
+ // Нет запущенной инстанции бегущей строки
+
+ // Инициализация ссылки на ядро
+ const _this = this;
+
+ // Запуск движения
+ this.#instance = setInterval(function () {
+ if (_this.#shell.childElementCount > 1) {
+ // Найдено содержимое бегущей строки (2 и более)
+
+ // Инициализация буфера для временных данных
+ let buffer;
+
+ // Инициализация данных первого элемента в строке
+ const first = {
+ element: (buffer = _this.#shell.firstElementChild),
+ coords: buffer.getBoundingClientRect()
+ };
+
+ if (_this.vertical) {
+ // Вертикальная бегущая строка
+
+ // Инициализация сдвига у первого элемента (движение)
+ first.offset = isNaN(
+ (buffer = parseFloat(first.element.style.marginTop))
+ )
+ ? 0
+ : buffer;
+
+ // Инициализация отступа до второго элемента у первого элемента (разделение)
+ first.separator = isNaN(
+ (buffer = parseFloat(
+ getComputedStyle(first.element).marginBottom
+ ))
+ )
+ ? 0
+ : buffer;
+
+ // Инициализация крайнего с конца ребра первого элемента в строке
+ first.end = first.coords.y + first.coords.height + first.separator;
+ } else {
+ // Горизонтальная бегущая строка
+
+ // Инициализация отступа у первого элемента (движение)
+ first.offset = isNaN(
+ (buffer = parseFloat(first.element.style.marginLeft))
+ )
+ ? 0
+ : buffer;
+
+ // Инициализация отступа до второго элемента у первого элемента (разделение)
+ first.separator = isNaN(
+ (buffer = parseFloat(getComputedStyle(first.element).marginRight))
+ )
+ ? 0
+ : buffer;
+
+ // Инициализация крайнего с конца ребра первого элемента в строке
+ first.end = first.coords.x + first.coords.width + first.separator;
+ }
+
+ if (
+ (_this.vertical &&
+ Math.round(first.end) < _this.#shell.offsetTop) ||
+ (!_this.vertical && Math.round(first.end) < _this.#shell.offsetLeft)
+ ) {
+ // Элемент (вместе с отступом до второго элемента) вышел из области видимости (строки)
+
+ if (
+ (_this.transfer === null && _this.#transfer) ||
+ _this.transfer === true
+ ) {
+ // Перенос разрешен
+
+ if (_this.vertical) {
+ // Вертикальная бегущая строка
+
+ // Удаление отступов (движения)
+ first.element.style.marginTop = null;
+ } else {
+ // Горизонтальная бегущая строка
+
+ // Удаление отступов (движения)
+ first.element.style.marginLeft = null;
+ }
+
+ // Копирование первого элемента в конец строки
+ _this.#shell.appendChild(first.element);
+
+ if (_this.events.get("transfer.end")) {
+ // Запрошен вызов события: "перемещение в конец"
+
+ // Вызов события: "перемещение в конец"
+ document.dispatchEvent(
+ new CustomEvent(`hotline.${_this.#id}.transfer.end`, {
+ detail: {
+ element: first.element,
+ offset: -(
+ (_this.vertical
+ ? first.coords.height
+ : first.coords.width) + first.separator
+ )
+ }
+ })
+ );
+ }
+ }
+ } else if (
+ (_this.vertical &&
+ Math.round(first.coords.y) > _this.#shell.offsetTop) ||
+ (!_this.vertical &&
+ Math.round(first.coords.x) > _this.#shell.offsetLeft)
+ ) {
+ // Передняя (движущая) граница первого элемента вышла из области видимости
+
+ if (
+ (_this.transfer === null && _this.#transfer) ||
+ _this.transfer === true
+ ) {
+ // Перенос разрешен
+
+ // Инициализация отступа у последнего элемента (разделение)
+ const separator =
+ (buffer = isNaN(
+ (buffer = parseFloat(
+ getComputedStyle(_this.#shell.lastElementChild)[
+ _this.vertical ? "marginBottom" : "marginRight"
+ ]
+ ))
+ )
+ ? 0
+ : buffer) === 0
+ ? first.separator
+ : buffer;
+
+ // Инициализация координат первого элемента в строке
+ const coords = _this.#shell.lastElementChild.getBoundingClientRect();
+
+ if (_this.vertical) {
+ // Вертикальная бегущая строка
+
+ // Удаление отступов (движения)
+ _this.#shell.lastElementChild.style.marginTop =
+ -coords.height - separator + "px";
+ } else {
+ // Горизонтальная бегущая строка
+
+ // Удаление отступов (движения)
+ _this.#shell.lastElementChild.style.marginLeft =
+ -coords.width - separator + "px";
+ }
+
+ // Копирование последнего элемента в начало строки
+ _this.#shell.insertBefore(
+ _this.#shell.lastElementChild,
+ first.element
+ );
+
+ // Удаление отступов у второго элемента в строке (движения)
+ _this.#shell.children[1].style[
+ _this.vertical ? "marginTop" : "marginLeft"
+ ] = null;
+
+ if (_this.events.get("transfer.start")) {
+ // Запрошен вызов события: "перемещение в начало"
+
+ // Вызов события: "перемещение в начало"
+ document.dispatchEvent(
+ new CustomEvent(`hotline.${_this.#id}.transfer.start`, {
+ detail: {
+ element: _this.#shell.lastElementChild,
+ offset:
+ (_this.vertical ? coords.height : coords.width) +
+ separator
+ }
+ })
+ );
+ }
+ }
+ } else {
+ // Элемент в области видимости
+
+ if ((_this.move === null && _this.#move) || _this.move === true) {
+ // Движение разрешено
+
+ // Запись новых координат сдвига
+ const offset = first.offset + _this.step;
+
+ // Запись сдвига (движение)
+ _this.offset(offset);
+
+ if (_this.events.get("move")) {
+ // Запрошен вызов события: "движение"
+
+ // Вызов события: "движение"
+ document.dispatchEvent(
+ new CustomEvent(`hotline.${_this.#id}.move`, {
+ detail: {
+ from: first.offset,
+ to: offset
+ }
+ })
+ );
+ }
+ }
+ }
+ }
+ }, _this.delay);
+
+ if (this.hover) {
+ // Запрошена возможность останавливать бегущую строку
+
+ // Инициализация сдвига
+ let offset = 0;
+
+ // Инициализация слушателя события при перемещении элемента в бегущей строке
+ const listener = function (e) {
+ // Увеличение сдвига
+ offset += e.detail.offset ?? 0;
+ };
+
+ // Инициализация обработчика наведения курсора (остановка движения)
+ this.#shell.onmouseover = function (e) {
+ // Курсор наведён на бегущую строку
+
+ // Блокировка движения
+ _this.#move = false;
+
+ if (_this.events.get("move.block")) {
+ // Запрошен вызов события: "блокировка движения"
+
+ // Вызов события: "блокировка движения"
+ document.dispatchEvent(
+ new CustomEvent(`hotline.${_this.#id}.move.block`)
+ );
+ }
+
+ if (_this.movable) {
+ // Запрошена возможность двигать бегущую строку
+
+ _this.#shell.onmousedown = function (onmousedown) {
+ // Курсор активирован
+
+ // Инициализация слушателей события перемещения элемента в бегущей строке
+ document.addEventListener(
+ `hotline.${_this.#id}.transfer.start`,
+ listener
+ );
+ document.addEventListener(
+ `hotline.${_this.#id}.transfer.end`,
+ listener
+ );
+
+ // Инициализация буфера для временных данных
+ let buffer;
+
+ // Инициализация данных первого элемента в строке
+ const first = {
+ offset: isNaN(
+ (buffer = parseFloat(
+ _this.vertical
+ ? _this.#shell.firstElementChild.style.marginTop
+ : _this.#shell.firstElementChild.style.marginLeft
+ ))
+ )
+ ? 0
+ : buffer
+ };
+
+ document.onmousemove = function (onmousemove) {
+ // Курсор движется
+
+ if (_this.vertical) {
+ // Вертикальная бегущая строка
+
+ // Инициализация буфера местоположения
+ const from = _this.#shell.firstElementChild.style.marginTop;
+ const to = onmousemove.pageY - (onmousedown.pageY + offset - first.offset);
+
+ // Движение
+ _this.#shell.firstElementChild.style.marginTop = to +
+ "px";
+
+ if (_this.events.get("onmousemove")) {
+ // Запрошен вызов события: "перемещение мышью"
+
+ // Вызов события: "перемещение мышью"
+ document.dispatchEvent(
+ new CustomEvent(`hotline.${_this.#id}.onmousemove`, {
+ detail: { from, to }
+ })
+ );
+ }
+ } else {
+ // Горизонтальная бегущая строка
+
+ // Инициализация буфера местоположения
+ const from = _this.#shell.firstElementChild.style.marginLeft;
+ const to = onmousemove.pageX - (onmousedown.pageX + offset - first.offset);
+
+ // Движение
+ _this.#shell.firstElementChild.style.marginLeft = to + "px";
+
+ if (_this.events.get("onmousemove")) {
+ // Запрошен вызов события: "перемещение мышью"
+
+ // Вызов события: "перемещение мышью"
+ document.dispatchEvent(
+ new CustomEvent(`hotline.${_this.#id}.onmousemove`, {
+ detail: { from, to }
+ })
+ );
+ }
+ }
+
+ // Запись курсора
+ _this.#shell.style.cursor = "grabbing";
+ };
+ };
+
+ // Перещапись событий браузера (чтобы не дёргалось)
+ _this.#shell.ondragstart = null;
+
+ _this.#shell.onmouseup = function () {
+ // Курсор деактивирован
+
+ // Остановка обработки движения
+ document.onmousemove = null;
+
+ // Сброс сдвига
+ offset = 0;
+
+ document.removeEventListener(
+ `hotline.${_this.#id}.transfer.start`,
+ listener
+ );
+ document.removeEventListener(
+ `hotline.${_this.#id}.transfer.end`,
+ listener
+ );
+
+ // Восстановление курсора
+ _this.#shell.style.cursor = null;
+ };
+ }
+ };
+
+ // Инициализация обработчика отведения курсора (остановка движения)
+ this.#shell.onmouseleave = function (onmouseleave) {
+ // Курсор отведён от бегущей строки
+
+ if (!_this.sticky) {
+ // Отключено прилипание
+
+ // Остановка обработки движения
+ document.onmousemove = null;
+
+ document.removeEventListener(
+ `hotline.${_this.#id}.transfer.start`,
+ listener
+ );
+ document.removeEventListener(
+ `hotline.${_this.#id}.transfer.end`,
+ listener
+ );
+
+ // Восстановление курсора
+ _this.#shell.style.cursor = null;
+ }
+
+ // Сброс сдвига
+ offset = 0;
+
+ // Разблокировка движения
+ _this.#move = true;
+
+ if (_this.events.get("move.unblock")) {
+ // Запрошен вызов события: "разблокировка движения"
+
+ // Вызов события: "разблокировка движения"
+ document.dispatchEvent(
+ new CustomEvent(`hotline.${_this.#id}.move.unblock`)
+ );
+ }
+ };
+ }
+
+ if (this.wheel) {
+ // Запрошена возможность прокручивать колесом мыши
+
+ // Инициализация обработчика наведения курсора (остановка движения)
+ this.#shell.onwheel = function (e) {
+ // Курсор наведён на бегущую
+
+ // Инициализация буфера для временных данных
+ let buffer;
+
+ // Перемещение
+ _this.offset(
+ (isNaN(
+ (buffer = parseFloat(
+ _this.#shell.firstElementChild.style[
+ _this.vertical ? "marginTop" : "marginLeft"
+ ]
+ ))
+ )
+ ? 0
+ : buffer) +
+ (_this.delta === null
+ ? e.wheelDelta
+ : e.wheelDelta > 0
+ ? _this.delta
+ : -_this.delta)
+ );
+ };
+ }
+ }
+
+ if (this.observe) {
+ // Запрошено наблюдение за изменениями аттрибутов элемента бегущей строки
+
+ if (this.#observer === null) {
+ // Отсутствует наблюдатель
+
+ // Инициализация ссылки на ядро
+ const _this = this;
+
+ // Инициализация наблюдателя
+ this.#observer = new MutationObserver(function (mutations) {
+ for (const mutation of mutations) {
+ if (mutation.type === "attributes") {
+ // Запись параметра в инстанцию бегущей строки
+ _this.write(mutation.attributeName);
+ }
+ }
+
+ // Перезапуск бегущей строки
+ _this.restart();
+ });
+
+ // Активация наблюдения
+ this.#observer.observe(this.#shell, {
+ attributes: true
+ });
+ }
+ } else if (this.#observer instanceof MutationObserver) {
+ // Запрошено отключение наблюдения
+
+ // Деактивация наблюдения
+ this.#observer.disconnect();
+
+ // Удаление наблюдателя
+ this.#observer = null;
+ }
+
+ if (this.events.get("start")) {
+ // Запрошен вызов события: "запуск"
+
+ // Вызов события: "запуск"
+ document.dispatchEvent(new CustomEvent(`hotline.${this.#id}.start`));
+ }
+ }
+
+ stop() {
+ // Остановка бегущей строки
+ clearInterval(this.#instance);
+
+ // Удаление инстанции интервала
+ this.#instance = null;
+
+ if (this.events.get("stop")) {
+ // Запрошен вызов события: "остановка"
+
+ // Вызов события: "остановка"
+ document.dispatchEvent(new CustomEvent(`hotline.${this.#id}.stop`));
+ }
+ }
+
+ restart() {
+ // Остановка бегущей строки
+ this.stop();
+
+ // Запуск бегущей строки
+ this.start();
+ }
+
+ write(attribute) {
+ // Инициализация названия параметра
+ const parameter = (/^data-hotline-(\w+)$/.exec(attribute) ?? [, null])[1];
+
+ if (typeof parameter === "string") {
+ // Параметр найден
+
+ // Проверка на разрешение изменения
+ if (this.#block.has(parameter)) return;
+
+ // Инициализация значения параметра
+ const value = this.#shell.getAttribute(attribute);
+
+ // Инициализация буфера для временных данных
+ let buffer;
+
+ // Запись параметра
+ this[parameter] = isNaN((buffer = parseFloat(value)))
+ ? value === "true"
+ ? true
+ : value === "false"
+ ? false
+ : value
+ : buffer;
+ }
+ }
+
+ offset(value) {
+ // Запись отступа
+ this.#shell.firstElementChild.style[
+ this.vertical ? "marginTop" : "marginLeft"
+ ] = value + "px";
+
+ if (this.events.get("offset")) {
+ // Запрошен вызов события: "сдвиг"
+
+ // Вызов события: "сдвиг"
+ document.dispatchEvent(
+ new CustomEvent(`hotline.${this.#id}.offset`, {
+ detail: {
+ to: value
+ }
+ })
+ );
+ }
+ }
+
+ static preprocessing(event = false) {
+ // Инициализация счётчиков инстанций горячей строки
+ const success = new Set();
+ let error = 0;
+
+ for (const element of document.querySelectorAll('*[data-hotline="true"]')) {
+ // Перебор бегущих строк
+
+ if (typeof element.id === "string") {
+ // Найден идентификатор
+
+ // Инициализация инстанции бегущей строки
+ const hotline = new this(element.id, element);
+
+ for (const attribute of element.getAttributeNames()) {
+ // Перебор аттрибутов
+
+ // Запись параметра в инстанцию бегущей строки
+ hotline.write(attribute);
+ }
+
+ // Запуск бегущей строки
+ hotline.start();
+
+ // Запись инстанции бегущей строки в элемент
+ element.hotline = hotline;
+
+ // Запись в счётчик успешных инициализаций
+ success.add(hotline);
+ } else ++error;
+ }
+
+ if (event) {
+ // Запрошен вызов события: "предварительная подготовка"
+
+ // Вызов события: "предварительная подготовка"
+ document.dispatchEvent(
+ new CustomEvent(`hotline.preprocessed`, {
+ detail: {
+ success,
+ error
+ }
+ })
+ );
+ }
+ }
+}
+
+document.dispatchEvent(
+ new CustomEvent("hotline.loaded", {
+ detail: { hotline }
+ })
+);
diff --git a/mirzaev/site/wanda/system/public/js/js.cookie.min.js b/mirzaev/site/wanda/system/public/js/js.cookie.min.js
new file mode 100644
index 0000000..90a7672
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/js/js.cookie.min.js
@@ -0,0 +1,2 @@
+/*! js-cookie v3.0.1 | MIT */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self,function(){var n=e.Cookies,o=e.Cookies=t();o.noConflict=function(){return e.Cookies=n,o}}())}(this,(function(){"use strict";function e(e){for(var t=1;t 0.90) {
+ // 10%
+
+ troller.what.start();
+ // }
+ };
+
+ document.body.onmouseenter = function () {
+ troller.what.end();
+ };
+ },
+ disable() {
+ document.body.onmouseleave = document.body.onmouseenter = undefined;
+ },
+ start() {
+ // Отображение изображения
+ document.getElementById('what_image').classList.add('active');
+
+ // Инициализация элемента со звуком
+ const what_sound = document.getElementById('what_sound');
+
+ // Воспроизведение звука
+ what_sound.currentTime = 0;
+ what_sound.play();
+ },
+ end() {
+ // Сокрытие изображения
+ document.getElementById('what_image').classList.remove('active');
+
+ // Остановка звука
+ document.getElementById('what_sound').pause();
+ },
+ single(event = 'onmouseleave') {
+ if (typeof event === 'string') {
+ // Получены обязательные входные параметры
+ // Отображение изображения
+ document.getElementById('what_image').classList.add('active');
+
+ // Инициализация элемента со звуком
+ const what_sound = document.getElementById('what_sound');
+
+ // Воспроизведение звука
+ what_sound.currentTime = 0;
+ what_sound.play();
+
+ document.body[event] = function () {
+ troller.what.end();
+
+ document.body[event] = undefined;
+ };
+ }
+ }
+ }
+
+ static vk() {
+ setInterval(function () {
+ const sound = document.getElementById('sound_vk');
+
+ if (Math.random() > 0.95) {
+ // 5%
+
+ // Воспроизведение звука
+ sound.currentTime = 0;
+ sound.play();
+ }
+ }, 85000);
+ }
+
+ static whatsapp() {
+ setInterval(function () {
+ const sound = document.getElementById('sound_whatsup');
+
+ if (Math.random() > 0.97) {
+ // 3%
+
+ // Воспроизведение звука
+ sound.currentTime = 0;
+ sound.play();
+ }
+ }, 125000);
+ }
+
+ static iphone() {
+ setInterval(function () {
+ const sound = document.getElementById('sound_iphone');
+
+ if (Math.random() > 0.98) {
+ // 2%
+
+ // Воспроизведение звука
+ sound.currentTime = 0;
+ sound.play();
+ }
+ }, 265000);
+ }
+}
+
+if (Math.random() > 0.90) {
+ // 10%
+
+ troller.what.enable();
+}
+
+if (Math.random() > 0.90) {
+ // 10%
+
+ troller.vk();
+}
+
+
+if (Math.random() > 0.90) {
+ // 10%
+
+ troller.whatsapp();
+}
+
+if (Math.random() > 0.90) {
+ // 10%
+
+ troller.iphone();
+}
diff --git a/mirzaev/site/wanda/system/public/js/victor.js b/mirzaev/site/wanda/system/public/js/victor.js
new file mode 100644
index 0000000..f54d570
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/js/victor.js
@@ -0,0 +1 @@
+!function(t){if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else{var i;"undefined"!=typeof window?i=window:"undefined"!=typeof global?i=global:"undefined"!=typeof self&&(i=self),i.Victor=t()}}(function(){return function t(i,r,n){function o(s,h){if(!r[s]){if(!i[s]){var u="function"==typeof require&&require;if(!h&&u)return u(s,!0);if(e)return e(s,!0);throw new Error("Cannot find module '"+s+"'")}var p=r[s]={exports:{}};i[s][0].call(p.exports,function(t){var r=i[s][1][t];return o(r?r:t)},p,p.exports,t,i,r,n)}return r[s].exports}for(var e="function"==typeof require&&require,s=0;st&&(this.x*=i),Math.abs(this.y)>t&&(this.y*=i),this},n.prototype.randomize=function(t,i){return this.randomizeX(t,i),this.randomizeY(t,i),this},n.prototype.randomizeX=function(t,i){var r=Math.min(t.x,i.x),n=Math.max(t.x,i.x);return this.x=o(r,n),this},n.prototype.randomizeY=function(t,i){var r=Math.min(t.y,i.y),n=Math.max(t.y,i.y);return this.y=o(r,n),this},n.prototype.randomizeAny=function(t,i){return Math.round(Math.random())?this.randomizeX(t,i):this.randomizeY(t,i),this},n.prototype.unfloat=function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},n.prototype.toFixed=function(t){return"undefined"==typeof t&&(t=8),this.x=this.x.toFixed(t),this.y=this.y.toFixed(t),this},n.prototype.mixX=function(t,i){return"undefined"==typeof i&&(i=.5),this.x=(1-i)*this.x+i*t.x,this},n.prototype.mixY=function(t,i){return"undefined"==typeof i&&(i=.5),this.y=(1-i)*this.y+i*t.y,this},n.prototype.mix=function(t,i){return this.mixX(t,i),this.mixY(t,i),this},n.prototype.clone=function(){return new n(this.x,this.y)},n.prototype.copyX=function(t){return this.x=t.x,this},n.prototype.copyY=function(t){return this.y=t.y,this},n.prototype.copy=function(t){return this.copyX(t),this.copyY(t),this},n.prototype.zero=function(){return this.x=this.y=0,this},n.prototype.dot=function(t){return this.x*t.x+this.y*t.y},n.prototype.cross=function(t){return this.x*t.y-this.y*t.x},n.prototype.projectOnto=function(t){var i=(this.x*t.x+this.y*t.y)/(t.x*t.x+t.y*t.y);return this.x=i*t.x,this.y=i*t.y,this},n.prototype.horizontalAngle=function(){return Math.atan2(this.y,this.x)},n.prototype.horizontalAngleDeg=function(){return e(this.horizontalAngle())},n.prototype.verticalAngle=function(){return Math.atan2(this.x,this.y)},n.prototype.verticalAngleDeg=function(){return e(this.verticalAngle())},n.prototype.angle=n.prototype.horizontalAngle,n.prototype.angleDeg=n.prototype.horizontalAngleDeg,n.prototype.direction=n.prototype.horizontalAngle,n.prototype.rotate=function(t){var i=this.x*Math.cos(t)-this.y*Math.sin(t),r=this.x*Math.sin(t)+this.y*Math.cos(t);return this.x=i,this.y=r,this},n.prototype.rotateDeg=function(t){return t=s(t),this.rotate(t)},n.prototype.rotateTo=function(t){return this.rotate(t-this.angle())},n.prototype.rotateToDeg=function(t){return t=s(t),this.rotateTo(t)},n.prototype.rotateBy=function(t){var i=this.angle()+t;return this.rotate(i)},n.prototype.rotateByDeg=function(t){return t=s(t),this.rotateBy(t)},n.prototype.distanceX=function(t){return this.x-t.x},n.prototype.absDistanceX=function(t){return Math.abs(this.distanceX(t))},n.prototype.distanceY=function(t){return this.y-t.y},n.prototype.absDistanceY=function(t){return Math.abs(this.distanceY(t))},n.prototype.distance=function(t){return Math.sqrt(this.distanceSq(t))},n.prototype.distanceSq=function(t){var i=this.distanceX(t),r=this.distanceY(t);return i*i+r*r},n.prototype.length=function(){return Math.sqrt(this.lengthSq())},n.prototype.lengthSq=function(){return this.x*this.x+this.y*this.y},n.prototype.magnitude=n.prototype.length,n.prototype.isZero=function(){return 0===this.x&&0===this.y},n.prototype.isEqualTo=function(t){return this.x===t.x&&this.y===t.y},n.prototype.toString=function(){return"x:"+this.x+", y:"+this.y},n.prototype.toArray=function(){return[this.x,this.y]},n.prototype.toObject=function(){return{x:this.x,y:this.y}};var h=180/Math.PI},{}]},{},[1])(1)});
diff --git a/mirzaev/site/wanda/system/public/manifest.json b/mirzaev/site/wanda/system/public/manifest.json
new file mode 100644
index 0000000..013d4a6
--- /dev/null
+++ b/mirzaev/site/wanda/system/public/manifest.json
@@ -0,0 +1,41 @@
+{
+ "name": "App",
+ "icons": [
+ {
+ "src": "\/android-icon-36x36.png",
+ "sizes": "36x36",
+ "type": "image\/png",
+ "density": "0.75"
+ },
+ {
+ "src": "\/android-icon-48x48.png",
+ "sizes": "48x48",
+ "type": "image\/png",
+ "density": "1.0"
+ },
+ {
+ "src": "\/android-icon-72x72.png",
+ "sizes": "72x72",
+ "type": "image\/png",
+ "density": "1.5"
+ },
+ {
+ "src": "\/android-icon-96x96.png",
+ "sizes": "96x96",
+ "type": "image\/png",
+ "density": "2.0"
+ },
+ {
+ "src": "\/android-icon-144x144.png",
+ "sizes": "144x144",
+ "type": "image\/png",
+ "density": "3.0"
+ },
+ {
+ "src": "\/android-icon-192x192.png",
+ "sizes": "192x192",
+ "type": "image\/png",
+ "density": "4.0"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/mirzaev/site/wanda/system/public/ms-icon-144x144.png b/mirzaev/site/wanda/system/public/ms-icon-144x144.png
new file mode 100644
index 0000000..70b045c
Binary files /dev/null and b/mirzaev/site/wanda/system/public/ms-icon-144x144.png differ
diff --git a/mirzaev/site/wanda/system/public/ms-icon-150x150.png b/mirzaev/site/wanda/system/public/ms-icon-150x150.png
new file mode 100644
index 0000000..ce5f135
Binary files /dev/null and b/mirzaev/site/wanda/system/public/ms-icon-150x150.png differ
diff --git a/mirzaev/site/wanda/system/public/ms-icon-310x310.png b/mirzaev/site/wanda/system/public/ms-icon-310x310.png
new file mode 100644
index 0000000..c5e47e9
Binary files /dev/null and b/mirzaev/site/wanda/system/public/ms-icon-310x310.png differ
diff --git a/mirzaev/site/wanda/system/public/ms-icon-70x70.png b/mirzaev/site/wanda/system/public/ms-icon-70x70.png
new file mode 100644
index 0000000..536df03
Binary files /dev/null and b/mirzaev/site/wanda/system/public/ms-icon-70x70.png differ
diff --git a/mirzaev/site/wanda/system/public/sounds/iphone.mp3 b/mirzaev/site/wanda/system/public/sounds/iphone.mp3
new file mode 100644
index 0000000..f992318
Binary files /dev/null and b/mirzaev/site/wanda/system/public/sounds/iphone.mp3 differ
diff --git a/mirzaev/site/wanda/system/public/sounds/vk.mp3 b/mirzaev/site/wanda/system/public/sounds/vk.mp3
new file mode 100644
index 0000000..b166b2f
Binary files /dev/null and b/mirzaev/site/wanda/system/public/sounds/vk.mp3 differ
diff --git a/mirzaev/site/wanda/system/public/sounds/what.mp3 b/mirzaev/site/wanda/system/public/sounds/what.mp3
new file mode 100644
index 0000000..eec8939
Binary files /dev/null and b/mirzaev/site/wanda/system/public/sounds/what.mp3 differ
diff --git a/mirzaev/site/wanda/system/public/sounds/whatsup.mp3 b/mirzaev/site/wanda/system/public/sounds/whatsup.mp3
new file mode 100644
index 0000000..9c49d9d
Binary files /dev/null and b/mirzaev/site/wanda/system/public/sounds/whatsup.mp3 differ
diff --git a/mirzaev/site/wanda/system/public/storage/214547089/avatar/200x200.jpg b/mirzaev/site/wanda/system/public/storage/214547089/avatar/200x200.jpg
new file mode 100644
index 0000000..cfd288e
Binary files /dev/null and b/mirzaev/site/wanda/system/public/storage/214547089/avatar/200x200.jpg differ
diff --git a/mirzaev/site/wanda/system/settings/.gitignore b/mirzaev/site/wanda/system/settings/.gitignore
new file mode 100644
index 0000000..dac8cf6
--- /dev/null
+++ b/mirzaev/site/wanda/system/settings/.gitignore
@@ -0,0 +1 @@
+arangodb.php
diff --git a/mirzaev/site/wanda/system/settings/arangodb.php.sample b/mirzaev/site/wanda/system/settings/arangodb.php.sample
new file mode 100644
index 0000000..fc1c2d1
--- /dev/null
+++ b/mirzaev/site/wanda/system/settings/arangodb.php.sample
@@ -0,0 +1,8 @@
+ 'unix:///var/run/arangodb3/arango.sock',
+ 'database' => '',
+ 'name' => '',
+ 'password' => ''
+];
diff --git a/mirzaev/site/wanda/system/views/core.html b/mirzaev/site/wanda/system/views/core.html
new file mode 100644
index 0000000..980565d
--- /dev/null
+++ b/mirzaev/site/wanda/system/views/core.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+ {% use 'head.html' with title as head_title, meta as head_meta, css as head_css %}
+
+ {% block title %}
+ {{ block('head_title') }}
+ {% endblock %}
+
+ {% block meta %}
+ {{ block('head_meta') }}
+ {% endblock %}
+
+ {% block css %}
+ {{ block('head_css') }}
+ {% endblock %}
+
+
+
+ {% block body %}
+ {% endblock %}
+
+ {% block js %}
+ {% include 'js.html' %}
+ {% endblock %}
+
+ {% block js_init %}
+ {% endblock %}
+
+
+
diff --git a/mirzaev/site/wanda/system/views/head.html b/mirzaev/site/wanda/system/views/head.html
new file mode 100644
index 0000000..4b1bc8d
--- /dev/null
+++ b/mirzaev/site/wanda/system/views/head.html
@@ -0,0 +1,39 @@
+{% block title %}
+{% if head.title != empty %}{{head.title}}{% else %}Сайт про Ванду{% endif %}
+{% endblock %}
+
+{% block meta %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% for meta in head.metas %}
+
+{% endfor %}
+{% endblock %}
+
+{% block css %}
+
+{% endblock %}
diff --git a/mirzaev/site/wanda/system/views/index.html b/mirzaev/site/wanda/system/views/index.html
new file mode 100644
index 0000000..dee3711
--- /dev/null
+++ b/mirzaev/site/wanda/system/views/index.html
@@ -0,0 +1,23 @@
+{% extends "core.html" %}
+
+{% use "core.html" with css as core_css, body as core_body, js as core_js, js_init as core_js_init %}
+{% use "valentine.html" with css as valentine_css, body as valentine_body %}
+
+{% block css %}
+{{ block('core_css') }}
+{{ block('valentine_css') }}
+
+{% endblock %}
+
+{% block body %}
+
+
+Wanda Switch
+{{ block('valentine_body') }}
+{% endblock %}
+
+{% block js %}
+{% endblock %}
+
+{% block js_init %}
+{% endblock %}
diff --git a/mirzaev/site/wanda/system/views/js.html b/mirzaev/site/wanda/system/views/js.html
new file mode 100644
index 0000000..d8b0d76
--- /dev/null
+++ b/mirzaev/site/wanda/system/views/js.html
@@ -0,0 +1,3 @@
+{% block js %}
+
+{% endblock %}
diff --git a/mirzaev/site/wanda/system/views/manager.php b/mirzaev/site/wanda/system/views/manager.php
new file mode 100644
index 0000000..ba25378
--- /dev/null
+++ b/mirzaev/site/wanda/system/views/manager.php
@@ -0,0 +1,25 @@
+
+ */
+final class manager extends controller
+{
+ public function render(string $file, array $vars = []): ?string
+ {
+ // Генерация представления
+ return (new view(new FilesystemLoader(VIEWS)))->render($file, $vars);
+ }
+}
diff --git a/mirzaev/site/wanda/system/views/menu.html b/mirzaev/site/wanda/system/views/menu.html
new file mode 100644
index 0000000..98724f1
--- /dev/null
+++ b/mirzaev/site/wanda/system/views/menu.html
@@ -0,0 +1,41 @@
+
diff --git a/mirzaev/site/wanda/system/views/valentine.html b/mirzaev/site/wanda/system/views/valentine.html
new file mode 100644
index 0000000..65b1564
--- /dev/null
+++ b/mirzaev/site/wanda/system/views/valentine.html
@@ -0,0 +1,520 @@
+{% block css %}
+
+{% endblock %}
+
+{% block body %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}