Compare commits
No commits in common. "stable" and "0.1.0" have entirely different histories.
|
@ -1 +0,0 @@
|
||||||
vendor
|
|
|
@ -1,42 +1,25 @@
|
||||||
{
|
{
|
||||||
"name": "mirzaev/tordv-calculator",
|
"name": "mirzaev/calculator",
|
||||||
"description": "Калькулятор стоимости услуг по обработке металла",
|
"description": "Калькулятор рассчетов затрат для предприятия по резке металла",
|
||||||
"type": "site",
|
"type": "project",
|
||||||
"keywords": [
|
"license": "AGPL-3.0-or-later",
|
||||||
"site",
|
"homepage": "https://git.hood.su/mirzaev/calculator",
|
||||||
"calculator"
|
|
||||||
],
|
|
||||||
"readme": "README.md",
|
|
||||||
"homepage": "https://git.mirzaev.sexy/mirzaev/tordv-calculator",
|
|
||||||
"license": "WTFPL",
|
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
||||||
"email": "arsen@mirzaev.sexy",
|
"email": "arsen@mirzaev.sexy",
|
||||||
"homepage": "https://mirzaev.sexy",
|
"homepage": "https://mirzaev.sexy",
|
||||||
"role": "Programmer"
|
"role": "Developer"
|
||||||
}
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"email": "arsen@mirzaev.sexy",
|
|
||||||
"docs": "https://git.mirzaev.sexy/mirzaev/tordv-calculator/wiki",
|
|
||||||
"issues": "https://git.mirzaev.sexy/mirzaev/tordv-calculator/issues"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "funding",
|
|
||||||
"url": "https://fund.mirzaev.sexy"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.0.0",
|
"php": "^8.0.0",
|
||||||
"mirzaev/minimal": "^2.0.x-dev",
|
"mirzaev/minimal": "^2.0.x-dev",
|
||||||
"twig/twig": "^3.3",
|
"twig/twig": "^3.3"
|
||||||
"phpoffice/phpspreadsheet": "^1.20"
|
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"mirzaev\\tordv\\calculator\\": "mirzaev/tordv/calculator/system"
|
"mirzaev\\calculator\\": "mirzaev/calculator/system"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,267 +4,21 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "d63372480c8f1c3719fb9e69026eef21",
|
"content-hash": "0d3565d9ca1cb09d4e7dff2f43559d81",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
|
||||||
"name": "ezyang/htmlpurifier",
|
|
||||||
"version": "v4.16.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/ezyang/htmlpurifier.git",
|
|
||||||
"reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/523407fb06eb9e5f3d59889b3978d5bfe94299c8",
|
|
||||||
"reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"cerdic/css-tidy": "^1.7 || ^2.0",
|
|
||||||
"simpletest/simpletest": "dev-master"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
|
|
||||||
"ext-bcmath": "Used for unit conversion and imagecrash protection",
|
|
||||||
"ext-iconv": "Converts text to and from non-UTF-8 encodings",
|
|
||||||
"ext-tidy": "Used for pretty-printing HTML"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"files": [
|
|
||||||
"library/HTMLPurifier.composer.php"
|
|
||||||
],
|
|
||||||
"psr-0": {
|
|
||||||
"HTMLPurifier": "library/"
|
|
||||||
},
|
|
||||||
"exclude-from-classmap": [
|
|
||||||
"/library/HTMLPurifier/Language/"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"LGPL-2.1-or-later"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Edward Z. Yang",
|
|
||||||
"email": "admin@htmlpurifier.org",
|
|
||||||
"homepage": "http://ezyang.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Standards compliant HTML filter written in PHP",
|
|
||||||
"homepage": "http://htmlpurifier.org/",
|
|
||||||
"keywords": [
|
|
||||||
"html"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/ezyang/htmlpurifier/issues",
|
|
||||||
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.16.0"
|
|
||||||
},
|
|
||||||
"time": "2022-09-18T07:06:19+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "maennchen/zipstream-php",
|
|
||||||
"version": "v2.4.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
|
||||||
"reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3",
|
|
||||||
"reference": "3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-mbstring": "*",
|
|
||||||
"myclabs/php-enum": "^1.5",
|
|
||||||
"php": "^8.0",
|
|
||||||
"psr/http-message": "^1.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"ext-zip": "*",
|
|
||||||
"friendsofphp/php-cs-fixer": "^3.9",
|
|
||||||
"guzzlehttp/guzzle": "^6.5.3 || ^7.2.0",
|
|
||||||
"mikey179/vfsstream": "^1.6",
|
|
||||||
"php-coveralls/php-coveralls": "^2.4",
|
|
||||||
"phpunit/phpunit": "^8.5.8 || ^9.4.2",
|
|
||||||
"vimeo/psalm": "^5.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"ZipStream\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Paul Duncan",
|
|
||||||
"email": "pabs@pablotron.org"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Jonatan Männchen",
|
|
||||||
"email": "jonatan@maennchen.ch"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Jesse Donat",
|
|
||||||
"email": "donatj@gmail.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "András Kolesár",
|
|
||||||
"email": "kolesar@kolesar.hu"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
|
|
||||||
"keywords": [
|
|
||||||
"stream",
|
|
||||||
"zip"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
|
|
||||||
"source": "https://github.com/maennchen/ZipStream-PHP/tree/v2.4.0"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/maennchen",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://opencollective.com/zipstream",
|
|
||||||
"type": "open_collective"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2022-12-08T12:29:14+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "markbaker/complex",
|
|
||||||
"version": "3.0.2",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/MarkBaker/PHPComplex.git",
|
|
||||||
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
|
|
||||||
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "^7.2 || ^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
|
||||||
"phpcompatibility/php-compatibility": "^9.3",
|
|
||||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
|
|
||||||
"squizlabs/php_codesniffer": "^3.7"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Complex\\": "classes/src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Mark Baker",
|
|
||||||
"email": "mark@lange.demon.co.uk"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PHP Class for working with complex numbers",
|
|
||||||
"homepage": "https://github.com/MarkBaker/PHPComplex",
|
|
||||||
"keywords": [
|
|
||||||
"complex",
|
|
||||||
"mathematics"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/MarkBaker/PHPComplex/issues",
|
|
||||||
"source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
|
|
||||||
},
|
|
||||||
"time": "2022-12-06T16:21:08+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "markbaker/matrix",
|
|
||||||
"version": "3.0.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/MarkBaker/PHPMatrix.git",
|
|
||||||
"reference": "728434227fe21be27ff6d86621a1b13107a2562c"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
|
|
||||||
"reference": "728434227fe21be27ff6d86621a1b13107a2562c",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "^7.1 || ^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
|
||||||
"phpcompatibility/php-compatibility": "^9.3",
|
|
||||||
"phpdocumentor/phpdocumentor": "2.*",
|
|
||||||
"phploc/phploc": "^4.0",
|
|
||||||
"phpmd/phpmd": "2.*",
|
|
||||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
|
|
||||||
"sebastian/phpcpd": "^4.0",
|
|
||||||
"squizlabs/php_codesniffer": "^3.7"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Matrix\\": "classes/src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Mark Baker",
|
|
||||||
"email": "mark@demon-angel.eu"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PHP Class for working with matrices",
|
|
||||||
"homepage": "https://github.com/MarkBaker/PHPMatrix",
|
|
||||||
"keywords": [
|
|
||||||
"mathematics",
|
|
||||||
"matrix",
|
|
||||||
"vector"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
|
|
||||||
"source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
|
|
||||||
},
|
|
||||||
"time": "2022-12-02T22:17:43+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "mirzaev/minimal",
|
"name": "mirzaev/minimal",
|
||||||
"version": "2.0.x-dev",
|
"version": "2.0.x-dev",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.mirzaev.sexy/mirzaev/minimal",
|
"url": "https://git.hood.su/mirzaev/minimal",
|
||||||
"reference": "1f5685a20d41c1c11742f33138764b835ddd0198"
|
"reference": "b6f90b700116f20fe48725166ddfb8f6d27ae52d"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "~8.1"
|
"php": "~8.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-PDO": "To work with SQL-based databases (MySQL, PostreSQL...)"
|
"ext-PDO": "Для работы с базами данных на SQL (MySQL, PostreSQL...)"
|
||||||
},
|
},
|
||||||
"type": "framework",
|
"type": "framework",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -284,424 +38,42 @@
|
||||||
"role": "Developer"
|
"role": "Developer"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "Lightweight MVC framework that manages only the basic mechanisms, leaving the development of the programmer and not overloading the project",
|
"description": "Легковесный MVC фреймворк который следует твоим правилам, а не диктует свои",
|
||||||
"homepage": "https://git.mirzaev.sexy/mirzaev/minimal",
|
"homepage": "https://git.hood.su/mirzaev/minimal",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"framework",
|
"framework",
|
||||||
"mvc"
|
"mvc"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"docs": "https://git.mirzaev.sexy/mirzaev/minimal/wiki",
|
"docs": "https://git.hood.su/mirzaev/minimal/manual",
|
||||||
"issues": "https://git.mirzaev.sexy/mirzaev/minimal/issues"
|
"issues": "https://git.hood.su/mirzaev/minimal/issues"
|
||||||
},
|
},
|
||||||
"time": "2022-11-03T06:09:32+00:00"
|
"time": "2021-11-12T13:20:13+00:00"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "myclabs/php-enum",
|
|
||||||
"version": "1.8.4",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/myclabs/php-enum.git",
|
|
||||||
"reference": "a867478eae49c9f59ece437ae7f9506bfaa27483"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/myclabs/php-enum/zipball/a867478eae49c9f59ece437ae7f9506bfaa27483",
|
|
||||||
"reference": "a867478eae49c9f59ece437ae7f9506bfaa27483",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-json": "*",
|
|
||||||
"php": "^7.3 || ^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "^9.5",
|
|
||||||
"squizlabs/php_codesniffer": "1.*",
|
|
||||||
"vimeo/psalm": "^4.6.2"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"MyCLabs\\Enum\\": "src/"
|
|
||||||
},
|
|
||||||
"classmap": [
|
|
||||||
"stubs/Stringable.php"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "PHP Enum contributors",
|
|
||||||
"homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PHP Enum implementation",
|
|
||||||
"homepage": "http://github.com/myclabs/php-enum",
|
|
||||||
"keywords": [
|
|
||||||
"enum"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/myclabs/php-enum/issues",
|
|
||||||
"source": "https://github.com/myclabs/php-enum/tree/1.8.4"
|
|
||||||
},
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"url": "https://github.com/mnapoli",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2022-08-04T09:53:51+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "phpoffice/phpspreadsheet",
|
|
||||||
"version": "1.26.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
|
|
||||||
"reference": "5b6ceea9705b068f993e268e4debc566c2637063"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/5b6ceea9705b068f993e268e4debc566c2637063",
|
|
||||||
"reference": "5b6ceea9705b068f993e268e4debc566c2637063",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"ext-ctype": "*",
|
|
||||||
"ext-dom": "*",
|
|
||||||
"ext-fileinfo": "*",
|
|
||||||
"ext-gd": "*",
|
|
||||||
"ext-iconv": "*",
|
|
||||||
"ext-libxml": "*",
|
|
||||||
"ext-mbstring": "*",
|
|
||||||
"ext-simplexml": "*",
|
|
||||||
"ext-xml": "*",
|
|
||||||
"ext-xmlreader": "*",
|
|
||||||
"ext-xmlwriter": "*",
|
|
||||||
"ext-zip": "*",
|
|
||||||
"ext-zlib": "*",
|
|
||||||
"ezyang/htmlpurifier": "^4.15",
|
|
||||||
"maennchen/zipstream-php": "^2.1",
|
|
||||||
"markbaker/complex": "^3.0",
|
|
||||||
"markbaker/matrix": "^3.0",
|
|
||||||
"php": "^7.4 || ^8.0",
|
|
||||||
"psr/http-client": "^1.0",
|
|
||||||
"psr/http-factory": "^1.0",
|
|
||||||
"psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
|
|
||||||
"dompdf/dompdf": "^1.0 || ^2.0",
|
|
||||||
"friendsofphp/php-cs-fixer": "^3.2",
|
|
||||||
"mitoteam/jpgraph": "^10.2.4",
|
|
||||||
"mpdf/mpdf": "^8.1.1",
|
|
||||||
"phpcompatibility/php-compatibility": "^9.3",
|
|
||||||
"phpstan/phpstan": "^1.1",
|
|
||||||
"phpstan/phpstan-phpunit": "^1.0",
|
|
||||||
"phpunit/phpunit": "^8.5 || ^9.0",
|
|
||||||
"squizlabs/php_codesniffer": "^3.7",
|
|
||||||
"tecnickcom/tcpdf": "^6.5"
|
|
||||||
},
|
|
||||||
"suggest": {
|
|
||||||
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
|
|
||||||
"ext-intl": "PHP Internationalization Functions",
|
|
||||||
"mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
|
|
||||||
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
|
|
||||||
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Maarten Balliauw",
|
|
||||||
"homepage": "https://blog.maartenballiauw.be"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Mark Baker",
|
|
||||||
"homepage": "https://markbakeruk.net"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Franck Lefevre",
|
|
||||||
"homepage": "https://rootslabs.net"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Erik Tilt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Adrien Crivelli"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
|
|
||||||
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
|
|
||||||
"keywords": [
|
|
||||||
"OpenXML",
|
|
||||||
"excel",
|
|
||||||
"gnumeric",
|
|
||||||
"ods",
|
|
||||||
"php",
|
|
||||||
"spreadsheet",
|
|
||||||
"xls",
|
|
||||||
"xlsx"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
|
|
||||||
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.26.0"
|
|
||||||
},
|
|
||||||
"time": "2022-12-21T12:22:06+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "psr/http-client",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/php-fig/http-client.git",
|
|
||||||
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
|
|
||||||
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": "^7.0 || ^8.0",
|
|
||||||
"psr/http-message": "^1.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "1.0.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Psr\\Http\\Client\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "PHP-FIG",
|
|
||||||
"homepage": "http://www.php-fig.org/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Common interface for HTTP clients",
|
|
||||||
"homepage": "https://github.com/php-fig/http-client",
|
|
||||||
"keywords": [
|
|
||||||
"http",
|
|
||||||
"http-client",
|
|
||||||
"psr",
|
|
||||||
"psr-18"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/php-fig/http-client/tree/master"
|
|
||||||
},
|
|
||||||
"time": "2020-06-29T06:28:15+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "psr/http-factory",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/php-fig/http-factory.git",
|
|
||||||
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
|
|
||||||
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=7.0.0",
|
|
||||||
"psr/http-message": "^1.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "1.0.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Psr\\Http\\Message\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "PHP-FIG",
|
|
||||||
"homepage": "http://www.php-fig.org/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Common interfaces for PSR-7 HTTP message factories",
|
|
||||||
"keywords": [
|
|
||||||
"factory",
|
|
||||||
"http",
|
|
||||||
"message",
|
|
||||||
"psr",
|
|
||||||
"psr-17",
|
|
||||||
"psr-7",
|
|
||||||
"request",
|
|
||||||
"response"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/php-fig/http-factory/tree/master"
|
|
||||||
},
|
|
||||||
"time": "2019-04-30T12:38:16+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "psr/http-message",
|
|
||||||
"version": "1.0.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/php-fig/http-message.git",
|
|
||||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
|
||||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=5.3.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "1.0.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Psr\\Http\\Message\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "PHP-FIG",
|
|
||||||
"homepage": "http://www.php-fig.org/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Common interface for HTTP messages",
|
|
||||||
"homepage": "https://github.com/php-fig/http-message",
|
|
||||||
"keywords": [
|
|
||||||
"http",
|
|
||||||
"http-message",
|
|
||||||
"psr",
|
|
||||||
"psr-7",
|
|
||||||
"request",
|
|
||||||
"response"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/php-fig/http-message/tree/master"
|
|
||||||
},
|
|
||||||
"time": "2016-08-06T14:39:51+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "psr/simple-cache",
|
|
||||||
"version": "3.0.0",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/php-fig/simple-cache.git",
|
|
||||||
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
|
|
||||||
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"php": ">=8.0.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-master": "3.0.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"Psr\\SimpleCache\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"MIT"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "PHP-FIG",
|
|
||||||
"homepage": "https://www.php-fig.org/"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Common interfaces for simple caching",
|
|
||||||
"keywords": [
|
|
||||||
"cache",
|
|
||||||
"caching",
|
|
||||||
"psr",
|
|
||||||
"psr-16",
|
|
||||||
"simple-cache"
|
|
||||||
],
|
|
||||||
"support": {
|
|
||||||
"source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
|
|
||||||
},
|
|
||||||
"time": "2021-10-29T13:26:27+00:00"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-ctype",
|
"name": "symfony/polyfill-ctype",
|
||||||
"version": "v1.27.0",
|
"version": "v1.23.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
|
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
|
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
|
||||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
|
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.1"
|
"php": ">=7.1"
|
||||||
},
|
},
|
||||||
"provide": {
|
|
||||||
"ext-ctype": "*"
|
|
||||||
},
|
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-ctype": "For best performance"
|
"ext-ctype": "For best performance"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "1.27-dev"
|
"dev-main": "1.23-dev"
|
||||||
},
|
},
|
||||||
"thanks": {
|
"thanks": {
|
||||||
"name": "symfony/polyfill",
|
"name": "symfony/polyfill",
|
||||||
|
@ -709,12 +81,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
|
||||||
"bootstrap.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Symfony\\Polyfill\\Ctype\\": ""
|
"Symfony\\Polyfill\\Ctype\\": ""
|
||||||
}
|
},
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
|
@ -739,7 +111,7 @@
|
||||||
"portable"
|
"portable"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
|
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -755,35 +127,32 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-11-03T14:55:06+00:00"
|
"time": "2021-02-19T12:13:01+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-mbstring",
|
"name": "symfony/polyfill-mbstring",
|
||||||
"version": "v1.27.0",
|
"version": "v1.23.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
|
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
|
||||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.1"
|
"php": ">=7.1"
|
||||||
},
|
},
|
||||||
"provide": {
|
|
||||||
"ext-mbstring": "*"
|
|
||||||
},
|
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-mbstring": "For best performance"
|
"ext-mbstring": "For best performance"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-main": "1.27-dev"
|
"dev-main": "1.23-dev"
|
||||||
},
|
},
|
||||||
"thanks": {
|
"thanks": {
|
||||||
"name": "symfony/polyfill",
|
"name": "symfony/polyfill",
|
||||||
|
@ -791,12 +160,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
|
||||||
"bootstrap.php"
|
|
||||||
],
|
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Symfony\\Polyfill\\Mbstring\\": ""
|
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||||
}
|
},
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
"license": [
|
"license": [
|
||||||
|
@ -822,7 +191,7 @@
|
||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
|
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -838,20 +207,20 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-11-03T14:55:06+00:00"
|
"time": "2021-05-27T12:26:48+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
"version": "v3.4.3",
|
"version": "v3.3.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/twigphp/Twig.git",
|
"url": "https://github.com/twigphp/Twig.git",
|
||||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58"
|
"reference": "a27fa056df8a6384316288ca8b0fa3a35fdeb569"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a27fa056df8a6384316288ca8b0fa3a35fdeb569",
|
||||||
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58",
|
"reference": "a27fa056df8a6384316288ca8b0fa3a35fdeb569",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -866,7 +235,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "3.4-dev"
|
"dev-master": "3.3-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
@ -902,7 +271,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/twigphp/Twig/issues",
|
"issues": "https://github.com/twigphp/Twig/issues",
|
||||||
"source": "https://github.com/twigphp/Twig/tree/v3.4.3"
|
"source": "https://github.com/twigphp/Twig/tree/v3.3.3"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -914,7 +283,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2022-09-28T08:42:51+00:00"
|
"time": "2021-09-17T08:44:23+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
|
@ -929,5 +298,5 @@
|
||||||
"php": "^8.0.0"
|
"php": "^8.0.0"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.3.0"
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace mirzaev\calculator\controllers;
|
||||||
|
|
||||||
|
use mirzaev\calculator\controllers\core;
|
||||||
|
|
||||||
|
use Twig\Loader\FilesystemLoader;
|
||||||
|
use Twig\Environment as view;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Контроллер основной страницы
|
||||||
|
*
|
||||||
|
* @package mirzaev\calculator\controllers
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
final class calculator_controller extends core
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Калькулятор
|
||||||
|
*
|
||||||
|
* HTML-код с калькулятором
|
||||||
|
*
|
||||||
|
* @param array $vars Параметры
|
||||||
|
*/
|
||||||
|
public function index(array $vars = []): ?string
|
||||||
|
{
|
||||||
|
// Генерация представления
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'calculator' . DIRECTORY_SEPARATOR . 'index.html', $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Модуль: "тип пользователя"
|
||||||
|
*
|
||||||
|
* HTML-код с кнопками: "физическое лицо" и "юридическое лицо"
|
||||||
|
*
|
||||||
|
* @param array $vars Параметры
|
||||||
|
*/
|
||||||
|
public function buyer(array $vars = []): ?string
|
||||||
|
{
|
||||||
|
// Инициализация параметров
|
||||||
|
$vars['buyer'] = $vars['value'] ?? 'individual';
|
||||||
|
|
||||||
|
// Удаление параметров
|
||||||
|
unset($vars['value']);
|
||||||
|
|
||||||
|
// Генерация представления
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'buyer.html', $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Модуль: "сложность"
|
||||||
|
*
|
||||||
|
* HTML-код с кнопками: "легко", "средне" и "сложно"
|
||||||
|
*
|
||||||
|
* @param array $vars Параметры
|
||||||
|
*/
|
||||||
|
public function complexity(array $vars = []): ?string
|
||||||
|
{
|
||||||
|
// Инициализация параметров
|
||||||
|
$vars['complexity'] = $vars['value'] ?? 'medium';
|
||||||
|
|
||||||
|
// Удаление параметров
|
||||||
|
unset($vars['value']);
|
||||||
|
|
||||||
|
// Генерация представления
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'complexity.html', $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Модуль: "меню"
|
||||||
|
*
|
||||||
|
* HTML-код с кнопками добавления калькуляторов
|
||||||
|
*
|
||||||
|
* @param array $vars Параметры
|
||||||
|
*/
|
||||||
|
public function menu(array $vars = []): ?string
|
||||||
|
{
|
||||||
|
// Генерация представления
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'menu.html', $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Модуль: "результат"
|
||||||
|
*
|
||||||
|
* HTML-код с данными результата калькуляции
|
||||||
|
*
|
||||||
|
* @param array $vars Параметры
|
||||||
|
*/
|
||||||
|
public function result(array $vars = []): ?string
|
||||||
|
{
|
||||||
|
// Генерация представления
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'result.html', $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Модуль: "разделитель"
|
||||||
|
*
|
||||||
|
* HTML-код с разделителем элементов
|
||||||
|
*
|
||||||
|
* @param array $vars Параметры
|
||||||
|
*/
|
||||||
|
public function divider(array $vars = []): ?string
|
||||||
|
{
|
||||||
|
// Генерация представления
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'divider.html', $vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Лазерная резка
|
||||||
|
*
|
||||||
|
* HTML-код с калькулятором лазерной резки
|
||||||
|
*
|
||||||
|
* @param array $vars Параметры
|
||||||
|
*/
|
||||||
|
public function laser(array $vars = []): ?string
|
||||||
|
{
|
||||||
|
// Генерация представления
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'laser.html', $vars);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,17 +2,16 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\controllers;
|
namespace mirzaev\calculator\controllers;
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\views\manager;
|
use mirzaev\calculator\views\manager;
|
||||||
use mirzaev\tordv\calculator\models\core as models;
|
|
||||||
|
|
||||||
use mirzaev\minimal\controller;
|
use mirzaev\minimal\controller;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Менеджер представлений
|
* Менеджер представлений
|
||||||
*
|
*
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
* @package mirzaev\calculator\controllers
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
class core extends controller
|
class core extends controller
|
||||||
|
@ -26,9 +25,6 @@ class core extends controller
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
// Инициализация ядра моделей (соединение с базой данных...)
|
|
||||||
new models();
|
|
||||||
|
|
||||||
$this->view = new manager;
|
$this->view = new manager;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\controllers;
|
namespace mirzaev\calculator\controllers;
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\controllers\core;
|
use mirzaev\calculator\controllers\core;
|
||||||
|
|
||||||
use Twig\Loader\FilesystemLoader;
|
use Twig\Loader\FilesystemLoader;
|
||||||
use Twig\Environment as view;
|
use Twig\Environment as view;
|
||||||
|
@ -12,25 +12,19 @@ use Twig\Environment as view;
|
||||||
/**
|
/**
|
||||||
* Контроллер основной страницы
|
* Контроллер основной страницы
|
||||||
*
|
*
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
* @package mirzaev\calculator\controllers
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
final class errors_controller extends core
|
final class errors_controller extends core
|
||||||
{
|
{
|
||||||
public function error404(): string
|
public function error404()
|
||||||
{
|
{
|
||||||
// Запись кода ответа
|
|
||||||
http_response_code(404);
|
|
||||||
|
|
||||||
// Генерация представления
|
// Генерация представления
|
||||||
return 'Не найдено (404)';
|
return 'Не найдено (404)';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function error500(): string
|
public function error500()
|
||||||
{
|
{
|
||||||
// Запись кода ответа
|
|
||||||
http_response_code(500);
|
|
||||||
|
|
||||||
// Генерация представления
|
// Генерация представления
|
||||||
return 'Внутренняя ошибка (500)';
|
return 'Внутренняя ошибка (500)';
|
||||||
}
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace mirzaev\calculator\controllers;
|
||||||
|
|
||||||
|
use mirzaev\calculator\controllers\core;
|
||||||
|
|
||||||
|
use Twig\Loader\FilesystemLoader;
|
||||||
|
use Twig\Environment as view;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Контроллер основной страницы
|
||||||
|
*
|
||||||
|
* @package mirzaev\calculator\controllers
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
final class main_controller extends core
|
||||||
|
{
|
||||||
|
public function index(array $params = [])
|
||||||
|
{
|
||||||
|
// Генерация представления
|
||||||
|
return $this->view->render(DIRECTORY_SEPARATOR . 'main' . DIRECTORY_SEPARATOR . 'index.html');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#authentication>form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authentication>form>input:is([type="text"], [type="password"]) {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authentication>form>input:last-child {
|
||||||
|
margin-bottom: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authentication>form>.submit {
|
||||||
|
margin-top: 6px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authentication>form>.submit>label {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border: unset;
|
||||||
|
border-radius: 3px 0 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#authentication>form>.submit>input {
|
||||||
|
padding: 10px 20px;
|
||||||
|
flex-grow: 1;
|
||||||
|
border: unset;
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
#calculator :is(a, label)[type="button"] {
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 15px 20px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator :is(a, label)[type="button"]:last-child {
|
||||||
|
margin-right: unset;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>section:first-of-type {
|
||||||
|
margin-top: 35px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>section:last-child {
|
||||||
|
margin-bottom: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>section :is(a, label)[type="button"] {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>section :is(a, label)[type="button"]>img {
|
||||||
|
height: 70px;
|
||||||
|
margin: 8px auto 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>#result>:last-child {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>#result,
|
||||||
|
#calculator>#result :last-child>p {
|
||||||
|
font-weight: bold;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>#result :last-child>p * {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>#result>:last-child,
|
||||||
|
#calculator>#result :last-child>p>:is(#expenses, #income, #profit) {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>#result :last-child>p>:last-child {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>.divider+h3 {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting']) {
|
||||||
|
padding: 5px 30px 10px 30px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div>label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: auto 15px auto auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div:not(:last-child) {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div>div {
|
||||||
|
width: 60%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div>div {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div>div>:is(input, small, span):not(.measured, :last-child) {
|
||||||
|
margin-right: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div>div>:is(input, .unit) {
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div>div>input {
|
||||||
|
width: 25px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div>div>input.measured {
|
||||||
|
padding-right: 3px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div>div>small {
|
||||||
|
margin: auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#calculator>:is([id^='laser'], [id^='plasma'], [id^='bending'], [id^='painting'])>div>div>input+.unit {
|
||||||
|
margin: auto 0;
|
||||||
|
padding-top: unset;
|
||||||
|
padding-bottom: unset;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
* {
|
* {
|
||||||
font-family: "open sans";
|
font-family: "open sans";
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
@ -27,7 +26,6 @@ aside>section>h3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
:is(main, aside) {
|
:is(main, aside) {
|
||||||
min-height: calc(100vh - calc(16px + 40px) - 150px - 30px - 30px);
|
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
|
@ -46,10 +44,6 @@ main {
|
||||||
grid-column: 3;
|
grid-column: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
main>section {
|
|
||||||
min-height: 25vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
main>section>h2 {
|
main>section>h2 {
|
||||||
margin-left: 1.5rem;
|
margin-left: 1.5rem;
|
||||||
margin-top: unset;
|
margin-top: unset;
|
||||||
|
@ -61,6 +55,7 @@ main>section>h2+.divider {
|
||||||
margin-top: -1rem;
|
margin-top: -1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
header {
|
header {
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -74,7 +69,7 @@ header>nav {
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
padding: 8px 20%;
|
padding: 8px calc(18.5% - 20px);
|
||||||
position: sticky;
|
position: sticky;
|
||||||
display: flex;
|
display: flex;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
@ -95,11 +90,6 @@ header>nav *:hover,
|
||||||
header>nav>#logo>img:hover::before {
|
header>nav>#logo>img:hover::before {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
header>nav *:is(:active, :focus),
|
|
||||||
header>nav>#logo>img:is(:active, :focus)::before {
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
header>nav>#logo>img {
|
header>nav>#logo>img {
|
||||||
height: inherit;
|
height: inherit;
|
||||||
|
@ -170,7 +160,6 @@ input[type="submit"]:hover {
|
||||||
input[type="radio"]:checked+label[type="button"],
|
input[type="radio"]:checked+label[type="button"],
|
||||||
input[type="submit"]:is(:active, :focus) {
|
input[type="submit"]:is(:active, :focus) {
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
outline: none;
|
|
||||||
background-color: #aa4646;
|
background-color: #aa4646;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,22 +168,14 @@ input:is([type="checkbox"], [type="radio"]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
select,
|
select,
|
||||||
input:is([type="text"], [type="number"], [type="range"], [type="password"]),
|
input:is([type="text"], [type="password"]),
|
||||||
input:is([type="text"], [type="number"], [type="range"], [type="password"]).measured + .unit {
|
input:is([type="text"], [type="password"]).measured + .unit {
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
outline: unset;
|
outline: unset;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border: unset;
|
border: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="range"] {
|
|
||||||
cursor: grab;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="range"]:active {
|
|
||||||
cursor: grabbing;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
padding-top: unset;
|
padding-top: unset;
|
||||||
padding-bottom: unset;
|
padding-bottom: unset;
|
||||||
|
@ -205,7 +186,7 @@ select {
|
||||||
}
|
}
|
||||||
|
|
||||||
select.measured,
|
select.measured,
|
||||||
input:is([type="text"], [type="number"], [type="range"], [type="password"]).measured {
|
input:is([type="text"], [type="password"]).measured {
|
||||||
margin-right: unset;
|
margin-right: unset;
|
||||||
padding-right: 3px;
|
padding-right: 3px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
@ -213,7 +194,7 @@ input:is([type="text"], [type="number"], [type="range"], [type="password"]).meas
|
||||||
}
|
}
|
||||||
|
|
||||||
select.measured + .unit,
|
select.measured + .unit,
|
||||||
input:is([type="text"], [type="number"], [type="range"], [type="password"]).measured + .unit {
|
input:is([type="text"], [type="password"]).measured + .unit {
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
padding-left: unset;
|
padding-left: unset;
|
||||||
display: inline;
|
display: inline;
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace mirzaev\calculator;
|
||||||
|
|
||||||
|
use mirzaev\minimal\core;
|
||||||
|
use mirzaev\minimal\router;
|
||||||
|
|
||||||
|
define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views'));
|
||||||
|
|
||||||
|
// Автозагрузка
|
||||||
|
require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||||
|
|
||||||
|
// Инициализация маршрутазитора
|
||||||
|
$router = new router;
|
||||||
|
|
||||||
|
// Запись маршрутов
|
||||||
|
$router->write('/', 'main', 'index');
|
||||||
|
$router->write('/calculator', 'calculator', 'index');
|
||||||
|
$router->write('/calculator/generate/buyer', 'calculator', 'buyer');
|
||||||
|
$router->write('/calculator/generate/complexity', 'calculator', 'complexity');
|
||||||
|
$router->write('/calculator/generate/menu', 'calculator', 'menu');
|
||||||
|
$router->write('/calculator/generate/result', 'calculator', 'result');
|
||||||
|
$router->write('/calculator/generate/divider', 'calculator', 'divider');
|
||||||
|
$router->write('/calculator/generate/laser', 'calculator', 'laser');
|
||||||
|
|
||||||
|
// Инициализация ядра
|
||||||
|
$core = new Core(namespace: __NAMESPACE__, router: $router);
|
||||||
|
|
||||||
|
// Обработка запроса
|
||||||
|
echo $core->start();
|
|
@ -0,0 +1,257 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
let calculator = {
|
||||||
|
index: document.getElementById("calculator"),
|
||||||
|
calculators: [],
|
||||||
|
settings: {
|
||||||
|
defaults: {
|
||||||
|
buyer: 'individual',
|
||||||
|
complexity: 'hard',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
init() {
|
||||||
|
// Инициализация калькулятора
|
||||||
|
|
||||||
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ИЗБАВИТЬСЯ ОТ ТАЙМАУТОВ
|
||||||
|
|
||||||
|
this.generate.buyer(this.settings.defaults.buyer);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.generate.complexity(this.settings.defaults.complexity);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.generate.menu();
|
||||||
|
setTimeout(() => {
|
||||||
|
// this.calculate();
|
||||||
|
this.generate.result();
|
||||||
|
}, 100);
|
||||||
|
}, 100);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
console.log('[КАЛЬКУЛЯТОР] Инициализирован');
|
||||||
|
},
|
||||||
|
calculate(repeated = false) {
|
||||||
|
let result = document.getElementById("result");
|
||||||
|
|
||||||
|
if (result === null) {
|
||||||
|
// Не найден элемент с данными рассчета
|
||||||
|
|
||||||
|
// Инициализия
|
||||||
|
this.generate.result();
|
||||||
|
|
||||||
|
if (repeated === false) {
|
||||||
|
// Это первое выполнение функции в потенциальном цикле
|
||||||
|
|
||||||
|
// Повтор операции
|
||||||
|
this.calculate(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
generate: {
|
||||||
|
buyer(value = 'individual') {
|
||||||
|
// Запрос и генерация HTML с данными о типе покупателя (юр. лицо и физ. лицо)
|
||||||
|
|
||||||
|
const request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.open('GET', '/calculator/generate/buyer?value=' + value);
|
||||||
|
|
||||||
|
request.setRequestHeader('Content-Type', 'application/x-www-form-url');
|
||||||
|
|
||||||
|
request.addEventListener("readystatechange", () => {
|
||||||
|
if (request.readyState === 4 && request.status === 200) {
|
||||||
|
calculator.index.insertAdjacentHTML('beforeend', request.responseText);
|
||||||
|
|
||||||
|
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с кнопками выбора типа покупателя');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
},
|
||||||
|
complexity(value = 'medium') {
|
||||||
|
// Запрос и генерация HTML с данными о сложности работы
|
||||||
|
|
||||||
|
const request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.open('GET', '/calculator/generate/complexity?value=' + value);
|
||||||
|
|
||||||
|
request.setRequestHeader('Content-Type', 'application/x-www-form-url');
|
||||||
|
|
||||||
|
request.addEventListener("readystatechange", () => {
|
||||||
|
if (request.readyState === 4 && request.status === 200) {
|
||||||
|
calculator.index.insertAdjacentHTML('beforeend', request.responseText);
|
||||||
|
|
||||||
|
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с кнопками выбора сложности');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
},
|
||||||
|
menu() {
|
||||||
|
// Запрос и генерация HTML с кнопками добавления калькулятора
|
||||||
|
|
||||||
|
const request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.open('GET', '/calculator/generate/menu');
|
||||||
|
|
||||||
|
request.setRequestHeader('Content-Type', 'application/x-www-form-url');
|
||||||
|
|
||||||
|
request.addEventListener("readystatechange", () => {
|
||||||
|
if (request.readyState === 4 && request.status === 200) {
|
||||||
|
calculator.index.insertAdjacentHTML('beforeend', request.responseText);
|
||||||
|
|
||||||
|
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с кнопками добавления калькулятора');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
},
|
||||||
|
result() {
|
||||||
|
// Запрос и генерация HTML с данными о результате калькуляции
|
||||||
|
|
||||||
|
const request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.open('GET', '/calculator/generate/result');
|
||||||
|
|
||||||
|
request.setRequestHeader('Content-Type', 'application/x-www-form-url');
|
||||||
|
|
||||||
|
request.addEventListener("readystatechange", () => {
|
||||||
|
if (request.readyState === 4 && request.status === 200) {
|
||||||
|
calculator.index.insertAdjacentHTML('beforeend', request.responseText);
|
||||||
|
|
||||||
|
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с данными о результате калькуляции');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
},
|
||||||
|
divider(element, position) {
|
||||||
|
// Запрос и генерация HTML с данными о результате калькуляции
|
||||||
|
|
||||||
|
const request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.open('GET', '/calculator/generate/divider');
|
||||||
|
|
||||||
|
request.setRequestHeader('Content-Type', 'application/x-www-form-url');
|
||||||
|
|
||||||
|
request.addEventListener("readystatechange", () => {
|
||||||
|
if (request.readyState === 4 && request.status === 200) {
|
||||||
|
|
||||||
|
if (element === undefined || position === undefined) {
|
||||||
|
// Не задан элемент и позиция добавляемого разделителя
|
||||||
|
|
||||||
|
// Запись разделителя в конце калькулятора
|
||||||
|
calculator.index.insertAdjacentHTML('beforeend', request.responseText);
|
||||||
|
} else {
|
||||||
|
// Задан элемент и позиция добавляемого разделителя
|
||||||
|
|
||||||
|
// Запись разделителя по заданным параметрам
|
||||||
|
element.insertAdjacentHTML(position, request.responseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[КАЛЬКУЛЯТОР] Загружен разделитель');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
},
|
||||||
|
calculators: {
|
||||||
|
laser() {
|
||||||
|
// Запрос и генерация HTML с калькулятором лазерной резки
|
||||||
|
|
||||||
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ИЗБАВИТЬСЯ ОТ ТАЙМАУТОВ
|
||||||
|
|
||||||
|
const request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.open('GET', '/calculator/generate/laser');
|
||||||
|
|
||||||
|
request.setRequestHeader('Content-Type', 'application/x-www-form-url');
|
||||||
|
|
||||||
|
request.addEventListener("readystatechange", () => {
|
||||||
|
if (request.readyState === 4 && request.status === 200) {
|
||||||
|
// Поиск последнего калькулятора
|
||||||
|
let last = calculator.calculators[calculator.calculators.length - 1];
|
||||||
|
|
||||||
|
if (last !== undefined && last !== null) {
|
||||||
|
// Найден калькулятор
|
||||||
|
|
||||||
|
// Запись калькулятора после последнего калькулятора
|
||||||
|
last.insertAdjacentHTML('afterend', request.responseText);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// Инициализация разделителя перед меню
|
||||||
|
calculator.generate.divider(last, 'afterend');
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
// Не найден калькулятор
|
||||||
|
|
||||||
|
// Поиск меню
|
||||||
|
let menu = document.getElementById("menu");
|
||||||
|
|
||||||
|
if (menu !== null) {
|
||||||
|
// Найдено меню
|
||||||
|
|
||||||
|
// Инициализация разделителя перед меню
|
||||||
|
calculator.generate.divider(menu, 'beforebegin');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// Запись калькулятора перед меню
|
||||||
|
menu.insertAdjacentHTML('beforebegin', request.responseText);
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
// Не найдено меню
|
||||||
|
|
||||||
|
// Поиск результатов калькуляции
|
||||||
|
let result = document.getElementById("result");
|
||||||
|
|
||||||
|
if (result !== null) {
|
||||||
|
// Найден элемент с результатами калькуляции
|
||||||
|
|
||||||
|
// Инициализация разделителя перед меню
|
||||||
|
calculator.generate.divider(result, 'beforebegin');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// Запись калькулятора перед элементом с результатами калькуляции
|
||||||
|
result.insertAdjacentHTML('beforebegin', request.responseText);
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
// Не найден элемент с результатами калькуляции
|
||||||
|
|
||||||
|
// Инициализация разделителя перед меню
|
||||||
|
calculator.generate.divider();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// Запись калькулятора в конце калькулятора
|
||||||
|
calculator.index.insertAdjacentHTML('beforeend', request.responseText);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ИЗБАВИТЬСЯ ОТ ТАЙМАУТОВ
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// Поиск только что созданного калькулятора
|
||||||
|
let laser = document.getElementById('laser');
|
||||||
|
|
||||||
|
if (laser !== null) {
|
||||||
|
// Найден только что инициализированный (подразумевается) калькулятор лазерной резки
|
||||||
|
|
||||||
|
// Реинициализация идентификатора
|
||||||
|
laser.id = 'laser_' + calculator.calculators.length;
|
||||||
|
|
||||||
|
// Запись калькулятора в реестр
|
||||||
|
calculator.calculators.push(laser);
|
||||||
|
|
||||||
|
console.log('[КАЛЬКУЛЯТОР] Загружен калькулятор лазерной резки');
|
||||||
|
} else {
|
||||||
|
// Не найден только что инициализированный (подразумевается) калькулятор лазерной резки
|
||||||
|
|
||||||
|
console.log('[КАЛЬКУЛЯТОР] Не удалось инициализировать калькулятор лазерной резки');
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,26 @@
|
||||||
|
<link href="/css/auth.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<section id="authentication">
|
||||||
|
<h3>Аутентификация</h3>
|
||||||
|
<form method="post" accept-charset="UTF-8">
|
||||||
|
<input type="hidden" name="action" value="users/login">
|
||||||
|
|
||||||
|
<input id="loginName" type="text" name="loginName" placeholder="Почта"
|
||||||
|
value="{{ craft.app.user.rememberedUsername }}">
|
||||||
|
|
||||||
|
<input id="password" type="password" name="password" placeholder="Пароль">
|
||||||
|
|
||||||
|
<div class="submit">
|
||||||
|
<label class="button unselectable" for="rememberMe">
|
||||||
|
<i class="fas fa-unlock"></i>
|
||||||
|
</label>
|
||||||
|
<input type="checkbox" name="rememberMe" value="1">
|
||||||
|
|
||||||
|
<input type="submit" value="Войти">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if errorMessage is defined %}
|
||||||
|
<p>{{ errorMessage }}</p>
|
||||||
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
</section>
|
|
@ -5,7 +5,6 @@
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/cookie.js" defer></script>
|
|
||||||
<script type="text/javascript" src="/js/calculator.js" defer></script>
|
<script type="text/javascript" src="/js/calculator.js" defer></script>
|
||||||
<script>
|
<script>
|
||||||
if (document.readyState === "complete") {
|
if (document.readyState === "complete") {
|
|
@ -1,4 +1,4 @@
|
||||||
<section id="buyer" class="unselectable">
|
<section id="buyer">
|
||||||
<input id="individual" type="radio" name="buyer" value="individual" {% if buyer is same as('individual') %}checked{% endif %}>
|
<input id="individual" type="radio" name="buyer" value="individual" {% if buyer is same as('individual') %}checked{% endif %}>
|
||||||
<label type="button" for="individual">Физическое лицо</label>
|
<label type="button" for="individual">Физическое лицо</label>
|
||||||
<input id="entity" type="radio" name="buyer" value="entity" {% if buyer is same as('entity') %}checked{% endif %}>
|
<input id="entity" type="radio" name="buyer" value="entity" {% if buyer is same as('entity') %}checked{% endif %}>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<h3>Лазерная резка</h3>
|
||||||
|
<section id="laser">
|
||||||
|
<div>
|
||||||
|
<label>Металл</label>
|
||||||
|
<div>
|
||||||
|
<select name="metal">
|
||||||
|
<option value="steel">Сталь</option>
|
||||||
|
<option value="stainless_steel" selected>Нержавеющая сталь</option>
|
||||||
|
<option value="brass">Латунь</option>
|
||||||
|
<option value="copper">Медь</option>
|
||||||
|
<option value="aluminum">Алюминий</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Размер</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="measured" title="Длина" value="100">
|
||||||
|
<span class="unit unselectable">мм</span>
|
||||||
|
<small>x</small>
|
||||||
|
<input type="text" class="measured" title="Ширина" value="100">
|
||||||
|
<span class="unit unselectable">мм</span>
|
||||||
|
<small>x</small>
|
||||||
|
<input type="text" class="measured" title="Толщина" value="1">
|
||||||
|
<span class="unit unselectable">мм</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Отверстия</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="measured" title="Количество" value="1">
|
||||||
|
<span class="unit unselectable">шт</span>
|
||||||
|
<small>x</small>
|
||||||
|
<input type="text" class="measured" title="Диаметр" value="1">
|
||||||
|
<span class="unit unselectable">мм</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Количество</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="measured" title="Количество" value="1">
|
||||||
|
<span class="unit unselectable">шт</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
|
@ -1,4 +1,4 @@
|
||||||
<section id="menu" class="unselectable">
|
<section id="menu">
|
||||||
<a type="button" onclick="calculator.generate.calculators.laser(); return false;">
|
<a type="button" onclick="calculator.generate.calculators.laser(); return false;">
|
||||||
<img src="/img/laser.png" title="Добавить лазерную резку">
|
<img src="/img/laser.png" title="Добавить лазерную резку">
|
||||||
Лазерная резка
|
Лазерная резка
|
|
@ -1,4 +1,4 @@
|
||||||
<section id="complexity" class="unselectable">
|
<section id="complexity">
|
||||||
<input id="easy" type="radio" name="complexity" value="easy" {% if complexity is same as('easy') %}checked{% endif %}>
|
<input id="easy" type="radio" name="complexity" value="easy" {% if complexity is same as('easy') %}checked{% endif %}>
|
||||||
<label type="button" for="easy">
|
<label type="button" for="easy">
|
||||||
<img src="/img/easy.png" title="Лёгкий уровень сложности">
|
<img src="/img/easy.png" title="Лёгкий уровень сложности">
|
|
@ -0,0 +1 @@
|
||||||
|
<div class="divider"></div>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<section id="result">
|
||||||
|
<div>
|
||||||
|
<p>Расходы: <span id="expenses">0</span><span>рублей</span></p>
|
||||||
|
<p>Доход: <span id="income">0</span><span>рублей</span></p>
|
||||||
|
<p>Прибыль: <span id="profit">0</span><span>рублей</span></p>
|
||||||
|
</div>
|
||||||
|
</section>
|
|
@ -20,9 +20,7 @@
|
||||||
|
|
||||||
<aside>
|
<aside>
|
||||||
{% include 'sidebar.html' %}
|
{% include 'sidebar.html' %}
|
||||||
</aside>
|
</aside><!----><main>
|
||||||
|
|
||||||
<main>
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
{% include 'calculators/index.html' %}
|
{% include 'calculators/index.html' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -3,12 +3,7 @@
|
||||||
<a id="logo" href="/" title="Калькулятор расходов">
|
<a id="logo" href="/" title="Калькулятор расходов">
|
||||||
<img src="" alt="Калькулятор">
|
<img src="" alt="Калькулятор">
|
||||||
</a>
|
</a>
|
||||||
{% if account is not empty %}
|
|
||||||
<a class="link" href="/journal" title="Записи рассчётов">Журнал</a>
|
|
||||||
{% if account.permissions.settings is defined and account.permissions.settings == 1 %}
|
|
||||||
<a class="link" href="/settings" title="Настройки калькуляторов">Настройки</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
<a class="link" href="/contacts" title="Связь с администрацией">Контакты</a>
|
<a class="link" href="/contacts" title="Связь с администрацией">Контакты</a>
|
||||||
|
<a class="link" href="/journal" title="Записи рассчётов">Журнал</a>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\views;
|
namespace mirzaev\calculator\views;
|
||||||
|
|
||||||
use mirzaev\minimal\controller;
|
use mirzaev\minimal\controller;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use Twig\Environment as view;
|
||||||
/**
|
/**
|
||||||
* Менеджер представлений
|
* Менеджер представлений
|
||||||
*
|
*
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
* @package mirzaev\calculator\controllers
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
*/
|
*/
|
||||||
final class manager extends controller
|
final class manager extends controller
|
|
@ -1,158 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\controllers;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\controllers\core;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\accounts_model as accounts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Контроллер пользователей
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class accounts_controller extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Страница профиля
|
|
||||||
*
|
|
||||||
* @param array $params
|
|
||||||
*
|
|
||||||
* @todo 1. При истечению срока хранения куки аутентификации почему- то калькулятор ещё думает, что я аутентифицирован (вероятно одна из кук остаётся жива)
|
|
||||||
*/
|
|
||||||
public function index(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Регистрация
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры запроса
|
|
||||||
*
|
|
||||||
* @return string|null HTML-документ
|
|
||||||
*/
|
|
||||||
public function registration(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['account' => []];
|
|
||||||
|
|
||||||
if ($vars['account'] = accounts::registration(email: $vars['email'] ?? null, password: $vars['password'] ?? null, errors: $vars['errors']['account'])) {
|
|
||||||
// Удалось зарегистрироваться
|
|
||||||
|
|
||||||
if ($vars['account'] = accounts::authentication($vars['email'] ?? null, $vars['password'] ?? null, (bool) ($vars['remember'] ?? false), $vars)) {
|
|
||||||
// Удалось аутентифицироваться
|
|
||||||
} else {
|
|
||||||
// Не удалось аутентифицироваться
|
|
||||||
|
|
||||||
// Запись кода ответа
|
|
||||||
http_response_code(401);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Не удалось зарегистрироваться
|
|
||||||
|
|
||||||
// Запись кода ответа
|
|
||||||
http_response_code(401);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'main' . DIRECTORY_SEPARATOR . 'index.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Аутентификация
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры запроса
|
|
||||||
*
|
|
||||||
* @return string|null HTML-документ
|
|
||||||
*/
|
|
||||||
public function authentication(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['account' => []];
|
|
||||||
|
|
||||||
if ($vars['account'] = accounts::authentication($vars['email'] ?? null, $vars['password'] ?? null, (bool) ($vars['remember'] ?? false), errors: $vars['errors']['account'])) {
|
|
||||||
// Удалось аутентифицироваться
|
|
||||||
} else {
|
|
||||||
// Не удалось аутентифицироваться
|
|
||||||
|
|
||||||
// Запись кода ответа
|
|
||||||
http_response_code(401);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'main' . DIRECTORY_SEPARATOR . 'index.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Деаутентификация
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры запроса
|
|
||||||
*
|
|
||||||
* @return string|null HTML-документ
|
|
||||||
*/
|
|
||||||
public function deauthentication(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['account' => []];
|
|
||||||
|
|
||||||
if (accounts::deauthentication(errors: $vars['errors']['account'])) {
|
|
||||||
// Удалось деаутентифицироваться
|
|
||||||
|
|
||||||
// Деинициализация аккаунта
|
|
||||||
$vars['account'] = null;
|
|
||||||
} else {
|
|
||||||
// Не удалось деаутентифицироваться
|
|
||||||
|
|
||||||
// Запись кода ответа
|
|
||||||
http_response_code(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'main' . DIRECTORY_SEPARATOR . 'index.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Данные аккаунта
|
|
||||||
*
|
|
||||||
* Если информацию запрашивает администратор, то вернётся вся, иначе только разрешённая публично
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры запроса
|
|
||||||
*
|
|
||||||
* @return string JSON-документ
|
|
||||||
*/
|
|
||||||
public function data(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['account' => []];
|
|
||||||
|
|
||||||
if ($account = accounts::read(['id' => $vars['id']], $vars['errors'])) {
|
|
||||||
// Найдены данные запрашиваемого аккаунта
|
|
||||||
|
|
||||||
// Инициализация аккаунта
|
|
||||||
$vars['account'] = accounts::account($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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,266 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\controllers;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
use mirzaev\tordv\calculator\controllers\core;
|
|
||||||
use mirzaev\tordv\calculator\models\calculators_model as calculators;
|
|
||||||
use mirzaev\tordv\calculator\models\settings_model as settings;
|
|
||||||
use mirzaev\tordv\calculator\models\metals_model as metals;
|
|
||||||
|
|
||||||
use Twig\Loader\FilesystemLoader;
|
|
||||||
use Twig\Environment as view;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Контроллер основной страницы
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class calculator_controller extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Калькулятор
|
|
||||||
*
|
|
||||||
* HTML-код с калькулятором
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*/
|
|
||||||
public function index(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'calculator' . DIRECTORY_SEPARATOR . 'index.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модуль: "тип пользователя"
|
|
||||||
*
|
|
||||||
* HTML-код с кнопками: "физическое лицо" и "юридическое лицо"
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*/
|
|
||||||
public function buyer(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация параметров
|
|
||||||
$vars['buyer'] = $vars['value'] ?? 'individual';
|
|
||||||
|
|
||||||
// Удаление параметров
|
|
||||||
unset($vars['value']);
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'buyer.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модуль: "сложность"
|
|
||||||
*
|
|
||||||
* HTML-код с кнопками: "легко", "средне" и "сложно"
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*/
|
|
||||||
public function complexity(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация параметров
|
|
||||||
$vars['complexity'] = $vars['value'] ?? 'medium';
|
|
||||||
|
|
||||||
// Удаление параметров
|
|
||||||
unset($vars['value']);
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'complexity.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модуль: "меню"
|
|
||||||
*
|
|
||||||
* HTML-код с кнопками добавления калькуляторов
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*/
|
|
||||||
public function menu(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'menu.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модуль: "результат"
|
|
||||||
*
|
|
||||||
* HTML-код с данными результата калькуляции
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*/
|
|
||||||
public function result(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['calculators' => []];
|
|
||||||
|
|
||||||
// Инициализация данных калькулятора
|
|
||||||
$vars['discount'] = settings::read('discount', $vars['errors']['calculators']);
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'result.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модуль: "марка"
|
|
||||||
*
|
|
||||||
* HTML-код со списком марок металла
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*
|
|
||||||
* @todo 1. Если металл свой, то ничего не генерировать
|
|
||||||
*/
|
|
||||||
public function mark(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['calculators' => []];
|
|
||||||
|
|
||||||
// Инициализация списка марок
|
|
||||||
$vars['marks'] = metals::marks(empty($vars['type']) ? settings::read("default_type") : $vars['type'], $vars['errors'], $vars['errors']['calculators']);
|
|
||||||
|
|
||||||
// Инициализация значения по умолчанию
|
|
||||||
if (empty($vars['marks'])) $vars['marks'] = ['Не найдено'];
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'metals' . DIRECTORY_SEPARATOR . 'mark.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модуль: "разделитель"
|
|
||||||
*
|
|
||||||
* HTML-код с разделителем элементов
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*/
|
|
||||||
public function divider(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'divider.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Лазерная резка
|
|
||||||
*
|
|
||||||
* HTML-код с калькулятором лазерной резки
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*
|
|
||||||
* @todo 1. Заголовок калькулятора должен находиться внутри элемента калькулятора
|
|
||||||
* 2. Ограничение значений полей в зависимости от выбранной марки
|
|
||||||
*/
|
|
||||||
public function laser(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['calculators' => []];
|
|
||||||
|
|
||||||
// Инициализация данных калькулятора
|
|
||||||
$vars['calculators'] = ['laser' => [
|
|
||||||
'company' => settings::read('default_buyer', $vars['errors']['calculators']),
|
|
||||||
'complexity' => settings::read('default_complexity', $vars['errors']['calculators']),
|
|
||||||
'width' => (int) round((float) settings::read('default_width', $vars['errors']['calculators'])),
|
|
||||||
'height' => (int) round((float) settings::read('default_height', $vars['errors']['calculators'])),
|
|
||||||
'length' => (int) round((float) settings::read('default_length', $vars['errors']['calculators'])),
|
|
||||||
'amount' => (int) round((float) settings::read('default_amount', $vars['errors']['calculators'])),
|
|
||||||
'type' => settings::read('default_type', $vars['errors']['calculators']),
|
|
||||||
'holes' => (int) round((float) settings::read('default_holes', $vars['errors']['calculators'])),
|
|
||||||
'diameter' => (float) settings::read('default_diameter', $vars['errors']['calculators'])
|
|
||||||
]];
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'laser.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Расчёт
|
|
||||||
*
|
|
||||||
* Генерирует ответ в виде ['expenses' => 0, 'income' => 0, 'profit' => 0]
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*
|
|
||||||
* @todo
|
|
||||||
* 5. Убрать передачу цены работы (оставить только время работы в часах и цену за работу в час)
|
|
||||||
*/
|
|
||||||
public function calculate(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['calculators' => []];
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Инициализация параметров из тела запроса (подразумевается, что там массивы с параметрами)
|
|
||||||
$vars['input'] = json_decode(file_get_contents('php://input'), true);
|
|
||||||
|
|
||||||
$calculators = $vars['input']['calculators'];
|
|
||||||
$discount = $vars['input']['discount'];
|
|
||||||
$cutting = $vars['input']['cutting'];
|
|
||||||
|
|
||||||
// Инициализация переменных для буфера вывода
|
|
||||||
$machines = $managers = $engineers = $operators = $handymans = $other = 0;
|
|
||||||
|
|
||||||
if (count($calculators) > 0) {
|
|
||||||
// Найдены калькуляторы
|
|
||||||
|
|
||||||
foreach ($calculators as $i => $calculator) {
|
|
||||||
// Перебор калькуляторов
|
|
||||||
|
|
||||||
foreach (['calculator'] as &$parameter) {
|
|
||||||
// Перебор мета-параметров
|
|
||||||
|
|
||||||
// Инициализация общего параметра
|
|
||||||
$type = $calculator[$parameter];
|
|
||||||
|
|
||||||
// Инициализация параметра для обработчика калькулятора
|
|
||||||
unset($calculator[$parameter]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация номера калькулятора в его категории
|
|
||||||
$number = count($vars['errors']['calculators'][$type] ?? []);
|
|
||||||
|
|
||||||
// Инициализация журнала ошибок для калькулятора
|
|
||||||
$calculator['errors'] = [];
|
|
||||||
|
|
||||||
// Инициализация журнала ошибок для буфера вывода
|
|
||||||
$vars['errors']['calculators'][$type][$number] = &$calculator['errors'];
|
|
||||||
|
|
||||||
// Инициализация буфера параметров
|
|
||||||
$parameters = [];
|
|
||||||
|
|
||||||
// Инициализация параметра типа покупателя (подразумевается, что если не "entity", то "individual")
|
|
||||||
$parameters['company'] = $calculator['buyer'] === 'entity';
|
|
||||||
unset($calculator['buyer']);
|
|
||||||
|
|
||||||
// Перенос остальных параметров в буфер параметров
|
|
||||||
$parameters += $calculator;
|
|
||||||
|
|
||||||
// Расчёт
|
|
||||||
[$machines, $managers, $engineers, $operators, $handymans, $other] = calculators::$type(...$parameters + ['cutting' => $cutting]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Не найдены калькуляторы
|
|
||||||
|
|
||||||
throw new exception('Не найдены калькуляторы');
|
|
||||||
}
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$vars['errors']['calculators'][] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return json_encode([
|
|
||||||
'machines' => $machines,
|
|
||||||
'managers' => $managers,
|
|
||||||
'engineers' => $engineers,
|
|
||||||
'operators' => $operators,
|
|
||||||
'handymans' => $handymans,
|
|
||||||
'other' => $other + ['discount' => $discount],
|
|
||||||
'errors' => $vars['errors']
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\controllers;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\controllers\core;
|
|
||||||
use mirzaev\tordv\calculator\models\accounts_model as accounts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Контроллер контактов
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class contacts_controller extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Контакты (страница)
|
|
||||||
*
|
|
||||||
* HTML-документ с контактами
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*
|
|
||||||
* @return string HTML-докумкент
|
|
||||||
*/
|
|
||||||
public function index(array $vars = []): string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['contacts' => []];
|
|
||||||
|
|
||||||
// Инициализация аккаунта
|
|
||||||
$vars['account'] = accounts::account($vars['errors']['contacts']);
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'contacts' . DIRECTORY_SEPARATOR . 'index.html', $vars);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\controllers;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\controllers\core;
|
|
||||||
use mirzaev\tordv\calculator\models\accounts_model as accounts;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Контроллер журналов
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class journal_controller extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Журнал (страница)
|
|
||||||
*
|
|
||||||
* HTML-документ с журналом
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*
|
|
||||||
* @return string HTML-докумкент
|
|
||||||
*/
|
|
||||||
public function index(array $vars = []): string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['journal' => []];
|
|
||||||
|
|
||||||
// Инициализация аккаунта
|
|
||||||
$vars['account'] = accounts::account($vars['errors']['journal']);
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'journal' . DIRECTORY_SEPARATOR . 'index.html', $vars);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\controllers;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\controllers\core;
|
|
||||||
use mirzaev\tordv\calculator\models\accounts_model as accounts;
|
|
||||||
|
|
||||||
use Twig\Loader\FilesystemLoader;
|
|
||||||
use Twig\Environment as view;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Контроллер основной страницы
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class main_controller extends core
|
|
||||||
{
|
|
||||||
public function index(array $vars = [])
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['account' => []];
|
|
||||||
|
|
||||||
// Проверка аутентифицированности
|
|
||||||
$vars['account'] = accounts::account($vars['errors']);
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'main' . DIRECTORY_SEPARATOR . 'index.html', $vars);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\controllers;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\controllers\core;
|
|
||||||
use mirzaev\tordv\calculator\models\accounts_model as accounts;
|
|
||||||
use mirzaev\tordv\calculator\models\settings_model as settings;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Контроллер настроек
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class settings_controller extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Настройки (страница)
|
|
||||||
*
|
|
||||||
* HTML-документ со списком настроек
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*
|
|
||||||
* @return string HTML-докумкент или журнал ошибок
|
|
||||||
*/
|
|
||||||
public function index(array $vars = []): string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['settings' => []];
|
|
||||||
|
|
||||||
// Инициализация аккаунта
|
|
||||||
$vars['account'] = accounts::account($vars['errors']['settings']);
|
|
||||||
|
|
||||||
if (accounts::access('settings')) {
|
|
||||||
// Разрешён доступ к изменению настроек
|
|
||||||
|
|
||||||
// Инициализация настроек
|
|
||||||
$vars['settings'] = settings::translate(settings::filter(settings::read(errors: $vars['errors']['settings']), $vars['errors']['settings']), $vars['errors']['settings']);
|
|
||||||
|
|
||||||
// Генерация представления
|
|
||||||
return $this->view->render(DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'index.html', $vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($vars['errors']['settings'])) return '';
|
|
||||||
return json_encode($vars['errors']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Записать
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*
|
|
||||||
* @return string Журнал ошибок
|
|
||||||
*/
|
|
||||||
public function write(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['settings' => []];
|
|
||||||
|
|
||||||
// Инициализация аккаунта
|
|
||||||
$vars['account'] = accounts::account($vars['errors']['settings']);
|
|
||||||
|
|
||||||
if ($vars['account'] && $vars['account']['permissions']['settings'] ?? 0 === 1) {
|
|
||||||
// Удалось аутентифицироваться и пройдена проверка авторизации
|
|
||||||
|
|
||||||
// Инициализация калькуляторов из тела запроса (подразумевается, что там массивы с параметрами)
|
|
||||||
$vars['settings'] = json_decode(file_get_contents('php://input'), true);
|
|
||||||
|
|
||||||
foreach ($vars['settings'] ?? [] as $name => $value) {
|
|
||||||
// Перебор настроек
|
|
||||||
|
|
||||||
// Запись в базу данных
|
|
||||||
settings::write($name, $value, $vars['errors']['settings']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return json_encode($vars['errors']);
|
|
||||||
}
|
|
||||||
|
|
||||||
http_response_code(500);
|
|
||||||
|
|
||||||
return json_encode($vars['errors']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Прочитать
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*/
|
|
||||||
public function read(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['settings' => []];
|
|
||||||
|
|
||||||
// Инициализация аккаунта
|
|
||||||
$vars['account'] = accounts::account($vars['errors']['settings']);
|
|
||||||
|
|
||||||
// Инициализация буфера вывода
|
|
||||||
$settings = [];
|
|
||||||
|
|
||||||
foreach ($vars['settings'] ?? [] as $name) {
|
|
||||||
// Перебор настроек
|
|
||||||
|
|
||||||
$settings[] = settings::read($name, $vars['errors']['settings']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return json_encode($settings);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\controllers;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\controllers\core;
|
|
||||||
use mirzaev\tordv\calculator\models\accounts_model as accounts;
|
|
||||||
use mirzaev\tordv\calculator\models\supplies_model as supplies;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_aluminum_filter;
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_brass_filter;
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_copper_filter;
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_stainless_steel_filter;
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_steel_filter;
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_galvanized_steel_filter;
|
|
||||||
|
|
||||||
use Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Контроллер поставок
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\controllers
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class supplies_controller extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Записать
|
|
||||||
*
|
|
||||||
* @param array $vars Параметры
|
|
||||||
*/
|
|
||||||
public function write(array $vars = []): ?string
|
|
||||||
{
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$vars['errors'] = ['supplies' => []];
|
|
||||||
|
|
||||||
// Инициализация аккаунта
|
|
||||||
$vars['account'] = accounts::account($vars['errors']);
|
|
||||||
|
|
||||||
if ($vars['account'] && $vars['account']['permissions']['supplies'] ?? 0 === 1) {
|
|
||||||
// Удалось аутентифицироваться и пройдена проверка авторизации
|
|
||||||
|
|
||||||
// Сохранение файла
|
|
||||||
move_uploaded_file($_FILES['supplies']['tmp_name'], $file = SUPPLIES . DIRECTORY_SEPARATOR . $_FILES['supplies']['name']);
|
|
||||||
|
|
||||||
// Запись данных из файла в базу данных
|
|
||||||
try {
|
|
||||||
@supplies::write($file, new import_aluminum_filter);
|
|
||||||
@supplies::write($file, new import_brass_filter);
|
|
||||||
@supplies::write($file, new import_copper_filter);
|
|
||||||
@supplies::write($file, new import_stainless_steel_filter);
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$vars['errors']['supplies'] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
@supplies::write($file, new import_steel_filter, $vars['errors']['supplies']);
|
|
||||||
@supplies::write($file, new import_galvanized_steel_filter, $vars['errors']['supplies']);
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$vars['errors']['supplies'] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Если вернуть null покажет ошибку 404 (будет исправлено в будущих версиях mirzaev/minimal)
|
|
||||||
return json_encode($vars['errors']);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,621 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models;
|
|
||||||
|
|
||||||
use pdo;
|
|
||||||
use exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модель регистрации, аутентификации и авторизации
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class accounts_model extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Регистрация
|
|
||||||
*
|
|
||||||
* @param string $name Входной псевдоним
|
|
||||||
* @param string $email Почта
|
|
||||||
* @param string $password Пароль (password)
|
|
||||||
* @param bool $authentication Автоматическая аутентификация в случае успешной регистрации
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array|bool Аккаунт, если удалось аутентифицироваться
|
|
||||||
*/
|
|
||||||
public static function registration(string $name = null, string $email = null, string $password, array &$errors = []): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (static::account($errors)) {
|
|
||||||
// Аутентифицирован пользователь
|
|
||||||
|
|
||||||
// Запись ошибки
|
|
||||||
throw new exception('Уже аутентифицирован');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($account = static::read(['name' => $name]) or $account = static::read(['email' => $email]))) {
|
|
||||||
// Не удалось найти аккаунт
|
|
||||||
|
|
||||||
if (static::write($name, $email, $password, $errors)) {
|
|
||||||
// Удалось зарегистрироваться
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Удалось найти аккаунт
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Аутентификация
|
|
||||||
*
|
|
||||||
* @param string $login Входной псевдоним
|
|
||||||
* @param string $password Пароль (password)
|
|
||||||
* @param bool $remember Функция "Запомнить меня" - увеличенное время хранения cookies
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array Аккаунт (если не найден, то пустой массив)
|
|
||||||
*/
|
|
||||||
public static function authentication(string $login, string $password, bool $remember = false, array &$errors = []): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (static::account($errors)) {
|
|
||||||
// Аутентифицирован пользователь
|
|
||||||
|
|
||||||
// Запись ошибки
|
|
||||||
throw new exception('Уже аутентифицирован');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (empty($account = static::read(['name' => $login]) or $account = static::read(['email' => $login]))) {
|
|
||||||
// Не удалось найти аккаунт
|
|
||||||
|
|
||||||
throw new exception('Не удалось найти аккаунт');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (password_verify($password, $account['password'])) {
|
|
||||||
// Совпадают хеши паролей
|
|
||||||
|
|
||||||
// Инициализация идентификатора сессии
|
|
||||||
session_id($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[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Аутентификация
|
|
||||||
*
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return bool Удалось ли деаутентифицироваться
|
|
||||||
*/
|
|
||||||
public static function deauthentication(array &$errors = []): bool
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if ($account = static::account($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[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Прочитать данные аккаунта, если пользователь аутентифицирован
|
|
||||||
*
|
|
||||||
* Можно использовать как проверку на аутентифицированность
|
|
||||||
*
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array Аккаунт (если не найден, то пустой массив)
|
|
||||||
*
|
|
||||||
* @todo 1. Сделать в static::read() возможность передачи нескольких параметров и перенести туда непосредственно чтение аккаунта с проверкой хеша
|
|
||||||
*/
|
|
||||||
public static function account(array &$errors = []): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (!empty($_COOKIE['id']) && !empty($_COOKIE['hash'])) {
|
|
||||||
// Аутентифицирован аккаунт (найдены cookie и они хранят значения - подразумевается, что не null или пустое)
|
|
||||||
|
|
||||||
if ($_COOKIE['hash'] === static::hash((int) $_COOKIE['id'], errors: $errors)['hash']) {
|
|
||||||
// Совпадает переданный хеш с тем, что хранится в базе данных
|
|
||||||
} else {
|
|
||||||
// Не совпадает переданный хеш с тем, что хранится в базе данных
|
|
||||||
|
|
||||||
// Генерация ошибки
|
|
||||||
throw new exception('Вы аутентифицированы с другого устройства (не совпадают хеши аутентификации)');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("SELECT * FROM `accounts` WHERE `id` = :id && `hash` = :hash");
|
|
||||||
|
|
||||||
// Параметры запроса
|
|
||||||
$params = [
|
|
||||||
":id" => $_COOKIE['id'],
|
|
||||||
":hash" => $_COOKIE['hash'],
|
|
||||||
];
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute($params);
|
|
||||||
|
|
||||||
// Генерация ответа
|
|
||||||
if (empty($account = $request->fetch(pdo::FETCH_ASSOC))) {
|
|
||||||
// Не найдена связка идентификатора с хешем
|
|
||||||
|
|
||||||
// Генерация ошибки
|
|
||||||
throw new exception('Не найден пользотватель или время аутентификации истекло');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Чтение разрешений
|
|
||||||
$account['permissions'] = static::permissions((int) $account['id'], $errors);
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Прочитать разрешения аккаунта
|
|
||||||
*
|
|
||||||
* @param int $id Идентификатор аккаунта
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array Разрешения аккаунта, если найдены
|
|
||||||
*/
|
|
||||||
public static function permissions(int $id, array &$errors = []): array
|
|
||||||
{
|
|
||||||
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[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Проверить разрешение
|
|
||||||
*
|
|
||||||
* @param string $permission Разрешение
|
|
||||||
* @param int|null $id Идентификатор аккаунта
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return bool|null Статус разрешения, если оно записано
|
|
||||||
*/
|
|
||||||
public static function access(string $permission, int|null $id = null, array &$errors = []): ?bool
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация аккаунта
|
|
||||||
$account = isset($id) ? self::read(['id' => $id], $errors) : self::account($errors);
|
|
||||||
|
|
||||||
return isset($account['permissions'][$permission]) ? (bool) $account['permissions'][$permission] : null;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Запись пользователя в базу данных
|
|
||||||
*
|
|
||||||
* @param string|null $name Имя
|
|
||||||
* @param string|null $email Почта
|
|
||||||
* @param string|null $password Пароль
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array Аккаунт (если не найден, то пустой массив)
|
|
||||||
*/
|
|
||||||
public static function write(string|null $name = null, string|null $email = null, string|null $password = null, array &$errors = []): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация параметров запроса
|
|
||||||
$params = [];
|
|
||||||
|
|
||||||
if (isset($name)) {
|
|
||||||
try {
|
|
||||||
// Проверка параметра
|
|
||||||
if (iconv_strlen($name) < 3) throw new exception('Длина имени должна быть не менее 3 символов');
|
|
||||||
if (iconv_strlen($name) > 60) throw new exception('Длина имени должна быть не более 60 символов');
|
|
||||||
|
|
||||||
// Запись в буфер параметров запроса
|
|
||||||
$params[':name'] = $name;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine()
|
|
||||||
];
|
|
||||||
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($email)) {
|
|
||||||
try {
|
|
||||||
// Проверка параметра
|
|
||||||
if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) throw new exception('Не удалось распознать почту');
|
|
||||||
if (iconv_strlen($email) < 3) throw new exception('Длина почты должна быть не менее 3 символов');
|
|
||||||
if (iconv_strlen($email) > 60) throw new exception('Длина почты должна быть не более 80 символов');
|
|
||||||
|
|
||||||
// Запись в буфер параметров запроса
|
|
||||||
$params[':email'] = $email;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine()
|
|
||||||
];
|
|
||||||
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($password)) {
|
|
||||||
try {
|
|
||||||
// Проверка параметра
|
|
||||||
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);
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine()
|
|
||||||
];
|
|
||||||
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("INSERT INTO `accounts` (" . (isset($name) ? '`name`' : '') . (isset($name) && isset($email) ? ', ' : '') . (isset($email) ? '`email`' : '') . ((isset($name) || isset($email)) && isset($password) ? ', ' : '') . (isset($password) ? '`password`' : '') . ") VALUES (" . (isset($name) ? ':name' : '') . (isset($name) && isset($email) ? ', ' : '') . (isset($email) ? ':email' : '') . ((isset($name) || isset($email)) && isset($password) ? ', ' : '') . (isset($password) ? ':password' : '') . ")");
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute($params);
|
|
||||||
|
|
||||||
// Генерация ответа
|
|
||||||
$request->fetch(pdo::FETCH_ASSOC);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (isset($name)) {
|
|
||||||
// Передано имя аккаунта
|
|
||||||
|
|
||||||
// Чтение аккаунта
|
|
||||||
$account = static::read(['name' => $name]);
|
|
||||||
} else if (isset($email)) {
|
|
||||||
// Передана почта аккаунта
|
|
||||||
|
|
||||||
// Чтение аккаунта
|
|
||||||
$account = static::read(['email' => $email]);
|
|
||||||
} else {
|
|
||||||
// Не передано ни имя, ни почта
|
|
||||||
|
|
||||||
throw new exception('Не переданны данные для полноценной регистрации аккаунта');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$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[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Конец выполнения
|
|
||||||
end:
|
|
||||||
|
|
||||||
return isset($account) && $account ? $account : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Чтение пользователя из базы данных
|
|
||||||
*
|
|
||||||
* @param array $search Поиск ('поле' => 'значение'), работает только с одним полем
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array Аккаунт, если найден
|
|
||||||
*/
|
|
||||||
public static function read(array $search, array &$errors = []): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация данных для поиска
|
|
||||||
$field = array_keys($search)[0] ?? null;
|
|
||||||
$value = $search[$field] ?? null;
|
|
||||||
|
|
||||||
if (empty($field)) {
|
|
||||||
// Получено пустое значение поля
|
|
||||||
|
|
||||||
// Запись ошибки
|
|
||||||
throw new exception('Пустое значение поля для поиска');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("SELECT * FROM `accounts` WHERE `$field` = :field LIMIT 1");
|
|
||||||
|
|
||||||
// Параметры запроса
|
|
||||||
$params = [
|
|
||||||
":field" => $value,
|
|
||||||
];
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute($params);
|
|
||||||
|
|
||||||
// Генерация ответа
|
|
||||||
if ($account = $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[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Не найден аккаунт
|
|
||||||
|
|
||||||
throw new exception('Не удалось найти аккаунт');
|
|
||||||
}
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return isset($account) && $account ? $account : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Запись или чтение хеша из базы данных
|
|
||||||
*
|
|
||||||
* @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
|
|
||||||
{
|
|
||||||
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[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ['hash' => $hash, 'time' => $time];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,163 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models;
|
|
||||||
|
|
||||||
use exception;
|
|
||||||
use pdo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модель баллонов
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*
|
|
||||||
* @todo
|
|
||||||
* 1. Если длина реза баллона зависит от типа металла (учитывается) то перенести это в класс металлов
|
|
||||||
*/
|
|
||||||
final class baloons_model extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Используемый газ
|
|
||||||
*/
|
|
||||||
public string $gas;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Количество баллонов
|
|
||||||
*/
|
|
||||||
public float $amount = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Цена всех баллонов
|
|
||||||
*/
|
|
||||||
public float $cost;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Вычисление используемого газа
|
|
||||||
*
|
|
||||||
* @param float $length Толщина металла
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return string|null Название газа
|
|
||||||
*/
|
|
||||||
public function gas(float $length, array &$errors = []): ?string
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return $this->gas = match (true) {
|
|
||||||
$length >= 4 => 'oxygen',
|
|
||||||
default => 'air'
|
|
||||||
};
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Вычисление количества используемых баллонов
|
|
||||||
*
|
|
||||||
* @param string $metal Тип металла
|
|
||||||
* @param float $cutting Длина реза
|
|
||||||
* @param float $length Толщина листа
|
|
||||||
* @param string|null $gas Используемый газ
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return int|null Количество баллонов
|
|
||||||
*
|
|
||||||
* @todo
|
|
||||||
* 1. Добавить к баллонам уточнение чтобы считало не по листам а по объёму а лучше по длине реза
|
|
||||||
* 2. Определение длины реза по типу металла
|
|
||||||
*/
|
|
||||||
public function amount(string $metal, float $cutting, float $length, ?string $gas = null, array &$errors = []): ?float
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация входных параметров
|
|
||||||
$gas ?? $gas = &$this->gas;
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("SELECT `length` FROM `baloons` WHERE `gas` = :gas LIMIT 30");
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute([
|
|
||||||
':gas' => $gas
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Генерация ответа
|
|
||||||
$response = $request->fetch(pdo::FETCH_ASSOC);
|
|
||||||
|
|
||||||
// Проверка на полученные значения
|
|
||||||
if (!is_array($response)) return null;
|
|
||||||
|
|
||||||
// Вычисление длины реза на которое хватит баллона
|
|
||||||
$flow = $response['length'] / $length;
|
|
||||||
|
|
||||||
// Вычисление количества баллонов (округление к большему)
|
|
||||||
return $this->amount = $cutting / $flow;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Вычисление стоимости баллонов
|
|
||||||
*
|
|
||||||
* @param string $metal Тип металла
|
|
||||||
* @param int|null $gas Используемый газ
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return float|null Стоимость баллонов
|
|
||||||
*/
|
|
||||||
public function cost(string $metal, ?int $amount = null, ?string $gas = null, array &$errors = []): ?float
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация входных параметров
|
|
||||||
$amount ?? $amount = &$this->amount;
|
|
||||||
$gas ?? $gas = &$this->gas;
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("SELECT `cost` FROM `baloons` WHERE `gas` = :gas LIMIT 30");
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute([
|
|
||||||
':gas' => $gas
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Генерация ответа
|
|
||||||
$response = $request->fetch(pdo::FETCH_ASSOC);
|
|
||||||
|
|
||||||
// Проверка на полученные значения
|
|
||||||
if (!is_array($response)) return null;
|
|
||||||
|
|
||||||
// Инициализация стоимости всех баллонов
|
|
||||||
return $this->cost = $response['cost'] * $amount;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,473 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\settings_model as settings;
|
|
||||||
use mirzaev\tordv\calculator\models\metals_model as metals;
|
|
||||||
use mirzaev\tordv\calculator\models\baloons_model as baloons;
|
|
||||||
|
|
||||||
use exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модель калькуляторов
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class calculators_model extends core
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Расчёт стоимости переработки за 1 тонну
|
|
||||||
*
|
|
||||||
* @param string $complexity Сложность
|
|
||||||
* @param float $length Толщина
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return float Стоимость переработки за 1 тонну (руб)
|
|
||||||
*/
|
|
||||||
public static function reprocessing(string $complexity, float $length, array &$errors = []): ?float
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return (float) match (true) {
|
|
||||||
$length > 0 && $length < 4 => settings::read('reprocessing_' . $complexity . '_1_3', $errors),
|
|
||||||
$length > 3 && $length < 7 => settings::read('reprocessing_' . $complexity . '_4_6', $errors),
|
|
||||||
$length > 6 && $length < 11 => settings::read('reprocessing_' . $complexity . '_7_10', $errors),
|
|
||||||
default => settings::read('reprocessing_' . $complexity . '_10', $errors),
|
|
||||||
}
|
|
||||||
?? 0.0;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = $e->getMessage() . ':' . $e->getLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Расчёт коэффициента сложности детали
|
|
||||||
*
|
|
||||||
* Влияет на скорость реза
|
|
||||||
*
|
|
||||||
* @param string $complexity Сложность детали (easy, medium, hard)
|
|
||||||
* @param int|null $area Площадь детали
|
|
||||||
* @param float|null $length Толщина детали
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return float Коэффициент
|
|
||||||
*
|
|
||||||
* @todo
|
|
||||||
* 1. Коэффициент исходя из типа газа (баллоны)
|
|
||||||
*/
|
|
||||||
public static function coefficient(string $complexity, ?int $area = null, ?float $length = null, array &$errors = []): float|false
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Коэффициент полученный исходя из сложности детали
|
|
||||||
$coefficient = settings::read("coefficient_complexity_$complexity", $errors) ?? throw new exception("Не найдено: coefficient_complexity_$complexity");
|
|
||||||
|
|
||||||
if (
|
|
||||||
isset($area)
|
|
||||||
&& ($area <= (settings::read('coefficient_area_less', $errors) ?? throw new exception("Не найдено: coefficient_area_less"))
|
|
||||||
|| $area >= (settings::read('coefficient_area_more', $errors) ?? throw new exception("Не найдено: coefficient_area_more")))
|
|
||||||
) {
|
|
||||||
// Площадь детали не более и не менее заданных в базе данных размеров
|
|
||||||
|
|
||||||
// Прибавление коэффициента исходя из площади детали
|
|
||||||
$coefficient += settings::read('coefficient_area_degree', $errors) ?? throw new exception("Не найдено: coefficient_area_degree");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
isset($length)
|
|
||||||
&& ($length <= (settings::read('coefficient_length_less', $errors) ?? throw new exception("Не найдено: coefficient_length_less"))
|
|
||||||
|| $length >= (settings::read('coefficient_length_more', $errors) ?? throw new exception("Не найдено: coefficient_length_more")))
|
|
||||||
) {
|
|
||||||
// Толщина детали не более и не менее заданных в базе данных размеров
|
|
||||||
|
|
||||||
// Прибавление коэффициента исходя из толщины детали
|
|
||||||
// $coefficient += settings::read('coefficient_length_degree', $errors) ?? throw new exception("Не найдено: coefficient_length_degree");
|
|
||||||
// $coefficient -= settings::read('coefficient_length_degree', $errors) ?? throw new exception("Не найдено: coefficient_length_degree");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (float) $coefficient;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Расчёт стоимости работы сотрудника
|
|
||||||
*
|
|
||||||
* @param string $position Должность (manager, engineer, operator...)
|
|
||||||
* @param string $complexity Сложность детали (easy, medium, hard)
|
|
||||||
* @param int $company Для юридического лица? Иначе как для физического
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return int Стоимость (руб)
|
|
||||||
*/
|
|
||||||
public static function employee(string $position, string $complexity, bool $company = false, array &$errors = []): array|bool
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация категории работы для поиска данных
|
|
||||||
$type = $company ? 'entity' : 'individual';
|
|
||||||
|
|
||||||
// Инициализация всех времён работы (ч)
|
|
||||||
$min = settings::read($position . '_' . $type . '_min', $errors) ?? throw new exception('Не найдено: ' . $position . '_' . $type . '_min');
|
|
||||||
$max = settings::read($position . '_' . $type . '_max', $errors) ?? throw new exception('Не найдено: ' . $position . '_' . $type . '_max');
|
|
||||||
$average = ($min + $max) / 2;
|
|
||||||
|
|
||||||
// Инициализация времени работы
|
|
||||||
$time = (float) match ($complexity) {
|
|
||||||
'easy' => $min,
|
|
||||||
'medium' => $average,
|
|
||||||
'hard' => $max,
|
|
||||||
default => throw new exception('Неизвестный тип сложности детали')
|
|
||||||
};
|
|
||||||
|
|
||||||
// Инициализация цены за час
|
|
||||||
$hour = settings::read($position . '_' . $type . '_hour', $errors) ?? throw new exception('Не найдено: ' . $position . '_' . $type . '_hour');
|
|
||||||
|
|
||||||
return [
|
|
||||||
'time' => (float) $time,
|
|
||||||
'hour' => (float) $hour,
|
|
||||||
'cost' => $time * $hour
|
|
||||||
];
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Расчёт калькулятора лазерной резки
|
|
||||||
*
|
|
||||||
* @param bool|int|string|null $company Юридическое лицо? Или физическое лицо?
|
|
||||||
* @param string|null $complexity Сложность ('easy', 'medium', 'hard')
|
|
||||||
* @param int|string|null $width Высота (мм)
|
|
||||||
* @param int|string|null $height Ширина (мм)
|
|
||||||
* @param int|string|null $length Длина (мм)
|
|
||||||
* @param int|string|null $amount Количество
|
|
||||||
* @param string|null $type Тип металла
|
|
||||||
* @param string|null $mark Марка металла
|
|
||||||
* @param bool|null $out Наш металл?
|
|
||||||
* @param int|string|null $holes Количество отверстий
|
|
||||||
* @param int|string|null $diameter Диаметр отверстий (мм)
|
|
||||||
* @param float|null $cutting Длина реза (мм)
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array|bool Аккаунт, если удалось аутентифицироваться
|
|
||||||
*
|
|
||||||
* @todo
|
|
||||||
* 22. Выводится результат даже если не аутентифицирован (проблема с куки)
|
|
||||||
* 39. Переделать массивы в объекты там, где позволяет случай
|
|
||||||
* 40. Перенести лазерный станок в отдельную таблицу в базе данных со всеми его данными
|
|
||||||
* 43. Удаление калькуляторов
|
|
||||||
* @ 44. от 750 +1 лист от 3
|
|
||||||
* @ 45. от 0.5 до 3 от 620 +1
|
|
||||||
*/
|
|
||||||
public static function laser(
|
|
||||||
bool|int|string|null $company = null,
|
|
||||||
?string $complexity = null,
|
|
||||||
int|string|null $width = null,
|
|
||||||
int|string|null $height = null,
|
|
||||||
float|string|null $length = null,
|
|
||||||
float|string|null $amount = null,
|
|
||||||
?string $type = null,
|
|
||||||
?string $mark = null,
|
|
||||||
?bool $our = null,
|
|
||||||
int|string|null $holes = null,
|
|
||||||
float|string|null $diameter = null,
|
|
||||||
float|null $cutting = null,
|
|
||||||
array &$errors = []
|
|
||||||
): array {
|
|
||||||
// Инициализация журнала ошибок
|
|
||||||
$errors['laser'] ?? $errors['laser'] = [];
|
|
||||||
$i = count($errors['laser']);
|
|
||||||
$errors['laser'][$i] = [];
|
|
||||||
$errors = $errors['laser'][$i];
|
|
||||||
|
|
||||||
// Инициализация переменных для буфера вывода
|
|
||||||
$machines = $managers = $engineers = $operators = $handymans = $other = [];
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Инициализация значений по умолчанию
|
|
||||||
$company = $company ?? throw new exception('Не передан параметр company');
|
|
||||||
$complexity = $complexity ?? throw new exception('Не передан параметр complexity');
|
|
||||||
$width = (int) $width ?? throw new exception('Не передан параметр width');
|
|
||||||
$height = (int) $height ?? throw new exception('Не передан параметр height');
|
|
||||||
$length = (float) $length ?? throw new exception('Не передан параметр length');
|
|
||||||
$amount = (float) $amount ?? throw new exception('Не передан параметр amount');
|
|
||||||
$type = $type ?? throw new exception('Не передан параметр type');
|
|
||||||
$mark = $mark ?? throw new exception('Не передан параметр mark');
|
|
||||||
$our = (bool) $our ?? true;
|
|
||||||
$holes = (int) $holes ?? throw new exception('Не передан параметр holes');
|
|
||||||
$diameter = (float) $diameter ?? throw new exception('Не передан параметр diameter');
|
|
||||||
$cutting = (float) $cutting ?? throw new exception('Не передан параметр time');
|
|
||||||
|
|
||||||
if ($width <= 0 || $height <= 0 || $length <= 0) {
|
|
||||||
// Неподходящие для выполнения значения
|
|
||||||
|
|
||||||
throw new exception('Передан нулевой размер одной из сторон заготовки');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация инстанции баллонов
|
|
||||||
$baloons = new baloons;
|
|
||||||
|
|
||||||
// Вычисление используемого газа
|
|
||||||
$baloons->gas($length, $errors) ?? throw new exception('Не удалось вычислить тип газа для резки');
|
|
||||||
|
|
||||||
// Инициализация станка для буфера вывода
|
|
||||||
$machine = [
|
|
||||||
'amount' => $amount
|
|
||||||
];
|
|
||||||
|
|
||||||
// Инициализация буфера остальных вычислений для буфера вывода
|
|
||||||
$other = [
|
|
||||||
'additive' => (float) settings::read('additive', $errors) ?? throw new exception('Не найдено: additive')
|
|
||||||
];
|
|
||||||
|
|
||||||
// // Инициализация прибавок к наценке
|
|
||||||
// $increase_300_3000 = (float) settings::read('additive_increase_300_3000', $errors) ?? throw new exception('Не найдено: additive_increase_300_3000');
|
|
||||||
|
|
||||||
// if ($amount >= 300) {
|
|
||||||
// // Количество заказанных деталей равно или более чем 300 шт.
|
|
||||||
|
|
||||||
// for ($i = 0; $i <= $amount; ++$i) {
|
|
||||||
// // Перебор по количеству изготавливаемых деталей
|
|
||||||
|
|
||||||
// // Количество заказанных деталей равно или более чем 300 шт. и равно или менее чем 3000 шт.
|
|
||||||
// if ($amount <= 3000) $other['additive'] += $increase_300_3000;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $other['additive'] = 1.07;
|
|
||||||
|
|
||||||
// Площадь
|
|
||||||
$area = $width * $height;
|
|
||||||
|
|
||||||
// Объём
|
|
||||||
$volume = $area * $length;
|
|
||||||
|
|
||||||
// Стоимость киловатта электроэнергии
|
|
||||||
$electricity = settings::read('electricity', $errors) ?? throw new exception('Не найдено: electricity');
|
|
||||||
|
|
||||||
// Потребляемая электроэнергия станком (квт/ч)
|
|
||||||
$power = settings::read('laser_power', $errors) ?? throw new exception('Не найдено: laser_power');
|
|
||||||
|
|
||||||
// Чтение данных листа металла (почему-то не читает если передать $length = 0.8)
|
|
||||||
$list = metals::read($type, $mark, $length, $errors);
|
|
||||||
|
|
||||||
// Проверка
|
|
||||||
if (empty($list['ton'])) throw new exception('Не удалось найти цену за тонну');
|
|
||||||
if (empty($list['width'])) throw new exception('Не удалось найти ширину листа');
|
|
||||||
if (empty($list['height'])) throw new exception('Не удалось найти высоту листа');
|
|
||||||
if ((int) $list['width'] < $width) throw new exception('Ширина детали крупнее чем у исходного листа');
|
|
||||||
if ((int) $list['height'] < $height) throw new exception('Высота детали крупнее чем у исходного листа');
|
|
||||||
|
|
||||||
// Объём листа металла
|
|
||||||
$list['volume'] = $list['width'] * $list['height'] * $length;
|
|
||||||
|
|
||||||
// Инициализация характеристик металла
|
|
||||||
$metal = [
|
|
||||||
'cut' => metals::cut($type, $baloons->gas, $length, $errors),
|
|
||||||
'weight' => metals::kg($type, $errors) * $length,
|
|
||||||
'cost' => $list['ton'] / 1000 // Цена за килограмм
|
|
||||||
];
|
|
||||||
|
|
||||||
if ($metal['cut'] <= 0 || $metal['weight'] <= 0 || $metal['cost'] <= 0) {
|
|
||||||
// Неподходящие для выполнения значения
|
|
||||||
|
|
||||||
throw new exception('Ошибка при вычислении характеристик металла');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cutting === 0.0) {
|
|
||||||
// Не передана длина реза
|
|
||||||
|
|
||||||
if ($holes == 0 ?? $diameter == 0) {
|
|
||||||
// Не переданы данные об отверстиях
|
|
||||||
|
|
||||||
// Длина реза (мм)
|
|
||||||
$cutting = ($width * 2 + $height * 2) * self::coefficient($complexity, $area, $length, $errors);
|
|
||||||
} else {
|
|
||||||
// Переданы данные об отверстиях
|
|
||||||
|
|
||||||
// Длина реза (мм)
|
|
||||||
$cutting = (3.1416 * $diameter * $holes + $width * 2 + $height * 2) * self::coefficient($complexity, $area, $length, $errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Запись в буфер вывода
|
|
||||||
$other['cutting'] = $cutting;
|
|
||||||
|
|
||||||
// Время реза одной детали (c)
|
|
||||||
$time = $cutting / $metal['cut'];
|
|
||||||
|
|
||||||
// Стоимость реза в час (руб)
|
|
||||||
$hour = $electricity * $power;
|
|
||||||
|
|
||||||
// Стоимость электроэнергии за работу станка
|
|
||||||
$machine['electricity'] = $time * $amount / 60 / 60 * $hour;
|
|
||||||
|
|
||||||
// Вес металла (кг)
|
|
||||||
$weight = $width * $height * $amount / 1000000 * $metal['weight'];
|
|
||||||
|
|
||||||
// Стоимость переработки (руб)
|
|
||||||
$other['reprocessing'] = self::reprocessing($complexity, $length, $errors) / 1000 * $weight;
|
|
||||||
|
|
||||||
// Стоимость аренды помещения
|
|
||||||
$other['rent'] = $time * $amount / 60 / 60 * (int) settings::read('rent', $errors) ?? throw new exception('Не найдено: rent');
|
|
||||||
|
|
||||||
// (Наш металл) Стоимость металла (руб)
|
|
||||||
if ($our) $machine['metal'] = $weight * $metal['cost'];
|
|
||||||
|
|
||||||
// Инициализация времени загрузки металла на станок
|
|
||||||
$load = (float) settings::read('handyman_metal_load_time') ?? throw new exception('Не найдено: handyman_metal_load_time');
|
|
||||||
|
|
||||||
// Инициализация стоимости часа
|
|
||||||
$hour = (float) settings::read('handyman_hour') ?? throw new exception('Не найдено: handyman_hour');
|
|
||||||
|
|
||||||
// Инициализация количества разнорабочих
|
|
||||||
$workers = settings::read('laser_handymans_amount') ?? throw new exception('Не найдено: laser_handymans_amount');
|
|
||||||
|
|
||||||
// Вычисление количества листов
|
|
||||||
for ($lists = 0; ++$lists * $list['volume'] < $volume * $amount;);
|
|
||||||
|
|
||||||
// Условия для прибавления листа (костыль)
|
|
||||||
if (($length > 3 && ($width >= 750 || $height >= 750))
|
|
||||||
|| ($length >= 0.5 && $length <= 3 && ($width >= 620 || $height >= 620))
|
|
||||||
) ++$list;
|
|
||||||
|
|
||||||
// Инициализация данных линзы
|
|
||||||
$lense = [
|
|
||||||
'cost' => (int) settings::read('laser_lense_cost', $errors) ?? throw new exception('Не найдено: laser_lense_cost'),
|
|
||||||
'length' => (int) settings::read('laser_lense_flow', $errors) ?? throw new exception('Не найдено: laser_lense_flow')
|
|
||||||
];
|
|
||||||
|
|
||||||
// Вычисление количества используемых линз
|
|
||||||
$lenses = $cutting / $lense['length'];
|
|
||||||
|
|
||||||
// Запись данных о линзах в буфер вывода (стоимость)
|
|
||||||
$machine['lenses'] = $lenses * $lense['cost'];
|
|
||||||
|
|
||||||
// Вычисление количества использованных баллонов
|
|
||||||
$baloons->amount($type, $cutting * $amount, $length, errors: $errors) ?? throw new exception('Не удалось вычислить количество используемых баллонов');
|
|
||||||
|
|
||||||
// Вычисление стоимости баллонов
|
|
||||||
$baloons->cost($type, errors: $errors) ?? throw new exception('Не удалось вычислить стоимость баллонов');
|
|
||||||
|
|
||||||
// Запись данных о баллонах в буфер вывода
|
|
||||||
$other['baloons'] = [
|
|
||||||
'amount' => $baloons->amount,
|
|
||||||
'cost' => $baloons->cost
|
|
||||||
];
|
|
||||||
|
|
||||||
// Запись данных о баллонах в буфер вывода
|
|
||||||
$other['baloons'] = [
|
|
||||||
'amount' => $baloons->amount,
|
|
||||||
'cost' => $baloons->cost
|
|
||||||
];
|
|
||||||
|
|
||||||
// Вычисление времени работы разнорабочих (ч)
|
|
||||||
$work = $lists * $load / 60;
|
|
||||||
|
|
||||||
// Инициализация итератора
|
|
||||||
$i = 0;
|
|
||||||
|
|
||||||
while (++$i <= $workers) {
|
|
||||||
// Перебор разнорабочих
|
|
||||||
|
|
||||||
// Инициализация разнорабочего
|
|
||||||
$handymans[$i] = [
|
|
||||||
'time' => $work, // Время работы (ч)
|
|
||||||
'hour' => $hour, // Стоимость работы в час (руб)
|
|
||||||
'cost' => $work * $hour // Стоимость работы
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($company) {
|
|
||||||
// Юридическое лицо
|
|
||||||
|
|
||||||
// Инициализация менеджеров
|
|
||||||
$managers = [static::employee('manager', $complexity, true, errors: $errors)];
|
|
||||||
|
|
||||||
// Инициализация инженеров
|
|
||||||
$engineers = [static::employee('engineer', $complexity, true, errors: $errors)];
|
|
||||||
|
|
||||||
// Инициализация стоимости работы оператора
|
|
||||||
$operator = static::employee('operator', $complexity, true, errors: $errors);
|
|
||||||
|
|
||||||
// Инициализация стоимости 1 часа работы оператора
|
|
||||||
$hour = settings::read('operator_entity_hour') ?? throw new exception('Не найдено: operator_entity_hour');
|
|
||||||
|
|
||||||
// Инициализация операторов
|
|
||||||
$operators = [
|
|
||||||
[
|
|
||||||
'time' => [
|
|
||||||
'design' => $operator['time'],
|
|
||||||
'machine' => $time * $amount / 60 / 60 + $work
|
|
||||||
],
|
|
||||||
'hour' => $operator['hour']
|
|
||||||
]
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
// Физическое лицо
|
|
||||||
|
|
||||||
// Инициализация менеджеров
|
|
||||||
$managers = [static::employee('manager', $complexity, errors: $errors)];
|
|
||||||
|
|
||||||
// Инициализация инженеров
|
|
||||||
$engineers = [static::employee('engineer', $complexity, errors: $errors)];
|
|
||||||
|
|
||||||
// Инициализация данных оператора
|
|
||||||
$operator = static::employee('operator', $complexity, errors: $errors);
|
|
||||||
|
|
||||||
// Инициализация стоимости 1 часа работы оператора
|
|
||||||
$hour = settings::read('operator_individual_hour') ?? throw new exception('Не найдено: operator_individual_hour');
|
|
||||||
|
|
||||||
// Инициализация операторов
|
|
||||||
$operators = [
|
|
||||||
[
|
|
||||||
'time' => [
|
|
||||||
'design' => $operator['time'],
|
|
||||||
'machine' => ($time * $amount / 60 / 60) + $work
|
|
||||||
],
|
|
||||||
'hour' => $operator['hour']
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
$machine['depreciation'] = $time * $amount / 60 / 60 * (int) settings::read('laser_depreciation', $errors) ?? throw new exception('Не найдено: laser_depreciation');
|
|
||||||
|
|
||||||
// Инициализация станков
|
|
||||||
$machines = [
|
|
||||||
$machine
|
|
||||||
];
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [$machines, $managers, $engineers, $operators, $handymans, $other];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,139 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models;
|
|
||||||
|
|
||||||
use mirzaev\minimal\model;
|
|
||||||
|
|
||||||
use pdo;
|
|
||||||
use pdoexception;
|
|
||||||
|
|
||||||
use exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ядро моделей
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
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)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models\filters;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_filter_noname_1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтр импорта цен на алюминий от неизвестного поставщика под номером 1
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models\filters
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class import_aluminum_filter extends import_filter_noname_1
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Название металла
|
|
||||||
*/
|
|
||||||
public string $metal = 'aluminum';
|
|
||||||
|
|
||||||
public function readCell($columnAddress, $row, $worksheetName = '')
|
|
||||||
{
|
|
||||||
if ($row >= 16 && $row <= 17) {
|
|
||||||
// Найдены строки с маркой АД1Н
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 20 && $row <= 28) {
|
|
||||||
// Найдены строки с маркой A5H
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 30 && $row <= 54) {
|
|
||||||
// Найдены строки с маркой АМГ2М
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 56 && $row <= 82) {
|
|
||||||
// Найдены строки с маркой АМГ3М
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 84 && $row <= 105) {
|
|
||||||
// Найдены строки с маркой АМГ5М
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 107 && $row <= 119) {
|
|
||||||
// Найдены строки с маркой АМГ6М
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models\filters;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_filter_noname_1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтр импорта цен на латунь от неизвестного поставщика под номером 1
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models\filters
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class import_brass_filter extends import_filter_noname_1
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Название металла
|
|
||||||
*/
|
|
||||||
public string $metal = 'brass';
|
|
||||||
|
|
||||||
public function readCell($columnAddress, $row, $worksheetName = '')
|
|
||||||
{
|
|
||||||
if ($row >= 553 && $row <= 568) {
|
|
||||||
// Найдены строки с маркой Л63
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 570 && $row <= 577) {
|
|
||||||
// Найдены строки с маркой ЛС59-1
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models\filters;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_filter_noname_1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтр импорта цен на медь от неизвестного поставщика под номером 1
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models\filters
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class import_copper_filter extends import_filter_noname_1
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Название металла
|
|
||||||
*/
|
|
||||||
public string $metal = 'copper';
|
|
||||||
|
|
||||||
public function readCell($columnAddress, $row, $worksheetName = '')
|
|
||||||
{
|
|
||||||
if ($row >= 717 && $row <= 735) {
|
|
||||||
// Найдены строки с маркой М1
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models\filters;
|
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter as filter;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Интерфейс фильтра импорта
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models\filters
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
interface import_filter extends filter
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Чтение ячейки
|
|
||||||
*
|
|
||||||
* @param [type] $columnAddress
|
|
||||||
* @param [type] $row
|
|
||||||
* @param string $worksheetName
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function readCell($columnAddress, $row, $worksheetName = '');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтрация и запись прочитанных данных из EXCEL-документа
|
|
||||||
*
|
|
||||||
* @param int $supply Идентификатор поставки (для записи в БД)
|
|
||||||
* @param Worksheet $spreadsheet Таблица с прочитанными данными
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return int Количество записанных строк
|
|
||||||
*/
|
|
||||||
public function write(int $supply, Worksheet $spreadsheet, array &$errors = []): int;
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models\filters;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_filter as filter;
|
|
||||||
use mirzaev\tordv\calculator\models\metals_model as metals;
|
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтр импорта для документов от "МЕТАЛЛСЕРВИС"
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models\filters
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
class import_filter_mc implements filter
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Название металла
|
|
||||||
*/
|
|
||||||
public string $metal = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Чтение ячейки
|
|
||||||
*
|
|
||||||
* @param [type] $columnAddress
|
|
||||||
* @param [type] $row
|
|
||||||
* @param string $worksheetName
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function readCell($columnAddress, $row, $worksheetName = '')
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтрация и запись прочитанных данных из EXCEL-документа
|
|
||||||
*
|
|
||||||
* @param int $supply Идентификатор поставки (для записи в БД)
|
|
||||||
* @param Worksheet $spreadsheet Таблица с прочитанными данными
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return int Количество записанных строк
|
|
||||||
*/
|
|
||||||
public function write(int $supply, Worksheet $spreadsheet, array &$errors = []): int
|
|
||||||
{
|
|
||||||
// Инициализация счётчика записанных данных
|
|
||||||
$writed = 0;
|
|
||||||
|
|
||||||
for ($row = 1; $row <= $spreadsheet->getHighestRow(); ++$row) {
|
|
||||||
// Перебор строк
|
|
||||||
|
|
||||||
// Инициализация переменных
|
|
||||||
$width = $height = $length = $piece = $ton = null;
|
|
||||||
|
|
||||||
for ($col = 'A'; $col <= $spreadsheet->getHighestColumn(); ++$col) {
|
|
||||||
// Перебор столбцов
|
|
||||||
|
|
||||||
if ($col === 'B') {
|
|
||||||
// Колонка с размером
|
|
||||||
|
|
||||||
// Чтение из ячейки
|
|
||||||
$size = $spreadsheet->getCell($col . $row)->getValue();
|
|
||||||
} else if ($col === 'C') {
|
|
||||||
// Колонка с маркой
|
|
||||||
|
|
||||||
// Чтение из ячейки
|
|
||||||
$mark = $spreadsheet->getCell($col . $row)->getValue();
|
|
||||||
} else if ($col === 'E') {
|
|
||||||
// Колонка с ценой за тонну
|
|
||||||
|
|
||||||
// Чтение из ячейки
|
|
||||||
$ton = (int) round((float) $spreadsheet->getCell($col . $row)->getCalculatedValue());
|
|
||||||
} else if ($col === 'I') {
|
|
||||||
// Колонка с ценой за штуку
|
|
||||||
|
|
||||||
// Чтение из ячейки
|
|
||||||
$piece = (int) round((float) $spreadsheet->getCell($col . $row)->getCalculatedValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Пропуск пустых строк
|
|
||||||
if (empty($size) || empty($mark) || empty($ton) || empty($piece)) continue;
|
|
||||||
|
|
||||||
// Извлечение размеров
|
|
||||||
preg_match_all('/[\d,\.]+/', $size, $matches);
|
|
||||||
|
|
||||||
// Запись размеров
|
|
||||||
$length = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[0][0]));
|
|
||||||
$width = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[0][1]));
|
|
||||||
$height = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[0][2]));
|
|
||||||
|
|
||||||
// Запись металла
|
|
||||||
metals::write($supply, $this->metal, $mark, $width, $height, $length, $piece, $ton, $errors) ? ++$writed : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $writed;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models\filters;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_filter as filter;
|
|
||||||
use mirzaev\tordv\calculator\models\metals_model as metals;
|
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтр импорта для документов от неизвестного поставщика под номером 1
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models\filters
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
class import_filter_noname_1 implements filter
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Название металла
|
|
||||||
*/
|
|
||||||
public string $metal = '';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Чтение ячейки
|
|
||||||
*
|
|
||||||
* @param [type] $columnAddress
|
|
||||||
* @param [type] $row
|
|
||||||
* @param string $worksheetName
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function readCell($columnAddress, $row, $worksheetName = '')
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтрация и запись прочитанных данных из EXCEL-документа
|
|
||||||
*
|
|
||||||
* @param int $supply Идентификатор поставки (для записи в БД)
|
|
||||||
* @param Worksheet $spreadsheet Таблица с прочитанными данными
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return int Количество записанных строк
|
|
||||||
*/
|
|
||||||
public function write(int $supply, Worksheet $spreadsheet, array &$errors = []): int
|
|
||||||
{
|
|
||||||
// Инициализация счётчика записанных данных
|
|
||||||
$writed = 0;
|
|
||||||
|
|
||||||
for ($row = 1; $row <= $spreadsheet->getHighestRow(); ++$row) {
|
|
||||||
// Перебор строк
|
|
||||||
|
|
||||||
// Инициализация переменных
|
|
||||||
$width = $height = $length = $piece = $ton = null;
|
|
||||||
|
|
||||||
for ($col = 1; $col <= coordinate::columnIndexFromString($spreadsheet->getHighestColumn()); ++$col) {
|
|
||||||
// Перебор столбцов
|
|
||||||
|
|
||||||
if ($col === 1) {
|
|
||||||
// Колонка с металлом
|
|
||||||
|
|
||||||
// Чтение из ячейки
|
|
||||||
$metal = $spreadsheet->getCellByColumnAndRow($col, $row)->getValue();
|
|
||||||
} else if ($col === 14) {
|
|
||||||
// Колонка с коэффициентом
|
|
||||||
|
|
||||||
// Чтение из ячейки
|
|
||||||
$coefficient = (float) $spreadsheet->getCellByColumnAndRow($col, $row)->getValue();
|
|
||||||
} else if ($col === 15) {
|
|
||||||
// Колонка с ценой
|
|
||||||
|
|
||||||
// Чтение из ячейки
|
|
||||||
$piece = (int) $spreadsheet->getCellByColumnAndRow($col, $row)->getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Пропуск пустых строк
|
|
||||||
if (empty($metal)) continue;
|
|
||||||
|
|
||||||
// Извлечение размеров
|
|
||||||
preg_match_all('/[\sxх]([\d]+[,\.]?[\d]?)/', $metal, $matches);
|
|
||||||
|
|
||||||
// Запись размеров
|
|
||||||
$length = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[1][0]));
|
|
||||||
$width = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[1][1]));
|
|
||||||
$height = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[1][2]));
|
|
||||||
|
|
||||||
// Извлечение марки металла
|
|
||||||
preg_match_all('/\d+\s+(.*)$/', $metal, $matches);
|
|
||||||
|
|
||||||
// Запись марки металла
|
|
||||||
$mark = trim((string) $matches[1][0]);
|
|
||||||
|
|
||||||
if ($length > 0 && $width > 0 && $height > 0 && !empty($mark) && $piece > 0 && $coefficient > 0) {
|
|
||||||
// Найдены все размеры, марка, цена и коэффициент
|
|
||||||
|
|
||||||
// Цена за тонну
|
|
||||||
$ton = (int) round((float) ($piece / $coefficient * 1000));
|
|
||||||
|
|
||||||
// Запись металла
|
|
||||||
metals::write($supply, $this->metal, $mark, $width, $height, $length, $piece, $ton, $errors) ? ++$writed : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $writed;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models\filters;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_filter_noname_1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтр импорта цен на оцинкованную сталь от "МЕТАЛЛСЕРВИС"
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models\filters
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*
|
|
||||||
* @todo 1. Доделать 982 до 992 строки
|
|
||||||
* 2. Доделать 1069 до 1077 строки
|
|
||||||
*/
|
|
||||||
final class import_galvanized_steel_filter extends import_filter_mc
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Название металла
|
|
||||||
*/
|
|
||||||
public string $metal = 'galvanized_steel';
|
|
||||||
|
|
||||||
public function readCell($columnAddress, $row, $worksheetName = '')
|
|
||||||
{
|
|
||||||
if ($row >= 398 && $row <= 404) {
|
|
||||||
// Найдены строки с данными (Лист оцинкованный ГОСТ 14918-80)
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,71 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models\filters;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_filter_noname_1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтр импорта цен на нержавеющую сталь от неизвестного поставщика под номером 1
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models\filters
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*
|
|
||||||
* @todo 1. Доделать 982 до 992 строки
|
|
||||||
* 2. Доделать 1069 до 1077 строки
|
|
||||||
*/
|
|
||||||
final class import_stainless_steel_filter extends import_filter_noname_1
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Название металла
|
|
||||||
*/
|
|
||||||
public string $metal = 'stainless_steel';
|
|
||||||
|
|
||||||
public function readCell($columnAddress, $row, $worksheetName = '')
|
|
||||||
{
|
|
||||||
if ($row >= 958 && $row <= 982) {
|
|
||||||
// Найдены строки с маркой 12Х18Н10Т AISI 321
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 994 && $row <= 1000) {
|
|
||||||
// Найдены строки с маркой 08Х17 AISI 430 BA
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 1003 && $row <= 1005) {
|
|
||||||
// Найдены строки с маркой 08Х18Н10 AISI 304 BA+PVC
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 1011 && $row <= 1022) {
|
|
||||||
// Найдены строки с маркой 08Х17 AISI 430 2B
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 1024 && $row <= 1069) {
|
|
||||||
// Найдены строки с маркой 08Х18Н10 AISI 304
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 1079 && $row <= 1090) {
|
|
||||||
// Найдены строки с маркой 08Х17 AISI430 4N+PE
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 1092 && $row <= 1099) {
|
|
||||||
// Найдены строки с маркой 08Х18Н10 AISI 304 4N+PE
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models\filters;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_filter_mc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтр импорта цен на чёрную сталь от "МЕТАЛЛСЕРВИС"
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models\filters
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class import_steel_filter extends import_filter_mc
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Название металла
|
|
||||||
*/
|
|
||||||
public string $metal = 'steel';
|
|
||||||
|
|
||||||
public function readCell($columnAddress, $row, $worksheetName = '')
|
|
||||||
{
|
|
||||||
if ($row >= 305 && $row <= 313) {
|
|
||||||
// Найдены строки с данными (Лист холоднокатаный ГОСТ 16523-97)
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 317 && $row <= 345) {
|
|
||||||
// Найдены строки с данными (Лист горячекатаный ГОСТ 16523-97; ГОСТ 14637-89)
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 349 && $row <= 358) {
|
|
||||||
// Найдены строки с данными (Лист горячекатаный низколегированный ГОСТ 19281-89)
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 385 && $row <= 389) {
|
|
||||||
// Найдены строки с данными (Лист рифленый ГОСТ 8568-77)
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($row >= 393 && $row <= 394) {
|
|
||||||
// Найдены строки с данными (Лист просечно-вытяжной ТУ 36.26.11-5-89)
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,232 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\settings_model as settings;
|
|
||||||
use mirzaev\tordv\calculator\models\accounts_model as accounts;
|
|
||||||
|
|
||||||
use pdo;
|
|
||||||
use exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модель металла
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class metals_model extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Расчёт скорость реза металла
|
|
||||||
*
|
|
||||||
* @param string $metal Металл
|
|
||||||
* @param string $gas Газ
|
|
||||||
* @param float $lenght Толщина
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return float|int Скорость реза (мм/с)
|
|
||||||
*/
|
|
||||||
public static function cut(string $metal, string $gas, float $lenght, array &$errors = []): float|int
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return (float) settings::read("cut_speed_${metal}_${gas}_$lenght", $errors) ?? throw new exception('Не удалось определить скорость реза металла');
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Определение веса
|
|
||||||
*
|
|
||||||
* @param string $type Тип
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return float|null Вес (кг)
|
|
||||||
*/
|
|
||||||
public static function kg(string $type = 'stainless_steel', array &$errors = []): ?float
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return (float) match ($type) {
|
|
||||||
'steel' => 8,
|
|
||||||
'galvanized_steel' => 8,
|
|
||||||
'stainless_steel' => 8.7,
|
|
||||||
'brass' => 8.7,
|
|
||||||
'copper' => 9,
|
|
||||||
'aluminum' => 3,
|
|
||||||
default => throw new exception('Не удалось определить тип металла')
|
|
||||||
};
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Запись в базу данных
|
|
||||||
*
|
|
||||||
* @param int $supply Идентификатор записи поставки в базе данных
|
|
||||||
* @param string $type Тип
|
|
||||||
* @param string $mark Марка
|
|
||||||
* @param float $width Ширина (мм)
|
|
||||||
* @param float $height Высота (мм)
|
|
||||||
* @param float $length Толщина (мм)
|
|
||||||
* @param int $piece Цена за лист (руб)
|
|
||||||
* @param int $ton Цена за тонну (руб)
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return bool Статус записи
|
|
||||||
*/
|
|
||||||
public static function write(int $supply, string $type, string $mark, float $width, float $height, float $length, int $piece, int $ton, array &$errors = []): bool
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if ($account = accounts::account($errors)) {
|
|
||||||
// Инициализирован аккаунт
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("INSERT INTO `metals` (`supply`, `type`, `mark`, `width`, `height`, `length`, `piece`, `ton`, `account`) VALUES (:supply, :type, :mark, :width, :height, :length, :piece, :ton, :account)");
|
|
||||||
|
|
||||||
// Инициализация параметров
|
|
||||||
$params = [
|
|
||||||
':supply' => $supply,
|
|
||||||
':type' => $type,
|
|
||||||
':mark' => $mark,
|
|
||||||
':width' => $width,
|
|
||||||
':height' => $height,
|
|
||||||
':length' => $length,
|
|
||||||
':piece' => $piece,
|
|
||||||
':ton' => $ton,
|
|
||||||
':account' => $account['id'],
|
|
||||||
];
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute($params);
|
|
||||||
|
|
||||||
// Получение ответа
|
|
||||||
return $request->fetch(pdo::FETCH_ASSOC) !== false;
|
|
||||||
}
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Чтение из базы данных
|
|
||||||
*
|
|
||||||
* Очищает от дубликатов
|
|
||||||
*
|
|
||||||
* @param string $type Тип
|
|
||||||
* @param string $mark Марка
|
|
||||||
* @param float $length Толщина
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return float|null Цена за 1 килограмм (руб)
|
|
||||||
*/
|
|
||||||
public static function read(string $type, string $mark, float $length, array &$errors = []): ?array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("SELECT `width`, `height`, `piece`, `ton` FROM `metals` WHERE `type` = :type && `mark` = :mark && `length` = :length LIMIT 30");
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute([
|
|
||||||
':type' => $type,
|
|
||||||
':mark' => $mark,
|
|
||||||
':length' => $length
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Генерация ответа
|
|
||||||
$response = $request->fetchAll(pdo::FETCH_ASSOC);
|
|
||||||
|
|
||||||
// Проверка на полученные значения
|
|
||||||
if (!is_array($response)) return false;
|
|
||||||
|
|
||||||
if (count($response) === 1) return $response[0];
|
|
||||||
else if (count($response) > 1) {
|
|
||||||
// Найдено более чем одно значение
|
|
||||||
|
|
||||||
// Инициализация буфера вывода
|
|
||||||
$buffer = $response[0];
|
|
||||||
|
|
||||||
foreach ($response as $metal) {
|
|
||||||
// Перебор полученных значений металлов
|
|
||||||
|
|
||||||
// Запись в буфер металла с самой большей площадью листа
|
|
||||||
if (($metal['width'] * $metal['height']) > ($buffer['width'] * $buffer['height'])) $buffer = $metal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $metal;
|
|
||||||
}
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Поиск и чтение марок металла
|
|
||||||
*
|
|
||||||
* Очищает от дубликатов
|
|
||||||
*
|
|
||||||
* @param string $type Тип
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return float|null Цена за 1 килограмм (руб)
|
|
||||||
*/
|
|
||||||
public static function marks(string $type = '*', array &$errors = []): ?array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("SELECT DISTINCT `mark` FROM `metals` WHERE `type` = :type");
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute([':type' => $type]);
|
|
||||||
|
|
||||||
// Генерация ответа
|
|
||||||
$response = $request->fetchAll(pdo::FETCH_COLUMN);
|
|
||||||
|
|
||||||
return $response === false ? null : (array) $response;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,265 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models;
|
|
||||||
|
|
||||||
use pdo;
|
|
||||||
use exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модель настроек
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class settings_model extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Записать настройку
|
|
||||||
*
|
|
||||||
* @param string $name Название параметра
|
|
||||||
* @param int|float|string|bool $value Значение параметра
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return bool Статус записи
|
|
||||||
*/
|
|
||||||
public static function write(string $name, int|float|string|bool $value, array &$errors = []): bool
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("SELECT MAX(`id`) FROM `settings`");
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute();
|
|
||||||
|
|
||||||
// Получение ответа
|
|
||||||
$id = (int) $request->fetchColumn();
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("UPDATE `settings` SET `$name` = :value WHERE `id` = $id");
|
|
||||||
|
|
||||||
// Параметры запроса
|
|
||||||
$params = [
|
|
||||||
":value" => $value
|
|
||||||
];
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute($params);
|
|
||||||
|
|
||||||
// Получение ответа
|
|
||||||
return $request->fetch(pdo::FETCH_ASSOC) !== false;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Прочитать настройку
|
|
||||||
*
|
|
||||||
* @param string $name Название параметра
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return int|float|string|array|null Значение параметра
|
|
||||||
*/
|
|
||||||
public static function read(string $name = '*', array &$errors = []): int|float|string|array|null
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("SELECT $name FROM `settings` WHERE `id` = (SELECT MAX(`id`) FROM `settings`) ORDER BY `id` DESC LIMIT 1");
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute();
|
|
||||||
|
|
||||||
// Генерация ответа
|
|
||||||
$response = $name === '*' ? $request->fetch(pdo::FETCH_ASSOC) : $request->fetchColumn();
|
|
||||||
|
|
||||||
return $response === false ? null : $response;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Прочитать названия настроек
|
|
||||||
*
|
|
||||||
* @param int $limit Максимальное ограничение
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array|null Значение параметра
|
|
||||||
*/
|
|
||||||
public static function names(int $limit = 5000, array &$errors = []): ?array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("SELECT TABLE_NAME AS 'settings' FROM INFORMATION_SCHEMA.COLUMNS WHERE `table_name` = 'settings'");
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute();
|
|
||||||
|
|
||||||
// Генерация ответа
|
|
||||||
$response = $request->fetchColumn();
|
|
||||||
|
|
||||||
return $response === false ? null : (array) $response;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Фильтровать настройки
|
|
||||||
*
|
|
||||||
* Удаляет из массива ненужные данные (id, create...)
|
|
||||||
*
|
|
||||||
* @param array $settings Настройки
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array Настройки
|
|
||||||
*/
|
|
||||||
public static function filter(array $settings, array &$errors = []): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация буфера вывода
|
|
||||||
$buffer = [];
|
|
||||||
|
|
||||||
foreach ($settings as $setting => $value) {
|
|
||||||
// Перебор настроек
|
|
||||||
|
|
||||||
if ($setting === 'id') continue;
|
|
||||||
if ($setting === 'create') continue;
|
|
||||||
|
|
||||||
$buffer[$setting] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $buffer ?? $settings;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Перевести настройки на русский язык
|
|
||||||
*
|
|
||||||
* @param array $settings Настройки
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return array Настройки
|
|
||||||
*/
|
|
||||||
public static function translate(array $settings, array &$errors = []): array
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
// Инициализация буфера вывода
|
|
||||||
$buffer = [];
|
|
||||||
|
|
||||||
foreach ($settings as $setting => $value) {
|
|
||||||
// Перебор настроек
|
|
||||||
|
|
||||||
$buffer[] = [
|
|
||||||
'russian' => match ($setting) {
|
|
||||||
'default_buyer' => 'Покупатель по умолч.',
|
|
||||||
'default_complexity' => 'Сложность по умолч.',
|
|
||||||
'default_width' => 'Ширина по умолч. (мм)',
|
|
||||||
'default_height' => 'Высота по умолч. (мм)',
|
|
||||||
'default_length' => 'Толщина по умолч. (мм)',
|
|
||||||
'default_amount' => 'Количество по умолч. (шт)',
|
|
||||||
'default_type' => 'Тип металла по умолч.',
|
|
||||||
'default_holes' => 'Отверстия по умол. (шт)',
|
|
||||||
'default_diameter' => 'Диаметр отверстий по умол. (мм)',
|
|
||||||
'electricity' => 'Стоимость 1квт',
|
|
||||||
'laser_power' => 'Потребление лазер. станка (квт)',
|
|
||||||
'manager_individual_min' => 'Менеджер для физ. лица мин. (ч)',
|
|
||||||
'manager_individual_max' => 'Менеджер для физ. лица макс. (ч)',
|
|
||||||
'manager_entity_min' => 'Менеджер для юр. лица мин. (ч)',
|
|
||||||
'manager_entity_max' => 'Менеджер для юр. лица макс. (ч)',
|
|
||||||
'manager_entity_hour' => 'Менеджер для юр. лица (руб/час)',
|
|
||||||
'manager_individual_hour' => 'Менеджер для физ. лица (руб/час)',
|
|
||||||
'engineer_entity_min' => 'Инженер для юр. лица мин. (ч)',
|
|
||||||
'engineer_entity_max' => 'Инженер для юр. лица макс. (ч)',
|
|
||||||
'engineer_entity_hour' => 'Инженер для юр. лица (руб/час)',
|
|
||||||
'engineer_individual_min' => 'Инженер для физ. лица мин. (ч)',
|
|
||||||
'engineer_individual_max' => 'Инженер для физ. лица макс. (ч)',
|
|
||||||
'engineer_individual_hour' => 'Инженер для физ. лица (руб/час)',
|
|
||||||
'operator_entity_min' => 'Оператор для юр. лица мин. (ч)',
|
|
||||||
'operator_entity_max' => 'Оператор для юр. лица макс. (ч)',
|
|
||||||
'operator_individual_min' => 'Оператор для физ. лица мин. (ч)',
|
|
||||||
'operator_individual_max' => 'Оператор для физ. лица макс. (ч)',
|
|
||||||
'operator_entity_hour' => 'Оператор для юр. лица (руб/час)',
|
|
||||||
'operator_individual_hour' => 'Оператор для физ. лица (руб/час)',
|
|
||||||
'coefficient_area_less' => 'Штраф если пл. меньше (мм)',
|
|
||||||
'coefficient_area_more' => 'Штраф если пл. больше (мм)',
|
|
||||||
'coefficient_area_degree' => 'Коэфф. для штрафа по площади',
|
|
||||||
'coefficient_complexity_easy' => 'Коэфф. низкой слож.',
|
|
||||||
'coefficient_complexity_medium' => 'Коэфф. средней слож.',
|
|
||||||
'coefficient_complexity_hard' => 'Коэфф. высокой слож.',
|
|
||||||
'list_width' => 'Ширина листа (мм)',
|
|
||||||
'list_height' => 'Высота листа (мм)',
|
|
||||||
'metal_cost_easy_1_3' => 'Тонна 1-3мм низкая слож. (руб)',
|
|
||||||
'metal_cost_medium_1_3' => 'Тонна 1-3мм средняя слож. (руб)',
|
|
||||||
'metal_cost_hard_1_3' => 'Тонна 1-3мм высокая слож. (руб)',
|
|
||||||
'metal_cost_easy_4_6' => 'Тонна 4-6мм низкая слож. (руб)',
|
|
||||||
'metal_cost_medium_4_6' => 'Тонна 4-6мм средняя слож. (руб)',
|
|
||||||
'metal_cost_hard_4_6' => 'Тонна 4-6мм высокая слож. (руб)',
|
|
||||||
'metal_cost_easy_7_10' => 'Тонна 7-10мм низкая слож. (руб)',
|
|
||||||
'metal_cost_medium_7_10' => 'Тонна 7-10мм средняя слож. (руб)',
|
|
||||||
'metal_cost_hard_7_10' => 'Тонна 7-10мм высокая слож. (руб)',
|
|
||||||
'metal_cost_easy_10' => 'Тонна >10мм низкая слож. (руб)',
|
|
||||||
'metal_cost_medium_10' => 'Тонна >10мм средняя слож. (руб)',
|
|
||||||
'metal_cost_hard_10' => 'Тонна >10мм высокая слож. (руб)',
|
|
||||||
'additive' => 'Коэфф. наценки',
|
|
||||||
'handyman_hour' => 'Разнорабочий (руб/ч)',
|
|
||||||
'handyman_metal_load_time' => 'Время установки металла (мин)',
|
|
||||||
'laser_handymans_amount' => 'Разнорабочие для лазерного станка',
|
|
||||||
default => $setting
|
|
||||||
},
|
|
||||||
'english' => $setting,
|
|
||||||
'value' => $value
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $buffer ?? $settings;
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[]= [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $settings;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator\models;
|
|
||||||
|
|
||||||
use mirzaev\tordv\calculator\models\accounts_model as accounts;
|
|
||||||
use mirzaev\tordv\calculator\models\filters\import_filter as filter;
|
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Reader\Xls as reader;
|
|
||||||
|
|
||||||
use pdo;
|
|
||||||
use exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Модель поставки
|
|
||||||
*
|
|
||||||
* @package mirzaev\tordv\calculator\models
|
|
||||||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
|
||||||
*/
|
|
||||||
final class supplies_model extends core
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Запись в базу данных
|
|
||||||
*
|
|
||||||
* @param string $file Путь до файла
|
|
||||||
* @param filter|null $filter Фильтр строк
|
|
||||||
* @param array &$errors Журнал ошибок
|
|
||||||
*
|
|
||||||
* @return bool Статус записи
|
|
||||||
*/
|
|
||||||
public static function write(string $file, ?filter $filter = null, array &$errors = []): bool
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (file_exists($file) && $account = accounts::account($errors)) {
|
|
||||||
// Найден файл и инициализирован аккаунт
|
|
||||||
|
|
||||||
// Инициализация обработчика документа
|
|
||||||
$reader = new reader();
|
|
||||||
|
|
||||||
// Инициализация фильтра строк
|
|
||||||
if (isset($filter)) $reader->setReadFilter($filter);
|
|
||||||
|
|
||||||
// Чтение файла
|
|
||||||
$spreadsheet = $reader->load($file)->getActiveSheet();
|
|
||||||
|
|
||||||
// Инициализация запроса
|
|
||||||
$request = static::$db->prepare("INSERT INTO `supplies` (`account`) VALUES (:account)");
|
|
||||||
|
|
||||||
// Инициализация параметров
|
|
||||||
$params = [
|
|
||||||
':account' => $account['id'],
|
|
||||||
];
|
|
||||||
|
|
||||||
// Отправка запроса
|
|
||||||
$request->execute($params);
|
|
||||||
|
|
||||||
// Запись идентификатора поставки
|
|
||||||
$supply = (int) (static::$db->lastInsertId() ?? throw new exception('Не удалось найти идентификатор записанной поставки'));
|
|
||||||
|
|
||||||
// Запись в базу данных
|
|
||||||
$filter->write($supply, $spreadsheet, $errors);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// Не найден файл
|
|
||||||
|
|
||||||
throw new exception("Файл не найден: $file");
|
|
||||||
}
|
|
||||||
} catch (exception $e) {
|
|
||||||
// Запись в журнал ошибок
|
|
||||||
$errors[] = [
|
|
||||||
'text' => $e->getMessage(),
|
|
||||||
'file' => $e->getFile(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'stack' => $e->getTrace()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
index.php
|
|
|
@ -1,67 +0,0 @@
|
||||||
#authentication>:is(form, div) {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication .exit {
|
|
||||||
margin-top: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication p {
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication p>span {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication>form>input:is([type="text"], [type="password"]) {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication>form>input:last-child {
|
|
||||||
margin-bottom: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication>form>.submit {
|
|
||||||
margin-top: 6px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication>form>.submit>label {
|
|
||||||
padding: 10px 20px;
|
|
||||||
border: unset;
|
|
||||||
border-radius: 3px 0 0 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication>form>.submit>input {
|
|
||||||
padding: 10px 20px;
|
|
||||||
flex-grow: 1;
|
|
||||||
border: unset;
|
|
||||||
border-radius: 0 3px 3px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#authentication>form>input[type=submit].registration {
|
|
||||||
padding: 7px 20px;
|
|
||||||
background-color: #57bb3b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication>form>input[type=submit].registration:hover {
|
|
||||||
background-color: #59ca3a;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication>form>input[type=submit].registration:is(:active, :focus) {
|
|
||||||
background-color: #52a93a;
|
|
||||||
}
|
|
||||||
|
|
||||||
#authentication>form>ul.errors {
|
|
||||||
margin-top: 18px;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
padding: 10px;
|
|
||||||
text-align: center;
|
|
||||||
list-style: none;
|
|
||||||
background-color: #ae8f8f;
|
|
||||||
}
|
|
|
@ -1,171 +0,0 @@
|
||||||
#calculator :is(a, label)[type="button"] {
|
|
||||||
margin-right: 10px;
|
|
||||||
padding: 15px 20px;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator :is(a, label)[type="button"]:last-child {
|
|
||||||
margin-right: unset;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>section:first-of-type {
|
|
||||||
margin-top: 35px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>section {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>section:last-child {
|
|
||||||
margin-bottom: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>section :is(a, label)[type="button"] {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>section :is(a, label)[type="button"]>img {
|
|
||||||
height: 70px;
|
|
||||||
margin: 8px auto 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>a#calculate {
|
|
||||||
padding: 10px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.divider+h3 {
|
|
||||||
margin-top: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator {
|
|
||||||
padding: 5px 30px 10px 30px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>label {
|
|
||||||
font-weight: bold;
|
|
||||||
margin: auto 15px auto auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div:not(:last-child) {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div {
|
|
||||||
width: 60%;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div {
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div>:is(input, small, span):not(.measured, :last-child) {
|
|
||||||
margin-right: 5px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div>:is(input, .unit) {
|
|
||||||
font-size: small;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div>input {
|
|
||||||
width: 50px;
|
|
||||||
padding: 5px 8px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div>input.measured {
|
|
||||||
padding-right: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div>small {
|
|
||||||
margin: auto 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div>input+.unit {
|
|
||||||
margin: auto 0;
|
|
||||||
padding-top: unset;
|
|
||||||
padding-bottom: unset;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div,
|
|
||||||
#calculator>.calculator>div>div>select {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div>input:is([type="checkbox"], [type="radio"]) {
|
|
||||||
width: min-content;
|
|
||||||
height: 1rem;
|
|
||||||
margin: auto 0;
|
|
||||||
padding: 0;
|
|
||||||
display: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div>input[type="range"] {
|
|
||||||
min-width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>.calculator>div>div>input[type="range"] {
|
|
||||||
min-width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>a {
|
|
||||||
margin: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>#errors {
|
|
||||||
margin-bottom: unset;
|
|
||||||
padding: 15px 25px;
|
|
||||||
background-color: #acacac;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>#errors:empty {
|
|
||||||
margin: unset;
|
|
||||||
padding: unset;
|
|
||||||
background-color: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>#errors>dt {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>#errors>dd {
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>div[type="row"]:first-of-type {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>div[type="row"]:last-of-type {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>div[type="row"] {
|
|
||||||
padding: 0 10px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
#calculator>#result>div[type="row"]>label {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
#settings>.setting {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings>.setting:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
#settings>.setting>label {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings>.setting>input {
|
|
||||||
width: 20%;
|
|
||||||
margin-right: 15%;
|
|
||||||
padding: 6px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings>h2.supplies {
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
Before Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 64 KiB |
|
@ -1,51 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace mirzaev\tordv\calculator;
|
|
||||||
|
|
||||||
use mirzaev\minimal\core;
|
|
||||||
use mirzaev\minimal\router;
|
|
||||||
|
|
||||||
define('SUPPLIES', realpath('supplies'));
|
|
||||||
define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views'));
|
|
||||||
define('TYPE', 'mysql');
|
|
||||||
define('BASE', 'calculator');
|
|
||||||
define('HOST', '127.0.0.1');
|
|
||||||
define('LOGIN', 'root');
|
|
||||||
define('PASSWORD', '');
|
|
||||||
|
|
||||||
// Автозагрузка
|
|
||||||
require __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
|
||||||
|
|
||||||
// Инициализация маршрутазитора
|
|
||||||
$router = new router;
|
|
||||||
|
|
||||||
// Запись маршрутов
|
|
||||||
$router->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('/account/data', 'accounts', 'data', 'POST');
|
|
||||||
$router->write('/calculator', 'calculator', 'index', 'POST');
|
|
||||||
$router->write('/calculator/generate/buyer', 'calculator', 'buyer', 'POST');
|
|
||||||
$router->write('/calculator/generate/complexity', 'calculator', 'complexity', 'POST');
|
|
||||||
$router->write('/calculator/generate/menu', 'calculator', 'menu', 'POST');
|
|
||||||
$router->write('/calculator/generate/result', 'calculator', 'result', 'POST');
|
|
||||||
$router->write('/calculator/generate/mark', 'calculator', 'mark', 'POST');
|
|
||||||
$router->write('/calculator/generate/divider', 'calculator', 'divider', 'POST');
|
|
||||||
$router->write('/calculator/generate/laser', 'calculator', 'laser', 'POST');
|
|
||||||
$router->write('/calculator/calculate', 'calculator', 'calculate', 'POST');
|
|
||||||
$router->write('/settings', 'settings', 'index', 'GET');
|
|
||||||
$router->write('/settings/write', 'settings', 'write', 'POST');
|
|
||||||
$router->write('/settings/read', 'settings', 'read', 'POST');
|
|
||||||
$router->write('/supplies/write', 'supplies', 'write', 'POST');
|
|
||||||
$router->write('/journal', 'journal', 'index', 'GET');
|
|
||||||
$router->write('/contacts', 'contacts', 'index', 'GET');
|
|
||||||
|
|
||||||
// Инициализация ядра
|
|
||||||
$core = new Core(namespace: __NAMESPACE__, router: $router);
|
|
||||||
|
|
||||||
// Обработка запроса
|
|
||||||
echo $core->start();
|
|
|
@ -1,37 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function remember_switch(target) {
|
|
||||||
if (target.classList.contains('fa-unlock')) {
|
|
||||||
// Найден "открытый замок"
|
|
||||||
|
|
||||||
// Перезапись на "закрытый замок"
|
|
||||||
target.classList.remove('fa-unlock');
|
|
||||||
target.classList.add('fa-lock');
|
|
||||||
|
|
||||||
// Изменение отправляемого значения
|
|
||||||
document.querySelector('input[name=' + target.getAttribute('for') + ']').checked = true;
|
|
||||||
} else {
|
|
||||||
// Не найден "открытый замок", подразумевается, что найден "закрытый замок"
|
|
||||||
|
|
||||||
// Перезапись на "открытый замок"
|
|
||||||
target.classList.remove('fa-lock');
|
|
||||||
target.classList.add('fa-unlock');
|
|
||||||
|
|
||||||
// Изменение отправляемого значения
|
|
||||||
document.querySelector('input[name=' + target.getAttribute('for') + ']').checked = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function authentication(form) {
|
|
||||||
// Инициализация адреса отправки формы
|
|
||||||
form.action = '/account/authentication';
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function registration(form) {
|
|
||||||
// Инициализация адреса отправки формы
|
|
||||||
form.action = '/account/registration';
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,577 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let calculator = {
|
|
||||||
index: document.getElementById("calculator"),
|
|
||||||
calculators: [],
|
|
||||||
account: [],
|
|
||||||
settings: {
|
|
||||||
defaults: {
|
|
||||||
buyer: 'individual',
|
|
||||||
complexity: 'medium',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
init() {
|
|
||||||
// Инициализация калькулятора
|
|
||||||
|
|
||||||
this.generate.buyer(this.settings.defaults.buyer)
|
|
||||||
.then(
|
|
||||||
success => {
|
|
||||||
this.generate.complexity(this.settings.defaults.complexity)
|
|
||||||
.then(
|
|
||||||
success => {
|
|
||||||
this.generate.menu()
|
|
||||||
.then(
|
|
||||||
success => {
|
|
||||||
this.authenticate(cookie.read('id'))
|
|
||||||
.then(
|
|
||||||
success => {
|
|
||||||
// Запись данных аккаунта
|
|
||||||
this.account = success;
|
|
||||||
|
|
||||||
if (this.account !== undefined && typeof this.account === 'object' && this.account.permissions !== undefined) {
|
|
||||||
// Найден аккаунт
|
|
||||||
|
|
||||||
if (this.account.permissions.calculate == 1) {
|
|
||||||
// Разрешено использовать калькулятор
|
|
||||||
|
|
||||||
this.generate.result();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Инициализирован');
|
|
||||||
},
|
|
||||||
authenticate(id) {
|
|
||||||
// Запрос и генерация HTML с данными о типе покупателя (юр. лицо и физ. лицо)'
|
|
||||||
|
|
||||||
return fetch('/account/data?id=' + id, {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/x-www-form-urlencoded" }
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
return response.json().then(
|
|
||||||
success => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Загружены данные пользователя: ' + id);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить данные пользователя: ' + id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
calculate() {
|
|
||||||
// Запрос и генерация HTML с данными о рассчете со всех калькуляторов
|
|
||||||
|
|
||||||
// Инициализация параметров
|
|
||||||
let cutting = document.getElementById('cutting');
|
|
||||||
let discount = document.getElementById('discount');
|
|
||||||
|
|
||||||
// Инициализация буфера запроса
|
|
||||||
let query = {
|
|
||||||
calculators: {},
|
|
||||||
cutting: +cutting.value ?? 0,
|
|
||||||
discount: +discount.value ?? 0
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const number in this.calculators) {
|
|
||||||
// Перебор калькуляторов
|
|
||||||
|
|
||||||
// Инициализация буфера запроса для нового калькулятора
|
|
||||||
query['calculators'][number] = {};
|
|
||||||
|
|
||||||
// Инициализация типа калькулятора
|
|
||||||
query['calculators'][number]['calculator'] = this.calculators[number].getAttribute('data-calculator');
|
|
||||||
|
|
||||||
for (const buyer of this.index.querySelectorAll('input[name="buyer"]')) {
|
|
||||||
// Перебор полей с параметрами типа заказчика
|
|
||||||
|
|
||||||
if (buyer.checked) {
|
|
||||||
// Найдено выбранное поле
|
|
||||||
|
|
||||||
// Запись в буфер запроса
|
|
||||||
query['calculators'][number]['buyer'] = buyer.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const complexity of this.index.querySelectorAll('input[name="complexity"]')) {
|
|
||||||
// Перебор полей с параметрами сложности
|
|
||||||
|
|
||||||
if (complexity.checked) {
|
|
||||||
// Найдено выбранное поле
|
|
||||||
|
|
||||||
// Запись в буфер запроса
|
|
||||||
query['calculators'][number]['complexity'] = complexity.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const field of this.calculators[number].querySelectorAll('[data-calculator-parameter]')) {
|
|
||||||
// Перебор полей с параметрами
|
|
||||||
|
|
||||||
if (field.getAttribute('type') === 'checkbox') {
|
|
||||||
// Флажок
|
|
||||||
|
|
||||||
// Запись в буфер запроса
|
|
||||||
query['calculators'][number][field.getAttribute('data-calculator-parameter')] = field.checked;
|
|
||||||
} else if (field.getAttribute('type') === 'text' || field.getAttribute('type') === 'number' || field.getAttribute('type') === 'range') {
|
|
||||||
// Текстовое, цифровое поле или ползунок
|
|
||||||
|
|
||||||
// Запись в буфер запроса
|
|
||||||
query['calculators'][number][field.getAttribute('data-calculator-parameter')] = field.value;
|
|
||||||
} else {
|
|
||||||
// Элемент с тегом <select> (подразумевается)
|
|
||||||
|
|
||||||
// Запись в буфер запроса
|
|
||||||
query['calculators'][number][field.getAttribute('data-calculator-parameter')] = field.value ?? field.options[field.selectedIndex].text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fetch('/calculator/calculate', {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/json" },
|
|
||||||
body: JSON.stringify(query)
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.json().then(
|
|
||||||
success => {
|
|
||||||
// Инициализация буфера расходов
|
|
||||||
let expenses = 0;
|
|
||||||
|
|
||||||
// Инициализация буфера с данными расчёта
|
|
||||||
let result;
|
|
||||||
|
|
||||||
if (this.generate.error(success.errors) > 0) {
|
|
||||||
// Найдены ошибки
|
|
||||||
|
|
||||||
// Генерация текста ответа
|
|
||||||
result = 'Ошибка';
|
|
||||||
} else {
|
|
||||||
// Не найдены ошибки
|
|
||||||
|
|
||||||
if (success.other.cutting !== undefined) {
|
|
||||||
// Получены данные времени работы
|
|
||||||
|
|
||||||
// Запись полученных данных
|
|
||||||
cutting.value = success.other.cutting;
|
|
||||||
cutting.parentElement.children[0].innerText = 'Длина реза 1 детали (' + cutting.value + 'мм)';
|
|
||||||
|
|
||||||
// Разблокировка параметра
|
|
||||||
cutting.removeAttribute('disabled');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success.other.discount !== undefined) {
|
|
||||||
// Получены данные скидки
|
|
||||||
|
|
||||||
// Запись полученных данных
|
|
||||||
discount.value = success.other.discount;
|
|
||||||
discount.parentElement.children[0].innerText = 'Скидка (' + discount.value + '%)';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [, machine] of Object.entries(success.machines)) {
|
|
||||||
// Перебор станков
|
|
||||||
|
|
||||||
// Прибавление данных станка к буферу расходов
|
|
||||||
expenses += (machine.electricity + (machine.metal ?? 0));
|
|
||||||
|
|
||||||
// Прибавление амортизации к буферу вывода
|
|
||||||
expenses += machine.reprocessing ?? 0;
|
|
||||||
|
|
||||||
// Прибавление линз к буферу вывода
|
|
||||||
expenses += machine.lenses ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [, manager] of Object.entries(success.managers)) {
|
|
||||||
// Перебор менеджеров
|
|
||||||
|
|
||||||
// Прибавление данных менеджера к буферу расходов
|
|
||||||
expenses += manager.time * manager.hour;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [, engineer] of Object.entries(success.engineers)) {
|
|
||||||
// Перебор инженеров
|
|
||||||
|
|
||||||
// Прибавление данных инженера к буферу расходов
|
|
||||||
expenses += engineer.time * engineer.hour;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [, operator] of Object.entries(success.operators)) {
|
|
||||||
// Перебор операторов
|
|
||||||
|
|
||||||
// Прибавление данных оператора к буферу расходов
|
|
||||||
expenses += (operator.time.design + operator.time.machine) * operator.hour;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const [, handyman] of Object.entries(success.handymans)) {
|
|
||||||
// Перебор разнорабочих
|
|
||||||
|
|
||||||
// Прибавление данных к буферу расходов
|
|
||||||
expenses += handyman.time * handyman.hour;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Прибавление аренды к буферу расходов
|
|
||||||
expenses += success.other.rent ?? 0;
|
|
||||||
|
|
||||||
// Прибавление переработки к буферу расходов
|
|
||||||
expenses += success.other.reprocessing ?? 0;
|
|
||||||
|
|
||||||
// Прибавление баллонов к буферу расходов
|
|
||||||
expenses += success.other.baloons.cost ?? 0;
|
|
||||||
|
|
||||||
// Вычисление наценки (коэффициент)
|
|
||||||
expenses *= success.other.additive ?? 1;
|
|
||||||
|
|
||||||
// Вычитание скидки менеджера
|
|
||||||
expenses -= expenses * ((discount.value ?? 100) / 100);
|
|
||||||
|
|
||||||
// Округление
|
|
||||||
expenses = expenses.toFixed(2);
|
|
||||||
|
|
||||||
// Генерация текста ответа
|
|
||||||
result = expenses + ' рублей';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.generate.result(result)) {
|
|
||||||
console.log(`[КАЛЬКУЛЯТОР] Сгенерирован результат: ${expenses} рублей`);
|
|
||||||
} else {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось сгенерировать результат');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось сгенерировать результат');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
generate: {
|
|
||||||
buyer(value = 'individual') {
|
|
||||||
// Запрос и генерация HTML с данными о типе покупателя (юр. лицо и физ. лицо)
|
|
||||||
|
|
||||||
return fetch('/calculator/generate/buyer?value=' + value, {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/x-www-form-urlencoded" }
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.text().then(
|
|
||||||
success => {
|
|
||||||
calculator.index.insertAdjacentHTML('beforeend', success);
|
|
||||||
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с кнопками выбора типа покупателя');
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить элемент с кнопками выбора типа покупателя');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
complexity(value = 'medium') {
|
|
||||||
// Запрос и генерация HTML с данными о сложности работы
|
|
||||||
|
|
||||||
return fetch('/calculator/generate/complexity?value=' + value, {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/x-www-form-urlencoded" }
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.text().then(
|
|
||||||
success => {
|
|
||||||
calculator.index.insertAdjacentHTML('beforeend', success);
|
|
||||||
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с кнопками выбора сложности');
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить элемент с кнопками выбора сложности');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
menu() {
|
|
||||||
// Запрос и генерация HTML с кнопками добавления калькулятора
|
|
||||||
|
|
||||||
return fetch('/calculator/generate/menu', {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/x-www-form-urlencoded" }
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.text().then(
|
|
||||||
success => {
|
|
||||||
calculator.index.insertAdjacentHTML('beforeend', success);
|
|
||||||
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с кнопками добавления калькулятора');
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить элемент с кнопками добавления калькулятора');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
mark(element, type = '') {
|
|
||||||
// Запрос и генерация HTML с полем выбора марки металла
|
|
||||||
|
|
||||||
return fetch('/calculator/generate/mark?type=' + type, {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/x-www-form-urlencoded" }
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.text().then(
|
|
||||||
success => {
|
|
||||||
// Поиск устаревшего списка с марками
|
|
||||||
let old = element.querySelectorAll('select[name="mark"]')[0];
|
|
||||||
|
|
||||||
if (old !== undefined) {
|
|
||||||
// Найден список с марками
|
|
||||||
|
|
||||||
// Деинициализация
|
|
||||||
old.parentElement.parentElement.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация оболочки в которую необходимо записать список
|
|
||||||
let wrap = element.querySelectorAll('select[name="type"]')[0].parentElement.parentElement
|
|
||||||
|
|
||||||
// Запись полученного списка в оболочку
|
|
||||||
wrap.insertAdjacentHTML('afterend', success);
|
|
||||||
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Загружен список с марками металла');
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить список с марками металла');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
divider(element, position) {
|
|
||||||
// Запрос и генерация HTML с данными о результате калькуляции
|
|
||||||
|
|
||||||
return fetch('/calculator/generate/divider', {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/x-www-form-urlencoded" }
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.text().then(
|
|
||||||
success => {
|
|
||||||
if (element === undefined || position === undefined) {
|
|
||||||
// Не задан элемент и позиция добавляемого разделителя
|
|
||||||
|
|
||||||
// Запись разделителя в конце калькулятора
|
|
||||||
calculator.index.insertAdjacentHTML('beforeend', success);
|
|
||||||
} else {
|
|
||||||
// Задан элемент и позиция добавляемого разделителя
|
|
||||||
|
|
||||||
// Запись разделителя по заданным параметрам
|
|
||||||
element.insertAdjacentHTML(position, success);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Загружен разделитель');
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить разделитель');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
result(expenses) {
|
|
||||||
// Запрос и генерация HTML с данными о результате калькуляции
|
|
||||||
|
|
||||||
function request() {
|
|
||||||
return fetch('/calculator/generate/result', {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/x-www-form-urlencoded" }
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.text().then(
|
|
||||||
success => {
|
|
||||||
calculator.index.insertAdjacentHTML('beforeend', success);
|
|
||||||
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с данными о результате калькуляции');
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить элемент с данными о результате калькуляции');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.getElementById("result") === null) {
|
|
||||||
// Не найден элемент с данными расчётов
|
|
||||||
} else {
|
|
||||||
// Найден элемент с данными расчётов
|
|
||||||
|
|
||||||
if (expenses !== undefined) {
|
|
||||||
// Переданы расходы
|
|
||||||
|
|
||||||
// Инициализация элемента
|
|
||||||
let element = document.getElementById('calculate');
|
|
||||||
|
|
||||||
if (element == null) {
|
|
||||||
// Не найден элемент с результатом расчёта
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Запись расходов в элемент (подразумевается кнопка отправки на расчёт)
|
|
||||||
element.innerText = expenses;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return request();
|
|
||||||
},
|
|
||||||
error(errors = []) {
|
|
||||||
// Генерация ошибки
|
|
||||||
|
|
||||||
// Инициализация количества обработанных ошибок
|
|
||||||
let amount = 0;
|
|
||||||
|
|
||||||
if (typeof errors === 'object') {
|
|
||||||
// Передан массив с ошибками и он является массивом
|
|
||||||
|
|
||||||
// Инициализация буфера для проверки вложенности массива
|
|
||||||
let first = Object.values(errors)[0];
|
|
||||||
|
|
||||||
if (first !== undefined && first.text === undefined) {
|
|
||||||
// Найден массив с ошибками (категория)
|
|
||||||
|
|
||||||
// Вход в рекурсию
|
|
||||||
amount += this.error(first);
|
|
||||||
} else {
|
|
||||||
// Не найден массив с ошибками (подразумевается, что это и есть информация об ошибке)
|
|
||||||
|
|
||||||
// Инициализация элемента-оболочки
|
|
||||||
let list = document.getElementById('errors');
|
|
||||||
|
|
||||||
// Перезапись данных об ошибках
|
|
||||||
list.innerText = '';
|
|
||||||
|
|
||||||
// Проверка на наличие ошибок
|
|
||||||
if (errors.length === 0) return false;
|
|
||||||
|
|
||||||
if (list !== null) {
|
|
||||||
// Оболочка найдена
|
|
||||||
|
|
||||||
for (const [, error] of Object.entries(errors)) {
|
|
||||||
// Перебор станков
|
|
||||||
|
|
||||||
// Инициализация элемента-заголовка
|
|
||||||
let term = document.createElement('dt');
|
|
||||||
|
|
||||||
// Запись содержимого
|
|
||||||
term.innerText = error.text;
|
|
||||||
|
|
||||||
// Инициализация элемента-описания
|
|
||||||
let definition = document.createElement('dd');
|
|
||||||
|
|
||||||
// Запись содержимого
|
|
||||||
definition.innerText = error.file + ' в строке ' + error.line;
|
|
||||||
|
|
||||||
// input.setAttribute('id', element.id);
|
|
||||||
|
|
||||||
// Запись в список
|
|
||||||
list.insertAdjacentElement('beforeend', term);
|
|
||||||
list.insertAdjacentElement('beforeend', definition);
|
|
||||||
|
|
||||||
// Добавление к счётчику обработанных ошибок
|
|
||||||
++amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return amount;
|
|
||||||
},
|
|
||||||
calculators: {
|
|
||||||
laser() {
|
|
||||||
// Запрос и генерация HTML с калькулятором лазерной резки
|
|
||||||
|
|
||||||
function write(target, position, html) {
|
|
||||||
if (target === undefined || position === undefined || html === undefined) return false;
|
|
||||||
|
|
||||||
// Запись калькулятора после последнего калькулятора
|
|
||||||
target.insertAdjacentHTML(position, html);
|
|
||||||
|
|
||||||
// Поиск калькуляторов
|
|
||||||
let calculators = calculator.index.querySelectorAll('section[data-calculator]');
|
|
||||||
|
|
||||||
// Инициализация идентификатора калькулятора
|
|
||||||
let id = calculators.length - 1;
|
|
||||||
|
|
||||||
// Запись калькулятору его идентификатора
|
|
||||||
calculators[id].id = 'laser_' + id;
|
|
||||||
|
|
||||||
// Запись в реестр последнего калькулятора (подразумевается, что он новый и только что был записан)
|
|
||||||
calculator.calculators.push(calculators[id]);
|
|
||||||
|
|
||||||
// Запись в журнал
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Инициализирован калькулятор лазерной резки');
|
|
||||||
|
|
||||||
// Инициализация поля с маркой металла
|
|
||||||
calculator.generate.mark(calculators[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fetch('/calculator/generate/laser', {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/x-www-form-urlencoded" }
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.text().then(
|
|
||||||
success => {
|
|
||||||
// Поиск последнего калькулятора
|
|
||||||
let last = calculator.calculators[calculator.calculators.length - 1];
|
|
||||||
|
|
||||||
if (last !== undefined && last !== null) {
|
|
||||||
// Найден калькулятор
|
|
||||||
|
|
||||||
// Инициализация разделителя перед меню
|
|
||||||
calculator.generate.divider(last, 'afterend').then(divider => write(last, 'afterend', success));
|
|
||||||
} else {
|
|
||||||
// Не найден калькулятор
|
|
||||||
|
|
||||||
calculator.generate.divider(menu, 'beforebegin').then(
|
|
||||||
first => {
|
|
||||||
// Поиск меню
|
|
||||||
let menu = document.getElementById("menu");
|
|
||||||
|
|
||||||
if (menu !== null) {
|
|
||||||
// Найдено меню
|
|
||||||
|
|
||||||
// Инициализация разделителя перед меню
|
|
||||||
calculator.generate.divider(menu, 'beforebegin').then(divider => write(menu, 'beforebegin', success));
|
|
||||||
} else {
|
|
||||||
// Не найдено меню
|
|
||||||
|
|
||||||
// Поиск результатов калькуляции
|
|
||||||
let result = document.getElementById("result");
|
|
||||||
|
|
||||||
if (result !== null) {
|
|
||||||
// Найден элемент с результатами калькуляции
|
|
||||||
|
|
||||||
// Инициализация разделителя перед меню
|
|
||||||
calculator.generate.divider(result, 'beforebegin').then(result => write(result, 'beforebegin', success));
|
|
||||||
} else {
|
|
||||||
// Не найден элемент с результатами калькуляции
|
|
||||||
|
|
||||||
// Инициализация разделителя перед меню
|
|
||||||
calculator.generate.divider().then(result => write(calculator.index, 'beforeend', success));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
// Запись в журнал
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось инициализировать калькулятор лазерной резки');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,55 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let cookie = {
|
|
||||||
read(name) {
|
|
||||||
// Поиск по регулярному выражению
|
|
||||||
let matches = document.cookie.match(new RegExp(
|
|
||||||
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
|
|
||||||
));
|
|
||||||
|
|
||||||
return matches ? decodeURIComponent(matches[1]) : undefined;
|
|
||||||
},
|
|
||||||
write(name, value, options = {}) {
|
|
||||||
// Инициализация параметров
|
|
||||||
options = {
|
|
||||||
path: '/',
|
|
||||||
...options
|
|
||||||
};
|
|
||||||
|
|
||||||
if (options.expires instanceof Date) {
|
|
||||||
// Передана инстанция Date
|
|
||||||
|
|
||||||
// Запись параметра истечения срока
|
|
||||||
options.expires = options.expires.toUTCString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация cookie
|
|
||||||
let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value);
|
|
||||||
|
|
||||||
for (let optionKey in options) {
|
|
||||||
// Перебор параметров
|
|
||||||
|
|
||||||
// Запись в cookie названия параметра
|
|
||||||
updatedCookie += "; " + optionKey;
|
|
||||||
|
|
||||||
// Инициализация значения параметра
|
|
||||||
let optionValue = options[optionKey];
|
|
||||||
|
|
||||||
if (optionValue !== true) {
|
|
||||||
// Найдено значение параметра
|
|
||||||
|
|
||||||
// Запись в cookie значения параметра
|
|
||||||
updatedCookie += "=" + optionValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Конкатенация нового cookie с остальными
|
|
||||||
document.cookie = updatedCookie;
|
|
||||||
},
|
|
||||||
delete(name) {
|
|
||||||
// Удаление
|
|
||||||
setCookie(name, "", {
|
|
||||||
'max-age': -1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,36 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let settings = {
|
|
||||||
write(input) {
|
|
||||||
if (input !== undefined && input !== null) {
|
|
||||||
// Передан элемент
|
|
||||||
|
|
||||||
// Инициализация буфера с данными запроса
|
|
||||||
let body = {};
|
|
||||||
|
|
||||||
// Запись в буфер
|
|
||||||
body[input.name] = input.value;
|
|
||||||
|
|
||||||
return fetch('/settings/write', {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "content-type": "application/json" },
|
|
||||||
body: JSON.stringify(body)
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.text().then(
|
|
||||||
success => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Записана настройка: ' + input.name);
|
|
||||||
|
|
||||||
// Переоткрытие страницы
|
|
||||||
// location.reload();
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось записать настройку: ' + input.name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,32 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let supplies = {
|
|
||||||
write(file) {
|
|
||||||
if (file !== undefined && file !== null) {
|
|
||||||
// Передан файл
|
|
||||||
|
|
||||||
// Инициализация буфера с данными запроса
|
|
||||||
let data = new FormData;
|
|
||||||
|
|
||||||
// Запись в буфер
|
|
||||||
data.append('supplies', file);
|
|
||||||
|
|
||||||
return fetch('/supplies/write', {
|
|
||||||
method: "POST",
|
|
||||||
body: data
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
response.text().then(
|
|
||||||
success => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] Загружены данные о поставках металла');
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить данные о поставках металла');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,39 +0,0 @@
|
||||||
<link href="/css/auth.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<section id="authentication">
|
|
||||||
{% if account is not empty %}
|
|
||||||
<h3>Аккаунт</h3>
|
|
||||||
<div>
|
|
||||||
<p><b>Почта:</b> <span>{{ account.email }}</span></p>
|
|
||||||
<a class="exit" type="button" href='/account/deauthentication'>Выход</a>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<h3>Аутентификация</h3>
|
|
||||||
<form method="POST" accept-charset="UTF-8">
|
|
||||||
<input type="text" name="email" placeholder="Почта">
|
|
||||||
<input type="password" name="password" placeholder="Пароль">
|
|
||||||
|
|
||||||
<div class="submit">
|
|
||||||
<label class="button unselectable fas fa-unlock" for="remember"
|
|
||||||
onclick="return remember_switch(this);"></label>
|
|
||||||
<input type="checkbox" name="remember" value="1">
|
|
||||||
<input type="submit" value="Войти" onclick="return authentication(this.parentElement.parentElement);">
|
|
||||||
</div>
|
|
||||||
<input type="submit" class="registration" value="Зарегистрироваться"
|
|
||||||
onclick="return registration(this.parentElement);">
|
|
||||||
|
|
||||||
{% if errors is not empty %}
|
|
||||||
{% if errors.account is not empty %}
|
|
||||||
<ul class="errors">
|
|
||||||
{% for error in errors.account %}
|
|
||||||
<li>{{ error }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/auth.js" defer></script>
|
|
|
@ -1,10 +0,0 @@
|
||||||
<div>
|
|
||||||
<label>Марка</label>
|
|
||||||
<div>
|
|
||||||
<select name="mark" data-calculator-parameter="mark" title="Марка стали">
|
|
||||||
{% for mark in marks %}
|
|
||||||
<option value="{{ mark }}">{{ mark }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,69 +0,0 @@
|
||||||
<h3>Лазерная резка <span title="Удалить"></span></h3>
|
|
||||||
<section class="calculator" data-calculator="laser">
|
|
||||||
<div>
|
|
||||||
<label>Тип</label>
|
|
||||||
<div>
|
|
||||||
<select name="type" data-calculator-parameter="type" title="Тип стали"
|
|
||||||
onchange="calculator.generate.mark(this.parentElement.parentElement.parentElement, this.value)">
|
|
||||||
<option value="steel">Сталь</option>
|
|
||||||
<option value="galvanized_steel">Оцинкованная сталь</option>
|
|
||||||
<option value="stainless_steel">Нержавеющая сталь</option>
|
|
||||||
<option value="brass">Латунь</option>
|
|
||||||
<option value="copper">Медь</option>
|
|
||||||
<option value="aluminum">Алюминий</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label>Размер</label>
|
|
||||||
<div>
|
|
||||||
<input data-calculator-parameter="width" type="number" class="measured" title="Длина детали"
|
|
||||||
value="{{ calculators.laser.width }}" min="{{ calculators.laser.width.min ?? 1 }}"
|
|
||||||
max="{{ calculators.laser.width.max ?? 3000 }}">
|
|
||||||
<span class="unit unselectable">мм</span>
|
|
||||||
<small>x</small>
|
|
||||||
<input data-calculator-parameter="height" type="number" class="measured" title="Ширина детали"
|
|
||||||
value="{{ calculators.laser.height }}" min="{{ calculators.laser.height.min ?? 1 }}"
|
|
||||||
max="{{ calculators.laser.height.max ?? 3000 }}">
|
|
||||||
<span class="unit unselectable">мм</span>
|
|
||||||
<small>x</small>
|
|
||||||
<input data-calculator-parameter="length" type="number" class="measured" title="Толщина детали"
|
|
||||||
value="{{ calculators.laser.length }}" min="{{ calculators.laser.length.min ?? 1 }}"
|
|
||||||
max="{{ calculators.laser.length.max ?? 20 }}">
|
|
||||||
<span class="unit unselectable">мм</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label>Отверстия</label>
|
|
||||||
<div>
|
|
||||||
<input data-calculator-parameter="holes" type="number" class="measured" title="Количество отверстий"
|
|
||||||
value="{{ calculators.laser.holes }}" min="{{ calculators.laser.holes.min ?? 0 }}"
|
|
||||||
max="{{ calculators.laser.holes.max ?? 100 }}">
|
|
||||||
<span class="unit unselectable">шт</span>
|
|
||||||
<small>x</small>
|
|
||||||
<input data-calculator-parameter="diameter" type="number" class="measured" title="Диаметр отверстий"
|
|
||||||
value="{{ calculators.laser.diameter }}" min="{{ calculators.laser.diameter.min ?? 0 }}"
|
|
||||||
max="{{ calculators.laser.diameter.max ?? 100 }}">
|
|
||||||
<span class="unit unselectable">мм</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label>Количество</label>
|
|
||||||
<div>
|
|
||||||
<input data-calculator-parameter="amount" type="number" class="measured" title="Количество изделий"
|
|
||||||
value="{{ calculators.laser.amount }}" min="{{ calculators.laser.amount.min ?? 1 }}"
|
|
||||||
max="{{ calculators.laser.amount.max ?? 10000 }}">
|
|
||||||
<span class="unit unselectable">шт</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="our">Наш металл</label>
|
|
||||||
<div>
|
|
||||||
<input data-calculator-parameter="our" type="checkbox" title="Используется наш металл" checked>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
|
@ -1,6 +0,0 @@
|
||||||
<section id="buyer" class="unselectable">
|
|
||||||
<input id="individual" type="radio" name="buyer" value="individual" {% if buyer is same as('individual') %}checked{% endif %}>
|
|
||||||
<label type="button" for="individual">Физическое лицо</label>
|
|
||||||
<input id="entity" type="radio" name="buyer" value="entity" {% if buyer is same as('entity') %}checked{% endif %}>
|
|
||||||
<label type="button" for="entity">Юридическое лицо</label>
|
|
||||||
</section>
|
|
|
@ -1 +0,0 @@
|
||||||
<div class="divider unselectable"></div>
|
|
|
@ -1,46 +0,0 @@
|
||||||
<section id="result">
|
|
||||||
<div type="row">
|
|
||||||
<label>Длина реза 1 детали ({{ cutting.default ?? 0 }}мм)</label>
|
|
||||||
<input id="cutting" type="range" title="Длина реза 1 детали "
|
|
||||||
value="{{ cutting.default ?? 0 }}" min="{{ cutting.min ?? 0 }}" max="{{ cutting.max ?? 10000 }}"
|
|
||||||
step="{{ cutting.step ?? 1 }}"
|
|
||||||
oninput="this.parentElement.children[0].innerText = 'Длина реза 1 детали (' + this.value + 'мм)';" disabled>
|
|
||||||
<!-- <datalist id="cutting_level">
|
|
||||||
<option value="0" label="{{ cutting.min ?? 0 }}%">
|
|
||||||
<option value="10">
|
|
||||||
<option value="20">
|
|
||||||
<option value="30">
|
|
||||||
<option value="40">
|
|
||||||
<option value="50" label="{{ ((cutting.max ?? 10000) + (cutting.min ?? 0)) / 2 }}%">
|
|
||||||
<option value="60">
|
|
||||||
<option value="70">
|
|
||||||
<option value="80">
|
|
||||||
<option value="90">
|
|
||||||
<option value="100" label="{{ cutting.max ?? 100005 }}%">
|
|
||||||
</datalist> -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div type="row">
|
|
||||||
<label>Скидка ({{ discount.default ?? 0 }}%)</label>
|
|
||||||
<input id="discount" type="range" title="Скидка менеджера"
|
|
||||||
value="{{ discount.default ?? 0 }}" min="{{ discount.min ?? 0 }}" max="{{ discount.max ?? 5 }}"
|
|
||||||
step="{{ discount.step ?? 1 }}"
|
|
||||||
oninput="this.parentElement.children[0].innerText = 'Скидка (' + this.value + '%)';">
|
|
||||||
|
|
||||||
<!-- <datalist id="discount_level">
|
|
||||||
<option value="0" label="{{ calculators.discount.min ?? 0 }}%">
|
|
||||||
<option value="10">
|
|
||||||
<option value="20">
|
|
||||||
<option value="30">
|
|
||||||
<option value="40">
|
|
||||||
<option value="50" label="{{ ((calculators.discount.max ?? 5) + (discount.min ?? 0)) / 2 }}%">
|
|
||||||
<option value="60">
|
|
||||||
<option value="70">
|
|
||||||
<option value="80">
|
|
||||||
<option value="90">
|
|
||||||
<option value="100" label="{{ discount.max ?? 5 }}%">
|
|
||||||
</datalist> -->
|
|
||||||
</div>
|
|
||||||
<a id="calculate" class="unselectable" type="button" onclick="return calculator.calculate();">0 рублей</a>
|
|
||||||
<dl id="errors"></dl>
|
|
||||||
</section>
|
|
|
@ -1,10 +0,0 @@
|
||||||
{% extends "core.html" %}
|
|
||||||
|
|
||||||
{% block main %}
|
|
||||||
<link href="/css/contacts.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<section id="contacts">
|
|
||||||
<h2>Контакты</h2>
|
|
||||||
<div class="divider"></div>
|
|
||||||
</section>
|
|
||||||
{% endblock %}
|
|
|
@ -1,10 +0,0 @@
|
||||||
{% extends "core.html" %}
|
|
||||||
|
|
||||||
{% block main %}
|
|
||||||
<link href="/css/journal.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<section id="journal">
|
|
||||||
<h2>Журнал</h2>
|
|
||||||
<div class="divider"></div>
|
|
||||||
</section>
|
|
||||||
{% endblock %}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{% extends "core.html" %}
|
|
||||||
|
|
||||||
{% block main %}
|
|
||||||
<link href="/css/settings.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<section id="settings">
|
|
||||||
<h2>Настройки</h2>
|
|
||||||
<div class="divider"></div>
|
|
||||||
{% for setting in settings %}
|
|
||||||
<div class="setting">
|
|
||||||
<label class="unselectable" for="{{ setting.english }}">{{ setting.russian }}</label>
|
|
||||||
<input id="{{ setting.english }}" type="text" name="{{ setting.english }}" value="{{ setting.value }}" onchange="settings.write(this)">
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% if account.permissions.supplies is defined and account.permissions.supplies == 1 %}
|
|
||||||
<h2 class="supplies">Поставки</h2>
|
|
||||||
<div class="divider"></div>
|
|
||||||
<input type="file" name="supply" onchange="supplies.write(this.files[0])">
|
|
||||||
{% endif %}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/settings.js" defer></script>
|
|
||||||
<script type="text/javascript" src="/js/supplies.js" defer></script>
|
|
||||||
{% endblock %}
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInitd3c0e906485ab41f428834e64f63b2f8::getLoader();
|
|
@ -0,0 +1,479 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||||
|
*
|
||||||
|
* $loader = new \Composer\Autoload\ClassLoader();
|
||||||
|
*
|
||||||
|
* // register classes with namespaces
|
||||||
|
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||||
|
* $loader->add('Symfony', __DIR__.'/framework');
|
||||||
|
*
|
||||||
|
* // activate the autoloader
|
||||||
|
* $loader->register();
|
||||||
|
*
|
||||||
|
* // to enable searching the include path (eg. for PEAR packages)
|
||||||
|
* $loader->setUseIncludePath(true);
|
||||||
|
*
|
||||||
|
* In this example, if you try to use a class in the Symfony\Component
|
||||||
|
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||||
|
* the autoloader will first look for the class under the component/
|
||||||
|
* directory, and it will then fallback to the framework/ directory if not
|
||||||
|
* found before giving up.
|
||||||
|
*
|
||||||
|
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @see https://www.php-fig.org/psr/psr-0/
|
||||||
|
* @see https://www.php-fig.org/psr/psr-4/
|
||||||
|
*/
|
||||||
|
class ClassLoader
|
||||||
|
{
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
|
// PSR-4
|
||||||
|
private $prefixLengthsPsr4 = array();
|
||||||
|
private $prefixDirsPsr4 = array();
|
||||||
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
|
// PSR-0
|
||||||
|
private $prefixesPsr0 = array();
|
||||||
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
private $useIncludePath = false;
|
||||||
|
private $classMap = array();
|
||||||
|
private $classMapAuthoritative = false;
|
||||||
|
private $missingClasses = array();
|
||||||
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return $this->prefixDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFallbackDirs()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFallbackDirsPsr4()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClassMap()
|
||||||
|
{
|
||||||
|
return $this->classMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $classMap Class to filename map
|
||||||
|
*/
|
||||||
|
public function addClassMap(array $classMap)
|
||||||
|
{
|
||||||
|
if ($this->classMap) {
|
||||||
|
$this->classMap = array_merge($this->classMap, $classMap);
|
||||||
|
} else {
|
||||||
|
$this->classMap = $classMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param array|string $paths The PSR-0 root directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*/
|
||||||
|
public function add($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->fallbackDirsPsr0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$this->fallbackDirsPsr0,
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = $prefix[0];
|
||||||
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($prepend) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param array|string $paths The PSR-4 base directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->fallbackDirsPsr4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$this->fallbackDirsPsr4,
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||||
|
// Register directories for a new namespace.
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
} elseif ($prepend) {
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
(array) $paths,
|
||||||
|
$this->prefixDirsPsr4[$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$this->prefixDirsPsr4[$prefix],
|
||||||
|
(array) $paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
|
* replacing any others previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param array|string $paths The PSR-0 base directories
|
||||||
|
*/
|
||||||
|
public function set($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr0 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
|
* replacing any others previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param array|string $paths The PSR-4 base directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function setPsr4($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr4 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on searching the include path for class files.
|
||||||
|
*
|
||||||
|
* @param bool $useIncludePath
|
||||||
|
*/
|
||||||
|
public function setUseIncludePath($useIncludePath)
|
||||||
|
{
|
||||||
|
$this->useIncludePath = $useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to check if the autoloader uses the include path to check
|
||||||
|
* for classes.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getUseIncludePath()
|
||||||
|
{
|
||||||
|
return $this->useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns off searching the prefix and fallback directories for classes
|
||||||
|
* that have not been registered with the class map.
|
||||||
|
*
|
||||||
|
* @param bool $classMapAuthoritative
|
||||||
|
*/
|
||||||
|
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||||
|
{
|
||||||
|
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should class lookup fail if not found in the current class map?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isClassMapAuthoritative()
|
||||||
|
{
|
||||||
|
return $this->classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
|
*
|
||||||
|
* @param string|null $apcuPrefix
|
||||||
|
*/
|
||||||
|
public function setApcuPrefix($apcuPrefix)
|
||||||
|
{
|
||||||
|
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getApcuPrefix()
|
||||||
|
{
|
||||||
|
return $this->apcuPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*/
|
||||||
|
public function register($prepend = false)
|
||||||
|
{
|
||||||
|
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||||
|
|
||||||
|
if (null === $this->vendorDir) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($prepend) {
|
||||||
|
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||||
|
} else {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters this instance as an autoloader.
|
||||||
|
*/
|
||||||
|
public function unregister()
|
||||||
|
{
|
||||||
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
|
if (null !== $this->vendorDir) {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given class or interface.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
* @return bool|null True if loaded, null otherwise
|
||||||
|
*/
|
||||||
|
public function loadClass($class)
|
||||||
|
{
|
||||||
|
if ($file = $this->findFile($class)) {
|
||||||
|
includeFile($file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the path to the file where the class is defined.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
*
|
||||||
|
* @return string|false The path if found, false otherwise
|
||||||
|
*/
|
||||||
|
public function findFile($class)
|
||||||
|
{
|
||||||
|
// class map lookup
|
||||||
|
if (isset($this->classMap[$class])) {
|
||||||
|
return $this->classMap[$class];
|
||||||
|
}
|
||||||
|
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||||
|
if ($hit) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->findFileWithExtension($class, '.php');
|
||||||
|
|
||||||
|
// Search for Hack files if we are running on HHVM
|
||||||
|
if (false === $file && defined('HHVM_VERSION')) {
|
||||||
|
$file = $this->findFileWithExtension($class, '.hh');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
apcu_add($this->apcuPrefix.$class, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $file) {
|
||||||
|
// Remember that this class does not exist.
|
||||||
|
$this->missingClasses[$class] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently registered loaders indexed by their corresponding vendor directories.
|
||||||
|
*
|
||||||
|
* @return self[]
|
||||||
|
*/
|
||||||
|
public static function getRegisteredLoaders()
|
||||||
|
{
|
||||||
|
return self::$registeredLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findFileWithExtension($class, $ext)
|
||||||
|
{
|
||||||
|
// PSR-4 lookup
|
||||||
|
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
|
||||||
|
$first = $class[0];
|
||||||
|
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||||
|
$subPath = $class;
|
||||||
|
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||||
|
$subPath = substr($subPath, 0, $lastPos);
|
||||||
|
$search = $subPath . '\\';
|
||||||
|
if (isset($this->prefixDirsPsr4[$search])) {
|
||||||
|
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||||
|
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||||
|
if (file_exists($file = $dir . $pathEnd)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-4 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 lookup
|
||||||
|
if (false !== $pos = strrpos($class, '\\')) {
|
||||||
|
// namespaced class name
|
||||||
|
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||||
|
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||||
|
} else {
|
||||||
|
// PEAR-like class name
|
||||||
|
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->prefixesPsr0[$first])) {
|
||||||
|
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 include paths.
|
||||||
|
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope isolated include.
|
||||||
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*/
|
||||||
|
function includeFile($file)
|
||||||
|
{
|
||||||
|
include $file;
|
||||||
|
}
|
|
@ -0,0 +1,319 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace Composer;
|
||||||
|
|
||||||
|
use Composer\Autoload\ClassLoader;
|
||||||
|
use Composer\Semver\VersionParser;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class InstalledVersions
|
||||||
|
{
|
||||||
|
private static $installed = array (
|
||||||
|
'root' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => NULL,
|
||||||
|
'name' => 'mirzaev/calculator',
|
||||||
|
),
|
||||||
|
'versions' =>
|
||||||
|
array (
|
||||||
|
'mirzaev/calculator' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => NULL,
|
||||||
|
),
|
||||||
|
'mirzaev/minimal' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => '2.0.x-dev',
|
||||||
|
'version' => '2.0.9999999.9999999-dev',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => 'b6f90b700116f20fe48725166ddfb8f6d27ae52d',
|
||||||
|
),
|
||||||
|
'symfony/polyfill-ctype' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => 'v1.23.0',
|
||||||
|
'version' => '1.23.0.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => '46cd95797e9df938fdd2b03693b5fca5e64b01ce',
|
||||||
|
),
|
||||||
|
'symfony/polyfill-mbstring' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => 'v1.23.1',
|
||||||
|
'version' => '1.23.1.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => '9174a3d80210dca8daa7f31fec659150bbeabfc6',
|
||||||
|
),
|
||||||
|
'twig/twig' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => 'v3.3.3',
|
||||||
|
'version' => '3.3.3.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => 'a27fa056df8a6384316288ca8b0fa3a35fdeb569',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
private static $canGetVendors;
|
||||||
|
private static $installedByVendor = array();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function getInstalledPackages()
|
||||||
|
{
|
||||||
|
$packages = array();
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
$packages[] = array_keys($installed['versions']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (1 === \count($packages)) {
|
||||||
|
return $packages[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function isInstalled($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (isset($installed['versions'][$packageName])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||||
|
{
|
||||||
|
$constraint = $parser->parseConstraints($constraint);
|
||||||
|
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||||
|
|
||||||
|
return $provided->matches($constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function getVersionRanges($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ranges = array();
|
||||||
|
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(' || ', $ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function getVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function getPrettyVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function getReference($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['reference'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function getRootPackage()
|
||||||
|
{
|
||||||
|
$installed = self::getInstalled();
|
||||||
|
|
||||||
|
return $installed[0]['root'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function getRawData()
|
||||||
|
{
|
||||||
|
return self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function reload($data)
|
||||||
|
{
|
||||||
|
self::$installed = $data;
|
||||||
|
self::$installedByVendor = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static function getInstalled()
|
||||||
|
{
|
||||||
|
if (null === self::$canGetVendors) {
|
||||||
|
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||||
|
}
|
||||||
|
|
||||||
|
$installed = array();
|
||||||
|
|
||||||
|
if (self::$canGetVendors) {
|
||||||
|
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||||
|
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir];
|
||||||
|
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$installed[] = self::$installed;
|
||||||
|
|
||||||
|
return $installed;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_classmap.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
|
);
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_files.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||||
|
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||||
|
);
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
);
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_psr4.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(dirname(__FILE__));
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'mirzaev\\minimal\\' => array($vendorDir . '/mirzaev/minimal/mirzaev/minimal/system'),
|
||||||
|
'mirzaev\\calculator\\' => array($baseDir . '/mirzaev/calculator/system'),
|
||||||
|
'Twig\\' => array($vendorDir . '/twig/twig/src'),
|
||||||
|
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||||
|
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
|
||||||
|
);
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
|
class ComposerAutoloaderInitd3c0e906485ab41f428834e64f63b2f8
|
||||||
|
{
|
||||||
|
private static $loader;
|
||||||
|
|
||||||
|
public static function loadClassLoader($class)
|
||||||
|
{
|
||||||
|
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||||
|
require __DIR__ . '/ClassLoader.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Autoload\ClassLoader
|
||||||
|
*/
|
||||||
|
public static function getLoader()
|
||||||
|
{
|
||||||
|
if (null !== self::$loader) {
|
||||||
|
return self::$loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
require __DIR__ . '/platform_check.php';
|
||||||
|
|
||||||
|
spl_autoload_register(array('ComposerAutoloaderInitd3c0e906485ab41f428834e64f63b2f8', 'loadClassLoader'), true, true);
|
||||||
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
|
||||||
|
spl_autoload_unregister(array('ComposerAutoloaderInitd3c0e906485ab41f428834e64f63b2f8', 'loadClassLoader'));
|
||||||
|
|
||||||
|
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||||
|
if ($useStaticLoader) {
|
||||||
|
require __DIR__ . '/autoload_static.php';
|
||||||
|
|
||||||
|
call_user_func(\Composer\Autoload\ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::getInitializer($loader));
|
||||||
|
} else {
|
||||||
|
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||||
|
foreach ($map as $namespace => $path) {
|
||||||
|
$loader->set($namespace, $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
$map = require __DIR__ . '/autoload_psr4.php';
|
||||||
|
foreach ($map as $namespace => $path) {
|
||||||
|
$loader->setPsr4($namespace, $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||||
|
if ($classMap) {
|
||||||
|
$loader->addClassMap($classMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$loader->register(true);
|
||||||
|
|
||||||
|
if ($useStaticLoader) {
|
||||||
|
$includeFiles = Composer\Autoload\ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$files;
|
||||||
|
} else {
|
||||||
|
$includeFiles = require __DIR__ . '/autoload_files.php';
|
||||||
|
}
|
||||||
|
foreach ($includeFiles as $fileIdentifier => $file) {
|
||||||
|
composerRequired3c0e906485ab41f428834e64f63b2f8($fileIdentifier, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function composerRequired3c0e906485ab41f428834e64f63b2f8($fileIdentifier, $file)
|
||||||
|
{
|
||||||
|
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||||
|
require $file;
|
||||||
|
|
||||||
|
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_static.php @generated by Composer
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
class ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8
|
||||||
|
{
|
||||||
|
public static $files = array (
|
||||||
|
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||||
|
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixLengthsPsr4 = array (
|
||||||
|
'm' =>
|
||||||
|
array (
|
||||||
|
'mirzaev\\minimal\\' => 16,
|
||||||
|
'mirzaev\\calculator\\' => 19,
|
||||||
|
),
|
||||||
|
'T' =>
|
||||||
|
array (
|
||||||
|
'Twig\\' => 5,
|
||||||
|
),
|
||||||
|
'S' =>
|
||||||
|
array (
|
||||||
|
'Symfony\\Polyfill\\Mbstring\\' => 26,
|
||||||
|
'Symfony\\Polyfill\\Ctype\\' => 23,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixDirsPsr4 = array (
|
||||||
|
'mirzaev\\minimal\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/mirzaev/minimal/mirzaev/minimal/system',
|
||||||
|
),
|
||||||
|
'mirzaev\\calculator\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/../..' . '/mirzaev/calculator/system',
|
||||||
|
),
|
||||||
|
'Twig\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/twig/twig/src',
|
||||||
|
),
|
||||||
|
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
||||||
|
),
|
||||||
|
'Symfony\\Polyfill\\Ctype\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $classMap = array (
|
||||||
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function getInitializer(ClassLoader $loader)
|
||||||
|
{
|
||||||
|
return \Closure::bind(function () use ($loader) {
|
||||||
|
$loader->prefixLengthsPsr4 = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$prefixLengthsPsr4;
|
||||||
|
$loader->prefixDirsPsr4 = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$prefixDirsPsr4;
|
||||||
|
$loader->classMap = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$classMap;
|
||||||
|
|
||||||
|
}, null, ClassLoader::class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,297 @@
|
||||||
|
{
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "mirzaev/minimal",
|
||||||
|
"version": "2.0.x-dev",
|
||||||
|
"version_normalized": "2.0.9999999.9999999-dev",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.hood.su/mirzaev/minimal",
|
||||||
|
"reference": "b6f90b700116f20fe48725166ddfb8f6d27ae52d"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "~8.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-PDO": "Для работы с базами данных на SQL (MySQL, PostreSQL...)"
|
||||||
|
},
|
||||||
|
"time": "2021-11-12T13:20:13+00:00",
|
||||||
|
"type": "framework",
|
||||||
|
"installation-source": "source",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"mirzaev\\minimal\\": "mirzaev/minimal/system"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"WTFPL"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Arsen Mirzaev Tatyano-Muradovich",
|
||||||
|
"email": "arsen@mirzaev.sexy",
|
||||||
|
"homepage": "https://mirzaev.sexy",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Легковесный MVC фреймворк который следует твоим правилам, а не диктует свои",
|
||||||
|
"homepage": "https://git.hood.su/mirzaev/minimal",
|
||||||
|
"keywords": [
|
||||||
|
"framework",
|
||||||
|
"mvc"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"docs": "https://git.hood.su/mirzaev/minimal/manual",
|
||||||
|
"issues": "https://git.hood.su/mirzaev/minimal/issues"
|
||||||
|
},
|
||||||
|
"install-path": "../mirzaev/minimal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-ctype",
|
||||||
|
"version": "v1.23.0",
|
||||||
|
"version_normalized": "1.23.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||||
|
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
|
||||||
|
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-ctype": "For best performance"
|
||||||
|
},
|
||||||
|
"time": "2021-02-19T12:13:01+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.23-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Ctype\\": ""
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Gert de Pagter",
|
||||||
|
"email": "BackEndTea@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for ctype functions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"ctype",
|
||||||
|
"polyfill",
|
||||||
|
"portable"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"install-path": "../symfony/polyfill-ctype"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-mbstring",
|
||||||
|
"version": "v1.23.1",
|
||||||
|
"version_normalized": "1.23.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
|
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
|
||||||
|
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-mbstring": "For best performance"
|
||||||
|
},
|
||||||
|
"time": "2021-05-27T12:26:48+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.23-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill for the Mbstring extension",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"mbstring",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"install-path": "../symfony/polyfill-mbstring"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "twig/twig",
|
||||||
|
"version": "v3.3.3",
|
||||||
|
"version_normalized": "3.3.3.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/twigphp/Twig.git",
|
||||||
|
"reference": "a27fa056df8a6384316288ca8b0fa3a35fdeb569"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a27fa056df8a6384316288ca8b0fa3a35fdeb569",
|
||||||
|
"reference": "a27fa056df8a6384316288ca8b0fa3a35fdeb569",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.2.5",
|
||||||
|
"symfony/polyfill-ctype": "^1.8",
|
||||||
|
"symfony/polyfill-mbstring": "^1.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"psr/container": "^1.0",
|
||||||
|
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0"
|
||||||
|
},
|
||||||
|
"time": "2021-09-17T08:44:23+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.3-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Twig\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com",
|
||||||
|
"homepage": "http://fabien.potencier.org",
|
||||||
|
"role": "Lead Developer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Twig Team",
|
||||||
|
"role": "Contributors"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Armin Ronacher",
|
||||||
|
"email": "armin.ronacher@active-4.com",
|
||||||
|
"role": "Project Founder"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Twig, the flexible, fast, and secure template language for PHP",
|
||||||
|
"homepage": "https://twig.symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"templating"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/twigphp/Twig/issues",
|
||||||
|
"source": "https://github.com/twigphp/Twig/tree/v3.3.3"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/twig/twig",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"install-path": "../twig/twig"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dev": true,
|
||||||
|
"dev-package-names": []
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php return array (
|
||||||
|
'root' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => NULL,
|
||||||
|
'name' => 'mirzaev/calculator',
|
||||||
|
),
|
||||||
|
'versions' =>
|
||||||
|
array (
|
||||||
|
'mirzaev/calculator' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => NULL,
|
||||||
|
),
|
||||||
|
'mirzaev/minimal' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => '2.0.x-dev',
|
||||||
|
'version' => '2.0.9999999.9999999-dev',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => 'b6f90b700116f20fe48725166ddfb8f6d27ae52d',
|
||||||
|
),
|
||||||
|
'symfony/polyfill-ctype' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => 'v1.23.0',
|
||||||
|
'version' => '1.23.0.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => '46cd95797e9df938fdd2b03693b5fca5e64b01ce',
|
||||||
|
),
|
||||||
|
'symfony/polyfill-mbstring' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => 'v1.23.1',
|
||||||
|
'version' => '1.23.1.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => '9174a3d80210dca8daa7f31fec659150bbeabfc6',
|
||||||
|
),
|
||||||
|
'twig/twig' =>
|
||||||
|
array (
|
||||||
|
'pretty_version' => 'v3.3.3',
|
||||||
|
'version' => '3.3.3.0',
|
||||||
|
'aliases' =>
|
||||||
|
array (
|
||||||
|
),
|
||||||
|
'reference' => 'a27fa056df8a6384316288ca8b0fa3a35fdeb569',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// platform_check.php @generated by Composer
|
||||||
|
|
||||||
|
$issues = array();
|
||||||
|
|
||||||
|
if (!(PHP_VERSION_ID >= 80000)) {
|
||||||
|
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.0". You are running ' . PHP_VERSION . '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($issues) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trigger_error(
|
||||||
|
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Polyfill\Ctype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ctype implementation through regex.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @author Gert de Pagter <BackEndTea@gmail.com>
|
||||||
|
*/
|
||||||
|
final class Ctype
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-alnum
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_alnum($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text is a letter, FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-alpha
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_alpha($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-cntrl
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_cntrl($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-digit
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_digit($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-graph
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_graph($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text is a lowercase letter.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-lower
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_lower($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-print
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_print($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-punct
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_punct($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-space
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_space($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text is an uppercase letter.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-upper
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_upper($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @see https://php.net/ctype-xdigit
|
||||||
|
*
|
||||||
|
* @param string|int $text
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ctype_xdigit($text)
|
||||||
|
{
|
||||||
|
$text = self::convert_int_to_char_for_ctype($text);
|
||||||
|
|
||||||
|
return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts integers to their char versions according to normal ctype behaviour, if needed.
|
||||||
|
*
|
||||||
|
* If an integer between -128 and 255 inclusive is provided,
|
||||||
|
* it is interpreted as the ASCII value of a single character
|
||||||
|
* (negative values have 256 added in order to allow characters in the Extended ASCII range).
|
||||||
|
* Any other integer is interpreted as a string containing the decimal digits of the integer.
|
||||||
|
*
|
||||||
|
* @param string|int $int
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private static function convert_int_to_char_for_ctype($int)
|
||||||
|
{
|
||||||
|
if (!\is_int($int)) {
|
||||||
|
return $int;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int < -128 || $int > 255) {
|
||||||
|
return (string) $int;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($int < 0) {
|
||||||
|
$int += 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \chr($int);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2018-2019 Fabien Potencier
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1,12 @@
|
||||||
|
Symfony Polyfill / Ctype
|
||||||
|
========================
|
||||||
|
|
||||||
|
This component provides `ctype_*` functions to users who run php versions without the ctype extension.
|
||||||
|
|
||||||
|
More information can be found in the
|
||||||
|
[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
|
||||||
|
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
|
||||||
|
This library is released under the [MIT license](LICENSE).
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Symfony\Polyfill\Ctype as p;
|
||||||
|
|
||||||
|
if (\PHP_VERSION_ID >= 80000) {
|
||||||
|
return require __DIR__.'/bootstrap80.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('ctype_alnum')) {
|
||||||
|
function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_alpha')) {
|
||||||
|
function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_cntrl')) {
|
||||||
|
function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_digit')) {
|
||||||
|
function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_graph')) {
|
||||||
|
function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_lower')) {
|
||||||
|
function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_print')) {
|
||||||
|
function ctype_print($text) { return p\Ctype::ctype_print($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_punct')) {
|
||||||
|
function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_space')) {
|
||||||
|
function ctype_space($text) { return p\Ctype::ctype_space($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_upper')) {
|
||||||
|
function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_xdigit')) {
|
||||||
|
function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Symfony\Polyfill\Ctype as p;
|
||||||
|
|
||||||
|
if (!function_exists('ctype_alnum')) {
|
||||||
|
function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_alpha')) {
|
||||||
|
function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_cntrl')) {
|
||||||
|
function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_digit')) {
|
||||||
|
function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_graph')) {
|
||||||
|
function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_lower')) {
|
||||||
|
function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_print')) {
|
||||||
|
function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_punct')) {
|
||||||
|
function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_space')) {
|
||||||
|
function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_upper')) {
|
||||||
|
function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); }
|
||||||
|
}
|
||||||
|
if (!function_exists('ctype_xdigit')) {
|
||||||
|
function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); }
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-ctype",
|
||||||
|
"type": "library",
|
||||||
|
"description": "Symfony polyfill for ctype functions",
|
||||||
|
"keywords": ["polyfill", "compatibility", "portable", "ctype"],
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Gert de Pagter",
|
||||||
|
"email": "BackEndTea@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": { "Symfony\\Polyfill\\Ctype\\": "" },
|
||||||
|
"files": [ "bootstrap.php" ]
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-ctype": "For best performance"
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.23-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2015-2019 Fabien Potencier
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1,870 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Polyfill\Mbstring;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
|
||||||
|
*
|
||||||
|
* Implemented:
|
||||||
|
* - mb_chr - Returns a specific character from its Unicode code point
|
||||||
|
* - mb_convert_encoding - Convert character encoding
|
||||||
|
* - mb_convert_variables - Convert character code in variable(s)
|
||||||
|
* - mb_decode_mimeheader - Decode string in MIME header field
|
||||||
|
* - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
|
||||||
|
* - mb_decode_numericentity - Decode HTML numeric string reference to character
|
||||||
|
* - mb_encode_numericentity - Encode character to HTML numeric string reference
|
||||||
|
* - mb_convert_case - Perform case folding on a string
|
||||||
|
* - mb_detect_encoding - Detect character encoding
|
||||||
|
* - mb_get_info - Get internal settings of mbstring
|
||||||
|
* - mb_http_input - Detect HTTP input character encoding
|
||||||
|
* - mb_http_output - Set/Get HTTP output character encoding
|
||||||
|
* - mb_internal_encoding - Set/Get internal character encoding
|
||||||
|
* - mb_list_encodings - Returns an array of all supported encodings
|
||||||
|
* - mb_ord - Returns the Unicode code point of a character
|
||||||
|
* - mb_output_handler - Callback function converts character encoding in output buffer
|
||||||
|
* - mb_scrub - Replaces ill-formed byte sequences with substitute characters
|
||||||
|
* - mb_strlen - Get string length
|
||||||
|
* - mb_strpos - Find position of first occurrence of string in a string
|
||||||
|
* - mb_strrpos - Find position of last occurrence of a string in a string
|
||||||
|
* - mb_str_split - Convert a string to an array
|
||||||
|
* - mb_strtolower - Make a string lowercase
|
||||||
|
* - mb_strtoupper - Make a string uppercase
|
||||||
|
* - mb_substitute_character - Set/Get substitution character
|
||||||
|
* - mb_substr - Get part of string
|
||||||
|
* - mb_stripos - Finds position of first occurrence of a string within another, case insensitive
|
||||||
|
* - mb_stristr - Finds first occurrence of a string within another, case insensitive
|
||||||
|
* - mb_strrchr - Finds the last occurrence of a character in a string within another
|
||||||
|
* - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive
|
||||||
|
* - mb_strripos - Finds position of last occurrence of a string within another, case insensitive
|
||||||
|
* - mb_strstr - Finds first occurrence of a string within another
|
||||||
|
* - mb_strwidth - Return width of string
|
||||||
|
* - mb_substr_count - Count the number of substring occurrences
|
||||||
|
*
|
||||||
|
* Not implemented:
|
||||||
|
* - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
|
||||||
|
* - mb_ereg_* - Regular expression with multibyte support
|
||||||
|
* - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
|
||||||
|
* - mb_preferred_mime_name - Get MIME charset string
|
||||||
|
* - mb_regex_encoding - Returns current encoding for multibyte regex as string
|
||||||
|
* - mb_regex_set_options - Set/Get the default options for mbregex functions
|
||||||
|
* - mb_send_mail - Send encoded mail
|
||||||
|
* - mb_split - Split multibyte string using regular expression
|
||||||
|
* - mb_strcut - Get part of string
|
||||||
|
* - mb_strimwidth - Get truncated string with specified width
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class Mbstring
|
||||||
|
{
|
||||||
|
public const MB_CASE_FOLD = \PHP_INT_MAX;
|
||||||
|
|
||||||
|
private const CASE_FOLD = [
|
||||||
|
['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
|
||||||
|
['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'],
|
||||||
|
];
|
||||||
|
|
||||||
|
private static $encodingList = ['ASCII', 'UTF-8'];
|
||||||
|
private static $language = 'neutral';
|
||||||
|
private static $internalEncoding = 'UTF-8';
|
||||||
|
|
||||||
|
public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
|
||||||
|
{
|
||||||
|
if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
|
||||||
|
$fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
|
||||||
|
} else {
|
||||||
|
$fromEncoding = self::getEncoding($fromEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
$toEncoding = self::getEncoding($toEncoding);
|
||||||
|
|
||||||
|
if ('BASE64' === $fromEncoding) {
|
||||||
|
$s = base64_decode($s);
|
||||||
|
$fromEncoding = $toEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('BASE64' === $toEncoding) {
|
||||||
|
return base64_encode($s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
|
||||||
|
if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
|
||||||
|
$fromEncoding = 'Windows-1252';
|
||||||
|
}
|
||||||
|
if ('UTF-8' !== $fromEncoding) {
|
||||||
|
$s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('HTML-ENTITIES' === $fromEncoding) {
|
||||||
|
$s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
|
||||||
|
$fromEncoding = 'UTF-8';
|
||||||
|
}
|
||||||
|
|
||||||
|
return \iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
|
||||||
|
{
|
||||||
|
$ok = true;
|
||||||
|
array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
|
||||||
|
if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
|
||||||
|
$ok = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return $ok ? $fromEncoding : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_decode_mimeheader($s)
|
||||||
|
{
|
||||||
|
return \iconv_mime_decode($s, 2, self::$internalEncoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
|
||||||
|
{
|
||||||
|
trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_decode_numericentity($s, $convmap, $encoding = null)
|
||||||
|
{
|
||||||
|
if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
|
||||||
|
trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $encoding && !is_scalar($encoding)) {
|
||||||
|
trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
|
||||||
|
|
||||||
|
return ''; // Instead of null (cf. mb_encode_numericentity).
|
||||||
|
}
|
||||||
|
|
||||||
|
$s = (string) $s;
|
||||||
|
if ('' === $s) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$encoding = self::getEncoding($encoding);
|
||||||
|
|
||||||
|
if ('UTF-8' === $encoding) {
|
||||||
|
$encoding = null;
|
||||||
|
if (!preg_match('//u', $s)) {
|
||||||
|
$s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$s = \iconv($encoding, 'UTF-8//IGNORE', $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cnt = floor(\count($convmap) / 4) * 4;
|
||||||
|
|
||||||
|
for ($i = 0; $i < $cnt; $i += 4) {
|
||||||
|
// collector_decode_htmlnumericentity ignores $convmap[$i + 3]
|
||||||
|
$convmap[$i] += $convmap[$i + 2];
|
||||||
|
$convmap[$i + 1] += $convmap[$i + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
$s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
|
||||||
|
$c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
|
||||||
|
for ($i = 0; $i < $cnt; $i += 4) {
|
||||||
|
if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
|
||||||
|
return self::mb_chr($c - $convmap[$i + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $m[0];
|
||||||
|
}, $s);
|
||||||
|
|
||||||
|
if (null === $encoding) {
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \iconv('UTF-8', $encoding.'//IGNORE', $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
|
||||||
|
{
|
||||||
|
if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
|
||||||
|
trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $encoding && !is_scalar($encoding)) {
|
||||||
|
trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
|
||||||
|
|
||||||
|
return null; // Instead of '' (cf. mb_decode_numericentity).
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $is_hex && !is_scalar($is_hex)) {
|
||||||
|
trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$s = (string) $s;
|
||||||
|
if ('' === $s) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$encoding = self::getEncoding($encoding);
|
||||||
|
|
||||||
|
if ('UTF-8' === $encoding) {
|
||||||
|
$encoding = null;
|
||||||
|
if (!preg_match('//u', $s)) {
|
||||||
|
$s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$s = \iconv($encoding, 'UTF-8//IGNORE', $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
|
||||||
|
|
||||||
|
$cnt = floor(\count($convmap) / 4) * 4;
|
||||||
|
$i = 0;
|
||||||
|
$len = \strlen($s);
|
||||||
|
$result = '';
|
||||||
|
|
||||||
|
while ($i < $len) {
|
||||||
|
$ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
|
||||||
|
$uchr = substr($s, $i, $ulen);
|
||||||
|
$i += $ulen;
|
||||||
|
$c = self::mb_ord($uchr);
|
||||||
|
|
||||||
|
for ($j = 0; $j < $cnt; $j += 4) {
|
||||||
|
if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
|
||||||
|
$cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
|
||||||
|
$result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result .= $uchr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $encoding) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \iconv('UTF-8', $encoding.'//IGNORE', $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_convert_case($s, $mode, $encoding = null)
|
||||||
|
{
|
||||||
|
$s = (string) $s;
|
||||||
|
if ('' === $s) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$encoding = self::getEncoding($encoding);
|
||||||
|
|
||||||
|
if ('UTF-8' === $encoding) {
|
||||||
|
$encoding = null;
|
||||||
|
if (!preg_match('//u', $s)) {
|
||||||
|
$s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$s = \iconv($encoding, 'UTF-8//IGNORE', $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\MB_CASE_TITLE == $mode) {
|
||||||
|
static $titleRegexp = null;
|
||||||
|
if (null === $titleRegexp) {
|
||||||
|
$titleRegexp = self::getData('titleCaseRegexp');
|
||||||
|
}
|
||||||
|
$s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
|
||||||
|
} else {
|
||||||
|
if (\MB_CASE_UPPER == $mode) {
|
||||||
|
static $upper = null;
|
||||||
|
if (null === $upper) {
|
||||||
|
$upper = self::getData('upperCase');
|
||||||
|
}
|
||||||
|
$map = $upper;
|
||||||
|
} else {
|
||||||
|
if (self::MB_CASE_FOLD === $mode) {
|
||||||
|
$s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static $lower = null;
|
||||||
|
if (null === $lower) {
|
||||||
|
$lower = self::getData('lowerCase');
|
||||||
|
}
|
||||||
|
$map = $lower;
|
||||||
|
}
|
||||||
|
|
||||||
|
static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
$len = \strlen($s);
|
||||||
|
|
||||||
|
while ($i < $len) {
|
||||||
|
$ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
|
||||||
|
$uchr = substr($s, $i, $ulen);
|
||||||
|
$i += $ulen;
|
||||||
|
|
||||||
|
if (isset($map[$uchr])) {
|
||||||
|
$uchr = $map[$uchr];
|
||||||
|
$nlen = \strlen($uchr);
|
||||||
|
|
||||||
|
if ($nlen == $ulen) {
|
||||||
|
$nlen = $i;
|
||||||
|
do {
|
||||||
|
$s[--$nlen] = $uchr[--$ulen];
|
||||||
|
} while ($ulen);
|
||||||
|
} else {
|
||||||
|
$s = substr_replace($s, $uchr, $i - $ulen, $ulen);
|
||||||
|
$len += $nlen - $ulen;
|
||||||
|
$i += $nlen - $ulen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $encoding) {
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \iconv('UTF-8', $encoding.'//IGNORE', $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_internal_encoding($encoding = null)
|
||||||
|
{
|
||||||
|
if (null === $encoding) {
|
||||||
|
return self::$internalEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
$normalizedEncoding = self::getEncoding($encoding);
|
||||||
|
|
||||||
|
if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
|
||||||
|
self::$internalEncoding = $normalizedEncoding;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (80000 > \PHP_VERSION_ID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_language($lang = null)
|
||||||
|
{
|
||||||
|
if (null === $lang) {
|
||||||
|
return self::$language;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($normalizedLang = strtolower($lang)) {
|
||||||
|
case 'uni':
|
||||||
|
case 'neutral':
|
||||||
|
self::$language = $normalizedLang;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (80000 > \PHP_VERSION_ID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_list_encodings()
|
||||||
|
{
|
||||||
|
return ['UTF-8'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_encoding_aliases($encoding)
|
||||||
|
{
|
||||||
|
switch (strtoupper($encoding)) {
|
||||||
|
case 'UTF8':
|
||||||
|
case 'UTF-8':
|
||||||
|
return ['utf8'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_check_encoding($var = null, $encoding = null)
|
||||||
|
{
|
||||||
|
if (null === $encoding) {
|
||||||
|
if (null === $var) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$encoding = self::$internalEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
|
||||||
|
{
|
||||||
|
if (null === $encodingList) {
|
||||||
|
$encodingList = self::$encodingList;
|
||||||
|
} else {
|
||||||
|
if (!\is_array($encodingList)) {
|
||||||
|
$encodingList = array_map('trim', explode(',', $encodingList));
|
||||||
|
}
|
||||||
|
$encodingList = array_map('strtoupper', $encodingList);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($encodingList as $enc) {
|
||||||
|
switch ($enc) {
|
||||||
|
case 'ASCII':
|
||||||
|
if (!preg_match('/[\x80-\xFF]/', $str)) {
|
||||||
|
return $enc;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'UTF8':
|
||||||
|
case 'UTF-8':
|
||||||
|
if (preg_match('//u', $str)) {
|
||||||
|
return 'UTF-8';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (0 === strncmp($enc, 'ISO-8859-', 9)) {
|
||||||
|
return $enc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_detect_order($encodingList = null)
|
||||||
|
{
|
||||||
|
if (null === $encodingList) {
|
||||||
|
return self::$encodingList;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!\is_array($encodingList)) {
|
||||||
|
$encodingList = array_map('trim', explode(',', $encodingList));
|
||||||
|
}
|
||||||
|
$encodingList = array_map('strtoupper', $encodingList);
|
||||||
|
|
||||||
|
foreach ($encodingList as $enc) {
|
||||||
|
switch ($enc) {
|
||||||
|
default:
|
||||||
|
if (strncmp($enc, 'ISO-8859-', 9)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// no break
|
||||||
|
case 'ASCII':
|
||||||
|
case 'UTF8':
|
||||||
|
case 'UTF-8':
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$encodingList = $encodingList;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strlen($s, $encoding = null)
|
||||||
|
{
|
||||||
|
$encoding = self::getEncoding($encoding);
|
||||||
|
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||||
|
return \strlen($s);
|
||||||
|
}
|
||||||
|
|
||||||
|
return @\iconv_strlen($s, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
|
||||||
|
{
|
||||||
|
$encoding = self::getEncoding($encoding);
|
||||||
|
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||||
|
return strpos($haystack, $needle, $offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
$needle = (string) $needle;
|
||||||
|
if ('' === $needle) {
|
||||||
|
if (80000 > \PHP_VERSION_ID) {
|
||||||
|
trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \iconv_strpos($haystack, $needle, $offset, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
|
||||||
|
{
|
||||||
|
$encoding = self::getEncoding($encoding);
|
||||||
|
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||||
|
return strrpos($haystack, $needle, $offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($offset != (int) $offset) {
|
||||||
|
$offset = 0;
|
||||||
|
} elseif ($offset = (int) $offset) {
|
||||||
|
if ($offset < 0) {
|
||||||
|
if (0 > $offset += self::mb_strlen($needle)) {
|
||||||
|
$haystack = self::mb_substr($haystack, 0, $offset, $encoding);
|
||||||
|
}
|
||||||
|
$offset = 0;
|
||||||
|
} else {
|
||||||
|
$haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pos = '' !== $needle || 80000 > \PHP_VERSION_ID
|
||||||
|
? \iconv_strrpos($haystack, $needle, $encoding)
|
||||||
|
: self::mb_strlen($haystack, $encoding);
|
||||||
|
|
||||||
|
return false !== $pos ? $offset + $pos : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_str_split($string, $split_length = 1, $encoding = null)
|
||||||
|
{
|
||||||
|
if (null !== $string && !is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
|
||||||
|
trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 > $split_length = (int) $split_length) {
|
||||||
|
if (80000 > \PHP_VERSION_ID) {
|
||||||
|
trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \ValueError('Argument #2 ($length) must be greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $encoding) {
|
||||||
|
$encoding = mb_internal_encoding();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
|
||||||
|
$rx = '/(';
|
||||||
|
while (65535 < $split_length) {
|
||||||
|
$rx .= '.{65535}';
|
||||||
|
$split_length -= 65535;
|
||||||
|
}
|
||||||
|
$rx .= '.{'.$split_length.'})/us';
|
||||||
|
|
||||||
|
return preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
$length = mb_strlen($string, $encoding);
|
||||||
|
|
||||||
|
for ($i = 0; $i < $length; $i += $split_length) {
|
||||||
|
$result[] = mb_substr($string, $i, $split_length, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strtolower($s, $encoding = null)
|
||||||
|
{
|
||||||
|
return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strtoupper($s, $encoding = null)
|
||||||
|
{
|
||||||
|
return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_substitute_character($c = null)
|
||||||
|
{
|
||||||
|
if (null === $c) {
|
||||||
|
return 'none';
|
||||||
|
}
|
||||||
|
if (0 === strcasecmp($c, 'none')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (80000 > \PHP_VERSION_ID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_substr($s, $start, $length = null, $encoding = null)
|
||||||
|
{
|
||||||
|
$encoding = self::getEncoding($encoding);
|
||||||
|
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||||
|
return (string) substr($s, $start, null === $length ? 2147483647 : $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($start < 0) {
|
||||||
|
$start = \iconv_strlen($s, $encoding) + $start;
|
||||||
|
if ($start < 0) {
|
||||||
|
$start = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $length) {
|
||||||
|
$length = 2147483647;
|
||||||
|
} elseif ($length < 0) {
|
||||||
|
$length = \iconv_strlen($s, $encoding) + $length - $start;
|
||||||
|
if ($length < 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string) \iconv_substr($s, $start, $length, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
|
||||||
|
{
|
||||||
|
$haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
|
||||||
|
$needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
|
||||||
|
|
||||||
|
return self::mb_strpos($haystack, $needle, $offset, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
|
||||||
|
{
|
||||||
|
$pos = self::mb_stripos($haystack, $needle, 0, $encoding);
|
||||||
|
|
||||||
|
return self::getSubpart($pos, $part, $haystack, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
|
||||||
|
{
|
||||||
|
$encoding = self::getEncoding($encoding);
|
||||||
|
if ('CP850' === $encoding || 'ASCII' === $encoding) {
|
||||||
|
$pos = strrpos($haystack, $needle);
|
||||||
|
} else {
|
||||||
|
$needle = self::mb_substr($needle, 0, 1, $encoding);
|
||||||
|
$pos = \iconv_strrpos($haystack, $needle, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::getSubpart($pos, $part, $haystack, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
|
||||||
|
{
|
||||||
|
$needle = self::mb_substr($needle, 0, 1, $encoding);
|
||||||
|
$pos = self::mb_strripos($haystack, $needle, $encoding);
|
||||||
|
|
||||||
|
return self::getSubpart($pos, $part, $haystack, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
|
||||||
|
{
|
||||||
|
$haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
|
||||||
|
$needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
|
||||||
|
|
||||||
|
return self::mb_strrpos($haystack, $needle, $offset, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
|
||||||
|
{
|
||||||
|
$pos = strpos($haystack, $needle);
|
||||||
|
if (false === $pos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($part) {
|
||||||
|
return substr($haystack, 0, $pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return substr($haystack, $pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_get_info($type = 'all')
|
||||||
|
{
|
||||||
|
$info = [
|
||||||
|
'internal_encoding' => self::$internalEncoding,
|
||||||
|
'http_output' => 'pass',
|
||||||
|
'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
|
||||||
|
'func_overload' => 0,
|
||||||
|
'func_overload_list' => 'no overload',
|
||||||
|
'mail_charset' => 'UTF-8',
|
||||||
|
'mail_header_encoding' => 'BASE64',
|
||||||
|
'mail_body_encoding' => 'BASE64',
|
||||||
|
'illegal_chars' => 0,
|
||||||
|
'encoding_translation' => 'Off',
|
||||||
|
'language' => self::$language,
|
||||||
|
'detect_order' => self::$encodingList,
|
||||||
|
'substitute_character' => 'none',
|
||||||
|
'strict_detection' => 'Off',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ('all' === $type) {
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
|
if (isset($info[$type])) {
|
||||||
|
return $info[$type];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_http_input($type = '')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_http_output($encoding = null)
|
||||||
|
{
|
||||||
|
return null !== $encoding ? 'pass' === $encoding : 'pass';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_strwidth($s, $encoding = null)
|
||||||
|
{
|
||||||
|
$encoding = self::getEncoding($encoding);
|
||||||
|
|
||||||
|
if ('UTF-8' !== $encoding) {
|
||||||
|
$s = \iconv($encoding, 'UTF-8//IGNORE', $s);
|
||||||
|
}
|
||||||
|
|
||||||
|
$s = preg_replace('/[\x{1100}-\x{115F}\x{2329}\x{232A}\x{2E80}-\x{303E}\x{3040}-\x{A4CF}\x{AC00}-\x{D7A3}\x{F900}-\x{FAFF}\x{FE10}-\x{FE19}\x{FE30}-\x{FE6F}\x{FF00}-\x{FF60}\x{FFE0}-\x{FFE6}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}]/u', '', $s, -1, $wide);
|
||||||
|
|
||||||
|
return ($wide << 1) + \iconv_strlen($s, 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_substr_count($haystack, $needle, $encoding = null)
|
||||||
|
{
|
||||||
|
return substr_count($haystack, $needle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_output_handler($contents, $status)
|
||||||
|
{
|
||||||
|
return $contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_chr($code, $encoding = null)
|
||||||
|
{
|
||||||
|
if (0x80 > $code %= 0x200000) {
|
||||||
|
$s = \chr($code);
|
||||||
|
} elseif (0x800 > $code) {
|
||||||
|
$s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
|
||||||
|
} elseif (0x10000 > $code) {
|
||||||
|
$s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
|
||||||
|
} else {
|
||||||
|
$s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
|
||||||
|
$s = mb_convert_encoding($s, $encoding, 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mb_ord($s, $encoding = null)
|
||||||
|
{
|
||||||
|
if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
|
||||||
|
$s = mb_convert_encoding($s, 'UTF-8', $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 === \strlen($s)) {
|
||||||
|
return \ord($s);
|
||||||
|
}
|
||||||
|
|
||||||
|
$code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
|
||||||
|
if (0xF0 <= $code) {
|
||||||
|
return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
|
||||||
|
}
|
||||||
|
if (0xE0 <= $code) {
|
||||||
|
return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
|
||||||
|
}
|
||||||
|
if (0xC0 <= $code) {
|
||||||
|
return (($code - 0xC0) << 6) + $s[2] - 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getSubpart($pos, $part, $haystack, $encoding)
|
||||||
|
{
|
||||||
|
if (false === $pos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($part) {
|
||||||
|
return self::mb_substr($haystack, 0, $pos, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::mb_substr($haystack, $pos, null, $encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function html_encoding_callback(array $m)
|
||||||
|
{
|
||||||
|
$i = 1;
|
||||||
|
$entities = '';
|
||||||
|
$m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
|
||||||
|
|
||||||
|
while (isset($m[$i])) {
|
||||||
|
if (0x80 > $m[$i]) {
|
||||||
|
$entities .= \chr($m[$i++]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (0xF0 <= $m[$i]) {
|
||||||
|
$c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
|
||||||
|
} elseif (0xE0 <= $m[$i]) {
|
||||||
|
$c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
|
||||||
|
} else {
|
||||||
|
$c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
$entities .= '&#'.$c.';';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function title_case(array $s)
|
||||||
|
{
|
||||||
|
return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getData($file)
|
||||||
|
{
|
||||||
|
if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
|
||||||
|
return require $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getEncoding($encoding)
|
||||||
|
{
|
||||||
|
if (null === $encoding) {
|
||||||
|
return self::$internalEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('UTF-8' === $encoding) {
|
||||||
|
return 'UTF-8';
|
||||||
|
}
|
||||||
|
|
||||||
|
$encoding = strtoupper($encoding);
|
||||||
|
|
||||||
|
if ('8BIT' === $encoding || 'BINARY' === $encoding) {
|
||||||
|
return 'CP850';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('UTF8' === $encoding) {
|
||||||
|
return 'UTF-8';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $encoding;
|
||||||
|
}
|
||||||
|
}
|