From 7fe34899a9c73597f3dad529ff1b1c0ba1ce88a7 Mon Sep 17 00:00:00 2001 From: Arsen Mirzaev Tatyano-Muradovich Date: Fri, 22 Aug 2025 10:02:21 +0300 Subject: [PATCH] refresh after 3-4 years --- .gitignore | 0 LICENSE | 0 README.md | 0 composer.json | 47 +- composer.lock | 230 ++++-- .../surikov/system/controllers/accounts.php | 283 +++++++ kodorvan/surikov/system/controllers/books.php | 313 ++++++++ .../surikov/system/controllers/contacts.php | 72 ++ kodorvan/surikov/system/controllers/core.php | 88 +++ .../surikov/system/controllers/errors.php | 45 ++ kodorvan/surikov/system/controllers/index.php | 72 ++ .../surikov/system/controllers/kemenov.php | 74 ++ .../surikov/system/controllers/surikov.php | 72 ++ kodorvan/surikov/system/models/account.php | 711 ++++++++++++++++++ kodorvan/surikov/system/models/book.php | 412 ++++++++++ kodorvan/surikov/system/models/core.php | 54 ++ .../surikov}/system/public/css/auth.css | 0 .../surikov}/system/public/css/books.css | 0 .../surikov}/system/public/css/main.css | 0 .../surikov}/system/public/css/pages.css | 0 .../surikov}/system/public/css/upload.css | 0 .../system/public/img/background_1.png | Bin .../system/public/img/background_1.svg | 0 .../system/public/img/background_2.png | Bin .../system/public/img/surikovlib_logo_1.svg | 0 .../public/img/surikovlib_logo_1_white.svg | 0 .../surikov}/system/public/img/ФЖ-28.png | Bin .../surikov}/system/public/img/школьникам.png | Bin kodorvan/surikov/system/public/index.php | 58 ++ .../surikov}/system/public/js/auth.js | 0 .../surikov}/system/public/js/delete.js | 0 .../surikov}/system/public/js/rotate.js | 0 kodorvan/surikov/system/settings/.gitignore | 1 + kodorvan/surikov/system/settings/database.php | 10 + .../surikov}/system/storage/.gitignore | 0 .../surikov}/system/storage/books/.gitkeep | 0 .../surikov}/system/storage/temp/.gitkeep | 0 kodorvan/surikov/system/views/templater.php | 213 ++++++ .../views/themes/default/authentication.html | 0 .../views/themes/default}/books/book.html | 2 +- .../views/themes/default}/books/index.html | 2 +- .../system/views/themes/default}/core.html | 12 +- .../system/views/themes/default}/footer.html | 0 .../system/views/themes/default}/head.html | 0 .../system/views/themes/default}/header.html | 0 .../system/views/themes/default}/js.html | 0 .../views/themes/default}/main/index.html | 2 +- .../themes/default}/pages/contacts/index.html | 2 +- .../themes/default}/pages/kemenov/index.html | 2 +- .../themes/default}/pages/surikov/index.html | 2 +- .../system/views/themes/default}/sidebar.html | 4 +- .../system/views/themes/default}/vk.html | 0 .../controllers/accounts_controller.php | 168 ----- .../system/controllers/books_controller.php | 191 ----- .../controllers/contacts_controller.php | 28 - .../surikovlib/system/controllers/core.php | 34 - .../system/controllers/errors_controller.php | 31 - .../system/controllers/kemenov_controller.php | 28 - .../system/controllers/main_controller.php | 32 - .../system/controllers/surikov_controller.php | 28 - .../system/models/accounts_model.php | 638 ---------------- .../surikovlib/system/models/books_model.php | 358 --------- mirzaev/surikovlib/system/models/core.php | 139 ---- .../system/public/Nginx_1.21_vhost.conf | 105 --- mirzaev/surikovlib/system/public/index.php | 49 -- mirzaev/surikovlib/system/views/manager.php | 25 - 66 files changed, 2686 insertions(+), 1951 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 composer.json mode change 100644 => 100755 composer.lock create mode 100755 kodorvan/surikov/system/controllers/accounts.php create mode 100755 kodorvan/surikov/system/controllers/books.php create mode 100755 kodorvan/surikov/system/controllers/contacts.php create mode 100755 kodorvan/surikov/system/controllers/core.php create mode 100755 kodorvan/surikov/system/controllers/errors.php create mode 100755 kodorvan/surikov/system/controllers/index.php create mode 100755 kodorvan/surikov/system/controllers/kemenov.php create mode 100755 kodorvan/surikov/system/controllers/surikov.php create mode 100755 kodorvan/surikov/system/models/account.php create mode 100755 kodorvan/surikov/system/models/book.php create mode 100755 kodorvan/surikov/system/models/core.php rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/css/auth.css (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/css/books.css (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/css/main.css (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/css/pages.css (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/css/upload.css (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/img/background_1.png (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/img/background_1.svg (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/img/background_2.png (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/img/surikovlib_logo_1.svg (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/img/surikovlib_logo_1_white.svg (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/img/ФЖ-28.png (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/img/школьникам.png (100%) mode change 100644 => 100755 create mode 100755 kodorvan/surikov/system/public/index.php rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/js/auth.js (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/js/delete.js (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/public/js/rotate.js (100%) mode change 100644 => 100755 create mode 100644 kodorvan/surikov/system/settings/.gitignore create mode 100644 kodorvan/surikov/system/settings/database.php rename {mirzaev/surikovlib => kodorvan/surikov}/system/storage/.gitignore (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/storage/books/.gitkeep (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib => kodorvan/surikov}/system/storage/temp/.gitkeep (100%) mode change 100644 => 100755 create mode 100755 kodorvan/surikov/system/views/templater.php rename mirzaev/surikovlib/system/views/auth.html => kodorvan/surikov/system/views/themes/default/authentication.html (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/books/book.html (97%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/books/index.html (96%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/core.html (53%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/footer.html (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/head.html (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/header.html (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/js.html (100%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/main/index.html (79%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/pages/contacts/index.html (98%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/pages/kemenov/index.html (97%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/pages/surikov/index.html (98%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/sidebar.html (50%) mode change 100644 => 100755 rename {mirzaev/surikovlib/system/views => kodorvan/surikov/system/views/themes/default}/vk.html (100%) mode change 100644 => 100755 delete mode 100644 mirzaev/surikovlib/system/controllers/accounts_controller.php delete mode 100644 mirzaev/surikovlib/system/controllers/books_controller.php delete mode 100644 mirzaev/surikovlib/system/controllers/contacts_controller.php delete mode 100644 mirzaev/surikovlib/system/controllers/core.php delete mode 100644 mirzaev/surikovlib/system/controllers/errors_controller.php delete mode 100644 mirzaev/surikovlib/system/controllers/kemenov_controller.php delete mode 100644 mirzaev/surikovlib/system/controllers/main_controller.php delete mode 100644 mirzaev/surikovlib/system/controllers/surikov_controller.php delete mode 100644 mirzaev/surikovlib/system/models/accounts_model.php delete mode 100644 mirzaev/surikovlib/system/models/books_model.php delete mode 100644 mirzaev/surikovlib/system/models/core.php delete mode 100644 mirzaev/surikovlib/system/public/Nginx_1.21_vhost.conf delete mode 100644 mirzaev/surikovlib/system/public/index.php delete mode 100644 mirzaev/surikovlib/system/views/manager.php diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/composer.json b/composer.json old mode 100644 new mode 100755 index 0a56bd8..fa1d347 --- a/composer.json +++ b/composer.json @@ -1,25 +1,26 @@ { - "name": "mirzaev/surikovlib", - "description": "Онлайн библеотека музея имени Сурикова", - "type": "project", - "license": "AGPL-3.0-or-later", - "homepage": "https://git.hood.su/mirzaev/surikovlib", - "authors": [ - { - "name": "Arsen Mirzaev Tatyano-Muradovich", - "email": "arsen@mirzaev.sexy", - "homepage": "https://mirzaev.sexy", - "role": "Developer" - } - ], - "require": { - "php": "^8.0.0", - "mirzaev/minimal": "^2.0.x-dev", - "twig/twig": "^3.3" - }, - "autoload": { - "psr-4": { - "mirzaev\\surikovlib\\": "mirzaev/surikovlib/system" - } - } + "name": "kodorvan/surikov", + "description": "Online library of the Surikov Museum", + "type": "project", + "license": "WTFPL", + "homepage": "https://git.svoboda.works/kodorvan/surikov", + "authors": [ + { + "name": "Arsen Mirzaev Tatyano-Muradovich", + "email": "arsen@mirzaev.sexy", + "homepage": "https://mirzaev.sexy", + "role": "Developer" + } + ], + "require": { + "php": "^8.4.0", + "mirzaev/minimal": "^3.6.2", + "twig/twig": "^3.3", + "mirzaev/languages": "^1.0" + }, + "autoload": { + "psr-4": { + "kodorvan\\surikov\\": "kodorvan/surikov/system" + } + } } diff --git a/composer.lock b/composer.lock old mode 100644 new mode 100755 index 7e1eada..e196ea7 --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,59 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1c826a114d11e8301a0f17171d987459", + "content-hash": "97cd0861246168b4da62751f2317bc62", "packages": [ { - "name": "mirzaev/minimal", - "version": "2.0.x-dev", + "name": "mirzaev/languages", + "version": "1.0.2", "source": { "type": "git", - "url": "https://git.hood.su/mirzaev/minimal", - "reference": "7777d7af1733d661a36551a0fdcf27a972e4ef81" + "url": "https://git.svoboda.works/mirzaev/languages", + "reference": "eceff49204c718243f24e3da42294c5ea5b29e01" }, "require": { - "php": "~8.0" + "php": "^8.4" }, - "suggest": { - "ext-PDO": "Для работы с базами данных на SQL (MySQL, PostreSQL...)" + "type": "library", + "autoload": { + "psr-4": { + "mirzaev\\languages\\": "mirzaev/languages/system" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "WTFPL" + ], + "authors": [ + { + "name": "Arsen Mirzaev Tatyano-Muradovich", + "email": "arsen@mirzaev.sexy", + "homepage": "https://mirzaev.sexy", + "role": "Creator" + } + ], + "description": "Library for easy languages support", + "homepage": "https://git.svoboda.works/mirzaev/languages", + "keywords": [ + "enumeration", + "languages" + ], + "support": { + "issues": "https://git.svoboda.works/mirzaev/languages/issues", + "wiki": "https://git.svoboda.works/mirzaev/languages/wiki" + }, + "time": "2025-08-21T14:50:06+00:00" + }, + { + "name": "mirzaev/minimal", + "version": "3.6.2", + "source": { + "type": "git", + "url": "https://git.svoboda.works/mirzaev/minimal", + "reference": "d9e4e0af6cffc169831eec798d00e53187839b8e" + }, + "require": { + "php": "~8.4" }, "type": "framework", "autoload": { @@ -35,37 +73,105 @@ "name": "Arsen Mirzaev Tatyano-Muradovich", "email": "arsen@mirzaev.sexy", "homepage": "https://mirzaev.sexy", - "role": "Developer" + "role": "Programmer" } ], - "description": "Легковесный MVC фреймворк который следует твоим правилам, а не диктует свои", - "homepage": "https://git.hood.su/mirzaev/minimal", + "description": "My vision of a good framework", + "homepage": "https://git.mirzaev.sexy/mirzaev/minimal", "keywords": [ "framework", + "lightweight", "mvc" ], "support": { - "docs": "https://git.hood.su/mirzaev/minimal/manual", - "issues": "https://git.hood.su/mirzaev/minimal/issues" + "docs": "https://git.mirzaev.sexy/mirzaev/minimal/wiki", + "issues": "https://git.mirzaev.sexy/mirzaev/minimal/issues" }, - "time": "2022-03-03T21:15:52+00:00" + "time": "2025-07-16T01:09:25+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.25.0", + "name": "symfony/deprecation-contracts", + "version": "v3.6.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "30885182c981ab175d4d034db0f6f469898070ab" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", - "reference": "30885182c981ab175d4d034db0f6f469898070ab", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -75,12 +181,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -114,7 +217,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" }, "funding": [ { @@ -125,29 +228,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2021-10-20T20:35:02+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.25.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -157,12 +265,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -197,7 +302,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.25.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -208,43 +313,50 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2021-11-30T18:21:41+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "twig/twig", - "version": "v3.3.8", + "version": "v3.21.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "972d8604a92b7054828b539f2febb0211dd5945c" + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/972d8604a92b7054828b539f2febb0211dd5945c", - "reference": "972d8604a92b7054828b539f2febb0211dd5945c", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d", + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1.0", + "symfony/deprecation-contracts": "^2.5|^3", "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" + "phpstan/phpstan": "^2.0", + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - } - }, "autoload": { + "files": [ + "src/Resources/core.php", + "src/Resources/debug.php", + "src/Resources/escaper.php", + "src/Resources/string_loader.php" + ], "psr-4": { "Twig\\": "src/" } @@ -277,7 +389,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.3.8" + "source": "https://github.com/twigphp/Twig/tree/v3.21.1" }, "funding": [ { @@ -289,20 +401,18 @@ "type": "tidelift" } ], - "time": "2022-02-04T06:59:48+00:00" + "time": "2025-05-03T07:21:55+00:00" } ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "mirzaev/minimal": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^8.0.0" + "php": "^8.4.0" }, - "platform-dev": [], - "plugin-api-version": "2.2.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/kodorvan/surikov/system/controllers/accounts.php b/kodorvan/surikov/system/controllers/accounts.php new file mode 100755 index 0000000..98d973d --- /dev/null +++ b/kodorvan/surikov/system/controllers/accounts.php @@ -0,0 +1,283 @@ + + */ +final class accounts extends core +{ + /** + * Errors + * + * @var array $errors Registry of errors + */ + protected array $errors = [ + 'system' => [], + 'account' => [] + ]; + + /** + * Account page + * + * @return null + */ + public function index(): null + { + if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) { + // Request for any response + + // Render page + $page = $this->view->render('pages/account/index.html'); + + // Sending response + $this->response + ->status(status::ok) + ->start() + ->clean() + ->sse() + ->write($page) + ->validate($this->request) + ?->body() + ->end(); + + // Deinitializing rendered page + unset($page); + + // Exit (success) + return null; + } + + // Exit (fail) + return null; + } + + /** + * Registration + * + * @param string|null $mail Mail + * @param string|null $password Password + * @param int|string|bool|null $remember Remember + * @param string|null $redirect Redirect @deprecated + * + * @return null + */ + public function registration( + ?string $mail = null, + ?string $password = null, + int|string|bool|null $remember = null, + ?string $redirect = null + ): null { + if ($this->view->account = account::registrate(mail: $mail, password: $password, errors: $this->errors['account'])) { + // Registered + + // Filtering the remember argument + $remember = (bool) $remember; + + if ($this->view->account = account::authenticate(mail: $mail, password: $password, remember: $remember, errors: $this->errors['account'])) { + // Authenticated + } else { + // Not authenticated + + // Sending response + $this->response + ->status(status::forbidden) + ->start() + ->clean() + ->sse() + ->validate($this->request) + ?->body() + ->end(); + } + } else { + // Not registered +var_dump($this->errors); die; + // Sending response + $this->response + ->status(status::unauthorized) + ->start() + ->clean() + ->sse() + ->validate($this->request) + ?->body() + ->end(); + } + + // Initializing path to redirecting @deprecated + $redirect ??= $_SERVER['HTTP_REFERER'] ?? '/'; + + // Redirecting + header("Location: $redirect", response_code: status::see_other->value); + + // Exit (success) + return null; + } + + /** + * Authentication + * + * @param string|null $mail Mail + * @param string|null $password Password + * @param int|string|bool|null $remember Remember + * @param string|null $redirect Redirect @deprecated + * + * @return null + */ + public function authentication( + ?string $mail = null, + ?string $password = null, + int|string|bool|null $remember = null, + ?string $redirect = null + ): ?string { + // Filtering the remember argument + $remember = (bool) $remember; + + if ($this->view->account = account::authenticate(mail: $mail, password: $password, remember: $remember, errors: $this->errors['account'])) { + // Authenticated + } else { + // Not authenticated + + // Sending response + $this->response + ->status(status::forbidden) + ->start() + ->clean() + ->sse() + ->validate($this->request) + ?->body() + ->end(); + } + + // Initializing path to redirecting @deprecated + $redirect ??= $_SERVER['HTTP_REFERER'] ?? '/'; + + // Redirecting + header("Location: $redirect", response_code: status::see_other->value); + + // Exit (success) + return null; + } + + /** + * Deauthentication + * + * @return null + */ + public function deauthentication(): null + { + if (account::deauthenticate(errors: $this->errors['account'])) { + // Deauthenticated + } else { + // Not deauthenticated + + // Sending response + $this->response + ->status(status::internal_server_error) + ->start() + ->clean() + ->sse() + ->validate($this->request) + ?->body() + ->end(); + } + + // Перенаправление + header('Location: /', response_code: status::see_other->value); + + // Exit (success) + return null; + } + + /** + * Data + * + * If the information requested is not by an administrator, + * only publicly permitted information will be returned. + * + * @param int|null $identifier Identifier + * + * @return string JSON-документ + */ + public function data(?int $identifier = null): ?string + { + if ($account = account::read(expressions: ['identifier' => $identifier], errors: $this->errors['account'])) { + // Found the account + + // Initializing the account + $this->view->account = account::initialize(errors: $this->errors['account']); + + if ($this->view->account) { + // Initialized the account + + if ($this->view->account->permissions['accounts'] ?? 0 === 1) { + // Authorized to accounts + } else { + // Not authorized to accounts + + // Deinitializing the account private properties + unset($account->password, $account->hash, $account->time); + } + + if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) { + // Request for any response + + // Render page + $page = $this->view->render('pages/account/index.html'); + + // Sending response + $this->response + ->status(status::ok) + ->start() + ->clean() + ->sse() + ->json($account) + ->validate($this->request) + ?->body() + ->end(); + + // Deinitializing rendered page + unset($page); + + // Exit (success) + return null; + } + } + } else { + // Not found the account + + // Sending response + $this->response + ->status(status::not_found) + ->start() + ->clean() + ->sse() + ->validate($this->request) + ?->body() + ->end(); + } + + // Exit (success) + return null; + } +} diff --git a/kodorvan/surikov/system/controllers/books.php b/kodorvan/surikov/system/controllers/books.php new file mode 100755 index 0000000..95293e6 --- /dev/null +++ b/kodorvan/surikov/system/controllers/books.php @@ -0,0 +1,313 @@ + + */ +final class books extends core +{ + /** + * Errors + * + * @var array $errors Registry of errors + */ + protected array $errors = [ + 'system' => [], + 'account' => [], + 'books' => [] + ]; + + /** + * Books page (or the book page) + * + * @param int|string|null $identifier Identifier of the book + * @param int|string $page Page if the book + * + * @return null + */ + public function index( + int|string|null $identifier = null, + int|string $page = 1 + ): null { + // Normalizing the page argument + $page = (int) $page; + if ($page < 1) $page = 1; + + if (isset($identifier)) { + // Received the book identifier (the book) + + // Initializing the book + $this->view->book = book::read(expressions: ['identifier' => (int) $identifier])[0] ?? null; + + if (empty($page)) { + // Received the book page + + // Initializing the book page + $this->view->page = $page; + } + + if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) { + // Request for any response + + // Render page + $page = $this->view->render('books/book.html'); + + // Sending response + $this->response + ->start() + ->clean() + ->sse() + ->write($page) + ->validate($this->request) + ?->body() + ->end(); + + // Deinitializing rendered page + unset($page); + + // Exit (success) + return null; + } + } else { + // Not received the book identifier (all books) + + // Reading books + $this->view->books = book::read(limit: 30, page: $page); + + if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) { + // Request for any response + + // Render page + $page = $this->view->render('books/index.html'); + + // Sending response + $this->response + ->start() + ->clean() + ->sse() + ->write($page) + ->validate($this->request) + ?->body() + ->end(); + + // Deinitializing rendered page + unset($page); + + // Exit (success) + return null; + } + } + + // Exit (fail) + return null; + } + + /** + * Write + * + * Import books into the storage and the database + * + * @return null + */ + public function write(): null + { + if (account::initialize(errors: $this->errors['account'])->access('books')) { + // Initialized account and authorized to books + + if (count($books = book::import(files: $this->request->files['books'] ?? [], errors: $this->errors['books'])) > 0) { + // Imported books + } else { + // Not imported books + } + } + + // Redirecting + header(header: 'Location: /books', response_code: status::see_other->value); + + // Exit (success) + return null; + } + + /** + * Read + * + * Read the book page file (expected jpeg image) + * + * @param int|string|null $identifier Identifier of the book + * @param int|string|null $page Page of the book + * + * @return string|null The book page file + */ + public function read( + int|string|null $identifier = null, + int|string|null $page = 1 + ): ?string { + // Normalizing the identifier argument + $identifier = (int) $identifier; + + // Normalizing the page argument + $page = (int) $page; + if ($page < 1) $page = 1; + + // Initializing the book file path + $file = \STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $identifier . DIRECTORY_SEPARATOR . $page . '.jpg'; + + if (file_exists($file)) { + // Found the book page file + + // Initializing headers + header('Content-Description: File Transfer'); + header('Content-Type: image/jpeg'); + header('Content-Disposition: attachment; filename=' . basename($file)); + header('Content-Transfer-Encoding: binary'); + header('Content-Length: ' . filesize($file)); + + // Cleaning the output buffer + ob_end_clean(); + + // Exit (success) + return file_get_contents($file); + } + + // Exit (fail) + return null; + } + + /** + * Delete + * + * Delete the book from the storage and the database + * + * @param int|string|null $identifier Identifier of the book + * + * @return null + */ + public function delete(int|string|null $identifier = null): null + { + if (account::initialize(errors: $this->errors['account'])->access('books')) { + // Initialized account and authorized to books + + // Initializing the processing status + $status = false; + + // Normalizing the identifier argument + $identifier = (int) $identifier; + + if (book::delete(identifier: $identifier, errors: $this->errors['books'])) { + // Deleted the book from the database + + // Initializing the book directory path + $directory = \STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $identifier; + + if (file_exists($directory)) { + // Found the book directory + + // Deletimg the book from the storage + exec('rm -rf ' . escapeshellarg($directory)); + + // Writing the processing status + $status = true; + } + } + + if (str_contains($this->request->headers['accept'] ?? '', content::json->value)) { + // Request for JSON response + + // Sending response + $this->response + ->start() + ->clean() + ->sse() + ->json([ + 'status' => $status, + 'errors' => $this->errors + ]) + ->validate($this->request) + ?->body() + ->end(); + + // Exit (success) + return null; + } + } + + // Exit (fail) + return null; + } + + /** + * Rotate + * + * Rotate the book image in the storage + * + * @param int|string|null $identifier Identifier of the book + * @param int|string|null $page Page of the book + * + * @return null + */ + public function rotate( + int|string|null $identifier = null, + int|string|null $page = 1 + ): null { + if (account::initialize(errors: $this->errors['account'])->access('books')) { + // Initialized account and authorized to books + + // Normalizing the identifier argument + $identifier = (int) $identifier; + + // Normalizing the page argument + $page = (int) $page; + + // Rotating the book page file + $status = book::rotate(identifier: $identifier, page: $page, errors: $this->errors['books']); + + if (str_contains($this->request->headers['accept'] ?? '', content::json->value)) { + // Request for JSON response + + // Sending response + $this->response + ->start() + ->clean() + ->sse() + ->json([ + 'status' => $status, + 'errors' => $this->errors + ]) + ->validate($this->request) + ?->body() + ->end(); + + // Exit (success) + return null; + } + } + + // Exit (fail) + return null; + } +} diff --git a/kodorvan/surikov/system/controllers/contacts.php b/kodorvan/surikov/system/controllers/contacts.php new file mode 100755 index 0000000..5bddf58 --- /dev/null +++ b/kodorvan/surikov/system/controllers/contacts.php @@ -0,0 +1,72 @@ + + */ +final class contacts extends core +{ + /** + * Errors + * + * @var array $errors Registry of errors + */ + protected array $errors = [ + 'system' => [], + 'account' => [] + ]; + + /** + * Contacts page + * + * @return null + */ + public function index(): null + { + if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) { + // Request for any response + + // Render page + $page = $this->view->render('pages/contacts/index.html'); + + // Sending response + $this->response + ->start() + ->clean() + ->sse() + ->write($page) + ->validate($this->request) + ?->body() + ->end(); + + // Deinitializing rendered page + unset($page); + + // Exit (success) + return null; + } + + // Exit (fail) + return null; + } +} diff --git a/kodorvan/surikov/system/controllers/core.php b/kodorvan/surikov/system/controllers/core.php new file mode 100755 index 0000000..0c55965 --- /dev/null +++ b/kodorvan/surikov/system/controllers/core.php @@ -0,0 +1,88 @@ + + */ +class core extends controller +{ + /** + * Language + * + * @var language $language Language + */ + protected language $language = language::ru; + + /** + * Response + * + * @see https://wiki.php.net/rfc/property-hooks (find a table about backed and virtual hooks) + * + * @var response $response Response + */ + protected response $response { + // Read + get => $this->response ??= $this->request->response(); + } + + /** + * Errors + * + * @var array $errors Registry of errors + */ + protected array $errors = [ + 'system' => [], + 'account' => [] + ]; + + /** + * Constructor + * + * @param minimal $core Instance of the MINIMAL + * @param bool $initialize Initialize a controller? + * + * @return void + */ + public function __construct(minimal $core) + { + // Blocking requests from CloudFlare (better to write this blocking into nginx config file) + if (isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] === 'nginx-ssl early hints') return status::bruh->label; + + // Initializing the models core + new models(); + + // Initializing the view template engine instance + $this->view = new templater(account::initialize(errors: $this->errors['account'])); + + // For the extends system + parent::__construct(core: $core); + } +} diff --git a/kodorvan/surikov/system/controllers/errors.php b/kodorvan/surikov/system/controllers/errors.php new file mode 100755 index 0000000..9f30b12 --- /dev/null +++ b/kodorvan/surikov/system/controllers/errors.php @@ -0,0 +1,45 @@ + + */ +final class errors_controller extends core +{ + /** + * Errors + * + * @var array $errors Registry of errors + */ + protected array $errors = [ + 'system' => [], + 'account' => [] + ]; + + public function error404(): ?string + { + // Генерация представления + return 'Ошибка 404 (не найдено)'; + } + + public function error500(): ?string + { + // Генерация представления + return 'Ошибка 500 (на стороне сервера)'; + } +} diff --git a/kodorvan/surikov/system/controllers/index.php b/kodorvan/surikov/system/controllers/index.php new file mode 100755 index 0000000..0d18462 --- /dev/null +++ b/kodorvan/surikov/system/controllers/index.php @@ -0,0 +1,72 @@ + + */ +final class index extends core +{ + /** + * Errors + * + * @var array $errors Registry of errors + */ + protected array $errors = [ + 'system' => [], + 'account' => [] + ]; + + /** + * Main page + * + * @return null + */ + public function index(): null + { + if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) { + // Request for any response + + // Render page + $page = $this->view->render('main/index.html'); + + // Sending response + $this->response + ->start() + ->clean() + ->sse() + ->write($page) + ->validate($this->request) + ?->body() + ->end(); + + // Deinitializing rendered page + unset($page); + + // Exit (success) + return null; + } + + // Exit (fail) + return null; + } +} diff --git a/kodorvan/surikov/system/controllers/kemenov.php b/kodorvan/surikov/system/controllers/kemenov.php new file mode 100755 index 0000000..97c81bf --- /dev/null +++ b/kodorvan/surikov/system/controllers/kemenov.php @@ -0,0 +1,74 @@ + + */ +final class kemenov extends core +{ + /** + * Errors + * + * @var array $errors Registry of errors + */ + protected array $errors = [ + 'system' => [], + 'account' => [] + ]; + + /** + * Kemenov page + * + * @return null + */ + public function index(): null + { + if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) { + // Request for any response + + // Render page + $page = $this->view->render('pages/kemenov/index.html'); + + // Sending response + $this->response + ->start() + ->clean() + ->sse() + ->write($page) + ->validate($this->request) + ?->body() + ->end(); + + // Deinitializing rendered page + unset($page); + + // Exit (success) + return null; + } + + // Exit (fail) + return null; + } +} diff --git a/kodorvan/surikov/system/controllers/surikov.php b/kodorvan/surikov/system/controllers/surikov.php new file mode 100755 index 0000000..19e7f2d --- /dev/null +++ b/kodorvan/surikov/system/controllers/surikov.php @@ -0,0 +1,72 @@ + + */ +final class surikov extends core +{ + /** + * Errors + * + * @var array $errors Registry of errors + */ + protected array $errors = [ + 'system' => [], + 'account' => [] + ]; + + /** + * Surikov page + * + * @return null + */ + public function index(): null + { + if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) { + // Request for any response + + // Render page + $page = $this->view->render('pages/surikov/index.html'); + + // Sending response + $this->response + ->start() + ->clean() + ->sse() + ->write($page) + ->validate($this->request) + ?->body() + ->end(); + + // Deinitializing rendered page + unset($page); + + // Exit (success) + return null; + } + + // Exit (fail) + return null; + } +} diff --git a/kodorvan/surikov/system/models/account.php b/kodorvan/surikov/system/models/account.php new file mode 100755 index 0000000..d86eb40 --- /dev/null +++ b/kodorvan/surikov/system/models/account.php @@ -0,0 +1,711 @@ + + */ +final class account extends core +{ + /** + * Identifier + * + * @var int $identifier + */ + public int $identifier; + + /** + * Mail + * + * @var string $mail + */ + public string $mail; + + /** + * Password + * + * @var string $password + */ + public string $password; + + /** + * Hash + * + * Hash of the session + * + * @var string|null $hash + */ + public ?string $hash = null; + + /** + * Time + * + * Time of the session + * + * @var int|null $time + */ + public ?int $time = null; + + /** + * Permissions + * + * @var array $permissions + */ + public array $permissions; + + /** + * Constructor + * + * @param array $parameters Parameters + * + * @return void + */ + public function __construct(array $parameters) + { + foreach ($parameters as $key => $value) { + // Iterating over parameters + + // Writing the property + if (property_exists($this, $key)) $this->$key = $value; + } + } + + /** + * Registrate + * + * @param string $mail Mail + * @param string $password Password + * @param bool $authenticate Authenticate the account after registration? + * @param array &$errors Registry of errors + * + * @return static|null Account + */ + public static function registrate(string $mail, string $password, bool $authenticate = true, array &$errors = []): ?static + { + try { + if (static::initialize(errors: $errors)) { + // Authenticated the account + + // Exit (fail) + throw new exception('Уже аутентифицирован'); + } + + if (empty($account = static::read(expressions: ['mail' => $mail]))) { + // Not found the account + + if (static::write(mail: $mail, password: $password, errors: $errors)) { + // Registrated the account + + if ($authenticate) { + // Requested authentication after registration + + // Authentication + $account = static::authenticate(mail: $mail, password: $password, remember: true, errors: $errors); + } + + // Exit (success) + return $account; + } + } else { + // Found the account + + // Exit (success) + return $account; + } + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return null; + } + + /** + * Authenticate + * + * @param string $mail Mail + * @param string $password Password + * @param bool $remember Increase time of the session? + * @param array &$errors Registry of errors + * + * @return static|null Account + */ + public static function authenticate(string $mail, string $password, bool $remember = false, array &$errors = []): ?static + { + try { + if (static::initialize(errors: $errors)) { + // Authenticated the account + + // Exit (fail) + throw new exception('Уже аутентифицирован'); + } + + if (empty($account = static::read(expressions: ['mail' => $mail]))) { + // Not found the account + + // Exit (fail) + throw new exception('Не удалось найти аккаунт'); + } + + if (password_verify($password, $account->password)) { + // Matches hashes + + // Initializing the session identifier + session_id((string) $account->identifier); + + // Initializing the session name + session_name('identifier'); + + // Initializing the session + session_start(); + + // Calculating the session time + $time = time() + ($remember ? 604800 : 86400); + + // Generating the session hash + $hash = static::hash(identifier: (int) $account->identifier, hash: crypt($account->password, time() . $account->identifier), time: $time, errors: $errors)['hash']; + + // Initializing cookies + setcookie(name: 'hash', value: $hash, expires_or_options: $time, path: '/', secure: true); + + // Exit (success) + return $account; + } else { + // Not matches hashes + + // Exit (fail) + throw new exception('Wrong password'); + } + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return null; + } + + /** + * Deauthenticate + * + * @param array &$errors Registry of errors + * + * @return bool The session is deauthenticated? + */ + public static function deauthenticate(array &$errors = []): bool + { + try { + if ($account = static::initialize(errors: $errors)) { + // Authenticated the account + + // Initializing the request + $request = static::$database->prepare("UPDATE `accounts` SET `hash` = null, `time` = 0 WHERE `identifier` = :identifier"); + + // Initializing parameters of the request + $parameters = [ + ":identifier" => $account->identifier, + ]; + + // Sending the request + $request->execute($parameters); + + // Generating the answer + $request->fetch(pdo::FETCH_ASSOC); + + // Deinitializing cookies + setcookie('identifier', '', 0, path: '/', secure: true); + setcookie('hash', '', 0, path: '/', secure: true); + + // Exit (fail) + return true; + } else { + // Not authenticated the account + + // Exit (fail) + throw new exception('Not authenticated'); + } + } catch (exception $e) { + // Exception + + // Writing into the registry of errors + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return false; + } + + /** + * Initializing + * + * Initializing of the account + * + * @param int|null $identifier Identifier of the account + * @param array &$errors Registry of errors + * + * @return static|null Account + * + * @deprecated + */ + public static function init(?int $identifier = null, array &$errors = []): ?static + { + // Exit (success/fail) + return static::initialize(identifier: $identifier, errors: $errors); + } + + /** + * Initialize + * + * Initializing of the account + * + * @param int|null $identifier Identifier of the account + * @param array &$errors Registry of errors + * + * @return static|null Account + */ + public static function initialize(?int $identifier = null, array &$errors = []): ?static + { + try { + if (isset($identifier)) { + // Recaifer identifier of the account + + if (empty($account = static::read(['identifier' => $identifier]))) { + // Found the account + + // Exit (fail) + throw new exception('Не найден пользователь'); + } + } else if (!empty($_COOKIE['identifier']) && !empty($_COOKIE['hash'])) { + // Found cookie with the account data (expected that is already authenticated) + + if ($_COOKIE['hash'] === static::hash(identifier: (int) $_COOKIE['identifier'], errors: $errors)['hash']) { + // Matches hashes from the cookie and the database + } else { + // Not matches hashes from the cookie and the database + + // Exit (fail) + throw new exception('Вы аутентифицированы с другого устройства (не совпадают хеши аутентификации)'); + } + + if (empty($account = static::read([ + 'identifier' => $_COOKIE['identifier'], + 'hash' => $_COOKIE['hash'] + ]))) { + // Not found the account or a connection with it + + // Exit (fail) + throw new exception('Не найден пользователь или время аутентификации истекло'); + } + } else { + // Not found parameters for authentication + + // Exit (fail) + return null; + } + + // Initializing permissions + $account->permissions = static::permissions(identifier: (int) $account->identifier, errors: $errors); + + // Exit (success) + return $account; + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return null; + } + + /** + * Permissions + * + * Read permissions of the account from the database + * + * @param int $identifier Identifier of the account + * @param array &$errors Registy of errors + * + * @return array Permissions of the account + */ + public static function permissions(int $identifier, array &$errors = []): array + { + try { + // Initializing the request + $request = static::$database->prepare("SELECT * FROM `permissions` WHERE `account` = :identifier"); + + // Initializing parametes of the request + $parameters = [ + ":identifier" => $identifier + ]; + + // Sending the request + $request->execute($parameters); + + // Generating the answer + if (empty($response = $request->fetch(pdo::FETCH_ASSOC))) { + // Not found permissions + + // Exit (fail) + throw new exception('Not found permissions'); + } + + // Deleting deprecated parameters + unset($response['identifier']); + + // Exit (success) + return $response; + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return []; + } + + /** + * Access + * + * Check for the account authorizing by the permission + * + * @param string $permission Permission + * @param array &$errors Registry of errors + * + * @return bool|null Authorized? + */ + public function access(string $permission, array &$errors = []): ?bool + { + try { + // Exit (success) + return isset($this->permissions[$permission]) ? (bool) $this->permissions[$permission] : null; + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors['account'][] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return null; + } + + /** + * Write + * + * Write the account into the database + * + * @param string $mail Mail + * @param string $password Password + * @param array &$errors Registry of errors + * + * @return static|null Account + */ + public static function write(string $mail, string $password, array &$errors = []): ?static + { + try { + // Initializing parameters of the request + $parameters = []; + + // Filtering the parameter + if (filter_var($mail, FILTER_VALIDATE_EMAIL) === false) throw new exception('Не удалось распознать почту'); + if (iconv_strlen($mail) < 3) throw new exception('Длина почты должна быть не менее 3 символов'); + if (iconv_strlen($mail) > 60) throw new exception('Длина почты должна быть не более 80 символов'); + + // Writing the parameter + $parameters[':mail'] = $mail; + + // Filtering the parameter + if (iconv_strlen($password) < 3) throw new exception('Длина пароля должна быть не менее 3 символов'); + if (iconv_strlen($password) > 60) throw new exception('Длина пароля должна быть не более 120 символов'); + + // Writing the parameter + $parameters[':password'] = password_hash($password, PASSWORD_BCRYPT); + + // Initializing the request + $request = static::$database->prepare("INSERT INTO `accounts` (" . (isset($name) ? '`name`' : '') . (isset($name) && isset($mail) ? ', ' : '') . (isset($mail) ? '`mail`' : '') . ((isset($name) || isset($mail)) && isset($password) ? ', ' : '') . (isset($password) ? '`password`' : '') . ") VALUES (" . (isset($name) ? ':name' : '') . (isset($name) && isset($mail) ? ', ' : '') . (isset($mail) ? ':mail' : '') . ((isset($name) || isset($mail)) && isset($password) ? ', ' : '') . (isset($password) ? ':password' : '') . ")"); + + // Sending the request + $request->execute($parameters); + + // Generating the answer + $request->fetch(pdo::FETCH_ASSOC); + + // Reading the account + $account = static::read(expressions: ['mail' => $mail]); + + if ($account instanceof static) { + // Registered the account + + // Initializing the request + $request = static::$database->prepare("INSERT INTO `permissions` (`account`) VALUES (:identifier)"); + + // Initializing parameters of the request + $parameters = [ + ':identifier' => $account->identifier + ]; + + // Sending the request + $request->execute($parameters); + + // Generating the answer + $request->fetch(pdo::FETCH_ASSOC); + + // Exit (success) + return $account; + } + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return null; + } + + /** + * Read + * + * Read the account from the database + * + * @param array $expressions Request expressions [name => value] + * @param array &$errors Registry of errors + * + * @return static|null Account + */ + public static function read(array $expressions, array &$errors = []): ?static + { + try { + // Initializing the request row + $row = 'WHERE '; + + // Declaring the request parameters + $parameters = []; + + foreach ($expressions as $name => $value) { + // Iterating over request expressions + + // Generating the request row + $row .= "`$name` = :$name &&"; + + // Generating the request parameters + $parameters[":$name"] = $value; + } + + // Cleaning the request row + $row = empty($expressions) ? '' : trim(trim($row, '&&')); + + // Initializing the request + $request = static::$database->prepare("SELECT * FROM `accounts` $row LIMIT 1"); + + // Sending the request + $request->execute($parameters); + + // Generating the response + $response = $request->fetch(pdo::FETCH_ASSOC); + + if (!empty($response) && $account = new static($response ?? [])) { + // Found the account + + if ($permissions = static::permissions(identifier: (int) $account->identifier, errors: $errors)) { + // Found the account permissions + + // Writing permissions into the account implementator + $account->permissions = $permissions; + } + + // Exit (success) + return $account; + } else { + // Not found the account + + // Exit (fail) + throw new exception('Not found the account'); + } + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return null; + } + + /** + * Hash + * + * Write or read the account hash from the database + * + * @param int $identifier Identifier + * @param int|null $hash Hash + * @param string|null $time Time + * @param array &$errors Registry of errors + * + * @return array|bool Read: ['hash' => $hash, 'time' => $time]; Write: true; Error: false + */ + public static function hash(int $identifier, string|null $hash = null, int|null $time = null, array &$errors = []): array|bool + { + try { + if (isset($hash, $time)) { + // Write (received hash and time) + + // Initializing the request + $request = static::$database->prepare("UPDATE `accounts` SET `hash` = :hash, `time` = :time WHERE `identifier` = :identifier"); + + // Initializing the request parameters + $parameters = [ + ":identifier" => $identifier, + ":hash" => $hash, + ":time" => $time, + ]; + + // Sending the request + $request->execute($parameters); + + // Generating the answer + $response = $request->fetch(pdo::FETCH_ASSOC); + + // Exit (success) + return ['hash' => $hash, 'time' => $time]; + } else { + // Read (not received hash and time) + + // Initializing the request + $request = static::$database->prepare("SELECT `hash`, `time` FROM `accounts` WHERE `identifier` = :identifier"); + + // Initializing the request parameters + $parameters = [ + ":identifier" => $identifier + ]; + + // Sending the request + $request->execute($parameters); + + // Generating the answer + extract((array) $request->fetch(pdo::FETCH_ASSOC)); + + if (!empty($response['time']) && $response['time'] <= time()) { + // Expired the hash + + // Initializing the request + $request = static::$database->prepare("UPDATE `accounts` SET `hash` = :hash, `time` = :time WHERE `identifier` = :identifier"); + + // Initializing the request parameters + $parameters = [ + ":identifier" => $identifier, + ":hash" => null, + ":time" => null, + ]; + + // Sending the request + $request->execute($parameters); + + // Generating the answer + $response = $request->fetch(pdo::FETCH_ASSOC); + + // Exit (fail) + throw new exception('Expired the hash'); + } + + // Exit (success) + return ['hash' => $hash, 'time' => $time]; + } + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors['account'][] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return false; + } +} diff --git a/kodorvan/surikov/system/models/book.php b/kodorvan/surikov/system/models/book.php new file mode 100755 index 0000000..536b705 --- /dev/null +++ b/kodorvan/surikov/system/models/book.php @@ -0,0 +1,412 @@ + + */ +final class book extends core +{ + /** + * Write + * + * Write into the database + * + * @param string $title Title + * @param string|null $description Description + * @param int|null $account Identifier of the account + * @param array &$errors Registry of errors + * + * @return int|null The book identifier + */ + public static function write(string $title, ?string $description = null, ?int $account = null, array &$errors = []): ?int + { + try { + // Initializing the account + $account = account::initialize($account, $errors); + + // Initializing the request + $request = static::$database->prepare("INSERT INTO `books` (`account`, `title`, `description`) VALUES (:account, :title, :description)"); + + // Initializing the request parameters + $parameters = [ + ':account' => $account->identifier, + ':title' => $title, + ':description' => $description + ]; + + // Sending the request + $request->execute($parameters); + + if ($id = static::$database->lastInsertId()) { + // Received the created book identifier + + // Exit (success) + return (int) $id; + } + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return null; + } + + /** + * Read + * + * Read books from the database + * + * @param array $expressions Request expressions + * @param int $limit Amount + * @param int $page Page (offset by $limit) + * @param array &$errors Registry of errors + * + * @return array|false Books + */ + public static function read(array $expressions = [], int $limit = 1, int $page = 1, array &$errors = []): array|false + { + try { + // Initializing the request row + $row = 'WHERE '; + + // Initializing the request parameters + $parameters = []; + + foreach ($expressions as $name => $value) { + // Iterating over the request expressions + + // Generating the request row + $row .= "`$name` = :$name &&"; + + // Generating the request parameters + $parameters[":$name"] = $value; + } + + // Cleaning the request row + $row = empty($expressions) ? '' : trim(trim($row, '&&')); + + // Initializing the page + $page = $limit * --$page; + + // Initializing the request + $request = static::$database->prepare("SELECT * FROM `books` $row LIMIT $page, $limit"); + + // Sending the request + $request->execute($parameters); + + // Exit (success) + return (array) $request->fetchAll(pdo::FETCH_ASSOC); + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return false; + } + + /** + * Delete + * + * Delete the book from the database + * + * @param int $identifier Identifier + * @param array &$errors Registry of errors + * + * @return bool Is the book was deleted? + */ + public static function delete(int $identifier, array &$errors = []): bool + { + try { + // Initializing the request + $request = static::$database->prepare("DELETE FROM `books` WHERE `identifier` = :identifier LIMIT 1"); + + // Sending the request + $request->execute([':identifier' => $identifier]); + + // Exit (success) + return true; + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return false; + } + + /** + * Import + * + * Import books into the storage and database + * + * @param array $files Books + * @param int|null $account Identifier of the account + * @param array &$errors Registry of errors + * + * @return array|false Imported books + */ + public static function import(array $files, ?int $account = null, array &$errors = []): array|false + { + try { + if (empty($files)) { + // Not received books + + // Exit (fail) + throw new exception('Не найдены книги для записи'); + } + + // Initializing the account + $account = account::initialize($account, $errors); + + // Declaring the buffer of saved books + $saved = []; + + for ($i = -1; count($files['name']) > ++$i;) { + // Iterating over books + + // Generating the book file hash + $hash = hash_file('md5', $files['tmp_name'][$i]) ?? 0; + + if (move_uploaded_file($files['tmp_name'][$i], \STORAGE . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $hash . '_' . $files['name'][$i])) { + // Saved the book file + + // Writing into the buffer of saved books + $saved[] = [ + 'name' => preg_replace('/\.pdf/', '', $files['name'])[0], + 'file' => $hash . '_' . $files['name'][$i] + ]; + } + } + + // Declaring buffer of writed books + $writed = []; + + foreach ($saved as $book) { + // Iterating over saved books + + try { + if ($identifier = static::write(title: $book['name'], description: 'Без описания', account: $account->identifier ?? null, errors: $errors)) { + // Writed book into the database + + // Initializing the book directory path + $directory = \STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $identifier . DIRECTORY_SEPARATOR; + + if (!file_exists($directory)) { + // Not found the book directory + + if (!mkdir($directory, 0755, true)) { + // Failed to create the book directory + + // Skipping (fail) + throw new exception('Не удалось записать директорию для книги'); + } + } + + // Initializing the book file path + $file = \STORAGE . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $book['file']; + + // Extracting images from the PDF document + exec("pdfimages -j '$file' '$directory'"); + + // Renaming files + exec("echo 'export j=-1; for i in $directory*.jpg; do let j+=1; mv \$i $directory\$j.jpg; done' | bash"); + + // Writing into the buffer of writed books + $writed[] = $identifier; + } else { + // Not writed into the database + + // Skipping (fail) + throw new exception('Не удалось записать книгу в базу данных', 500); + } + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + } + + // Exit (success) + return $writed; + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return false; + } + + /** + * Rotate + * + * Rotate the book page image + * + * @param int $identifier Identifier + * @param int $page Page (offset) + * @param array &$errors Registry of errors + * + * @return bool Is the book page was rotated? + */ + public static function rotate(int $identifier, int $page = 1, array &$errors = []): bool + { + try { + // Initializing the request + $request = static::$database->prepare("SELECT EXISTS (SELECT * FROM `books` WHERE `identifier` = :identifier LIMIT 1)"); + + // Sending the request + $request->execute([':identifier' => $identifier]); + + if ($request->fetch(pdo::FETCH_NUM)[0] === 1) { + // Found the book + + // Initializing the book directory path + $directory = \STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $identifier; + + // Initializing the book file path + $file = $directory . DIRECTORY_SEPARATOR . "$page.jpg"; + + // Initializing the book file new location path + $old = $directory . DIRECTORY_SEPARATOR . 'old' . DIRECTORY_SEPARATOR . "$page.jpg"; + + if (!file_exists($directory)) { + // Not found the book directory + + // Exit (fail) + throw new exception('Не удалось найти директорию книги'); + } + + // Инициализация директории оригинальных изображений + if (!file_exists($directory . DIRECTORY_SEPARATOR . 'old')) { + // Not found the directory for deprecated files + + if (!mkdir($directory . DIRECTORY_SEPARATOR . 'old', 0755, true)) { + // Failed to create the directory for deprecated files + + // Exit (fail) + throw new exception('Failed to create the directory for deprecated files'); + } + } + + // Moving the deprecated file + exec("mv $file $old"); + + // Rotating the deprecated file and moving back + exec("jpegtran -rotate 90 $old > $file"); + + // Exit (success) + return true; + } + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return false; + } + + /** + * Amount + * + * Calculate amount of pages in the book storage + * + * @param int $identifier Identifier + * @param array &$errors Registry of errors + * + * @return int|false Amount of pages + */ + public static function amount(int $id, array &$errors = []): int|false + { + try { + // Initializing the iterator + $page = 0; + + while (true) { + // Iterating over the book pages files in ascending order (from 0.jpg to 999.jpg and more) (!!! recursion !!!) + + if (!file_exists(\STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $id . DIRECTORY_SEPARATOR . $page++ . '.jpg')) { + // Not found the book page by the iterator + + // Exit (success) (!!! exit from the recursion !!!) + return $page; + } + } + } catch (exception $e) { + // Exception + + // Writing into the errors registry + $errors[] = [ + 'text' => $e->getMessage(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'stack' => $e->getTrace() + ]; + } + + // Exit (fail) + return false; + } +} diff --git a/kodorvan/surikov/system/models/core.php b/kodorvan/surikov/system/models/core.php new file mode 100755 index 0000000..5aacb9e --- /dev/null +++ b/kodorvan/surikov/system/models/core.php @@ -0,0 +1,54 @@ + + */ +class core extends model +{ + /** + * Database + * + * @see https://www.php.net/manual/en/book.pdo.php PDO + * + * @var pdo $database Database + */ + protected static pdo $database; + + /** + * Constructor + * + * + * @return void + */ + public function __construct() + { + // Initializing the database connetion + self::$database = new pdo(DATABASE['type'] . ':dbname=' . DATABASE['name'] . ';host=' . DATABASE['host'], DATABASE['login'], DATABASE['password']); + } +} diff --git a/mirzaev/surikovlib/system/public/css/auth.css b/kodorvan/surikov/system/public/css/auth.css old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/css/auth.css rename to kodorvan/surikov/system/public/css/auth.css diff --git a/mirzaev/surikovlib/system/public/css/books.css b/kodorvan/surikov/system/public/css/books.css old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/css/books.css rename to kodorvan/surikov/system/public/css/books.css diff --git a/mirzaev/surikovlib/system/public/css/main.css b/kodorvan/surikov/system/public/css/main.css old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/css/main.css rename to kodorvan/surikov/system/public/css/main.css diff --git a/mirzaev/surikovlib/system/public/css/pages.css b/kodorvan/surikov/system/public/css/pages.css old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/css/pages.css rename to kodorvan/surikov/system/public/css/pages.css diff --git a/mirzaev/surikovlib/system/public/css/upload.css b/kodorvan/surikov/system/public/css/upload.css old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/css/upload.css rename to kodorvan/surikov/system/public/css/upload.css diff --git a/mirzaev/surikovlib/system/public/img/background_1.png b/kodorvan/surikov/system/public/img/background_1.png old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/img/background_1.png rename to kodorvan/surikov/system/public/img/background_1.png diff --git a/mirzaev/surikovlib/system/public/img/background_1.svg b/kodorvan/surikov/system/public/img/background_1.svg old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/img/background_1.svg rename to kodorvan/surikov/system/public/img/background_1.svg diff --git a/mirzaev/surikovlib/system/public/img/background_2.png b/kodorvan/surikov/system/public/img/background_2.png old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/img/background_2.png rename to kodorvan/surikov/system/public/img/background_2.png diff --git a/mirzaev/surikovlib/system/public/img/surikovlib_logo_1.svg b/kodorvan/surikov/system/public/img/surikovlib_logo_1.svg old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/img/surikovlib_logo_1.svg rename to kodorvan/surikov/system/public/img/surikovlib_logo_1.svg diff --git a/mirzaev/surikovlib/system/public/img/surikovlib_logo_1_white.svg b/kodorvan/surikov/system/public/img/surikovlib_logo_1_white.svg old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/img/surikovlib_logo_1_white.svg rename to kodorvan/surikov/system/public/img/surikovlib_logo_1_white.svg diff --git a/mirzaev/surikovlib/system/public/img/ФЖ-28.png b/kodorvan/surikov/system/public/img/ФЖ-28.png old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/img/ФЖ-28.png rename to kodorvan/surikov/system/public/img/ФЖ-28.png diff --git a/mirzaev/surikovlib/system/public/img/школьникам.png b/kodorvan/surikov/system/public/img/школьникам.png old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/img/школьникам.png rename to kodorvan/surikov/system/public/img/школьникам.png diff --git a/kodorvan/surikov/system/public/index.php b/kodorvan/surikov/system/public/index.php new file mode 100755 index 0000000..611d6dd --- /dev/null +++ b/kodorvan/surikov/system/public/index.php @@ -0,0 +1,58 @@ +router + ->write('/', new route('index', 'index'), 'GET') + ->write('/account/registration', new route('accounts', 'registration'), 'POST') + ->write('/account/authentication', new route('accounts', 'authentication'), 'POST') + ->write('/account/deauthentication', new route('accounts', 'deauthentication'), 'POST') + ->write('/account/deauthentication', new route('accounts', 'deauthentication'), 'GET') + ->write('/books', new route('books', 'index'), 'GET') + ->write('/books/$id', new route('books', 'index'), 'GET') + ->write('/books/$id/$page', new route('books', 'index'), 'GET') + ->write('/books/$id/$page/rotate', new route('books', 'rotate'), 'POST') + ->write('/books/$id/delete', new route('books', 'delete'), 'POST') + ->write('/storage/books/$id/$file', new route('books', 'read'), 'GET') + ->write('/storage/books/write', new route('books', 'write'), 'POST') + ->write('/kemenov', new route('kemenov', 'index'), 'GET') + ->write('/surikov', new route('surikov', 'index'), 'GET') + ->write('/contacts', new route('contacts', 'index'), 'GET'); + +// Handling the request +$core->start(); diff --git a/mirzaev/surikovlib/system/public/js/auth.js b/kodorvan/surikov/system/public/js/auth.js old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/js/auth.js rename to kodorvan/surikov/system/public/js/auth.js diff --git a/mirzaev/surikovlib/system/public/js/delete.js b/kodorvan/surikov/system/public/js/delete.js old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/js/delete.js rename to kodorvan/surikov/system/public/js/delete.js diff --git a/mirzaev/surikovlib/system/public/js/rotate.js b/kodorvan/surikov/system/public/js/rotate.js old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/public/js/rotate.js rename to kodorvan/surikov/system/public/js/rotate.js diff --git a/kodorvan/surikov/system/settings/.gitignore b/kodorvan/surikov/system/settings/.gitignore new file mode 100644 index 0000000..ac76a3f --- /dev/null +++ b/kodorvan/surikov/system/settings/.gitignore @@ -0,0 +1 @@ +*.sample.php diff --git a/kodorvan/surikov/system/settings/database.php b/kodorvan/surikov/system/settings/database.php new file mode 100644 index 0000000..467592e --- /dev/null +++ b/kodorvan/surikov/system/settings/database.php @@ -0,0 +1,10 @@ + 'mysql', + 'host' => '127.0.0.1', + 'name' => 'casino_2', + 'login' => 'brawl_stars', + 'password' => 'knopka_bablo_228' +]; diff --git a/mirzaev/surikovlib/system/storage/.gitignore b/kodorvan/surikov/system/storage/.gitignore old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/storage/.gitignore rename to kodorvan/surikov/system/storage/.gitignore diff --git a/mirzaev/surikovlib/system/storage/books/.gitkeep b/kodorvan/surikov/system/storage/books/.gitkeep old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/storage/books/.gitkeep rename to kodorvan/surikov/system/storage/books/.gitkeep diff --git a/mirzaev/surikovlib/system/storage/temp/.gitkeep b/kodorvan/surikov/system/storage/temp/.gitkeep old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/storage/temp/.gitkeep rename to kodorvan/surikov/system/storage/temp/.gitkeep diff --git a/kodorvan/surikov/system/views/templater.php b/kodorvan/surikov/system/views/templater.php new file mode 100755 index 0000000..dbb58db --- /dev/null +++ b/kodorvan/surikov/system/views/templater.php @@ -0,0 +1,213 @@ + + */ +final class templater extends controller implements array_access +{ + /** + * Twig + * + * @var twig $twig Instance of the twig templater + */ + readonly public twig $twig; + + /** + * Variables + * + * @var array $variables Registry of view global variables + */ + public array $variables = []; + + /** + * Constructor of an instance + * + * @return void + */ + public function __construct(?account $account = null) + { + // Initializing the Twig instance + $this->twig = new twig(new FilesystemLoader(VIEWS)); + + // Initializing global variables + $this->twig->addGlobal('theme', 'default'); + $this->twig->addGlobal('server', $_SERVER); + $this->twig->addGlobal('cookies', $_COOKIE); + if ($account instanceof account) $this->twig->addGlobal('account', $account); + $this->twig->addGlobal('language', $language = $session?->buffer['language'] ?? language::en); + } + + /** + * Render + * + * Render the HTML-document + * + * @param string $file Related path to a HTML-document + * @param array $variables Registry of variables to push into registry of global variables + * + * @return ?string HTML-document + */ + public function render(string $file, array $variables = []): ?string + { + // Generation and exit (success) + return $this->twig->render('themes' . DIRECTORY_SEPARATOR . $this->twig->getGlobals()['theme'] . DIRECTORY_SEPARATOR . $file, $variables + $this->variables); + + } + + /** + * Write + * + * Write the variable into the registry of the view global variables + * + * @param string $name Name of the variable + * @param mixed $value Value of the variable + * + * @return void + */ + public function __set(string $name, mixed $value = null): void + { + // Write the variable and exit (success) + $this->variables[$name] = $value; + } + + /** + * Read + * + * Read the variable from the registry of the view global variables + * + * @param string $name Name of the variable + * + * @return mixed Content of the variable, if they are found + */ + public function __get(string $name): mixed + { + // Read the variable and exit (success) + return $this->variables[$name]; + } + + /** + * Delete + * + * Delete the variable from the registry of the view global variables + * + * @param string $name Name of the variable + * + * @return void + */ + public function __unset(string $name): void + { + // Delete the variable and exit (success) + unset($this->variables[$name]); + } + + /** + * Check of initialization + * + * Check of initialization in the registry of the view global variables + * + * @param string $name Name of the variable + * + * @return bool The variable is initialized? + */ + public function __isset(string $name): bool + { + // Check of initialization of the variable and exit (success) + return isset($this->variables[$name]); + } + + /** + * Write + * + * Write the variable into the registry of the view global variables + * + * @param mixed $name Name of an offset of the variable + * @param mixed $value Value of the variable + * + * @return void + */ + public function offsetSet(mixed $name, mixed $value): void + { + // Write the variable and exit (success) + $this->variables[$name] = $value; + } + + /** + * Read + * + * Read the variable from the registry of the view global variables + * + * @param mixed $name Name of the variable + * + * @return mixed Content of the variable, if they are found + */ + public function offsetGet(mixed $name): mixed + { + // Read the variable and exit (success) + return $this->variables[$name]; + } + + /** + * Delete + * + * Delete the variable from the registry of the view global variables + * + * @param mixed $name Name of the variable + * + * @return void + */ + public function offsetUnset(mixed $name): void + { + // Delete the variable and exit (success) + unset($this->variables[$name]); + } + + /** + * Check of initialization + * + * Check of initialization in the registry of the view global variables + * + * @param mixed $name Name of the variable + * + * @return bool The variable is initialized? + */ + public function offsetExists(mixed $name): bool + { + // Check of initialization of the variable and exit (success) + return isset($this->variables[$name]); + } +} diff --git a/mirzaev/surikovlib/system/views/auth.html b/kodorvan/surikov/system/views/themes/default/authentication.html old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/views/auth.html rename to kodorvan/surikov/system/views/themes/default/authentication.html diff --git a/mirzaev/surikovlib/system/views/books/book.html b/kodorvan/surikov/system/views/themes/default/books/book.html old mode 100644 new mode 100755 similarity index 97% rename from mirzaev/surikovlib/system/views/books/book.html rename to kodorvan/surikov/system/views/themes/default/books/book.html index e8e50b1..fa861f1 --- a/mirzaev/surikovlib/system/views/books/book.html +++ b/kodorvan/surikov/system/views/themes/default/books/book.html @@ -1,4 +1,4 @@ -{% extends "core.html" %} +{% extends "/themes/default/core.html" %} {% block main %} diff --git a/mirzaev/surikovlib/system/views/books/index.html b/kodorvan/surikov/system/views/themes/default/books/index.html old mode 100644 new mode 100755 similarity index 96% rename from mirzaev/surikovlib/system/views/books/index.html rename to kodorvan/surikov/system/views/themes/default/books/index.html index c6afb3e..03c7c23 --- a/mirzaev/surikovlib/system/views/books/index.html +++ b/kodorvan/surikov/system/views/themes/default/books/index.html @@ -1,4 +1,4 @@ -{% extends "core.html" %} +{% extends "/themes/default/core.html" %} {% block main %} diff --git a/mirzaev/surikovlib/system/views/core.html b/kodorvan/surikov/system/views/themes/default/core.html old mode 100644 new mode 100755 similarity index 53% rename from mirzaev/surikovlib/system/views/core.html rename to kodorvan/surikov/system/views/themes/default/core.html index bc1c0ba..4692020 --- a/mirzaev/surikovlib/system/views/core.html +++ b/kodorvan/surikov/system/views/themes/default/core.html @@ -3,7 +3,7 @@ - {% include 'head.html' %} + {% include '/themes/default/head.html' %} @@ -15,20 +15,20 @@ - {% include 'header.html' %} + {% include '/themes/default/header.html' %}
{% block main %} - {% include 'calculators/index.html' %} + {% include '/themes/default/calculators/index.html' %} {% endblock %}
- {% include 'footer.html' %} + {% include '/themes/default/footer.html' %} - {% include 'js.html' %} + {% include '/themes/default/js.html' %} diff --git a/mirzaev/surikovlib/system/views/footer.html b/kodorvan/surikov/system/views/themes/default/footer.html old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/views/footer.html rename to kodorvan/surikov/system/views/themes/default/footer.html diff --git a/mirzaev/surikovlib/system/views/head.html b/kodorvan/surikov/system/views/themes/default/head.html old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/views/head.html rename to kodorvan/surikov/system/views/themes/default/head.html diff --git a/mirzaev/surikovlib/system/views/header.html b/kodorvan/surikov/system/views/themes/default/header.html old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/views/header.html rename to kodorvan/surikov/system/views/themes/default/header.html diff --git a/mirzaev/surikovlib/system/views/js.html b/kodorvan/surikov/system/views/themes/default/js.html old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/views/js.html rename to kodorvan/surikov/system/views/themes/default/js.html diff --git a/mirzaev/surikovlib/system/views/main/index.html b/kodorvan/surikov/system/views/themes/default/main/index.html old mode 100644 new mode 100755 similarity index 79% rename from mirzaev/surikovlib/system/views/main/index.html rename to kodorvan/surikov/system/views/themes/default/main/index.html index f113312..8823cfb --- a/mirzaev/surikovlib/system/views/main/index.html +++ b/kodorvan/surikov/system/views/themes/default/main/index.html @@ -1,4 +1,4 @@ -{% extends "core.html" %} +{% extends "/themes/default/core.html" %} {% block main %} diff --git a/mirzaev/surikovlib/system/views/pages/contacts/index.html b/kodorvan/surikov/system/views/themes/default/pages/contacts/index.html old mode 100644 new mode 100755 similarity index 98% rename from mirzaev/surikovlib/system/views/pages/contacts/index.html rename to kodorvan/surikov/system/views/themes/default/pages/contacts/index.html index 05e7d7f..d8bf47a --- a/mirzaev/surikovlib/system/views/pages/contacts/index.html +++ b/kodorvan/surikov/system/views/themes/default/pages/contacts/index.html @@ -1,4 +1,4 @@ -{% extends "core.html" %} +{% extends "/themes/default/core.html" %} {% block main %} diff --git a/mirzaev/surikovlib/system/views/pages/kemenov/index.html b/kodorvan/surikov/system/views/themes/default/pages/kemenov/index.html old mode 100644 new mode 100755 similarity index 97% rename from mirzaev/surikovlib/system/views/pages/kemenov/index.html rename to kodorvan/surikov/system/views/themes/default/pages/kemenov/index.html index 7d4f4c8..90ee665 --- a/mirzaev/surikovlib/system/views/pages/kemenov/index.html +++ b/kodorvan/surikov/system/views/themes/default/pages/kemenov/index.html @@ -1,4 +1,4 @@ -{% extends "core.html" %} +{% extends "/themes/default/core.html" %} {% block main %} diff --git a/mirzaev/surikovlib/system/views/pages/surikov/index.html b/kodorvan/surikov/system/views/themes/default/pages/surikov/index.html old mode 100644 new mode 100755 similarity index 98% rename from mirzaev/surikovlib/system/views/pages/surikov/index.html rename to kodorvan/surikov/system/views/themes/default/pages/surikov/index.html index 05e7d7f..d8bf47a --- a/mirzaev/surikovlib/system/views/pages/surikov/index.html +++ b/kodorvan/surikov/system/views/themes/default/pages/surikov/index.html @@ -1,4 +1,4 @@ -{% extends "core.html" %} +{% extends "/themes/default/core.html" %} {% block main %} diff --git a/mirzaev/surikovlib/system/views/sidebar.html b/kodorvan/surikov/system/views/themes/default/sidebar.html old mode 100644 new mode 100755 similarity index 50% rename from mirzaev/surikovlib/system/views/sidebar.html rename to kodorvan/surikov/system/views/themes/default/sidebar.html index faec26c..125ee07 --- a/mirzaev/surikovlib/system/views/sidebar.html +++ b/kodorvan/surikov/system/views/themes/default/sidebar.html @@ -1,6 +1,6 @@ -{% include 'auth.html' %} -{% include 'vk.html' %} +{% include '/themes/default/authentication.html' %} +{% include '/themes/default/vk.html' %} diff --git a/mirzaev/surikovlib/system/views/vk.html b/kodorvan/surikov/system/views/themes/default/vk.html old mode 100644 new mode 100755 similarity index 100% rename from mirzaev/surikovlib/system/views/vk.html rename to kodorvan/surikov/system/views/themes/default/vk.html diff --git a/mirzaev/surikovlib/system/controllers/accounts_controller.php b/mirzaev/surikovlib/system/controllers/accounts_controller.php deleted file mode 100644 index 396584b..0000000 --- a/mirzaev/surikovlib/system/controllers/accounts_controller.php +++ /dev/null @@ -1,168 +0,0 @@ - - */ -final class accounts_controller extends core -{ - /** - * Страница профиля - * - * @param array $vars - */ - public function index(array $vars = []): ?string - { - return null; - } - - /** - * Регистрация - * - * @param array $vars Параметры запроса - * - * @return string|null HTML-документ - */ - public function registration(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - if ($vars['account'] = accounts::registration(mail: $vars['mail'] ?? null, password: $vars['password'] ?? null, errors: $vars['errors'])) { - // Удалось зарегистрироваться - - if ($vars['account'] = accounts::authentication($vars['mail'] ?? null, $vars['password'] ?? null, (bool) ($vars['remember'] ?? false), $vars)) { - // Удалось аутентифицироваться - } else { - // Не удалось аутентифицироваться - - // Запись кода ответа - http_response_code(401); - } - } else { - // Не удалось зарегистрироваться - - // Запись кода ответа - http_response_code(401); - } - - // Инициализаци пути для перенаправления - $redirect = isset($vars['redirect']) ? $vars['redirect'] : $_SERVER['HTTP_REFERER'] ?? '/'; - - // Перенаправление - header("Location: $redirect", response_code: 303); - - return null; - } - - /** - * Аутентификация - * - * @param array $vars Параметры запроса - * - * @return string|null HTML-документ - */ - public function authentication(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - if ($vars['account'] = accounts::authentication($vars['mail'] ?? null, $vars['password'] ?? null, (bool) ($vars['remember'] ?? false), errors: $vars['errors'])) { - // Удалось аутентифицироваться - } else { - // Не удалось аутентифицироваться - - // Запись кода ответа - http_response_code(401); - } - - // Инициализаци пути для перенаправления - $redirect = isset($vars['redirect']) ? $vars['redirect'] : $_SERVER['HTTP_REFERER'] ?? '/'; - - // Перенаправление - header("Location: $redirect", response_code: 303); - - return null; - } - - /** - * Деаутентификация - * - * @param array $vars Параметры запроса - * - * @return string|null HTML-документ - */ - public function deauthentication(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - if (accounts::deauthentication(errors: $vars['errors'])) { - // Удалось деаутентифицироваться - - // Деинициализация аккаунта - $vars['account'] = null; - } else { - // Не удалось деаутентифицироваться - - // Запись кода ответа - http_response_code(500); - } - - // Перенаправление - header('Location: /', response_code: 303); - - return null; - } - - /** - * Данные аккаунта - * - * Если информацию запрашивает администратор, то вернётся вся, иначе только разрешённая публично - * - * @param array $vars Параметры запроса - * - * @return string JSON-документ - */ - public function data(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - if ($account = accounts::read(['id' => $vars['id']], $vars['errors'])) { - // Найдены данные запрашиваемого аккаунта - - // Инициализация аккаунта - $vars['account'] = accounts::init(errors: $vars['errors']); - - if ($vars['account'] && $vars['account']->permissions['accounts'] ?? 0 === 1) { - // Удалось аутентифицироваться и пройдена проверка авторизации - } else { - // Не удалось аутентифицироваться - - // Удаление запрещённых к публикации полей - $account->password = $account->hash = $account->time = null; - } - - // Генерация ответа - return json_encode($account ?? ''); - } else { - // Не найдены данные запрашиваемого аккаунта - - // Запись кода ответа - http_response_code(404); - } - - return null; - } -} diff --git a/mirzaev/surikovlib/system/controllers/books_controller.php b/mirzaev/surikovlib/system/controllers/books_controller.php deleted file mode 100644 index 5a193fd..0000000 --- a/mirzaev/surikovlib/system/controllers/books_controller.php +++ /dev/null @@ -1,191 +0,0 @@ - - */ -final class books_controller extends core -{ - /** - * Страница с книгами (или книгой) - * - * @param array $vars - */ - public function index(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - // Проверка аутентифицированности - $vars['account'] = accounts::init(errors: $vars['errors']); - - if (isset($vars['id'])) { - // Определённая книга - - // Чтение метаданных книги - $vars['book'] = books::read(['id' => $vars['id']])[0] ?? null; - - // Инициализация страницы - if (empty($vars['page']) || $vars['page'] < 0) $vars['page'] = 0; - - // Генерация представления - return $this->view->render(DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . 'book.html', $vars); - - } else { - // Все книги - - // Чтение книг - $vars['books'] = books::read(limit: 30, page: isset($vars['page']) && $vars['page'] > 0 ? $vars['page'] : 1); - - // Генерация представления - return $this->view->render(DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . 'index.html', $vars); - } - } - - /** - * Запись - * - * @param array $vars Параметры - * @param array $files Файлы - * - * @return string|null HTML-документ - */ - public function write(array $vars = [], array $files = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - if (accounts::init(errors: $vars['errors'])->access('books')) { - // Найден и авторизован аккаунт - - if (count($books = books::import($files['books'] ?? [], errors: $vars['errors'])) > 0) { - // Загружены книги - } else { - // Не загружены книги - } - } - - // Перенаправление - header('Location: /books', response_code: 303); - - return 'wtf'; - } - - /** - * Чтение - * - * @param array $vars - * - * @return string|null Файл, если найден - */ - public function read(array $vars = []): ?string - { - if (isset($vars['id'], $vars['file'])) { - // Найдены обязательные входные параметры - - // Инициализация пути до файла - $file = \STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $vars['id'] . DIRECTORY_SEPARATOR . $vars['file'] . '.jpg'; - - if (file_exists($file)) { - // Найден файл - - // Настройка заголовков - header('Content-Description: File Transfer'); - header('Content-Type: image/jpeg'); - header('Content-Disposition: attachment; filename=' . basename($file)); - header('Content-Transfer-Encoding: binary'); - header('Content-Length: ' . filesize($file)); - - // Очистить буфер вывода - ob_end_clean(); - - return file_get_contents($file); - } - } - - return null; - } - - /** - * Удаление - * - * @param array $vars Параметры запроса - * - * @return string|null HTML-документ - */ - public function delete(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - if (accounts::init(errors: $vars['errors'])->access('books')) { - // Найден и авторизован аккаунт - - if (isset($vars['id'])) { - // Найдены обязательные входные параметры - - if (books::delete((int) $vars['id'], $vars['errors'])) { - // Удалена книга из базы данных - - // Инициализация пути до книги - $book = \STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $vars['id']; - - if (file_exists($book)) { - // Найдена книга - - // Удаление книги - exec('rm -rf ' . escapeshellarg($book)); - - // Запись статуса выполнения в буфер вывода - $status = true; - } - } - } - } - - return json_encode([ - 'status' => $status ?? false, - 'errors' => $vars['errors'] - ]); - } - - /** - * Поворот - * - * @param array $vars - * - * @return string|null JSON - */ - public function rotate(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - if (accounts::init(errors: $vars['errors'])->access('books')) { - // Найден и авторизован аккаунт - - if (isset($vars['id'], $vars['page'])) { - // Найдены обязательные входные параметры - - // Поворот страницы - $status = books::rotate((int) $vars['id'], (int) $vars['page'], $vars['errors']); - } - } - - return json_encode([ - 'status' => $status ?? false, - 'errors' => $vars['errors'] - ]); - } -} diff --git a/mirzaev/surikovlib/system/controllers/contacts_controller.php b/mirzaev/surikovlib/system/controllers/contacts_controller.php deleted file mode 100644 index 130825c..0000000 --- a/mirzaev/surikovlib/system/controllers/contacts_controller.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final class contacts_controller extends core -{ - public function index(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - // Генерация представления - return $this->view->render(DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . 'contacts' . DIRECTORY_SEPARATOR . 'index.html', $vars); - } -} diff --git a/mirzaev/surikovlib/system/controllers/core.php b/mirzaev/surikovlib/system/controllers/core.php deleted file mode 100644 index c538d5c..0000000 --- a/mirzaev/surikovlib/system/controllers/core.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ -class core extends controller -{ - /** - * Конструктор - * - * @return void - */ - public function __construct() - { - parent::__construct(); - - // Инициализация ядра моделей (соединение с базой данных...) - new models(); - - $this->view = new manager; - } -} diff --git a/mirzaev/surikovlib/system/controllers/errors_controller.php b/mirzaev/surikovlib/system/controllers/errors_controller.php deleted file mode 100644 index 4263048..0000000 --- a/mirzaev/surikovlib/system/controllers/errors_controller.php +++ /dev/null @@ -1,31 +0,0 @@ - - */ -final class errors_controller extends core -{ - public function error404(): ?string - { - // Генерация представления - return 'Ошибка 404 (не найдено)'; - } - - public function error500(): ?string - { - // Генерация представления - return 'Ошибка 500 (на стороне сервера)'; - } -} diff --git a/mirzaev/surikovlib/system/controllers/kemenov_controller.php b/mirzaev/surikovlib/system/controllers/kemenov_controller.php deleted file mode 100644 index fddb25a..0000000 --- a/mirzaev/surikovlib/system/controllers/kemenov_controller.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final class kemenov_controller extends core -{ - public function index(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - // Генерация представления - return $this->view->render(DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . 'kemenov' . DIRECTORY_SEPARATOR . 'index.html', $vars); - } -} diff --git a/mirzaev/surikovlib/system/controllers/main_controller.php b/mirzaev/surikovlib/system/controllers/main_controller.php deleted file mode 100644 index 726b397..0000000 --- a/mirzaev/surikovlib/system/controllers/main_controller.php +++ /dev/null @@ -1,32 +0,0 @@ - - */ -final class main_controller extends core -{ - public function index(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - // Проверка аутентифицированности - $vars['account'] = accounts::init(errors: $vars['errors']); - - // Генерация представления - return $this->view->render(DIRECTORY_SEPARATOR . 'main' . DIRECTORY_SEPARATOR . 'index.html', $vars); - } -} diff --git a/mirzaev/surikovlib/system/controllers/surikov_controller.php b/mirzaev/surikovlib/system/controllers/surikov_controller.php deleted file mode 100644 index 86d7b3e..0000000 --- a/mirzaev/surikovlib/system/controllers/surikov_controller.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -final class surikov_controller extends core -{ - public function index(array $vars = []): ?string - { - // Инициализация журнала ошибок - $vars['errors'] = []; - - // Генерация представления - return $this->view->render(DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . 'surikov' . DIRECTORY_SEPARATOR . 'index.html', $vars); - } -} diff --git a/mirzaev/surikovlib/system/models/accounts_model.php b/mirzaev/surikovlib/system/models/accounts_model.php deleted file mode 100644 index 5498526..0000000 --- a/mirzaev/surikovlib/system/models/accounts_model.php +++ /dev/null @@ -1,638 +0,0 @@ - - */ -final class accounts_model extends core -{ - /** - * Идентификатор - */ - public int $id; - - /** - * Почта - */ - public string $mail; - - /** - * Пароль - */ - public string $password; - - /** - * Хеш - */ - public ?string $hash; - - /** - * Время активности хеша - */ - public int $time; - - /** - * Время активности хеша - */ - public array $permissions; - - /** - * Конструктор - * - * @param array $vars Параметры - */ - public function __construct(array $vars = []) { - foreach ($vars as $key => $value) { - // Перебор параметров - - // Запись свойства - if (property_exists($this, $key)) $this->$key = $value; - } - } - - /** - * Регистрация - * - * @param string $mail Почта - * @param string $password Пароль - * @param bool $authenticate Автоматическая аутентификация в случае успешной регистрации - * @param array &$errors Журнал ошибок - * - * @return static|null Аккаунт - */ - public static function registration(string $mail, string $password, bool $authenticate = true, array &$errors = []): ?static - { - // Инициализация журнала ошибок - $errors['account'] ?? $errors['account'] = []; - - try { - if (static::init(errors: $errors)) { - // Аутентифицирован пользователь - - // Запись ошибки - throw new exception('Уже аутентифицирован'); - } - - if (empty($account = static::read(['mail' => $mail]))) { - // Не удалось найти аккаунт - - if (static::write($mail, $password, $errors)) { - // Удалось зарегистрироваться - - if ($authenticate) { - // Запрошена аутентификация - - // Аутентификация - $account = static::authentication($mail, $password, true, $errors); - } - - return $account; - } - } else { - // Удалось найти аккаунт - - return $account; - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return null; - } - - /** - * Аутентификация - * - * @param string $mail Почта - * @param string $password Пароль - * @param bool $remember Функция "Запомнить меня" - увеличенное время хранения cookies - * @param array &$errors Журнал ошибок - * - * @return static|null Аккаунт - */ - public static function authentication(string $mail, string $password, bool $remember = false, array &$errors = []): ?static - { - // Инициализация журнала ошибок - $errors['account'] ?? $errors['account'] = []; - - try { - if (static::init(errors: $errors)) { - // Аутентифицирован пользователь - - // Запись ошибки - throw new exception('Уже аутентифицирован'); - } - - if (empty($account = static::read(['mail' => $mail]))) { - // Не удалось найти аккаунт - - throw new exception('Не удалось найти аккаунт'); - } - - - if (password_verify($password, $account->password)) { - // Совпадают хеши паролей - - // Инициализация идентификатора сессии - session_id((string) $account->id); - - // Инициализация названия сессии - session_name('id'); - - // Инициализация сессии - session_start(); - - // Инициализация времени хранения хеша - $time = time() + ($remember ? 604800 : 86400); - - // Инициализация хеша - $hash = static::hash((int) $account->id, crypt($account->password, time() . $account->id), $time, $errors)['hash']; - - // Инициализация cookies - setcookie('hash', $hash, $time, path: '/', secure: true); - - return $account; - } else { - // Не совпадают хеши паролей - - throw new exception('Неправильный пароль'); - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return null; - } - - /** - * Аутентификация - * - * @param array &$errors Журнал ошибок - * - * @return bool Удалось ли деаутентифицироваться - */ - public static function deauthentication(array &$errors = []): bool - { - // Инициализация журнала ошибок - $errors['account'] ?? $errors['account'] = []; - - try { - if ($account = static::init(errors: $errors)) { - // Аутентифицирован пользователь - - // Инициализация запроса - $request = static::$db->prepare("UPDATE `accounts` SET `hash` = null, `time` = 0 WHERE `id` = :id"); - - // Параметры запроса - $params = [ - ":id" => $account->id, - ]; - - // Отправка запроса - $request->execute($params); - - // Генерация ответа - $request->fetch(pdo::FETCH_ASSOC); - - // Деинициализация cookies - setcookie('id', '', 0, path: '/', secure: true); - setcookie('hash', '', 0, path: '/', secure: true); - - return true; - } else { - // Не аутентифицирован пользователь - - // Запись ошибки - throw new exception('Не аутентифицирован'); - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return false; - } - - /** - * Инициализация - * - * @param int|null $account Аккаунт (идентификатор) - * @param array &$errors Журнал ошибок - * - * @return static|null Аккаунт - */ - public static function init(?int $account = null, array &$errors = []): ?static - { - // Инициализация журнала ошибок - $errors['account'] ?? $errors['account'] = []; - - try { - if (isset($account)) { - // Получен идентификатор аккаунта - - if (empty($account = static::read(['id' => $account]))) { - // Не найден аккаунт - - // Генерация ошибки - throw new exception('Не найден пользователь'); - } - } else if (!empty($_COOKIE['id']) && !empty($_COOKIE['hash'])) { - // Найдены cookie с данными аккаунта (подразумевается, что он аутентифицирован) - - if ($_COOKIE['hash'] === static::hash((int) $_COOKIE['id'], errors: $errors)['hash']) { - // Совпадает переданный хеш с тем, что хранится в базе данных - } else { - // Не совпадает переданный хеш с тем, что хранится в базе данных - - // Генерация ошибки - throw new exception('Вы аутентифицированы с другого устройства (не совпадают хеши аутентификации)'); - } - - if (empty($account = static::read([ - 'id' => $_COOKIE['id'], - 'hash' => $_COOKIE['hash'] - ]))) { - // Не найден аккаунт или связка аккаунта с хешем - - // Генерация ошибки - throw new exception('Не найден пользователь или время аутентификации истекло'); - } - } else { - // Не найдены параметры для поиска аккаунта - - return null; - } - - // Чтение разрешений - $account->permissions = static::permissions((int) $account->id, $errors); - - return $account; - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][]= [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return null; - - } - - /** - * Прочитать разрешения из базы данных - * - * @param int $id Идентификатор аккаунта - * @param array &$errors Журнал ошибок - * - * @return array Разрешения аккаунта, если найдены - */ - public static function permissions(int $id, array &$errors = []): array - { - // Инициализация журнала ошибок - $errors['account'] ?? $errors['account'] = []; - - try { - // Инициализация запроса - $request = static::$db->prepare("SELECT * FROM `permissions` WHERE `id` = :id"); - - // Параметры запроса - $params = [ - ":id" => $id - ]; - - // Отправка запроса - $request->execute($params); - - // Генерация ответа - if (empty($response = $request->fetch(pdo::FETCH_ASSOC))) { - // Не найдены разрешения - - // Генерация ошибки - throw new exception('Не найдены разрешения'); - } - - // Удаление ненужных данных - unset($response['id']); - - return $response; - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return []; - } - - /** - * Проверить разрешение - * - * @param string $permission Разрешение - * @param array &$errors Журнал ошибок - * - * @return bool|null Статус разрешения, если оно записано - */ - public function access(string $permission, array &$errors = []): ?bool - { - // Инициализация журнала ошибок - $errors['account'] ?? $errors['account'] = []; - - try { - return isset($this->permissions[$permission]) ? (bool) $this->permissions[$permission] : null; - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][]= [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return null; - } - - /** - * Запись в базу данных - * - * @param string $mail Почта - * @param string $password Пароль - * @param array &$errors Журнал ошибок - * - * @return static|null Аккаунт - */ - public static function write(string $mail, string $password, array &$errors = []): ?static - { - // Инициализация журнала ошибок - $errors['account'] ?? $errors['account'] = []; - - try { - // Инициализация параметров запроса - $params = []; - - try { - // Проверка параметра - if (filter_var($mail, FILTER_VALIDATE_mail) === false) throw new exception('Не удалось распознать почту'); - if (iconv_strlen($mail) < 3) throw new exception('Длина почты должна быть не менее 3 символов'); - if (iconv_strlen($mail) > 60) throw new exception('Длина почты должна быть не более 80 символов'); - - // Запись в буфер параметров запроса - $params[':mail'] = $mail; - - // Проверка параметра - if (iconv_strlen($password) < 3) throw new exception('Длина пароля должна быть не менее 3 символов'); - if (iconv_strlen($password) > 60) throw new exception('Длина пароля должна быть не более 120 символов'); - - // Запись в буфер параметров запроса - $params[':password'] = password_hash($password, PASSWORD_BCRYPT); - - // Инициализация запроса - $request = static::$db->prepare("INSERT INTO `accounts` (" . (isset($name) ? '`name`' : '') . (isset($name) && isset($mail) ? ', ' : '') . (isset($mail) ? '`mail`' : '') . ((isset($name) || isset($mail)) && isset($password) ? ', ' : '') . (isset($password) ? '`password`' : '') . ") VALUES (" . (isset($name) ? ':name' : '') . (isset($name) && isset($mail) ? ', ' : '') . (isset($mail) ? ':mail' : '') . ((isset($name) || isset($mail)) && isset($password) ? ', ' : '') . (isset($password) ? ':password' : '') . ")"); - - // Отправка запроса - $request->execute($params); - - // Генерация ответа - $request->fetch(pdo::FETCH_ASSOC); - - // Чтение аккаунта - $account = static::read(['mail' => $mail]); - - // Инициализация запроса - $request = static::$db->prepare("INSERT INTO `permissions` (`id`) VALUES (:id)"); - - // Инициализация параметров - $params = [ - ':id' => $account->id - ]; - - // Отправка запроса - $request->execute($params); - - // Генерация ответа - $request->fetch(pdo::FETCH_ASSOC); - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - // Конец выполнения - end: - - return $account ?? []; - } - - /** - * Чтение из базы данных - * - * @param array $expression Выражение поиска ('поле' => 'значение') - * @param array &$errors Журнал ошибок - * - * @return static|null Аккаунт - */ - public static function read(array $expression, array &$errors = []): ?static - { - // Инициализация журнала ошибок - $errors['account'] ?? $errors['account'] = []; - - try { - // Инициализация выражения поиска - $where = 'WHERE '; - - // Инициализация параметров запроса - $params = []; - - foreach ($expression as $parameter => $value) { - // Перебор выражения поиска - - // Запись в строку запроса - $where .= "`$parameter` = :$parameter &&"; - - // Запись параметров запроса - $params[":$parameter"] = $value; - } - - // Очистка или реинициализация выражения поиска - $where = empty($expression) ? '' : trim(trim($where, '&&')); - - // Инициализация запроса - $request = static::$db->prepare("SELECT * FROM `accounts` $where LIMIT 1"); - - // Отправка запроса - $request->execute($params); - - // Генерация ответа - if ($account = new static($request->fetch(pdo::FETCH_ASSOC))) { - // Найден аккаунт - - try { - if ($permissions = static::permissions((int) $account->id, $errors)) { - // Найдены разрешения - - // Запись в буфер данных аккаунта - $account->permissions = $permissions; - } else { - // Не найдены разрешения - - throw new exception('Не удалось найти и прочитать разрешения'); - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine() - ]; - } - } else { - // Не найден аккаунт - - throw new exception('Не удалось найти аккаунт'); - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][]= [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return $account ?? null; - } - - /** - * Запись или чтение хеша из базы данных - * - * @param int $id Идентификатор аккаунта - * @param int|null $hash Хеш аутентифиакции - * @param string|null $time Время хранения хеша - * @param array &$errors Журнал ошибок - * - * @return array ['hash' => $hash, 'time' => $time] - */ - public static function hash(int $id, string|null $hash = null, int|null $time = null, array &$errors = []): array - { - // Инициализация журнала ошибок - $errors['account'] ?? $errors['account'] = []; - - try { - if (isset($hash, $time)) { - // Переданы хеш и его время хранения - - // Инициализация запроса - $request = static::$db->prepare("UPDATE `accounts` SET `hash` = :hash, `time` = :time WHERE `id` = :id"); - - // Параметры запроса - $params = [ - ":id" => $id, - ":hash" => $hash, - ":time" => $time, - ]; - - // Отправка запроса - $request->execute($params); - - // Генерация ответа - $request->fetch(pdo::FETCH_ASSOC); - } else { - // Не переданы хеш и его время хранения - - // Инициализация запроса - $request = static::$db->prepare("SELECT `hash`, `time` FROM `accounts` WHERE `id` = :id"); - - // Параметры запроса - $params = [ - ":id" => $id, - ]; - - // Отправка запроса - $request->execute($params); - - // Генерация ответа - extract((array) $request->fetch(pdo::FETCH_ASSOC)); - - if (!empty($response['time']) && $response['time'] <= time()) { - // Истекло время жизни хеша - - // Инициализация запроса - $request = static::$db->prepare("UPDATE `accounts` SET `hash` = :hash, `time` = :time WHERE `id` = :id"); - - // Параметры запроса - $params = [ - ":id" => $id, - ":hash" => null, - ":time" => null, - ]; - - // Отправка запроса - $request->execute($params); - - // Генерация ответа - $response = $request->fetch(pdo::FETCH_ASSOC); - - // Генерация ошибки - throw new exception('Время аутентификации истекло'); - } - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['account'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return ['hash' => $hash, 'time' => $time]; - } -} diff --git a/mirzaev/surikovlib/system/models/books_model.php b/mirzaev/surikovlib/system/models/books_model.php deleted file mode 100644 index 524aa80..0000000 --- a/mirzaev/surikovlib/system/models/books_model.php +++ /dev/null @@ -1,358 +0,0 @@ - - */ -final class books_model extends core -{ - /** - * Запись в базу данных - * - * @param string $title Название - * @param string|null $description Описание - * @param int|null $account Аккаунт (идентификатор) - * @param array &$errors Журнал ошибок - * - * @return int|null Идентификатор записанной книги - */ - public static function write(string $title, ?string $description = null, ?int $account = null, array &$errors = []): ?int - { - // Инициализация журнала ошибок - $errors['books'] ?? $errors['books'] = []; - - try { - // Инициализация аккаунта - $account = accounts::init($account, $errors); - - // Инициализация запроса - $request = static::$db->prepare("INSERT INTO `books` (`account`, `title`, `description`) VALUES (:account, :title, :description)"); - - // Инициализация параметров - $params = [ - ':account' => $account->id, - ':title' => $title, - ':description' => $description - ]; - - // Отправка запроса - $request->execute($params); - - if ($id = static::$db->lastInsertId()) { - // Получен идентификатор загруженной книги (подразумевается) - - return (int) $id; - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['books'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return null; - } - - /** - * Чтение - * - * @param array $expression Выражение поиска - * @param int $limit Ограничение по количеству - * @param int $page Страница (для списка книг) - * @param array &$errors Журнал ошибок - * - * @return array Книги - */ - public static function read(array $expression = [], int $limit = 1, int $page = 1, array &$errors = []): array - { - // Инициализация журнала ошибок - $errors['books'] ?? $errors['books'] = []; - - try { - // Инициализация выражения поиска - $where = 'WHERE '; - - // Инициализация параметров запроса - $params = []; - - foreach ($expression as $parameter => $value) { - // Перебор выражения поиска - - // Запись в строку запроса - $where .= "`$parameter` = :$parameter &&"; - - // Запись параметров запроса - $params[":$parameter"] = $value; - } - - // Очистка или реинициализация выражения поиска - $where = empty($expression) ? '' : trim(trim($where, '&&')); - - // Инициализация страницы - $page = $limit * --$page; - - // Инициализация запроса - $request = static::$db->prepare("SELECT * FROM `books` $where LIMIT $page, $limit"); - - // Отправка запроса - $request->execute($params); - - return (array) $request->fetchAll(pdo::FETCH_ASSOC); - } catch (exception $e) { - // Запись в журнал ошибок - $errors['books'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return []; - } - - /** - * Удаление из базы данных - * - * @param int $id Идентификатор - * @param array &$errors Журнал ошибок - * - * @return bool Статус выполнения - */ - public static function delete(int $id, array &$errors = []): bool - { - // Инициализация журнала ошибок - $errors['books'] ?? $errors['books'] = []; - - try { - // Инициализация запроса - $request = static::$db->prepare("DELETE FROM `books` WHERE `id` = :id LIMIT 1"); - - // Отправка запроса - $request->execute([':id' => $id]); - - return true; - } catch (exception $e) { - // Запись в журнал ошибок - $errors['books'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return false; - } - - /** - * Импорт - * - * @param array $books Книги (файлы) - * @param int|null $account Аккаунт (идентификатор) - * @param array &$errors Журнал ошибок - * - * @return array Записанные книги - */ - public static function import(array $books, ?int $account = null, array &$errors = []): array - { - // Инициализация журнала ошибок - $errors['books'] ?? $errors['books'] = []; - - try { - if (empty($books)) { - // Не найдены книги - - throw new exception('Не найдены книги для записи'); - } - - // Инициализация аккаунта - $account = accounts::init($account, $errors); - - // Инициализация буфера инициализированных книг - $initialized = []; - - for ($i = -1; count($books['name']) > ++$i;) { - // Перебор загруженных книг - - // Генерация хеша файла - $hash = hash_file('md5', $books['tmp_name'][$i]) ?? 0; - - if (move_uploaded_file($books['tmp_name'][$i], \STORAGE . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $hash . '_' . $books['name'][$i])) { - // Загружен и перемещён из временной папки файл с книгой - - // Извлечение имени файла - - // Запись в буфер инициализированных книг - $initialized[] = [ - 'name' => preg_replace('/\.pdf/', '', $books['name'])[0], - 'file' => $hash . '_' . $books['name'][$i] - ]; - } - } - - // Инициализация буфера записанных книг - $writed = []; - - foreach ($initialized as $book) { - // Перебор инициализированных книг - - try { - if ($id = static::write($book['name'], 'Без описания', $account->id ?? null, $errors)) { - // Записана в базу данных книга - - // Инициализация пути до хранилища - $directory = \STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $id . DIRECTORY_SEPARATOR; - - // Инициализация директории - if (!file_exists($directory)) if (!mkdir($directory, 0755, true)) throw new exception('Не удалось записать директорию для книги'); - - // Инициализация пути до временного файла - $file = \STORAGE . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $book['file']; - - // Извлечение изображений из PDF-документа - exec("pdfimages -j '$file' '$directory'"); - - // Переименование файлов в необходимый формат - exec("echo 'export j=-1; for i in $directory*.jpg; do let j+=1; mv \$i $directory\$j.jpg; done' | bash"); - - // Запись в буфер записанных книг - $writed[] = $id; - } else { - // Не записана в базу данных книга - - throw new exception('Не удалось записать книгу в базу данных', 500); - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['books'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['books'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return $writed ?? []; - } - - /** - * Чтение - * - * @param int $id Идентификатор - * @param int $page Страница (сдвиг) - * @param array &$errors Журнал ошибок - * - * @return bool Статус выполнения - */ - public static function rotate(int $id, int $page = 1, array &$errors = []): bool - { - // Инициализация журнала ошибок - $errors['books'] ?? $errors['books'] = []; - - try { - // Инициализация запроса - $request = static::$db->prepare("SELECT EXISTS (SELECT * FROM `books` WHERE `id` = :id LIMIT 1)"); - - // Отправка запроса - $request->execute([':id' => $id]); - - if ($request->fetch(pdo::FETCH_NUM)[0] === 1) { - // Найдена книга - - // Инициализация пути книги - $book = \STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $id; - - // Инициализация пути до файла - $file = $book . DIRECTORY_SEPARATOR . "$page.jpg"; - - // Инициализация пути до нового местоположения файла - $old = $book . DIRECTORY_SEPARATOR . 'old' . DIRECTORY_SEPARATOR . "$page.jpg"; - - // Инициализация директории - if (!file_exists($book)) throw new exception('Не удалось найти директорию книги'); - - // Инициализация директории оригинальных изображений - if (!file_exists($book . DIRECTORY_SEPARATOR . 'old')) if (!mkdir($book . DIRECTORY_SEPARATOR . 'old', 0755, true)) throw new exception('Не удалось записать директорию для оригинальных страниц книги'); - - // Перемещение страницы в директорию оригинальных страниц - exec("mv $file $old"); - - // Переворачивание файла и возвращение на нужное местоположение - exec("jpegtran -rotate 90 $old > $file"); - - return true; - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['books'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return false; - } - - /** - * Подсчёт количества страниц - * - * @param int $id Идентификатор - * @param array &$errors Журнал ошибок - * - * @return int|null Количество страниц - */ - public static function amount(int $id, array &$errors = []): ?int - { - // Инициализация журнала ошибок - $errors['books'] ?? $errors['books'] = []; - - try { - // Инициализация счётчика - $amount = -1; - - while (true) { - // Перебор директорий (!!! Рекурсия !!!) - - // Перебор изображений по возрастанию (от 0.jpg до 999.jpg и т.д.) - if (!file_exists(\STORAGE . DIRECTORY_SEPARATOR . 'books' . DIRECTORY_SEPARATOR . $id . DIRECTORY_SEPARATOR . ++$amount . '.jpg')) return $amount; - } - } catch (exception $e) { - // Запись в журнал ошибок - $errors['books'][] = [ - 'text' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'stack' => $e->getTrace() - ]; - } - - return null; - } -} diff --git a/mirzaev/surikovlib/system/models/core.php b/mirzaev/surikovlib/system/models/core.php deleted file mode 100644 index fb5326f..0000000 --- a/mirzaev/surikovlib/system/models/core.php +++ /dev/null @@ -1,139 +0,0 @@ - - */ -class core extends model -{ - /** - * Соединение с базой данных - */ - protected static PDO $db ; - - public function __construct(pdo $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 pdo) { - // Передано подходящее значение - - // Запись свойства (успех) - self::$db = $value; - } else { - // Передано неподходящее значение - - // Выброс исключения (неудача) - throw new exception('Соединение с базой данных ($this->db) должен быть инстанцией PDO', 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 pdo(\TYPE . ':dbname=' . \BASE . ';host=' . \HOST, LOGIN, PASSWORD)); - } - - 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/surikovlib/system/public/Nginx_1.21_vhost.conf b/mirzaev/surikovlib/system/public/Nginx_1.21_vhost.conf deleted file mode 100644 index 2ea3356..0000000 --- a/mirzaev/surikovlib/system/public/Nginx_1.21_vhost.conf +++ /dev/null @@ -1,105 +0,0 @@ -# ---------------------------- -# Host config -# ---------------------------- - -server { - - listen %ip%:%httpport%; - listen %ip%:%httpsport% ssl http2; - - server_name surikovlib.loc %aliases%; - root '%hostdir%'; - limit_conn addr 64; - autoindex off; - index index.php index.html index.htm; - - ssl_certificate '%sprogdir%/userdata/config/cert_files/server.crt'; - ssl_certificate_key '%sprogdir%/userdata/config/cert_files/server.key'; - # ssl_trusted_certificate ''; - - # Force HTTPS - # add_header Strict-Transport-Security 'max-age=2592000' always; - # if ($scheme ~* ^(?!https).*$) { - # return 301 https://$host$request_uri; - # } - - # Force www.site.com => site.com - # if ($host ~* ^www\.(.+)$) { - # return 301 $scheme://$1$request_uri; - # } - # Disable access to backup/config/command/log files - # if ($uri ~* ^.+\.(?:bak|co?nf|in[ci]|log|orig|sh|sql|tar|sql|t?gz|cmd|bat)$) { - # return 404; - # } - # Disable access to hidden files/folders - if ($uri ~* /\.(?!well-known)) { - return 404; - } - - # Disable MIME sniffing - add_header X-Content-Type-Options 'nosniff' always; - - location ~* ^.+\.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv|svgz?|ttf|ttc|otf|eot|woff2?)$ { - expires 1d; - access_log off; - } - - location / { - # Force index.php routing (if not found) - try_files $uri $uri/ /index.php$is_args$args; - - # Force index.php routing (all requests) - # rewrite ^/(.*)$ /index.php?/$1 last; - - location ~ \.php$ { - try_files $fastcgi_script_name =404; - - # limit_conn addr 16; - # limit_req zone=flood burst=32 nodelay; - - # add_header X-Frame-Options 'SAMEORIGIN' always; - # add_header Referrer-Policy 'no-referrer-when-downgrade' always; - # CSP syntax: (http: https: data: mediastream: blob: filesystem:) 'self' 'unsafe-inline' 'unsafe-eval' 'none' - # Content-Security-Policy-Report-Only (report-uri https://site.com/csp/) - # add_header Content-Security-Policy "default-src 'self'; connect-src 'self'; font-src 'self'; frame-src 'self'; img-src 'self'; manifest-src 'self'; media-src 'self'; object-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; base-uri 'none'; form-action 'self'; frame-ancestors 'self'; upgrade-insecure-requests" always; - fastcgi_pass backend; - include '%sprogdir%/userdata/config/nginx_fastcgi_params.txt'; - } - } - - # Service configuration (do not edit!) - # ---------------------------- - location /openserver/ { - root '%sprogdir%/modules/system/html'; - autoindex off; - index index.php index.html index.htm; - - %allow%allow all; - allow 127.0.0.0/8; - allow ::1/128; - allow %ips%; - deny all; - - location ~* ^/openserver/.+\.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv|svgz?|ttf|ttc|otf|eot|woff2?)$ { - expires 1d; - access_log off; - } - - location /openserver/server-status { - stub_status on; - } - - location ~ ^/openserver/.*\.php$ { - try_files $fastcgi_script_name =404; - fastcgi_index index.php; - fastcgi_pass backend; - include '%sprogdir%/userdata/config/nginx_fastcgi_params.txt'; - } - } - # End service configuration - # ---------------------------- -} - -# ---------------------------- -# End host config -# ---------------------------- diff --git a/mirzaev/surikovlib/system/public/index.php b/mirzaev/surikovlib/system/public/index.php deleted file mode 100644 index 6757108..0000000 --- a/mirzaev/surikovlib/system/public/index.php +++ /dev/null @@ -1,49 +0,0 @@ -write('/', 'main', 'index'); -$router->write('/account/registration', 'accounts', 'registration', 'POST'); -$router->write('/account/authentication', 'accounts', 'authentication', 'POST'); -$router->write('/account/deauthentication', 'accounts', 'deauthentication', 'POST'); -$router->write('/account/deauthentication', 'accounts', 'deauthentication', 'GET'); -$router->write('/books', 'books', 'index', 'GET'); -$router->write('/books/$id', 'books', 'index', 'GET'); -$router->write('/books/$id/$page', 'books', 'index', 'GET'); -$router->write('/books/$id/$page/rotate', 'books', 'rotate', 'POST'); -$router->write('/books/$id/delete', 'books', 'delete', 'POST'); -$router->write('/storage/books/$id/$file', 'books', 'read', 'GET'); -$router->write('/storage/books/write', 'books', 'write', 'POST'); -$router->write('/kemenov', 'kemenov', 'index', 'GET'); -$router->write('/surikov', 'surikov', 'index', 'GET'); -$router->write('/contacts', 'contacts', 'index', 'GET'); - -// Инициализация ядра -$core = new core(namespace: __NAMESPACE__, router: $router); - -// Обработка запроса -echo $core->start(); diff --git a/mirzaev/surikovlib/system/views/manager.php b/mirzaev/surikovlib/system/views/manager.php deleted file mode 100644 index 62485ee..0000000 --- a/mirzaev/surikovlib/system/views/manager.php +++ /dev/null @@ -1,25 +0,0 @@ - - */ -final class manager extends controller -{ - public function render(string $file, array $vars = []): ?string - { - // Генерация представления - return (new view(new FilesystemLoader(VIEWS)))->render($file, $vars); - } -}