add captcha and top sale commodityes chart
This commit is contained in:
parent
4c5908c5c8
commit
7c58275de6
|
@ -19,7 +19,7 @@
|
|||
"melipayamak/php": "1.0.0",
|
||||
"mpdf/mpdf": "^8.2",
|
||||
"nelmio/api-doc-bundle": "^4.34",
|
||||
"nelmio/cors-bundle": "^2.4",
|
||||
"nelmio/cors-bundle": "^2.5",
|
||||
"phpdocumentor/reflection-docblock": "^5.3",
|
||||
"phpoffice/phpspreadsheet": "^1.29",
|
||||
"phpstan/phpdoc-parser": "^1.16",
|
||||
|
|
126
hesabixCore/composer.lock
generated
126
hesabixCore/composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "0000709f0d53a720475e13fa5dae69ab",
|
||||
"content-hash": "66bf4d4239acf870e6cf14109284dd59",
|
||||
"packages": [
|
||||
{
|
||||
"name": "composer/pcre",
|
||||
|
@ -1228,16 +1228,16 @@
|
|||
},
|
||||
{
|
||||
"name": "doctrine/orm",
|
||||
"version": "2.20.1",
|
||||
"version": "2.20.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/orm.git",
|
||||
"reference": "e3cabade99ebccc6ba078884c1c5f250866a494e"
|
||||
"reference": "19912de9270fa6abb3d25a1a37784af6b818d534"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/orm/zipball/e3cabade99ebccc6ba078884c1c5f250866a494e",
|
||||
"reference": "e3cabade99ebccc6ba078884c1c5f250866a494e",
|
||||
"url": "https://api.github.com/repos/doctrine/orm/zipball/19912de9270fa6abb3d25a1a37784af6b818d534",
|
||||
"reference": "19912de9270fa6abb3d25a1a37784af6b818d534",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1324,9 +1324,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/orm/issues",
|
||||
"source": "https://github.com/doctrine/orm/tree/2.20.1"
|
||||
"source": "https://github.com/doctrine/orm/tree/2.20.2"
|
||||
},
|
||||
"time": "2024-12-19T06:48:36+00:00"
|
||||
"time": "2025-02-04T19:17:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/persistence",
|
||||
|
@ -1671,16 +1671,16 @@
|
|||
},
|
||||
{
|
||||
"name": "friendsofsymfony/ckeditor-bundle",
|
||||
"version": "2.5.0",
|
||||
"version": "2.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/FriendsOfSymfony/FOSCKEditorBundle.git",
|
||||
"reference": "9d4cd4f2db4d800164b9c3051e4bfdee21acb27f"
|
||||
"reference": "dc0f0dc1ba328e0adf5df0a37f1676b6072f46de"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/FriendsOfSymfony/FOSCKEditorBundle/zipball/9d4cd4f2db4d800164b9c3051e4bfdee21acb27f",
|
||||
"reference": "9d4cd4f2db4d800164b9c3051e4bfdee21acb27f",
|
||||
"url": "https://api.github.com/repos/FriendsOfSymfony/FOSCKEditorBundle/zipball/dc0f0dc1ba328e0adf5df0a37f1676b6072f46de",
|
||||
"reference": "dc0f0dc1ba328e0adf5df0a37f1676b6072f46de",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1708,6 +1708,7 @@
|
|||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.41",
|
||||
"matthiasnoback/symfony-dependency-injection-test": "^4.0 || ^5.0",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"symfony/console": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/phpunit-bridge": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
|
||||
|
@ -1746,9 +1747,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/FriendsOfSymfony/FOSCKEditorBundle/issues",
|
||||
"source": "https://github.com/FriendsOfSymfony/FOSCKEditorBundle/tree/2.5.0"
|
||||
"source": "https://github.com/FriendsOfSymfony/FOSCKEditorBundle/tree/2.6.0"
|
||||
},
|
||||
"time": "2024-01-23T15:35:55+00:00"
|
||||
"time": "2025-01-13T15:11:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "gregwar/captcha",
|
||||
|
@ -2458,16 +2459,16 @@
|
|||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.12.1",
|
||||
"version": "1.13.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845"
|
||||
"reference": "024473a478be9df5fdaca2c793f2232fe788e414"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845",
|
||||
"reference": "123267b2c49fbf30d78a7b2d333f6be754b94845",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414",
|
||||
"reference": "024473a478be9df5fdaca2c793f2232fe788e414",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2506,7 +2507,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/myclabs/DeepCopy/issues",
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.12.1"
|
||||
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2514,20 +2515,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-11-08T17:47:46+00:00"
|
||||
"time": "2025-02-12T12:17:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nelmio/api-doc-bundle",
|
||||
"version": "v4.36.1",
|
||||
"version": "v4.37.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nelmio/NelmioApiDocBundle.git",
|
||||
"reference": "cdc855ef8e6a811336c3a6c72fe99fbe13a78e37"
|
||||
"reference": "1497977f82d396f1dda8120434c6d29f3de683e6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nelmio/NelmioApiDocBundle/zipball/cdc855ef8e6a811336c3a6c72fe99fbe13a78e37",
|
||||
"reference": "cdc855ef8e6a811336c3a6c72fe99fbe13a78e37",
|
||||
"url": "https://api.github.com/repos/nelmio/NelmioApiDocBundle/zipball/1497977f82d396f1dda8120434c6d29f3de683e6",
|
||||
"reference": "1497977f82d396f1dda8120434c6d29f3de683e6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2628,7 +2629,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nelmio/NelmioApiDocBundle/issues",
|
||||
"source": "https://github.com/nelmio/NelmioApiDocBundle/tree/v4.36.1"
|
||||
"source": "https://github.com/nelmio/NelmioApiDocBundle/tree/v4.37.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2636,7 +2637,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-19T17:01:30+00:00"
|
||||
"time": "2025-02-14T12:47:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nelmio/cors-bundle",
|
||||
|
@ -3075,20 +3076,20 @@
|
|||
},
|
||||
{
|
||||
"name": "phpoffice/phpspreadsheet",
|
||||
"version": "1.29.9",
|
||||
"version": "1.29.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
|
||||
"reference": "ffb47b639649fc9c8a6fa67977a27b756592ed85"
|
||||
"reference": "c80041b1628c4f18030407134fe88303661d4e4e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/ffb47b639649fc9c8a6fa67977a27b756592ed85",
|
||||
"reference": "ffb47b639649fc9c8a6fa67977a27b756592ed85",
|
||||
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/c80041b1628c4f18030407134fe88303661d4e4e",
|
||||
"reference": "c80041b1628c4f18030407134fe88303661d4e4e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer/pcre": "^3.3",
|
||||
"composer/pcre": "^1||^2||^3",
|
||||
"ext-ctype": "*",
|
||||
"ext-dom": "*",
|
||||
"ext-fileinfo": "*",
|
||||
|
@ -3175,9 +3176,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
|
||||
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.9"
|
||||
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.10"
|
||||
},
|
||||
"time": "2025-01-26T04:55:00+00:00"
|
||||
"time": "2025-02-08T02:56:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpdoc-parser",
|
||||
|
@ -3810,31 +3811,31 @@
|
|||
},
|
||||
{
|
||||
"name": "setasign/fpdi",
|
||||
"version": "v2.6.2",
|
||||
"version": "v2.6.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Setasign/FPDI.git",
|
||||
"reference": "9e013b376939c0d4029f54150d2a16f3c67a5797"
|
||||
"reference": "67c31f5e50c93c20579ca9e23035d8c540b51941"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Setasign/FPDI/zipball/9e013b376939c0d4029f54150d2a16f3c67a5797",
|
||||
"reference": "9e013b376939c0d4029f54150d2a16f3c67a5797",
|
||||
"url": "https://api.github.com/repos/Setasign/FPDI/zipball/67c31f5e50c93c20579ca9e23035d8c540b51941",
|
||||
"reference": "67c31f5e50c93c20579ca9e23035d8c540b51941",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-zlib": "*",
|
||||
"php": "^5.6 || ^7.0 || ^8.0"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"setasign/tfpdf": "<1.31"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~5.7",
|
||||
"phpunit/phpunit": "^7",
|
||||
"setasign/fpdf": "~1.8.6",
|
||||
"setasign/tfpdf": "~1.33",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"tecnickcom/tcpdf": "~6.2"
|
||||
"tecnickcom/tcpdf": "^6.2"
|
||||
},
|
||||
"suggest": {
|
||||
"setasign/fpdf": "FPDI will extend this class but as it is also possible to use TCPDF or tFPDF as an alternative. There's no fixed dependency configured."
|
||||
|
@ -3870,7 +3871,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Setasign/FPDI/issues",
|
||||
"source": "https://github.com/Setasign/FPDI/tree/v2.6.2"
|
||||
"source": "https://github.com/Setasign/FPDI/tree/v2.6.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -3878,7 +3879,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-12-10T13:12:19+00:00"
|
||||
"time": "2025-02-05T13:22:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/apache-pack",
|
||||
|
@ -9039,20 +9040,20 @@
|
|||
},
|
||||
{
|
||||
"name": "twig/extra-bundle",
|
||||
"version": "v3.19.0",
|
||||
"version": "v3.20.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/twig-extra-bundle.git",
|
||||
"reference": "9746573ca4bc1cd03a767a183faadaf84e0c31fa"
|
||||
"reference": "9df5e1dbb6a68c0665ae5603f6f2c20815647876"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/9746573ca4bc1cd03a767a183faadaf84e0c31fa",
|
||||
"reference": "9746573ca4bc1cd03a767a183faadaf84e0c31fa",
|
||||
"url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/9df5e1dbb6a68c0665ae5603f6f2c20815647876",
|
||||
"reference": "9df5e1dbb6a68c0665ae5603f6f2c20815647876",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.2",
|
||||
"php": ">=8.1.0",
|
||||
"symfony/framework-bundle": "^5.4|^6.4|^7.0",
|
||||
"symfony/twig-bundle": "^5.4|^6.4|^7.0",
|
||||
"twig/twig": "^3.2|^4.0"
|
||||
|
@ -9097,7 +9098,7 @@
|
|||
"twig"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.19.0"
|
||||
"source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.20.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -9109,28 +9110,27 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-26T19:22:23+00:00"
|
||||
"time": "2025-02-08T09:47:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.19.0",
|
||||
"version": "v3.20.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "d4f8c2b86374f08efc859323dbcd95c590f7124e"
|
||||
"reference": "3468920399451a384bef53cf7996965f7cd40183"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/d4f8c2b86374f08efc859323dbcd95c590f7124e",
|
||||
"reference": "d4f8c2b86374f08efc859323dbcd95c590f7124e",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/3468920399451a384bef53cf7996965f7cd40183",
|
||||
"reference": "3468920399451a384bef53cf7996965f7cd40183",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.2",
|
||||
"php": ">=8.1.0",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/polyfill-ctype": "^1.8",
|
||||
"symfony/polyfill-mbstring": "^1.3",
|
||||
"symfony/polyfill-php81": "^1.29"
|
||||
"symfony/polyfill-mbstring": "^1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^2.0",
|
||||
|
@ -9177,7 +9177,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.19.0"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.20.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -9189,7 +9189,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-29T07:06:14+00:00"
|
||||
"time": "2025-02-13T08:34:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
|
@ -9251,16 +9251,16 @@
|
|||
},
|
||||
{
|
||||
"name": "zircote/swagger-php",
|
||||
"version": "5.0.3",
|
||||
"version": "5.0.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/zircote/swagger-php.git",
|
||||
"reference": "7708510b17502a416214148edaa8c9958b23b6cd"
|
||||
"reference": "2eb4005840058d8844a0bcc14403932331331068"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/7708510b17502a416214148edaa8c9958b23b6cd",
|
||||
"reference": "7708510b17502a416214148edaa8c9958b23b6cd",
|
||||
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/2eb4005840058d8844a0bcc14403932331331068",
|
||||
"reference": "2eb4005840058d8844a0bcc14403932331331068",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -9331,9 +9331,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/zircote/swagger-php/issues",
|
||||
"source": "https://github.com/zircote/swagger-php/tree/5.0.3"
|
||||
"source": "https://github.com/zircote/swagger-php/tree/5.0.5"
|
||||
},
|
||||
"time": "2025-01-15T21:02:43+00:00"
|
||||
"time": "2025-02-24T00:48:00+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
doctrine:
|
||||
dbal:
|
||||
url: '%env(resolve:DATABASE_URL)%'
|
||||
|
||||
# IMPORTANT: You MUST configure your server version,
|
||||
# either here or in the DATABASE_URL env var (see .env file)
|
||||
#server_version: '15'
|
||||
|
@ -16,6 +15,9 @@ doctrine:
|
|||
dir: '%kernel.project_dir%/src/Entity'
|
||||
prefix: 'App\Entity'
|
||||
alias: App
|
||||
dql:
|
||||
string_functions:
|
||||
CAST: App\Doctrine\Cast
|
||||
|
||||
when@test:
|
||||
doctrine:
|
||||
|
|
|
@ -8,10 +8,12 @@ framework:
|
|||
# Enables session support. Note that the session will ONLY be started if you read or write from it.
|
||||
# Remove or comment this section to explicitly disable session support.
|
||||
session:
|
||||
enabled: true
|
||||
handler_id: null
|
||||
cookie_secure: auto
|
||||
cookie_samesite: lax
|
||||
cookie_secure: true
|
||||
storage_factory_id: session.storage.factory.native
|
||||
cookie_lifetime: 3600 # 1 ساعت
|
||||
cookie_samesite: none # برای CORS باید Lax یا None باشه
|
||||
|
||||
#esi: true
|
||||
#fragments: true
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
# config/packages/nelmio_cors.yaml
|
||||
nelmio_cors:
|
||||
defaults:
|
||||
origin_regex: false
|
||||
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
|
||||
allow_origin: [ '*' ] # اجازه به همه دامنهها
|
||||
allow_methods: [ 'GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ]
|
||||
allow_headers: [ '*' ] # اجازه به همه هدرها
|
||||
expose_headers: [ 'Link' ]
|
||||
allow_credentials: true # اجازه ارسال کوکیها
|
||||
max_age: 3600
|
||||
paths:
|
||||
'^/':
|
||||
# اعمال تنظیمات به همه مسیرها
|
||||
allow_origin: [ '*' ]
|
||||
allow_methods: [ 'GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ]
|
||||
allow_headers: [ '*' ]
|
||||
expose_headers: [ 'Link' ]
|
||||
allow_credentials: true
|
||||
max_age: 3600
|
||||
paths:
|
||||
'^/': null
|
||||
|
|
|
@ -22,7 +22,10 @@ security:
|
|||
check_path: api_login
|
||||
username_path: mobile
|
||||
password_path: password
|
||||
|
||||
failure_handler: App\Security\AuthenticationFailureHandler
|
||||
form_login:
|
||||
# ...
|
||||
failure_handler: App\Security\AuthenticationFailureHandler
|
||||
custom_authenticators:
|
||||
- App\Security\ApiKeyAuthenticator
|
||||
- App\Security\ParttyAuthenticator
|
||||
|
|
|
@ -14,7 +14,10 @@ services:
|
|||
_defaults:
|
||||
autowire: true # Automatically injects dependencies in your services.
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
|
||||
App\Security\AuthenticationFailureHandler:
|
||||
arguments:
|
||||
$captchaService: '@App\Service\CaptchaService'
|
||||
$requestStack: '@request_stack'
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
App\:
|
||||
|
|
18
hesabixCore/src/Controller/CaptchaController.php
Normal file
18
hesabixCore/src/Controller/CaptchaController.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
// src/Controller/CaptchaController.php
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use App\Service\CaptchaService;
|
||||
|
||||
class CaptchaController extends AbstractController
|
||||
{
|
||||
#[Route('/api/captcha/image', name: 'api_captcha_image', methods: ['GET'])]
|
||||
public function generateCaptchaImage(SessionInterface $session,CaptchaService $captchaService): Response
|
||||
{
|
||||
return $captchaService->createCaptchaImage($session);
|
||||
}
|
||||
}
|
|
@ -63,6 +63,7 @@ class DashboardController extends AbstractController
|
|||
if(array_key_exists('persons',$params)) $setting->setPersons($params['persons']);
|
||||
if(array_key_exists('notif',$params)) $setting->setNotif($params['notif']);
|
||||
if(array_key_exists('sellChart',$params)) $setting->setSellChart($params['sellChart']);
|
||||
if(array_key_exists('topCommodities',$params)) $setting->setTopCommoditiesChart($params['topCommodities']);
|
||||
|
||||
$entityManagerInterface->persist($setting);
|
||||
$entityManagerInterface->flush();
|
||||
|
|
|
@ -17,6 +17,7 @@ use App\Entity\HesabdariRow;
|
|||
use App\Service\Explore;
|
||||
use App\Service\Jdate;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
@ -28,11 +29,13 @@ class ReportController extends AbstractController
|
|||
{
|
||||
private $em;
|
||||
private $provider;
|
||||
|
||||
function __construct(Provider $provider, EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->em = $entityManager;
|
||||
$this->provider = $provider;
|
||||
}
|
||||
|
||||
#[Route('/api/report/person/buysell', name: 'app_report_person_buysell')]
|
||||
public function app_report_person_buysell(Provider $provider, Jdate $jdate, Access $access, Request $request, EntityManagerInterface $entityManagerInterface): JsonResponse
|
||||
{
|
||||
|
@ -215,7 +218,6 @@ class ReportController extends AbstractController
|
|||
]);
|
||||
}
|
||||
|
||||
|
||||
$commodity = $entityManagerInterface->getRepository(Commodity::class)->findOneBy([
|
||||
'bid' => $acc['bid']->getId(),
|
||||
'code' => $params['commodity'],
|
||||
|
@ -285,4 +287,107 @@ class ReportController extends AbstractController
|
|||
}
|
||||
return $this->json($response);
|
||||
}
|
||||
|
||||
#[Route('/api/report/top-selling-commodities', name: 'app_report_top_selling_commodities', methods: ['POST'])]
|
||||
public function app_report_top_selling_commodities(Access $access, Explore $explore, Jdate $jdate, Request $request, EntityManagerInterface $entityManager, LoggerInterface $logger): JsonResponse
|
||||
{
|
||||
$acc = $access->hasRole('report');
|
||||
if (!$acc) {
|
||||
$acc = $access->hasRole('sell');
|
||||
if (!$acc) {
|
||||
throw $this->createAccessDeniedException('شما دسترسی لازم برای مشاهده این اطلاعات را ندارید.');
|
||||
}
|
||||
}
|
||||
|
||||
/** @var Business $business */
|
||||
$business = $acc['bid'];
|
||||
/** @var Year $year */
|
||||
$year = $acc['year'];
|
||||
|
||||
$payload = $request->getPayload();
|
||||
$period = $payload->get('period', 'year');
|
||||
$limit = (int) $payload->get('limit', 10);
|
||||
if ($limit < 3) {
|
||||
$limit = 3;
|
||||
}
|
||||
|
||||
$today = $jdate->GetTodayDate();
|
||||
list($currentYear, $currentMonth, $currentDay) = explode('/', $today);
|
||||
|
||||
switch ($period) {
|
||||
case 'today':
|
||||
$dateStart = $today;
|
||||
$dateEnd = $today;
|
||||
break;
|
||||
case 'week':
|
||||
$weekDay = (int) $jdate->jdate('w', time());
|
||||
$daysToSubtract = $weekDay;
|
||||
$dateStart = $jdate->shamsiDate(0, 0, -$daysToSubtract);
|
||||
$dateEnd = $jdate->shamsiDate(0, 0, 6 - $weekDay);
|
||||
break;
|
||||
case 'month':
|
||||
$dateStart = "$currentYear/$currentMonth/01";
|
||||
$dateEnd = "$currentYear/$currentMonth/" . $jdate->jdate('t', $jdate->jallaliToUnixTime("$currentYear/$currentMonth/01"));
|
||||
break;
|
||||
case 'year':
|
||||
default:
|
||||
$dateStart = $jdate->jdate('Y/m/d', $year->getStart());
|
||||
$dateEnd = $jdate->jdate('Y/m/d', $year->getEnd());
|
||||
break;
|
||||
}
|
||||
|
||||
$queryBuilder = $entityManager->createQueryBuilder();
|
||||
$queryBuilder
|
||||
->select('c') // Commodity
|
||||
->addSelect('SUM(CAST(hr.commdityCount AS INTEGER)) as totalCount')
|
||||
->addSelect('hr') // HesabdariRow
|
||||
->from(HesabdariRow::class, 'hr')
|
||||
->innerJoin('hr.doc', 'hd')
|
||||
->innerJoin('hr.commodity', 'c')
|
||||
->where('hd.bid = :business')
|
||||
->andWhere('hd.type = :type')
|
||||
->andWhere('hr.year = :year')
|
||||
->andWhere('hd.date BETWEEN :dateStart AND :dateEnd')
|
||||
->setParameter('business', $business)
|
||||
->setParameter('type', 'sell')
|
||||
->setParameter('year', $year)
|
||||
->setParameter('dateStart', $dateStart)
|
||||
->setParameter('dateEnd', $dateEnd)
|
||||
->groupBy('c.id, hr.id')
|
||||
->orderBy('totalCount', 'DESC')
|
||||
->setMaxResults($limit);
|
||||
|
||||
try {
|
||||
$results = $queryBuilder->getQuery()->getResult();
|
||||
$logger->info('Query executed successfully', [
|
||||
'sql' => $queryBuilder->getQuery()->getSQL(),
|
||||
'params' => $queryBuilder->getQuery()->getParameters()->toArray(),
|
||||
'results' => $results
|
||||
]);
|
||||
|
||||
if (empty($results)) {
|
||||
$logger->info('No results returned from query');
|
||||
return $this->json(['message' => 'No data found'], 200);
|
||||
}
|
||||
|
||||
$topCommodities = [];
|
||||
foreach ($results as $result) {
|
||||
// با توجه به لاگ، اندیس 0 الان HesabdariRow هست
|
||||
$row = $result[0]; // HesabdariRow
|
||||
$commodity = $row->getCommodity(); // Commodity از داخل HesabdariRow
|
||||
$totalCount = (int) $result['totalCount'];
|
||||
$topCommodities[] = $explore::ExploreCommodity($commodity, $totalCount);
|
||||
}
|
||||
|
||||
return $this->json($topCommodities);
|
||||
} catch (\Exception $e) {
|
||||
$logger->error('Error in top-selling commodities query', [
|
||||
'message' => $e->getMessage(),
|
||||
'sql' => $queryBuilder->getQuery()->getSQL(),
|
||||
'params' => $queryBuilder->getQuery()->getParameters()->toArray(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
return $this->json(['error' => 'An error occurred: ' . $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,9 +5,11 @@ namespace App\Controller;
|
|||
use App\Entity\Business;
|
||||
use App\Entity\EmailHistory;
|
||||
use App\Entity\Permission;
|
||||
use App\Service\CaptchaService;
|
||||
use App\Service\Extractor;
|
||||
use App\Service\Provider;
|
||||
use App\Service\SMS;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
@ -18,6 +20,7 @@ use Symfony\Bundle\SecurityBundle\Security;
|
|||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||
use Symfony\Component\Security\Http\Attribute\CurrentUser;
|
||||
use App\Entity\User;
|
||||
|
@ -52,60 +55,76 @@ class UserController extends AbstractController
|
|||
return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length);
|
||||
}
|
||||
|
||||
#[Route('/api/user/login', name: 'api_login')]
|
||||
public function api_login(TranslatorInterface $translatorInterface, Extractor $extractor, Request $request, #[CurrentUser] ?User $user, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
#[Route('/api/user/login', name: 'api_login', methods: ['POST'])]
|
||||
public function api_login(
|
||||
TranslatorInterface $translatorInterface,
|
||||
Extractor $extractor,
|
||||
Request $request,
|
||||
CaptchaService $captchaService,
|
||||
#[CurrentUser] ?User $user,
|
||||
EntityManagerInterface $entityManager
|
||||
): Response {
|
||||
$params = $request->getPayload()->all();
|
||||
if (array_key_exists('standard', $params)) {
|
||||
if (null === $user) {
|
||||
$captchaAnswer = $params['captcha_answer'] ?? '';
|
||||
$attemptKey = 'login_attempts';
|
||||
|
||||
// بررسی نیاز به کپچا
|
||||
$captchaRequired = $captchaService->isCaptchaRequired($attemptKey);
|
||||
if ($captchaRequired) {
|
||||
if (!$captchaService->validateCaptcha($captchaAnswer)) {
|
||||
return $this->json($extractor->operationFail(
|
||||
$translatorInterface->trans('login_fail'),
|
||||
empty($captchaAnswer) ? 'کپچا لازم است' : 'کپچا اشتباه است',
|
||||
400,
|
||||
['captcha_required' => true]
|
||||
));
|
||||
}
|
||||
if ($user->isActive() == false) {
|
||||
}
|
||||
|
||||
// چون #[CurrentUser] فقط در صورت احراز هویت موفق کاربر رو برمیگردونه،
|
||||
// اینجا فقط شرایط بعد از احراز هویت موفق بررسی میشه
|
||||
if (null === $user) {
|
||||
// این خط عملاً اجرا نمیشه چون Security Bundle شکست رو مدیریت میکنه
|
||||
// اما برای اطمینان نگهش داشتم
|
||||
$captchaService->incrementAttempts($attemptKey);
|
||||
return $this->json($extractor->operationFail(
|
||||
'حساب کاربری شما فعال نیست. لطفا با پشتیبانی تماس بگیرید'
|
||||
,
|
||||
$translatorInterface->trans('login_fail'),
|
||||
400,
|
||||
['captcha_required' => $captchaService->isCaptchaRequired($attemptKey)]
|
||||
));
|
||||
}
|
||||
|
||||
// بررسی وضعیت کاربر
|
||||
if ($user->isActive() == false) {
|
||||
$captchaService->incrementAttempts($attemptKey);
|
||||
return $this->json($extractor->operationFail(
|
||||
'حساب کاربری شما فعال نیست. لطفا با پشتیبانی تماس بگیرید',
|
||||
506,
|
||||
[
|
||||
'user' => $user->getUserIdentifier(),
|
||||
'active' => $user->isActive(),
|
||||
'captcha_required' => $captchaService->isCaptchaRequired($attemptKey)
|
||||
]
|
||||
));
|
||||
}
|
||||
|
||||
// ورود موفق
|
||||
$token = new UserToken();
|
||||
$token->setUser($user);
|
||||
$token->setToken($this->RandomString(254));
|
||||
$token->setTokenID($this->RandomString(254));
|
||||
$entityManager->persist($token);
|
||||
$entityManager->flush();
|
||||
|
||||
$captchaService->resetAttempts($attemptKey);
|
||||
return $this->json($extractor->operationSuccess([
|
||||
'user' => $user->getUserIdentifier(),
|
||||
'token' => $token->getToken(),
|
||||
'tokenID' => $token->getTokenID(),
|
||||
'active' => $user->isActive(),
|
||||
'captcha_required' => false
|
||||
]));
|
||||
} else {
|
||||
if (null === $user) {
|
||||
return $this->json([
|
||||
'message' => 'missing credentials',
|
||||
], Response::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
$token = new UserToken();
|
||||
$token->setUser($user);
|
||||
$token->setToken($this->RandomString(254));
|
||||
$token->setTokenID($this->RandomString(254));
|
||||
$entityManager->persist($token);
|
||||
$entityManager->flush();
|
||||
return $this->json([
|
||||
'user' => $user->getUserIdentifier(),
|
||||
'token' => $token->getToken(),
|
||||
'tokenID' => $token->getTokenID(),
|
||||
'active' => $user->isActive(),
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[Route('/api/user/has/role/{id}', name: 'api_user_has_role')]
|
||||
public function api_user_has_role(Extractor $extractor, #[CurrentUser] ?User $user, EntityManagerInterface $entityManager, $id): Response
|
||||
|
@ -279,23 +298,51 @@ class UserController extends AbstractController
|
|||
));
|
||||
}
|
||||
|
||||
#[Route('/api/user/register', name: 'api_user_register')]
|
||||
public function api_user_register(Extractor $extractor, registryMGR $registryMGR, SMS $SMS, MailerInterface $mailer, Request $request, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager): Response
|
||||
{
|
||||
#[Route('/api/user/register', name: 'api_user_register', methods: ['POST'])]
|
||||
public function api_user_register(
|
||||
Extractor $extractor,
|
||||
registryMGR $registryMGR,
|
||||
SMS $SMS,
|
||||
MailerInterface $mailer,
|
||||
Request $request,
|
||||
UserPasswordHasherInterface $userPasswordHasher,
|
||||
EntityManagerInterface $entityManager,
|
||||
CaptchaService $captchaService // اضافه کردن به آرگومانهای متد
|
||||
): Response {
|
||||
$params = [];
|
||||
if ($content = $request->getContent()) {
|
||||
$params = json_decode($content, true);
|
||||
}
|
||||
if (array_key_exists('name', $params) && array_key_exists('email', $params) && array_key_exists('mobile', $params) && array_key_exists('password', $params)) {
|
||||
|
||||
// همیشه کپچا رو چک میکنیم
|
||||
$captchaAnswer = $params['captcha_answer'] ?? '';
|
||||
if (!$captchaService->validateCaptcha($captchaAnswer)) {
|
||||
return $this->json($extractor->operationFail(
|
||||
empty($captchaAnswer) ? 'کپچا لازم است' : 'کپچا اشتباه است',
|
||||
400,
|
||||
['captcha_required' => true]
|
||||
));
|
||||
}
|
||||
|
||||
// ادامه منطق عضویت
|
||||
if (
|
||||
array_key_exists('name', $params) && array_key_exists('email', $params) &&
|
||||
array_key_exists('mobile', $params) && array_key_exists('password', $params)
|
||||
) {
|
||||
if ($entityManager->getRepository(User::class)->findOneBy(['email' => trim($params['email'])])) {
|
||||
return $this->json($extractor->operationFail(
|
||||
'پست الکترونیکی وارد شده قبلا ثبت شده است'
|
||||
'پست الکترونیکی وارد شده قبلا ثبت شده است',
|
||||
400,
|
||||
['captcha_required' => true]
|
||||
));
|
||||
} elseif ($entityManager->getRepository(User::class)->findOneBy(['mobile' => trim($params['mobile'])])) {
|
||||
return $this->json($extractor->operationFail(
|
||||
'شماره تلفن وارد شده قبلا ثبت شده است'
|
||||
'شماره تلفن وارد شده قبلا ثبت شده است',
|
||||
400,
|
||||
['captcha_required' => true]
|
||||
));
|
||||
}
|
||||
|
||||
$user = new User();
|
||||
$user->setEmail($params['email']);
|
||||
$user->setRoles(['ROLE_USER']);
|
||||
|
@ -313,11 +360,13 @@ class UserController extends AbstractController
|
|||
$user->setActive(false);
|
||||
$entityManager->persist($user);
|
||||
$entityManager->flush();
|
||||
|
||||
$SMS->send(
|
||||
[$user->getVerifyCode()],
|
||||
$registryMGR->get('sms', 'f2a'),
|
||||
$user->getMobile()
|
||||
);
|
||||
|
||||
try {
|
||||
$email = (new Email())
|
||||
->to($user->getEmail())
|
||||
|
@ -331,16 +380,22 @@ class UserController extends AbstractController
|
|||
|
||||
$mailer->send($email);
|
||||
} catch (Exception $exception) {
|
||||
// خطای ارسال ایمیل رو میتونید لاگ کنید، فعلاً نادیده میگیره
|
||||
}
|
||||
|
||||
return $this->json($extractor->operationSuccess([
|
||||
'id' => $user->getId()
|
||||
]));
|
||||
}
|
||||
|
||||
return $this->json($extractor->operationFail(
|
||||
'تمام موارد لازم را وارد کنید.'
|
||||
'تمام موارد لازم را وارد کنید.',
|
||||
400,
|
||||
['captcha_required' => true]
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
#[Route('/api/user/active/code/info/{id}', name: 'api_user_active_code_info')]
|
||||
public function api_user_active_code_info(registryMGR $registryMGR, MailerInterface $mailer, SMS $SMS, string $id, #[CurrentUser] ?User $user, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager, Request $request): Response
|
||||
{
|
||||
|
@ -479,35 +534,61 @@ class UserController extends AbstractController
|
|||
}
|
||||
return $this->json($extractor->operationFail('کد ارسالی اشتباه است.'));
|
||||
}
|
||||
#[Route('/api/user/forget/password/send-code', name: 'api_user_forget_password_send_code')]
|
||||
public function api_user_forget_password_send_code(Extractor $extractor, registryMGR $registryMGR, #[CurrentUser] ?User $user, SMS $SMS, MailerInterface $mailer, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager, Request $request): Response
|
||||
{
|
||||
|
||||
#[Route('/api/user/forget/password/send-code', name: 'api_user_forget_password_send_code', methods: ['POST'])]
|
||||
public function api_user_forget_password_send_code(
|
||||
Extractor $extractor,
|
||||
registryMGR $registryMGR,
|
||||
#[CurrentUser] ?User $user,
|
||||
SMS $SMS,
|
||||
MailerInterface $mailer,
|
||||
UserPasswordHasherInterface $userPasswordHasher,
|
||||
EntityManagerInterface $entityManager,
|
||||
Request $request,
|
||||
CaptchaService $captchaService
|
||||
): Response {
|
||||
$params = [];
|
||||
if ($content = $request->getContent()) {
|
||||
$params = json_decode($content, true);
|
||||
}
|
||||
|
||||
// همیشه کپچا رو چک میکنیم
|
||||
$captchaAnswer = $params['captcha_answer'] ?? '';
|
||||
if (!$captchaService->validateCaptcha($captchaAnswer)) {
|
||||
return $this->json($extractor->operationFail(
|
||||
empty($captchaAnswer) ? 'کپچا لازم است' : 'کپچا اشتباه است',
|
||||
400,
|
||||
['captcha_required' => true]
|
||||
));
|
||||
}
|
||||
|
||||
// ادامه منطق بازیابی
|
||||
if (!array_key_exists('mobile', $params)) {
|
||||
return $this->json($extractor->paramsNotSend());
|
||||
}
|
||||
|
||||
$user = $entityManager->getRepository(User::class)->findOneBy(['mobile' => $params['mobile']]);
|
||||
if (!$user) {
|
||||
return $this->json(data: $extractor->operationFail(
|
||||
return $this->json($extractor->operationFail(
|
||||
'کاربری با شماره تلفن وارد شده یافت نشد.',
|
||||
404
|
||||
404,
|
||||
['captcha_required' => true]
|
||||
));
|
||||
}
|
||||
if ($user->getVerifyCodeTime() > time()) {
|
||||
return $this->json(data: $extractor->operationFail(
|
||||
return $this->json($extractor->operationFail(
|
||||
'کد بازیابی رمز عبور اخیرا ارسال شده است. لطفا چند دقیقه دیگر مجددا درخواست خود را ارسال نمایید.',
|
||||
600
|
||||
600,
|
||||
['captcha_required' => true]
|
||||
));
|
||||
}
|
||||
|
||||
$user->setVerifyCode($this->RandomString(6, true));
|
||||
$user->setVerifyCodeTime(time() + 300);
|
||||
$entityManager->persist($user);
|
||||
$entityManager->flush();
|
||||
//send sms and email
|
||||
|
||||
// ارسال SMS و ایمیل
|
||||
$SMS->send(
|
||||
[$user->getVerifyCode()],
|
||||
$registryMGR->get('sms', 'recPassword'),
|
||||
|
@ -524,10 +605,12 @@ class UserController extends AbstractController
|
|||
);
|
||||
|
||||
$mailer->send($email);
|
||||
|
||||
return $this->json($extractor->operationSuccess([
|
||||
'id' => $user->getId(),
|
||||
]));
|
||||
}
|
||||
|
||||
#[Route('/api/user/save/mobile-number', name: 'api_user_save_mobile_number')]
|
||||
public function api_user_save_mobile_number(MailerInterface $mailer, SMS $SMS, #[CurrentUser] ?User $user, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager, Request $request): Response
|
||||
{
|
||||
|
|
28
hesabixCore/src/Doctrine/Cast.php
Normal file
28
hesabixCore/src/Doctrine/Cast.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
namespace App\Doctrine;
|
||||
|
||||
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
|
||||
use Doctrine\ORM\Query\Lexer;
|
||||
use Doctrine\ORM\Query\Parser;
|
||||
use Doctrine\ORM\Query\SqlWalker;
|
||||
|
||||
class Cast extends FunctionNode
|
||||
{
|
||||
private $expression;
|
||||
|
||||
public function parse(Parser $parser)
|
||||
{
|
||||
$parser->match(Lexer::T_IDENTIFIER); // CAST
|
||||
$parser->match(Lexer::T_OPEN_PARENTHESIS);
|
||||
$this->expression = $parser->ArithmeticExpression();
|
||||
$parser->match(Lexer::T_AS);
|
||||
$parser->match(Lexer::T_IDENTIFIER); // INTEGER یا هر نوع دیگه
|
||||
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
|
||||
}
|
||||
|
||||
public function getSql(SqlWalker $sqlWalker)
|
||||
{
|
||||
// به جای استفاده از $this->type، مستقیماً SIGNED رو میذاریم
|
||||
return 'CAST(' . $sqlWalker->walkArithmeticPrimary($this->expression) . ' AS SIGNED)';
|
||||
}
|
||||
}
|
|
@ -51,6 +51,9 @@ class DashboardSettings
|
|||
#[ORM\Column(nullable: true)]
|
||||
private ?bool $sellChart = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?bool $topCommoditiesChart = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
|
@ -199,4 +202,16 @@ class DashboardSettings
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isTopCommoditiesChart(): ?bool
|
||||
{
|
||||
return $this->topCommoditiesChart;
|
||||
}
|
||||
|
||||
public function setTopCommoditiesChart(?bool $topCommoditiesChart): static
|
||||
{
|
||||
$this->topCommoditiesChart = $topCommoditiesChart;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
// src/EventListener/AuthenticationFailureListener.php
|
||||
namespace App\EventListener;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\Security\Http\Event\AuthenticationFailureEvent;
|
||||
use App\Service\CaptchaService;
|
||||
|
||||
class AuthenticationFailureListener
|
||||
{
|
||||
private CaptchaService $captchaService;
|
||||
private SessionInterface $session;
|
||||
|
||||
public function __construct(CaptchaService $captchaService, SessionInterface $session)
|
||||
{
|
||||
$this->captchaService = $captchaService;
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(AuthenticationFailureEvent $event): void
|
||||
{
|
||||
$attemptKey = 'login_attempts';
|
||||
$this->captchaService->incrementAttempts($this->session, $attemptKey);
|
||||
}
|
||||
}
|
40
hesabixCore/src/Security/AuthenticationFailureHandler.php
Normal file
40
hesabixCore/src/Security/AuthenticationFailureHandler.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
// src/Security/AuthenticationFailureHandler.php
|
||||
namespace App\Security;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
|
||||
use App\Service\CaptchaService;
|
||||
|
||||
class AuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
|
||||
{
|
||||
private CaptchaService $captchaService;
|
||||
private RequestStack $requestStack;
|
||||
|
||||
public function __construct(CaptchaService $captchaService, RequestStack $requestStack)
|
||||
{
|
||||
$this->captchaService = $captchaService;
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): JsonResponse
|
||||
{
|
||||
$session = $this->requestStack->getSession();
|
||||
$attemptKey = 'login_attempts';
|
||||
$this->captchaService->incrementAttempts($attemptKey);
|
||||
|
||||
$attempts = $session->get($attemptKey, 0);
|
||||
$sessionId = $session->getId(); // برای چک کردن اینکه سشن ثابت میمونه یا نه
|
||||
|
||||
return new JsonResponse([
|
||||
'error' => 'احراز هویت نامعتبر می باشد.',
|
||||
'captcha_required' => $this->captchaService->isCaptchaRequired($attemptKey),
|
||||
'attempts' => $attempts,
|
||||
'last_attempt_time' => $session->get($attemptKey . '_time', 0),
|
||||
'session_id' => $sessionId // برای دیباگ
|
||||
], 401);
|
||||
}
|
||||
}
|
125
hesabixCore/src/Service/CaptchaService.php
Normal file
125
hesabixCore/src/Service/CaptchaService.php
Normal file
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
// src/Service/CaptchaService.php
|
||||
namespace App\Service;
|
||||
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class CaptchaService
|
||||
{
|
||||
private RequestStack $requestStack;
|
||||
|
||||
public function __construct(RequestStack $requestStack)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function createCaptchaImage(): Response
|
||||
{
|
||||
$session = $this->requestStack->getSession();
|
||||
|
||||
// تولید کپچا که با صفر شروع نشه
|
||||
$firstDigit = rand(1, 9); // رقم اول بین 1 تا 9
|
||||
$remainingDigits = str_pad(rand(0, 99999), 5, '0', STR_PAD_LEFT); // ۵ رقم بعدی
|
||||
$captchaCode = $firstDigit . $remainingDigits; // ترکیب به صورت ۶ رقمی
|
||||
|
||||
$persianNumbers = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
|
||||
$englishNumbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
||||
$captchaCodePersian = str_replace($englishNumbers, $persianNumbers, $captchaCode);
|
||||
|
||||
$session->set('captcha_code', $captchaCode);
|
||||
|
||||
$image = imagecreatetruecolor(200, 80);
|
||||
$backgroundColor = imagecolorallocate($image, 255, 255, 255);
|
||||
$textColor = imagecolorallocate($image, 0, 0, 0);
|
||||
imagefill($image, 0, 0, $backgroundColor);
|
||||
|
||||
$fontPath = __DIR__ . '/../Fonts/Vazirmatn-Black.ttf';
|
||||
imagettftext($image, 20, rand(-10, 10), 40, 50, $textColor, $fontPath, $captchaCodePersian);
|
||||
|
||||
$lineColor1 = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
|
||||
$lineColor2 = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
|
||||
imageline($image, rand(0, 50), rand(0, 80), rand(150, 200), rand(0, 80), $lineColor1);
|
||||
imageline($image, rand(0, 50), rand(0, 80), rand(150, 200), rand(0, 80), $lineColor2);
|
||||
|
||||
$circleColor = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
|
||||
imageellipse($image, rand(20, 180), rand(10, 70), rand(20, 50), rand(20, 50), $circleColor);
|
||||
|
||||
$squareColor = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
|
||||
$squareX = rand(20, 160);
|
||||
$squareY = rand(10, 40);
|
||||
$squareSize = rand(20, 40);
|
||||
imagerectangle($image, $squareX, $squareY, $squareX + $squareSize, $squareY + $squareSize, $squareColor);
|
||||
|
||||
imagefilter($image, IMG_FILTER_GAUSSIAN_BLUR);
|
||||
|
||||
$wavedImage = imagecreatetruecolor(200, 80);
|
||||
imagefill($wavedImage, 0, 0, $backgroundColor);
|
||||
for ($x = 0; $x < 200; $x++) {
|
||||
for ($y = 0; $y < 80; $y++) {
|
||||
$newX = $x + sin($y / 10) * 5;
|
||||
$newY = $y + cos($x / 10) * 5;
|
||||
if ($newX >= 0 && $newX < 200 && $newY >= 0 && $newY < 80) {
|
||||
$color = imagecolorat($image, $x, $y);
|
||||
imagesetpixel($wavedImage, (int)$newX, (int)$newY, $color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ob_start();
|
||||
imagepng($wavedImage);
|
||||
$imageData = ob_get_clean();
|
||||
imagedestroy($image);
|
||||
imagedestroy($wavedImage);
|
||||
|
||||
return new Response($imageData, 200, ['Content-Type' => 'image/png']);
|
||||
}
|
||||
|
||||
public function isCaptchaRequired(string $attemptKey): bool
|
||||
{
|
||||
$session = $this->requestStack->getSession();
|
||||
$attempts = $session->get($attemptKey, 0);
|
||||
$lastAttemptTime = $session->get($attemptKey . '_time', 0);
|
||||
$currentTime = time();
|
||||
$halfHour = 30 * 60;
|
||||
|
||||
if (($currentTime - $lastAttemptTime) > $halfHour) {
|
||||
$session->set($attemptKey, 0);
|
||||
$session->set($attemptKey . '_time', $currentTime);
|
||||
return false;
|
||||
}
|
||||
|
||||
return $attempts >= 3;
|
||||
}
|
||||
|
||||
public function validateCaptcha(string $captchaAnswer): bool
|
||||
{
|
||||
$session = $this->requestStack->getSession();
|
||||
if (empty($captchaAnswer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$storedCode = $session->get('captcha_code');
|
||||
if ($captchaAnswer === $storedCode) {
|
||||
$session->remove('captcha_code');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function incrementAttempts(string $attemptKey): void
|
||||
{
|
||||
$session = $this->requestStack->getSession();
|
||||
$attempts = $session->get($attemptKey, 0) + 1;
|
||||
$session->set($attemptKey, $attempts);
|
||||
$session->set($attemptKey . '_time', time());
|
||||
}
|
||||
|
||||
public function resetAttempts(string $attemptKey): void
|
||||
{
|
||||
$session = $this->requestStack->getSession();
|
||||
$session->set($attemptKey, 0);
|
||||
$session->set($attemptKey . '_time', time());
|
||||
}
|
||||
}
|
|
@ -584,7 +584,10 @@ class Explore
|
|||
'persons' => $item->isPersons(),
|
||||
'notif' => $item->isNotif(),
|
||||
'sellChart' => $item->isSellChart(),
|
||||
'topCommodities' => $item->isTopCommoditiesChart(),
|
||||
];
|
||||
if ($result['topCommodities'] === null)
|
||||
$result['topCommodities'] = true;
|
||||
if ($result['banks'] === null)
|
||||
$result['banks'] = true;
|
||||
if ($result['buys'] === null)
|
||||
|
|
|
@ -11,17 +11,17 @@ class Jdate
|
|||
{
|
||||
public function shamsiDate($nyear, $nmoon, $nday)
|
||||
{
|
||||
$reg_day = jdate("d","now");
|
||||
$reg_moon = jdate("m","now");
|
||||
$reg_year = jdate("y","now");
|
||||
$reg_day = $this->jdate("d", "now");
|
||||
$reg_moon = $this->jdate("m", "now");
|
||||
$reg_year = $this->jdate("Y", "now"); // تغییر از "y" به "Y" برای سال کامل
|
||||
|
||||
$end_year = jdate("y",jmaketime(0,0,0,$reg_moon+$nmoon,$reg_day+$nday,$reg_year+1300+$nyear));
|
||||
$end_moon = jdate("m",jmaketime(0,0,0,$reg_moon+$nmoon,$reg_day+$nday,$reg_year+1300+$nyear));
|
||||
$end_day = jdate("d",jmaketime(0,0,0,$reg_moon+$nmoon,$reg_day+$nday,$reg_year+1300+$nyear));
|
||||
$end_year = $this->jdate("Y", $this->jmktime(0, 0, 0, $reg_moon + $nmoon, $reg_day + $nday, $reg_year + $nyear)); // تغییر از "y" به "Y"
|
||||
$end_moon = $this->jdate("m", $this->jmktime(0, 0, 0, $reg_moon + $nmoon, $reg_day + $nday, $reg_year + $nyear));
|
||||
$end_day = $this->jdate("d", $this->jmktime(0, 0, 0, $reg_moon + $nmoon, $reg_day + $nday, $reg_year + $nyear));
|
||||
|
||||
if ($end_year < 10) $end_year = '0'.$end_year;
|
||||
if ($end_moon < 10) $end_moon = '0'.$end_moon;
|
||||
if ($end_day < 10) $end_day = '0'.$end_day;
|
||||
// حذف str_pad برای $end_year چون سال کامل رو میخواهیم
|
||||
$end_moon = str_pad($end_moon, 2, '0', STR_PAD_LEFT);
|
||||
$end_day = str_pad($end_day, 2, '0', STR_PAD_LEFT);
|
||||
|
||||
$new_date = $end_year . "/" . $end_moon . "/" . $end_day;
|
||||
|
||||
|
@ -32,10 +32,12 @@ class Jdate
|
|||
{
|
||||
return $this->jdate('Y/m/d', time());
|
||||
}
|
||||
public function time(){
|
||||
public function time()
|
||||
{
|
||||
return time();
|
||||
}
|
||||
public function fa2en($string) {
|
||||
public function fa2en($string)
|
||||
{
|
||||
return strtr($string, array('۰' => '0', '۱' => '1', '۲' => '2', '۳' => '3', '۴' => '4', '۵' => '5', '۶' => '6', '۷' => '7', '۸' => '8', '۹' => '9', '٠' => '0', '١' => '1', '٢' => '2', '٣' => '3', '٤' => '4', '٥' => '5', '٦' => '6', '٧' => '7', '٨' => '8', '٩' => '9'));
|
||||
}
|
||||
public function jallaliToUnixTime($stringTime, $persianNum = true)
|
||||
|
@ -47,10 +49,12 @@ class Jdate
|
|||
return strtotime($greDate[0] . '/' . $greDate[1] . '/' . $greDate[2]);
|
||||
}
|
||||
/* F */
|
||||
public function jdate($format,$timestamp='',$none='',$time_zone='Asia/Tehran',$tr_num='en'){
|
||||
public function jdate($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'en')
|
||||
{
|
||||
$T_sec = 0;/* <= رفع خطاي زمان سرور ، با اعداد '+' و '-' بر حسب ثانيه */
|
||||
if($time_zone!='local')date_default_timezone_set(($time_zone==='')?'Asia/Tehran':$time_zone);
|
||||
$ts=$T_sec+(($timestamp==='')?time():$this->tr_num($timestamp));
|
||||
if ($time_zone != 'local')
|
||||
date_default_timezone_set(($time_zone === '') ? 'Asia/Tehran' : $time_zone);
|
||||
$ts = $T_sec + (($timestamp === '' || $timestamp === 'now') ? time() : (int) $this->tr_num($timestamp));
|
||||
$date = explode('_', date('H_i_j_n_O_P_s_w_Y', $ts));
|
||||
list($j_y, $j_m, $j_d) = $this->gregorian_to_jalali($date[8], $date[3], $date[2]);
|
||||
$doy = ($j_m < 7) ? (($j_m - 1) * 31) + $j_d - 1 : (($j_m - 7) * 30) + $j_d + 185;
|
||||
|
@ -64,12 +68,21 @@ class Jdate
|
|||
continue;
|
||||
}
|
||||
switch ($sub) {
|
||||
case'E':case'R':case'x':case'X':
|
||||
case 'E':
|
||||
case 'R':
|
||||
case 'x':
|
||||
case 'X':
|
||||
$out .= 'http://jdf.scr.ir';
|
||||
break;
|
||||
case'B':case'e':case'g':
|
||||
case'G':case'h':case'I':
|
||||
case'T':case'u':case'Z':
|
||||
case 'B':
|
||||
case 'e':
|
||||
case 'g':
|
||||
case 'G':
|
||||
case 'h':
|
||||
case 'I':
|
||||
case 'T':
|
||||
case 'u':
|
||||
case 'Z':
|
||||
$out .= date($sub, $ts);
|
||||
break;
|
||||
case 'a':
|
||||
|
@ -182,7 +195,8 @@ class Jdate
|
|||
break;
|
||||
case 'W':
|
||||
$avs = (($date[7] == 6) ? 0 : $date[7] + 1) - ($doy % 7);
|
||||
if($avs<0)$avs+=7;
|
||||
if ($avs < 0)
|
||||
$avs += 7;
|
||||
$num = (int) (($doy + $avs) / 7);
|
||||
if ($avs < 4) {
|
||||
$num++;
|
||||
|
@ -190,7 +204,8 @@ class Jdate
|
|||
$num = ($avs == 4 or $avs == ((((($j_y % 33) % 4) - 2) == ((int) (($j_y % 33) * 0.05))) ? 5 : 4)) ? 53 : 52;
|
||||
}
|
||||
$aks = $avs + $kab;
|
||||
if($aks==7)$aks=0;
|
||||
if ($aks == 7)
|
||||
$aks = 0;
|
||||
$out .= (($kab + 363 - $doy) < $aks and $aks < 3) ? '01' : (($num < 10) ? '0' . $num : $num);
|
||||
break;
|
||||
case 'y':
|
||||
|
@ -202,16 +217,19 @@ class Jdate
|
|||
case 'z':
|
||||
$out .= $doy;
|
||||
break;
|
||||
default:$out.=$sub;
|
||||
default:
|
||||
$out .= $sub;
|
||||
}
|
||||
}
|
||||
return ($tr_num != 'en') ? $this->tr_num($out, 'fa', '.') : $out;
|
||||
}
|
||||
/* F */
|
||||
public function jstrftime($format,$timestamp='',$none='',$time_zone='Asia/Tehran',$tr_num='fa'){
|
||||
public function jstrftime($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa')
|
||||
{
|
||||
$T_sec = 0;/* <= رفع خطاي زمان سرور ، با اعداد '+' و '-' بر حسب ثانيه */
|
||||
if($time_zone!='local')date_default_timezone_set(($time_zone==='')?'Asia/Tehran':$time_zone);
|
||||
$ts=$T_sec+(($timestamp==='')?time():tr_num($timestamp));
|
||||
if ($time_zone != 'local')
|
||||
date_default_timezone_set(($time_zone === '') ? 'Asia/Tehran' : $time_zone);
|
||||
$ts = $T_sec + (($timestamp === '') ? time() : $this->tr_num($timestamp));
|
||||
$date = explode('_', date('h_H_i_j_n_s_w_Y', $ts));
|
||||
list($j_y, $j_m, $j_d) = $this->gregorian_to_jalali($date[7], $date[4], $date[3]);
|
||||
$doy = ($j_m < 7) ? (($j_m - 1) * 31) + $j_d - 1 : (($j_m - 7) * 30) + $j_d + 185;
|
||||
|
@ -252,14 +270,17 @@ class Jdate
|
|||
/* Week */
|
||||
case 'U':
|
||||
$avs = (($date[6] < 5) ? $date[6] + 2 : $date[6] - 5) - ($doy % 7);
|
||||
if($avs<0)$avs+=7;
|
||||
if ($avs < 0)
|
||||
$avs += 7;
|
||||
$num = (int) (($doy + $avs) / 7) + 1;
|
||||
if($avs>3 or $avs==1)$num--;
|
||||
if ($avs > 3 or $avs == 1)
|
||||
$num--;
|
||||
$out .= ($num < 10) ? '0' . $num : $num;
|
||||
break;
|
||||
case 'V':
|
||||
$avs = (($date[6] == 6) ? 0 : $date[6] + 1) - ($doy % 7);
|
||||
if($avs<0)$avs+=7;
|
||||
if ($avs < 0)
|
||||
$avs += 7;
|
||||
$num = (int) (($doy + $avs) / 7);
|
||||
if ($avs < 4) {
|
||||
$num++;
|
||||
|
@ -267,14 +288,17 @@ class Jdate
|
|||
$num = ($avs == 4 or $avs == ((((($j_y % 33) % 4) - 2) == ((int) (($j_y % 33) * 0.05))) ? 5 : 4)) ? 53 : 52;
|
||||
}
|
||||
$aks = $avs + $kab;
|
||||
if($aks==7)$aks=0;
|
||||
if ($aks == 7)
|
||||
$aks = 0;
|
||||
$out .= (($kab + 363 - $doy) < $aks and $aks < 3) ? '01' : (($num < 10) ? '0' . $num : $num);
|
||||
break;
|
||||
case 'W':
|
||||
$avs = (($date[6] == 6) ? 0 : $date[6] + 1) - ($doy % 7);
|
||||
if($avs<0)$avs+=7;
|
||||
if ($avs < 0)
|
||||
$avs += 7;
|
||||
$num = (int) (($doy + $avs) / 7) + 1;
|
||||
if($avs>3)$num--;
|
||||
if ($avs > 3)
|
||||
$num--;
|
||||
$out .= ($num < 10) ? '0' . $num : $num;
|
||||
break;
|
||||
/* Month */
|
||||
|
@ -376,14 +400,17 @@ class Jdate
|
|||
case '%':
|
||||
$out .= '%';
|
||||
break;
|
||||
default:$out.=$sub;
|
||||
default:
|
||||
$out .= $sub;
|
||||
}
|
||||
}
|
||||
return($tr_num!='en')?tr_num($out,'fa','.'):$out;
|
||||
return ($tr_num != 'en') ? $this->tr_num($out, 'fa', '.') : $out;
|
||||
}
|
||||
/* F */
|
||||
public function jmktime($h='',$m='',$s='',$jm='',$jd='',$jy='',$none='',$timezone='Asia/Tehran'){
|
||||
if($timezone!='local')date_default_timezone_set($timezone);
|
||||
public function jmktime($h = '', $m = '', $s = '', $jm = '', $jd = '', $jy = '', $none = '', $timezone = 'Asia/Tehran')
|
||||
{
|
||||
if ($timezone != 'local')
|
||||
date_default_timezone_set($timezone);
|
||||
if ($h === '') {
|
||||
return time();
|
||||
} else {
|
||||
|
@ -416,9 +443,10 @@ class Jdate
|
|||
}
|
||||
}
|
||||
/* F */
|
||||
public function jgetdate($timestamp='',$none='',$timezone='Asia/Tehran',$tn='en'){
|
||||
public function jgetdate($timestamp = '', $none = '', $timezone = 'Asia/Tehran', $tn = 'en')
|
||||
{
|
||||
$ts = ($timestamp === '') ? time() : $this->tr_num($timestamp);
|
||||
$jdate=explode('_',jdate('F_G_i_j_l_n_s_w_Y_z',$ts,'',$timezone,$tn));
|
||||
$jdate = explode('_', $this->jdate('F_G_i_j_l_n_s_w_Y_z', $ts, '', $timezone, $tn));
|
||||
return array(
|
||||
'seconds' => $this->tr_num((int) $this->tr_num($jdate[6]), $tn),
|
||||
'minutes' => $this->tr_num((int) $this->tr_num($jdate[2]), $tn),
|
||||
|
@ -434,19 +462,22 @@ class Jdate
|
|||
);
|
||||
}
|
||||
/* F */
|
||||
public function jcheckdate($jm,$jd,$jy){
|
||||
public function jcheckdate($jm, $jd, $jy)
|
||||
{
|
||||
list($jm, $jd, $jy) = explode('_', $this->tr_num($jm . '_' . $jd . '_' . $jy));
|
||||
$l_d = ($jm == 12) ? ((((($jy % 33) % 4) - 1) == ((int) (($jy % 33) * 0.05))) ? 30 : 29) : 31 - (int) ($jm / 6.5);
|
||||
return ($jm > 12 or $jd > $l_d or $jm < 1 or $jd < 1 or $jy < 1) ? false : true;
|
||||
}
|
||||
/* F */
|
||||
public function tr_num($str,$mod='en',$mf='٫'){
|
||||
public function tr_num($str, $mod = 'en', $mf = '٫')
|
||||
{
|
||||
$num_a = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.');
|
||||
$key_a = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', $mf);
|
||||
return ($mod == 'fa') ? str_replace($num_a, $key_a, $str) : str_replace($key_a, $num_a, $str);
|
||||
}
|
||||
/* F */
|
||||
public function jdate_words($array,$mod=''){
|
||||
public function jdate_words($array, $mod = '')
|
||||
{
|
||||
foreach ($array as $type => $num) {
|
||||
$num = (int) $this->tr_num($num);
|
||||
switch ($type) {
|
||||
|
@ -466,18 +497,54 @@ class Jdate
|
|||
$k4 = array('', 'یک', 'دو', 'سه', 'چهار', 'پنج', 'شش', 'هفت', 'هشت', 'نه');
|
||||
$h4 = $k4[$xy4];
|
||||
}
|
||||
$array[$type]=(($num>99)?str_replace(array('12','13','14','19','20')
|
||||
,array('هزار و دویست','هزار و سیصد','هزار و چهارصد','هزار و نهصد','دوهزار')
|
||||
,substr($num,0,2)).((substr($num,2,2)=='00')?'':' و '):'').$h3.$p34.$h34.$h4;
|
||||
$array[$type] = (($num > 99) ? str_replace(
|
||||
array('12', '13', '14', '19', '20')
|
||||
,
|
||||
array('هزار و دویست', 'هزار و سیصد', 'هزار و چهارصد', 'هزار و نهصد', 'دوهزار')
|
||||
,
|
||||
substr($num, 0, 2)
|
||||
) . ((substr($num, 2, 2) == '00') ? '' : ' و ') : '') . $h3 . $p34 . $h34 . $h4;
|
||||
break;
|
||||
case 'mm':
|
||||
$key = array('فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور', 'مهر', 'آبان', 'آذر', 'دی', 'بهمن', 'اسفند');
|
||||
$array[$type] = $key[$num - 1];
|
||||
break;
|
||||
case 'rr':
|
||||
$key=array('یک','دو','سه','چهار','پنج','شش','هفت','هشت','نه','ده','یازده','دوازده','سیزده'
|
||||
,'چهارده','پانزده','شانزده','هفده','هجده','نوزده','بیست','بیست و یک','بیست و دو','بیست و سه'
|
||||
,'بیست و چهار','بیست و پنج','بیست و شش','بیست و هفت','بیست و هشت','بیست و نه','سی','سی و یک');
|
||||
$key = array(
|
||||
'یک',
|
||||
'دو',
|
||||
'سه',
|
||||
'چهار',
|
||||
'پنج',
|
||||
'شش',
|
||||
'هفت',
|
||||
'هشت',
|
||||
'نه',
|
||||
'ده',
|
||||
'یازده',
|
||||
'دوازده',
|
||||
'سیزده'
|
||||
,
|
||||
'چهارده',
|
||||
'پانزده',
|
||||
'شانزده',
|
||||
'هفده',
|
||||
'هجده',
|
||||
'نوزده',
|
||||
'بیست',
|
||||
'بیست و یک',
|
||||
'بیست و دو',
|
||||
'بیست و سه'
|
||||
,
|
||||
'بیست و چهار',
|
||||
'بیست و پنج',
|
||||
'بیست و شش',
|
||||
'بیست و هفت',
|
||||
'بیست و هشت',
|
||||
'بیست و نه',
|
||||
'سی',
|
||||
'سی و یک'
|
||||
);
|
||||
$array[$type] = $key[$num - 1];
|
||||
break;
|
||||
case 'rh':
|
||||
|
@ -504,7 +571,8 @@ class Jdate
|
|||
$key = array('ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش');
|
||||
$array[$type] = $key[$num];
|
||||
break;
|
||||
default:$array[$type]=$num;
|
||||
default:
|
||||
$array[$type] = $num;
|
||||
}
|
||||
}
|
||||
return ($mod === '') ? $array : implode($mod, $array);
|
||||
|
@ -516,7 +584,8 @@ class Jdate
|
|||
1461 = 365*4 + 4/4 & 146097 = 365*400 + 400/4 - 400/100 + 400/400
|
||||
12053 = 365*33 + 32/4 & 36524 = 365*100 + 100/4 - 100/100 */
|
||||
/* F */
|
||||
public function gregorian_to_jalali($gy,$gm,$gd,$mod=''){
|
||||
public function gregorian_to_jalali($gy, $gm, $gd, $mod = '')
|
||||
{
|
||||
list($gy, $gm, $gd) = explode('_', $this->tr_num($gy . '_' . $gm . '_' . $gd));/* <= Extra :اين سطر ، جزء تابع اصلي نيست */
|
||||
$g_d_m = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
|
||||
if ($gy > 1600) {
|
||||
|
@ -533,7 +602,8 @@ class Jdate
|
|||
$jy += 4 * ((int) ($days / 1461));
|
||||
$days %= 1461;
|
||||
$jy += (int) (($days - 1) / 365);
|
||||
if($days > 365)$days=($days-1)%365;
|
||||
if ($days > 365)
|
||||
$days = ($days - 1) % 365;
|
||||
if ($days < 186) {
|
||||
$jm = 1 + (int) ($days / 31);
|
||||
$jd = 1 + ($days % 31);
|
||||
|
@ -544,7 +614,8 @@ class Jdate
|
|||
return ($mod === '') ? array($jy, $jm, $jd) : $jy . $mod . $jm . $mod . $jd;
|
||||
}
|
||||
/* F */
|
||||
public function jalali_to_gregorian($jy,$jm,$jd,$mod=''){
|
||||
public function jalali_to_gregorian($jy, $jm, $jd, $mod = '')
|
||||
{
|
||||
list($jy, $jm, $jd) = explode('_', $this->tr_num($jy . '_' . $jm . '_' . $jd));/* <= Extra :اين سطر ، جزء تابع اصلي نيست */
|
||||
if ($jy > 979) {
|
||||
$gy = 1600;
|
||||
|
@ -558,15 +629,18 @@ class Jdate
|
|||
if ($days > 36524) {
|
||||
$gy += 100 * ((int) (--$days / 36524));
|
||||
$days %= 36524;
|
||||
if($days >= 365)$days++;
|
||||
if ($days >= 365)
|
||||
$days++;
|
||||
}
|
||||
$gy += 4 * ((int) (($days) / 1461));
|
||||
$days %= 1461;
|
||||
$gy += (int) (($days - 1) / 365);
|
||||
if($days > 365)$days=($days-1)%365;
|
||||
if ($days > 365)
|
||||
$days = ($days - 1) % 365;
|
||||
$gd = $days + 1;
|
||||
foreach (array(0, 31, ((($gy % 4 == 0) and ($gy % 100 != 0)) or ($gy % 400 == 0)) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) as $gm => $v) {
|
||||
if($gd <= $v)break;
|
||||
if ($gd <= $v)
|
||||
break;
|
||||
$gd -= $v;
|
||||
}
|
||||
return ($mod === '') ? array($gy, $gm, $gd) : $gy . $mod . $gm . $mod . $gd;
|
||||
|
@ -586,7 +660,8 @@ class Jdate
|
|||
1 => 'ثانیه'
|
||||
);
|
||||
foreach ($tokens as $unit => $text) {
|
||||
if ($time < $unit) continue;
|
||||
if ($time < $unit)
|
||||
continue;
|
||||
$numberOfUnits = floor($time / $unit);
|
||||
return $numberOfUnits . ' ' . $text . ' قبل ';
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
1
public_html/bundles/nelmioapidoc/stoplight/styles.min.css
vendored
Normal file
1
public_html/bundles/nelmioapidoc/stoplight/styles.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public_html/bundles/nelmioapidoc/stoplight/web-components.min.js
vendored
Normal file
2
public_html/bundles/nelmioapidoc/stoplight/web-components.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
use App\Kernel;
|
||||
require_once dirname(__DIR__).'/hesabixCore/vendor/autoload_runtime.php';
|
||||
header("Access-Control-Allow-Credentials: true");
|
||||
return function (array $context) {
|
||||
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
};
|
Loading…
Reference in a new issue