Initial commit

This commit is contained in:
Developer
2025-04-21 16:03:20 +02:00
commit 2832896157
22874 changed files with 3092801 additions and 0 deletions

15
.editorconfig Normal file
View File

@@ -0,0 +1,15 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2

51
.env.example Normal file
View File

@@ -0,0 +1,51 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

15
.eslintrc.js vendored Normal file
View File

@@ -0,0 +1,15 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:vue/recommended',
],
rules: {
"indent": ['error', 2],
'quotes': ['warn', 'single'],
'semi': ['warn', 'never'],
'comma-dangle': ['warn', 'always-multiline'],
'vue/max-attributes-per-line': false,
'vue/require-default-prop': false,
'vue/singleline-html-element-content-newline': false,
}
}

5
.gitattributes vendored Normal file
View File

@@ -0,0 +1,5 @@
* text=auto
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
CHANGELOG.md export-ignore

17
.gitignore vendored Normal file
View File

@@ -0,0 +1,17 @@
/node_modules
/public/css
/public/hot
/public/js
/public/mix-manifest.json
/public/storage
/storage/*.key
/vendor
/docker
.DS_Store
.env
.env.backup
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log

8
.idea/.gitignore generated vendored Executable file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="framework" type="frameworkType"/>
<xs:complexType name="commandType">
<xs:all>
<xs:element type="xs:string" name="name" minOccurs="1" maxOccurs="1"/>
<xs:element type="xs:string" name="params" minOccurs="0" maxOccurs="1"/>
<xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
<xs:element type="optionsBeforeType" name="optionsBefore" minOccurs="0" maxOccurs="1"/>
</xs:all>
</xs:complexType>
<xs:complexType name="frameworkType">
<xs:sequence>
<xs:element type="xs:string" name="extraData" minOccurs="0" maxOccurs="1"/>
<xs:element type="commandType" name="command" maxOccurs="unbounded" minOccurs="0"/>
<xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="required"/>
<xs:attribute type="xs:string" name="invoke" use="required"/>
<xs:attribute type="xs:string" name="alias" use="required"/>
<xs:attribute type="xs:boolean" name="enabled" use="required"/>
<xs:attribute type="xs:integer" name="version" use="required"/>
<xs:attribute type="xs:string" name="frameworkId" use="optional"/>
</xs:complexType>
<xs:complexType name="optionsBeforeType">
<xs:sequence>
<xs:element type="optionType" name="option" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="optionType">
<xs:sequence>
<xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="required"/>
<xs:attribute type="xs:string" name="shortcut" use="optional"/>
<xs:attribute name="pattern" use="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="space"/>
<xs:enumeration value="equals"/>
<xs:enumeration value="unknown"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:schema>

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/teeaseer.iml" filepath="$PROJECT_DIR$/.idea/teeaseer.iml" />
</modules>
</component>
</project>

186
.idea/php.xml generated Normal file
View File

@@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
<path value="$PROJECT_DIR$/vendor/asm89/stack-cors" />
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
<path value="$PROJECT_DIR$/vendor/brick/math" />
<path value="$PROJECT_DIR$/vendor/brick/money" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<path value="$PROJECT_DIR$/vendor/opis/closure" />
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
<path value="$PROJECT_DIR$/vendor/qiwi/bill-payments-php-sdk" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
<path value="$PROJECT_DIR$/vendor/carbonphp/carbon-doctrine-types" />
<path value="$PROJECT_DIR$/vendor/swiftmailer/swiftmailer" />
<path value="$PROJECT_DIR$/vendor/dflydev/dot-access-data" />
<path value="$PROJECT_DIR$/vendor/moontoast/math" />
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
<path value="$PROJECT_DIR$/vendor/monolog/monolog" />
<path value="$PROJECT_DIR$/vendor/voku/portable-ascii" />
<path value="$PROJECT_DIR$/vendor/coderello/laravel-nova-lang" />
<path value="$PROJECT_DIR$/vendor/nesbot/carbon" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
<path value="$PROJECT_DIR$/vendor/paragonie/constant_time_encoding" />
<path value="$PROJECT_DIR$/vendor/paragonie/random_compat" />
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
<path value="$PROJECT_DIR$/vendor/ebess/advanced-nova-media-library" />
<path value="$PROJECT_DIR$/vendor/fakerphp/faker" />
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
<path value="$PROJECT_DIR$/vendor/phpoption/phpoption" />
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/doctrine/cache" />
<path value="$PROJECT_DIR$/vendor/doctrine/event-manager" />
<path value="$PROJECT_DIR$/vendor/doctrine/dbal" />
<path value="$PROJECT_DIR$/vendor/phpseclib/bcmath_compat" />
<path value="$PROJECT_DIR$/vendor/phpseclib/phpseclib" />
<path value="$PROJECT_DIR$/vendor/maximebf/debugbar" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/laravel/serializable-closure" />
<path value="$PROJECT_DIR$/vendor/laravel/ui" />
<path value="$PROJECT_DIR$/vendor/psr/http-factory" />
<path value="$PROJECT_DIR$/vendor/psr/http-message" />
<path value="$PROJECT_DIR$/vendor/laravel/nova" />
<path value="$PROJECT_DIR$/vendor/laravel/tinker" />
<path value="$PROJECT_DIR$/vendor/laravel/sail" />
<path value="$PROJECT_DIR$/vendor/laravel/framework" />
<path value="$PROJECT_DIR$/vendor/psr/clock" />
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/psr/http-client" />
<path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
<path value="$PROJECT_DIR$/vendor/psr/log" />
<path value="$PROJECT_DIR$/vendor/tijsverkoyen/css-to-inline-styles" />
<path value="$PROJECT_DIR$/vendor/mockery/mockery" />
<path value="$PROJECT_DIR$/vendor/interkassa/php-sdk" />
<path value="$PROJECT_DIR$/vendor/nette/utils" />
<path value="$PROJECT_DIR$/vendor/nette/schema" />
<path value="$PROJECT_DIR$/vendor/reinink/remember-query-strings" />
<path value="$PROJECT_DIR$/vendor/dragonmantank/cron-expression" />
<path value="$PROJECT_DIR$/vendor/spatie/laravel-medialibrary" />
<path value="$PROJECT_DIR$/vendor/spatie/image" />
<path value="$PROJECT_DIR$/vendor/spatie/laravel-enum" />
<path value="$PROJECT_DIR$/vendor/symfony/string" />
<path value="$PROJECT_DIR$/vendor/spatie/image-optimizer" />
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
<path value="$PROJECT_DIR$/vendor/spatie/temporary-directory" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php80" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
<path value="$PROJECT_DIR$/vendor/spatie/data-transfer-object" />
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
<path value="$PROJECT_DIR$/vendor/spatie/once" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/spatie/enum" />
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
<path value="$PROJECT_DIR$/vendor/graham-campbell/result-type" />
<path value="$PROJECT_DIR$/vendor/spatie/laravel-permission" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-iconv" />
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<path value="$PROJECT_DIR$/vendor/symfony/process" />
<path value="$PROJECT_DIR$/vendor/vlucas/phpdotenv" />
<path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
<path value="$PROJECT_DIR$/vendor/nunomaduro/collision" />
<path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
<path value="$PROJECT_DIR$/vendor/hamcrest/hamcrest-php" />
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
<path value="$PROJECT_DIR$/vendor/optimistdigital/nova-translations-loader" />
<path value="$PROJECT_DIR$/vendor/myclabs/php-enum" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-ctype" />
<path value="$PROJECT_DIR$/vendor/optimistdigital/nova-settings" />
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
<path value="$PROJECT_DIR$/vendor/ysv/nova-leader" />
<path value="$PROJECT_DIR$/vendor/symfony/intl" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php72" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php73" />
<path value="$PROJECT_DIR$/vendor/yoomoney/yookassa-sdk-validator" />
<path value="$PROJECT_DIR$/vendor/yoomoney/yookassa-sdk-php" />
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
<path value="$PROJECT_DIR$/vendor/fideloper/proxy" />
<path value="$PROJECT_DIR$/vendor/fruitcake/laravel-cors" />
<path value="$PROJECT_DIR$/vendor/filp/whoops" />
<path value="$PROJECT_DIR$/vendor/league/flysystem" />
<path value="$PROJECT_DIR$/vendor/league/glide-symfony" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/psy/psysh" />
<path value="$PROJECT_DIR$/vendor/league/mime-type-detection" />
<path value="$PROJECT_DIR$/vendor/vyuldashev/nova-permission" />
<path value="$PROJECT_DIR$/vendor/league/glide" />
<path value="$PROJECT_DIR$/vendor/php-ds/php-ds" />
<path value="$PROJECT_DIR$/vendor/league/glide-laravel" />
<path value="$PROJECT_DIR$/vendor/league/commonmark" />
<path value="$PROJECT_DIR$/vendor/league/config" />
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
<path value="$PROJECT_DIR$/vendor/inertiajs/inertia-laravel" />
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
<path value="$PROJECT_DIR$/vendor/tightenco/ziggy" />
<path value="$PROJECT_DIR$/vendor/cakephp/chronos" />
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
<path value="$PROJECT_DIR$/vendor/facade/ignition-contracts" />
<path value="$PROJECT_DIR$/vendor/unitpay/php-sdk" />
<path value="$PROJECT_DIR$/vendor/facade/ignition" />
<path value="$PROJECT_DIR$/vendor/facade/flare-client-php" />
<path value="$PROJECT_DIR$/vendor/ramsey/uuid" />
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
<path value="$PROJECT_DIR$/vendor/ramsey/collection" />
<path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
<path value="$PROJECT_DIR$/vendor/intervention/image" />
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
<path value="$PROJECT_DIR$/vendor/barryvdh/laravel-debugbar" />
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.4">
<option name="suggestChangeDefaultLanguageLevel" value="false" />
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PhpUnit">
<phpunit_settings>
<PhpUnitSettings configuration_file_path="$PROJECT_DIR$/phpunit.xml" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" use_configuration_file="true" />
</phpunit_settings>
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

10
.idea/phpunit.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PHPUnit">
<option name="directories">
<list>
<option value="$PROJECT_DIR$/tests" />
</list>
</option>
</component>
</project>

6
.idea/prettier.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PrettierConfiguration">
<option name="myConfigurationMode" value="AUTOMATIC" />
</component>
</project>

6
.idea/symfony2.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Symfony2PluginSettings">
<option name="pluginEnabled" value="true" />
</component>
</project>

178
.idea/teeaseer.iml generated Normal file
View File

@@ -0,0 +1,178 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/app" isTestSource="false" packagePrefix="App\" />
<sourceFolder url="file://$MODULE_DIR$/database/factories" isTestSource="false" packagePrefix="Database\Factories\" />
<sourceFolder url="file://$MODULE_DIR$/database/seeders" isTestSource="false" packagePrefix="Database\Seeders\" />
<sourceFolder url="file://$MODULE_DIR$/nova-components/NovaLeader/src" isTestSource="false" packagePrefix="Ysv\NovaLeader\" />
<sourceFolder url="file://$MODULE_DIR$/nova/src" isTestSource="false" packagePrefix="Laravel\Nova\" />
<sourceFolder url="file://$MODULE_DIR$/nova/src/Console/asset-stubs/src" isTestSource="false" packagePrefix="{{ escapedNamespace }}\" />
<sourceFolder url="file://$MODULE_DIR$/nova/src/Console/card-stubs/src" isTestSource="false" packagePrefix="{{ escapedNamespace }}\" />
<sourceFolder url="file://$MODULE_DIR$/nova/src/Console/field-stubs/src" isTestSource="false" packagePrefix="{{ escapedNamespace }}\" />
<sourceFolder url="file://$MODULE_DIR$/nova/src/Console/filter-stubs/src" isTestSource="false" packagePrefix="{{ escapedNamespace }}\" />
<sourceFolder url="file://$MODULE_DIR$/nova/src/Console/resource-tool-stubs/src" isTestSource="false" packagePrefix="{{ escapedNamespace }}\" />
<sourceFolder url="file://$MODULE_DIR$/nova/src/Console/theme-stubs/src" isTestSource="false" packagePrefix="{{ escapedNamespace }}\" />
<sourceFolder url="file://$MODULE_DIR$/nova/src/Console/tool-stubs/src" isTestSource="false" packagePrefix="{{ escapedNamespace }}\" />
<sourceFolder url="file://$MODULE_DIR$/nova/tests" isTestSource="true" packagePrefix="Laravel\Nova\Tests\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tests\" />
<excludeFolder url="file://$MODULE_DIR$/vendor/asm89/stack-cors" />
<excludeFolder url="file://$MODULE_DIR$/vendor/barryvdh/laravel-debugbar" />
<excludeFolder url="file://$MODULE_DIR$/vendor/brick/math" />
<excludeFolder url="file://$MODULE_DIR$/vendor/brick/money" />
<excludeFolder url="file://$MODULE_DIR$/vendor/cakephp/chronos" />
<excludeFolder url="file://$MODULE_DIR$/vendor/carbonphp/carbon-doctrine-types" />
<excludeFolder url="file://$MODULE_DIR$/vendor/coderello/laravel-nova-lang" />
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/dflydev/dot-access-data" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/dbal" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/deprecations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/event-manager" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/inflector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/instantiator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/lexer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/dragonmantank/cron-expression" />
<excludeFolder url="file://$MODULE_DIR$/vendor/ebess/advanced-nova-media-library" />
<excludeFolder url="file://$MODULE_DIR$/vendor/egulias/email-validator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/facade/flare-client-php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition" />
<excludeFolder url="file://$MODULE_DIR$/vendor/facade/ignition-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/fakerphp/faker" />
<excludeFolder url="file://$MODULE_DIR$/vendor/fideloper/proxy" />
<excludeFolder url="file://$MODULE_DIR$/vendor/filp/whoops" />
<excludeFolder url="file://$MODULE_DIR$/vendor/fruitcake/laravel-cors" />
<excludeFolder url="file://$MODULE_DIR$/vendor/graham-campbell/result-type" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
<excludeFolder url="file://$MODULE_DIR$/vendor/hamcrest/hamcrest-php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/inertiajs/inertia-laravel" />
<excludeFolder url="file://$MODULE_DIR$/vendor/interkassa/php-sdk" />
<excludeFolder url="file://$MODULE_DIR$/vendor/intervention/image" />
<excludeFolder url="file://$MODULE_DIR$/vendor/laravel/framework" />
<excludeFolder url="file://$MODULE_DIR$/vendor/laravel/nova" />
<excludeFolder url="file://$MODULE_DIR$/vendor/laravel/sail" />
<excludeFolder url="file://$MODULE_DIR$/vendor/laravel/serializable-closure" />
<excludeFolder url="file://$MODULE_DIR$/vendor/laravel/tinker" />
<excludeFolder url="file://$MODULE_DIR$/vendor/laravel/ui" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/commonmark" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/config" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/flysystem" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/glide" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/glide-laravel" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/glide-symfony" />
<excludeFolder url="file://$MODULE_DIR$/vendor/league/mime-type-detection" />
<excludeFolder url="file://$MODULE_DIR$/vendor/maennchen/zipstream-php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/maximebf/debugbar" />
<excludeFolder url="file://$MODULE_DIR$/vendor/mockery/mockery" />
<excludeFolder url="file://$MODULE_DIR$/vendor/monolog/monolog" />
<excludeFolder url="file://$MODULE_DIR$/vendor/moontoast/math" />
<excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/deep-copy" />
<excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/php-enum" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nesbot/carbon" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nette/schema" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nette/utils" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nikic/php-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nunomaduro/collision" />
<excludeFolder url="file://$MODULE_DIR$/vendor/opis/closure" />
<excludeFolder url="file://$MODULE_DIR$/vendor/optimistdigital/nova-settings" />
<excludeFolder url="file://$MODULE_DIR$/vendor/optimistdigital/nova-translations-loader" />
<excludeFolder url="file://$MODULE_DIR$/vendor/paragonie/constant_time_encoding" />
<excludeFolder url="file://$MODULE_DIR$/vendor/paragonie/random_compat" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/manifest" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
<excludeFolder url="file://$MODULE_DIR$/vendor/php-ds/php-ds" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpoption/phpoption" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpseclib/bcmath_compat" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpseclib/phpseclib" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-code-coverage" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-file-iterator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-invoker" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-text-template" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-timer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/clock" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/event-dispatcher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-client" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-factory" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-message" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/simple-cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psy/psysh" />
<excludeFolder url="file://$MODULE_DIR$/vendor/qiwi/bill-payments-php-sdk" />
<excludeFolder url="file://$MODULE_DIR$/vendor/ralouphie/getallheaders" />
<excludeFolder url="file://$MODULE_DIR$/vendor/ramsey/collection" />
<excludeFolder url="file://$MODULE_DIR$/vendor/ramsey/uuid" />
<excludeFolder url="file://$MODULE_DIR$/vendor/reinink/remember-query-strings" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/cli-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/comparator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/complexity" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/diff" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/environment" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/exporter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/global-state" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/lines-of-code" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-enumerator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-reflector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/recursion-context" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/resource-operations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/type" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/version" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/data-transfer-object" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/enum" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/image" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/image-optimizer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/laravel-enum" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/laravel-medialibrary" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/laravel-permission" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/once" />
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/temporary-directory" />
<excludeFolder url="file://$MODULE_DIR$/vendor/swiftmailer/swiftmailer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/css-selector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/error-handler" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/finder" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-kernel" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/intl" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mime" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-ctype" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-iconv" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php72" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php73" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php80" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/process" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/routing" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-dumper" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/yaml" />
<excludeFolder url="file://$MODULE_DIR$/vendor/theseer/tokenizer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/tightenco/ziggy" />
<excludeFolder url="file://$MODULE_DIR$/vendor/tijsverkoyen/css-to-inline-styles" />
<excludeFolder url="file://$MODULE_DIR$/vendor/unitpay/php-sdk" />
<excludeFolder url="file://$MODULE_DIR$/vendor/vlucas/phpdotenv" />
<excludeFolder url="file://$MODULE_DIR$/vendor/voku/portable-ascii" />
<excludeFolder url="file://$MODULE_DIR$/vendor/vyuldashev/nova-permission" />
<excludeFolder url="file://$MODULE_DIR$/vendor/webmozart/assert" />
<excludeFolder url="file://$MODULE_DIR$/vendor/yoomoney/yookassa-sdk-php" />
<excludeFolder url="file://$MODULE_DIR$/vendor/yoomoney/yookassa-sdk-validator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/ysv/nova-leader" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

21
.php_cs.dist Normal file
View File

@@ -0,0 +1,21 @@
<?php
// Reference: http://cs.sensiolabs.org/
return PhpCsFixer\Config::create()
->setUsingCache(false)
->setRiskyAllowed(true)
->setRules([
'@PHP70Migration' => true,
'@PHP71Migration' => true,
'@PSR2' => true,
// '@Symfony' => true,
'array_syntax' => ['syntax' => 'short'],
'increment_style' => ['style' => 'post'],
'no_multiline_whitespace_before_semicolons' => true,
'not_operator_with_successor_space' => true,
'ordered_imports' => ['sortAlgorithm' => 'alpha'],
'semicolon_after_instruction' => false,
'strict_comparison' => true,
'yoda_style' => false,
]);

13
.styleci.yml Normal file
View File

@@ -0,0 +1,13 @@
php:
preset: laravel
disabled:
- no_unused_imports
finder:
not-name:
- index.php
- server.php
js:
finder:
not-name:
- webpack.mix.js
css: true

62
README.md Normal file
View File

@@ -0,0 +1,62 @@
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400"></a></p>
<p align="center">
<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p>
## About Laravel
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
Laravel is accessible, powerful, and provides tools required for large, robust applications.
## Learning Laravel
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
## Laravel Sponsors
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
### Premium Partners
- **[Vehikl](https://vehikl.com/)**
- **[Tighten Co.](https://tighten.co)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Cubet Techno Labs](https://cubettech.com)**
- **[Cyber-Duck](https://cyber-duck.co.uk)**
- **[Many](https://www.many.co.uk)**
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
- **[DevSquad](https://devsquad.com)**
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
- **[OP.GG](https://op.gg)**
## Contributing
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
## Code of Conduct
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
## Security Vulnerabilities
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
## License
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

View File

@@ -0,0 +1,92 @@
<?php
namespace App\Console\Commands;
use DB;
use Carbon\Carbon;
use Illuminate\Console\Command;
use App\Domain\Points\Models\Point;
use App\Domain\Points\Enums\DirectionEnum;
use App\Domain\Subscriptions\Models\Package;
use App\Domain\Subscriptions\Models\Subscription;
use App\Domain\Subscriptions\Service\SubscriptionService;
class AutoSubscribeApp extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'teaser:auto-subs-app';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Autosubscription to the site';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$plan = Package::findOrFail(1);
$price = $plan->price;
$lists = DB::table('subscriptions')
->join('users', 'subscriptions.user_id', '=', 'users.id')
->selectRaw('subscriptions.user_id, MAX(subscriptions.ends_at) as last_time, users.autosubscription_site')
->groupBy('subscriptions.user_id', 'users.autosubscription_site')
->havingRaw('MAX(subscriptions.ends_at) <= ?', [now()])
->having('users.autosubscription_site', true)
->get();
foreach($lists as $list){
$balance = SubscriptionService::calculate($list->user_id);
$ends_at = Carbon::now()->addMonths();
if ($price > $balance) {
echo 'Недостаточно средств ' . $list->user_id . PHP_EOL;
DB::table('users')
->where('id', $list->user_id)
->update(['autosubscription_site' => false]);
continue;
}
$sub = new Subscription;
$sub->user_id = $list->user_id;
$sub->package_id = $plan->id;
$sub->price = $price;
$sub->ends_at = $ends_at;
$sub->status = 'complete'; //YSV ENUM!
$sub->save();
$point = new Point;
$point->user_id =$list->user_id;
$point->point = $price;
$point->type = 'Оплата за подписку'; //YSV ENUM!
$point->direction = DirectionEnum::EXPENSE();
$point->save();
}
return 0;
}
}

View File

@@ -0,0 +1,182 @@
<?php
namespace App\Console\Commands;
use DB;
use App\Models\User;
use Illuminate\Console\Command;
use App\Domain\Points\Models\Point;
use App\Domain\Users\Models\UserPackage;
use App\Domain\Points\Enums\DirectionEnum;
use App\Notifications\UserCustomPaidSubscription;
use App\Domain\Subscriptions\Service\SubscriptionService;
class AutoSubscribePaidUsers extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'teaser:user-auto-subs';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Auto-subscription for paid users';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
\DB::beginTransaction();
$users_package_customers = DB::table('users_package_customers')
// ->join('users_subscribers', 'users_package_customers.customer_id', '=', 'users_subscribers.subscriber_id')
->join('users_subscribers', function ($join) {
$join
->on('users_package_customers.user_id', '=', 'users_subscribers.subscriber_id')
->where('users_subscribers.autosubscription', true);
})
//->select('users_package_customers.*', 'users_subscribers.user_id as userId', 'users_subscribers.subscriber_id as subscriberId', 'users_subscribers.autosubscription')
->select(DB::raw('MAX(users_package_customers.time_end) as last_time,users_package_customers.customer_id,users_package_customers.package_id','users_subscribers.autosubscription'))
->groupBy('users_package_customers.customer_id', 'users_package_customers.package_id', 'users_subscribers.autosubscription')
->havingRaw('MAX(users_package_customers.time_end) <= ?', [now()])
->get();
foreach ($users_package_customers as $user_package_customers) {
$userCustomer = User::find($user_package_customers->customer_id);
$userPackage = UserPackage::find($user_package_customers->package_id);
$userHeadPackage = User::find($userPackage->user_id);
$balance = SubscriptionService::calculate($userCustomer->id);
if ($userPackage->price > $balance) {
DB::table('users_subscribers')
->where('user_id', $userCustomer->id)
->where('subscriber_id', $userHeadPackage->id)
->update(['autosubscription' => DB::raw('NOT autosubscription')]);
continue;
}
DB::table('users_package_customers')->insert([
'user_id' => $userHeadPackage->id,
'customer_id' => $userCustomer->id,
'package_id' => $userPackage->id,
'price' => $userPackage->price,
'time_end' => now()->addMonths(),
//'time_end' => now()->addMinutes(10),
'created_at' => now(),
]);
$point = new Point;
$point->user_id = $userCustomer->id;
$point->point = $userPackage->price;
$point->type = 'Оформлена подписка на пользователя: ' . $userHeadPackage->name . ' (' . $userHeadPackage->username . ')'; //YSV ENUM!
$point->direction = DirectionEnum::EXPENSE();
$point->save();
$point = new Point;
$point->user_id = $userHeadPackage->id;
$point->point = $userPackage->price;
$point->type = 'Пользователь оформил платную подписку: ' . $userCustomer->name . ' (' . $userCustomer->username . ')'; //YSV ENUM!
$point->direction = DirectionEnum::COMING();
$point->save();
$message = [
'user_id' => $userCustomer->id,
'node_id' => null,
];
$userHeadPackage->notify(new UserCustomPaidSubscription($message));
}
\DB::commit();
// dd($users_package_customers);
return 0;
// max
// $users_package_customers = DB::table('users_package_customers')
// ->select(DB::raw('max(time_end) as last_time, avg(attempt_auto_paid) as attempt_auto_paid_avg,customer_id,package_id'))
// ->groupBy('customer_id', 'package_id')
// ->havingRaw('MAX(time_end) <= ?', [now()])
// ->havingRaw('AVG(attempt_auto_paid) < ?', [3])
// ->get();
// foreach ($users_package_customers as $users_package_customer) {
// $userCustomer = User::find($users_package_customer->customer_id);
// $userPackage = UserPackage::find($users_package_customer->package_id);
// $userHeadPackage = User::find($userPackage->user_id);
// $balance = SubscriptionService::calculate($userCustomer->id);
// if ($userPackage->price > $balance) {
// DB::table('users_package_customers')
// ->where('customer_id', $users_package_customer->customer_id)
// ->where('package_id', $users_package_customer->package_id)
// ->increment('attempt_auto_paid');
// continue;
// }
// DB::table('users_package_customers')->insert([
// 'user_id' => $userHeadPackage->id,
// 'customer_id' => $userCustomer->id,
// 'package_id' => $userPackage->id,
// 'price' => $userPackage->price,
// // 'time_end' => now()->addMonths(),
// 'time_end' => now()->addMinutes(10),
// 'created_at' => now(),
// ]);
// $point = new Point;
// $point->user_id = $userCustomer->id;
// $point->point = $userPackage->price;
// $point->type = 'Оформлена подписка на пользователя: ' . $userHeadPackage->username; //YSV ENUM!
// $point->direction = DirectionEnum::EXPENSE();
// $point->save();
// $point = new Point;
// $point->user_id = $userHeadPackage->id;
// $point->point = $userPackage->price;
// $point->type = 'Пользователь оформил платную подписку: ' . $userCustomer->username; //YSV ENUM!
// $point->direction = DirectionEnum::COMING();
// $point->save();
// $message = [
// 'user_id' => $userCustomer->id,
// 'node_id' => null,
// ];
// $userHeadPackage->notify(new UserCustomPaidSubscription($message));
// }
// return 0;
}
}

43
app/Console/Kernel.php Normal file
View File

@@ -0,0 +1,43 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
//
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('teaser:user-auto-subs')->weekly();
$schedule->command('teaser:auto-subs-app')->weekly();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Domain\Comments\Models;
use App\Models\User;
use App\Models\Model;
use App\Domain\Feeds\Models\Feed;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Domain\Complaints\Models\CommentComplaint;
class Comment extends Model
{
use SoftDeletes;
public function feed()
{
return $this->belongsTo(Feed::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function answer_to()
{
return $this->belongsTo(User::class, 'to_user_id');
}
public function parent()
{
return $this->belongsTo(Comment::class, 'parent_id');
}
public function children()
{
return $this->hasMany(Comment::class, 'parent_id');
}
public function complaints()
{
return $this->hasMany(CommentComplaint::class);
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Domain\Comments\Observers;
use App\Domain\Comments\Models\Comment;
class NovaCommentObserver
{
public function deleting(Comment $comment)
{
if(!$comment->trashed()){
$complaints = $comment->complaints;
foreach ($complaints as $complaint) {
$complaint->status = 'reviewed_bad';
$complaint->moderator_checking_id = auth()->id();
$complaint->save();
}
}
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Domain\Complaints\Models;
use App\Models\User;
use App\Models\Model;
use App\Domain\Comments\Models\Comment;
use App\Domain\Complaints\Models\Reason;
class CommentComplaint extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function moderator()
{
return $this->belongsTo(User::class, 'moderator_checking_id');
}
public function reason()
{
return $this->belongsTo(Reason::class);
}
public function comment()
{
return $this->belongsTo(Comment::class);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Domain\Complaints\Models;
use App\Domain\Feeds\Models\Feed;
use App\Models\Model;
use App\Models\User;
class Complaint extends Model
{
public static function boot()
{
parent::boot();
}
public function user()
{
return $this->belongsTo(User::class);
}
public function moderator()
{
return $this->belongsTo(User::class, 'moderator_checking_id');
}
public function reason()
{
return $this->belongsTo(Reason::class);
}
public function feed()
{
return $this->belongsTo(Feed::class);
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace App\Domain\Complaints\Models;
use App\Models\Model;
class Reason extends Model
{
public $timestamps = false;
}

View File

@@ -0,0 +1,14 @@
<?php
namespace App\Domain\Complaints\Observers;
use App\Domain\Complaints\Models\Complaint;
class ComplaintObserver
{
public function updating(Complaint $complaint)
{
if (empty($complaint->moderator_checking_id)) {
$complaint->moderator_checking_id = auth()->user()->id;
}
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace App\Domain\Feeds\Action;
use App\Domain\Feeds\ToFeedAction;
use App\Domain\Tags\Action\CreateTagAction;
class CreateFeedAction
{
public $tooFeedAction;
public $tagAction;
public function __construct(ToFeedAction $tooFeedAction, CreateTagAction $tagAction)
{
$this->tooFeedAction = $tooFeedAction;
$this->tagAction = $tagAction;
}
public function __invoke($dataFeed)
{
$feed = ($this->tooFeedAction)($dataFeed);
if(count($dataFeed->tags)){
$idsTag = ($this->tagAction)($dataFeed->tags);
$feed->tags()->sync($idsTag);
}
}
}

View File

@@ -0,0 +1,136 @@
<?php
namespace App\Domain\Feeds\DataTransferObjects;
use App\Domain\Feeds\Enums\CollectionMediaEnum;
use App\Domain\Feeds\Service\FeedMediaTransform;
use Spatie\DataTransferObject\DataTransferObject;
class FeedData extends DataTransferObject
{
public static function fromAds($feed)
{
$user = new \stdClass();
$user->id = 999999;
$user->name = 'Реклама';
$user->username = 'Реклама';
$user->color = '#795541';
$user->user_char = 'AD';
return [
'id' => $feed->id,
'type' => $feed->type,
'user' => (array)$user,
'entity' => self::fromDataAds($feed, CollectionMediaEnum::COMMON()),
];
}
public static function fromDataAds($feed, $collection_media_name)
{
$entity = (object) [];
$entity->title = $feed->title;
$entity->body = nl2br($feed->body);
$entity->views_count = $feed->views_count;
$entity->slug = $feed->slug;
$entity->type = $feed->type;
$entity->created_at_humans = $feed->created_at->diffForHumans();
$mediaTransform = (new FeedMediaTransform($feed))
->addCollectionMediaName($collection_media_name)
->spot();
$entity->preview = $mediaTransform['preview'];
$entity->collection_medias = $mediaTransform['medias'];
$entity->is_ads = true;
$entity->is_repost = false;
$entity->price = null;
$entity->is_paid = 0;
$entity->likes = 0;
$entity->liked = false;
$entity->tags = [];
$entity->status = 1;
$entity->comments = 0;
return $entity;
}
public static function fromDataBaseWithUser($feed, $purchased_subscriptions_by_users = [])
{
$feed_is_restrict = false;
$feed_is_restrict_name = '';
$feed_user_id = $feed->user_id;
$is_my_feed = false;
if(auth()->user()){
$is_my_feed = auth()->user()->id === $feed_user_id;
}
$feed_is_semi_paid = $feed->is_paid === 2;
// $is_adult_feed = false;
// $is_my_settings_adult_restrict = auth()->user()->allow_adult_content;
$restrict_feed_adult = false;
// if(($is_my_settings_adult_restrict === false && $is_adult_feed) && $is_my_feed === false){
// $feed_is_restrict_name = 'adults';
// $restrict_feed_adult = true;
// }
$private_user_feed = $feed->user->private;
$restrict_feed_private_account = false;
if(($feed_is_semi_paid && $private_user_feed && !in_array($feed_user_id, $purchased_subscriptions_by_users)) && $is_my_feed === false){
$feed_is_restrict_name = 'prohibited';
$restrict_feed_private_account = true;
}
if($restrict_feed_adult || $restrict_feed_private_account){
$feed_is_restrict = true;
}
$user = $feed->user->only('id', 'name', 'username', 'photo_path', 'color', 'user_char', 'private');
return [
'id' => $feed->id,
'type' => $feed_is_restrict ? $feed_is_restrict_name : $feed->type,
'user' => $user,
'entity' => $feed_is_restrict ? null : self::fromData($feed, CollectionMediaEnum::COMMON()),
];
}
public static function fromData($feed, $collection_media_name)
{
$entity = (object) [];
$entity->title = $feed->title;
$entity->body = $feed->body;
$entity->views_count = $feed->views_count;
$entity->price = $feed->price;
$entity->is_paid = $feed->is_paid;
$entity->is_ads = false;
// $entity->is_adult = $feed->is_adult;
$entity->slug = $feed->slug;
$entity->type = $feed->type;
$entity->is_repost = $feed->is_repost;
$entity->likes = $feed->likes_count;
$entity->liked = $feed->liked ?? false;
$entity->tags = $feed->tags;
$entity->status = $feed->status;
$entity->comments = $feed->comments_count;
$entity->created_at_humans = $feed->created_at->diffForHumans();
$mediaTransform = (new FeedMediaTransform($feed))
->addCollectionMediaName($collection_media_name)
->spot();
$entity->preview = $mediaTransform['preview'];
$entity->collection_medias = $mediaTransform['medias'];
return $entity;
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Domain\Feeds\DataTransferObjects;
use Spatie\DataTransferObject\DataTransferObjectCollection;
class FeedDataCollection extends DataTransferObjectCollection
{
public static function create(array $data)
{
return new static(FeedData::arrayOf($data));
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Domain\Feeds\Enums;
use Spatie\Enum\Laravel\Enum;
/**
* @method static self PREVIEW()
* @method static self PAID()
* @method static self COMMON()
*/
final class CollectionMediaEnum extends Enum
{
protected static function values(): array
{
return [
'PREVIEW' => 'preview',
'PAID' => 'paid',
'COMMON' => 'common',
];
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Domain\Feeds\Enums;
use Spatie\Enum\Laravel\Enum;
/**
* @method static self PENDING()
* @method static self APPROVED()
* @method static self BANNED()
* @method static self EDITABLE()
*/
final class StatusEnum extends Enum
{
protected static function values(): array
{
return [
'PENDING' => 0,
'APPROVED' => 1,
'BANNED' => 2,
'EDITABLE' => 3,
];
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace App\Domain\Feeds\Models;
use App\Models\User;
use App\Models\Model;
use App\Domain\Tags\Models\Tag;
use Spatie\MediaLibrary\HasMedia;
use App\Domain\Feeds\Enums\StatusEnum;
use App\Domain\Comments\Models\Comment;
use App\Domain\Complaints\Models\Complaint;
use Spatie\MediaLibrary\InteractsWithMedia;
use App\Domain\Feeds\Observers\FeedObserver;
use Illuminate\Database\Eloquent\SoftDeletes;
class Feed extends Model implements HasMedia
{
use InteractsWithMedia, SoftDeletes;
public function getUserTypeAttribute()
{
return $this->user->type;
}
protected $casts = [
'is_paid' => 'integer',
'is_ads' => 'boolean',
'status' => StatusEnum::class,
];
protected static function boot()
{
parent::boot();
self::observe(FeedObserver::class);
}
public function feedable()
{
return $this->morphTo();
}
public function tags()
{
return $this->belongsToMany(Tag::class, 'feed_tags');
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function views()
{
return $this->belongsToMany(User::class, 'users_feeds_view');
}
public function likes()
{
return $this->belongsToMany(User::class, 'users_feeds_like');
}
public function user()
{
return $this->belongsTo(User::class);
}
public function who_boughts()
{
return $this->belongsToMany(User::class, 'user_feed_purchase')->withPivot('amount')->withTimestamps();
}
public function complaints()
{
return $this->hasMany(Complaint::class);
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Domain\Feeds\Observers;
use Illuminate\Support\Str;
use App\Domain\Feeds\Models\Feed;
use App\Events\FeedAddProcessed;
use App\Events\FeedRemoveProcessed;
use App\Events\FeedUpdateProcessed;
class FeedObserver
{
public function creating(Feed $feed)
{
$uuid = (string) Str::uuid();
$feed->slug = $uuid . '_' . $feed->type;
}
public function created(Feed $feed)
{
FeedAddProcessed::dispatch($feed);
}
public function deleted(Feed $feed)
{
FeedRemoveProcessed::dispatch($feed);
}
// public function forceDeleted(Feed $feed)
// {
// dd('forceDeleted');
// }
public function updated(Feed $feed)
{
FeedUpdateProcessed::dispatch($feed);
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Domain\Feeds\Observers;
use App\Models\User;
use App\Domain\Feeds\Models\Feed;
class NovaFeedAdsObserver
{
public function creating(Feed $feed){
if(str_contains( request()->getPathInfo(), '/nova-api/feed-ads')){
$user = User::system();
$feed->user_id = $user->id;
$feed->is_ads = true;
$feed->created_at = now();
$feed->updated_at = now();
}
}
}

View File

@@ -0,0 +1,61 @@
<?php
namespace App\Domain\Feeds\Observers;
use App\Domain\Feeds\Models\Feed;
use App\Notifications\RemoveFeed;
use App\Domain\Feeds\Enums\StatusEnum;
use App\Notifications\BannedMessageFeed;
class NovaFeedObserver
{
public function updating(Feed $feed)
{
$oldStatus = $feed->getOriginal('status');
$newStatus = $feed->status;
if(($oldStatus === StatusEnum::PENDING() || $oldStatus === StatusEnum::EDITABLE()) && $newStatus === StatusEnum::BANNED()){
$user = $feed->user;
$message = [
'user_id' => $user->id,
'node_id' => $feed->id,
'text' => $feed->status_note,
'success' => false
];
$user->notify(new BannedMessageFeed($message));
}
if(($oldStatus === StatusEnum::PENDING() || $oldStatus === StatusEnum::EDITABLE()) && $newStatus === StatusEnum::APPROVED()){
$user = $feed->user;
$message = [
'user_id' => $user->id,
'node_id' => $feed->id,
'text' => $feed->status_note,
'success' => true
];
$user->notify(new BannedMessageFeed($message));
$feed->status_note = '';
}
}
public function deleting(Feed $feed)
{
if(!$feed->trashed()){
$complaints = $feed->complaints;
foreach ($complaints as $complaint) {
$complaint->status = 'reviewed_bad';
$complaint->moderator_checking_id = auth()->id();
$complaint->save();
}
$user = $feed->user;
$message = [
'user_id' => $user->id,
'node_id' => $feed->id,
];
$user->notify(new RemoveFeed($message));
}
}
}

View File

@@ -0,0 +1,262 @@
<?php
namespace App\Domain\Feeds\Queries;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Feeds\Enums\StatusEnum;
use Illuminate\Database\Eloquent\Builder;
use App\Domain\Feeds\DataTransferObjects\FeedData;
use App\Domain\Subscriptions\Service\SubscriptionService;
class FeedQueryBuilder
{
const PAGINATION_COUNT = 10;
public $feed;
public $pagination = true;
public $onlyActiveFeed = true;
public $nextCursor;
public $is_ads = false;
public $hasPages;
public function __construct($query = null)
{
if($query){
$this->feed = $query;
}else{
$this->feed = Feed::query();
}
}
public function enableAdvertising()
{
$this->is_ads = true;
return $this;
}
public function search($filters)
{
$this->feed->when($filters['search'] ?? null, function ($query, $search) {
$query->where(function ($query) use ($search) {
$query->where('title', 'ilike', '%'.$search.'%')
->orWhere('body', 'ilike', '%'.$search.'%');
});
});
return $this;
}
public function addTags($tags)
{
$this->feed->whereHas('tags', function (Builder $query) use($tags) {
$query->whereIn('id', $tags);
});
return $this;
}
public function addType($type)
{
if($type == 'image'){
//$this->feed->whereHasMorph('feedable', [Image::class]);
$this->feed->where('type', 'images');
}
if($type == 'video'){
// $this->feed->whereHasMorph('feedable', [Video::class]);
$this->feed->where('type', 'videos');
}
if($type == 'music'){
//$this->feed->whereHasMorph('feedable', [Music::class]);
$this->feed->where('type', 'musics');
}
return $this;
}
public function filter($filter = null)
{
if($filter === 'hot'){
return $this->order('likes_count');
}
return $this->order();
}
public function order($by = null)
{
if($by){
$this->feed->orderBy($by, 'desc');
}else{
$this->feed->orderBy('id', 'desc');
}
return $this;
}
public function selectBy($where, $by)
{
$this->feed->where($where, $by);
return $this;
}
public function selectByIds($ids)
{
if(is_array($ids)){
$this->feed->whereIn('id', $ids);
}else{
$this->feed->where('id', $ids);
}
return $this;
}
public function withTrashed() {
$this->feed->withTrashed();
return $this;
}
public function disableActiveFeed()
{
$this->onlyActiveFeed = false;
return $this;
}
public function disablePaginate()
{
$this->pagination = false;
return $this;
}
public function getData()
{
if($this->onlyActiveFeed){
$this->feed = $this->feed->where('status', StatusEnum::APPROVED());
}
$this->feed = $this->feed->withCount([
'comments',
'likes',
]);
if(auth()->user()){
$this->feed = $this->feed
->withCount(['likes as liked' => function (Builder $query) {
$query->where('user_id', auth()->user()->id);
}])
->withCasts(['liked' => 'boolean']);
}
if($this->pagination){
$this->feed = $this->feed->cursorPaginate(self::PAGINATION_COUNT);
$this->getCursorHash();
}else{
$this->feed = $this->feed->get();
}
return $this;
}
protected function getCursorHash()
{
$this->hasPages = $this->feed->hasMorePages();
$this->nextCursor = get_cursor_hash($this->feed);
}
public function withTags()
{
$this->feed->with('tags:id,name,slug');
return $this;
}
public function withUser()
{
$this->feed->with('user:id,first_name,last_name,username,photo_path,color,user_char,private');
return $this;
}
public function withFeedable()
{
// $this->feed->with('media');
// :id,model_type,model_id,name,file_name,collection_name,custom_properties
if(auth()->user()){
$this->feed->withCount('media')
->with(['media' => function($query){
// withCount('likes')->withCasts(['likes_count' => 'boolean']);
$query->withCount(['likes' => function (Builder $query) {
$query->where('user_id', auth()->user()->id);
}])->withCasts(['likes_count' => 'boolean']);
}]);
}else{
$this->feed->with('media');
}
return $this;
// $this->feed->with('feedable', function (MorphTo $morphTo) {
// $morphTo->morphWith([
// Image::class => ['media'],
// Video::class => ['media'],
// Music::class => ['media'],
// ]);
// });
// return $this;
}
public function transformData()
{
$feed_collect = collect();
if(auth()->user()){
$purchased_subscriptions_by_users = \DB::table('users_package_customers')
->where('customer_id', auth()->user()->id)
->where('time_end', '>', now())
->pluck('user_id')->toArray();
}else{
$purchased_subscriptions_by_users = [];
}
foreach ($this->feed as $feed) {
$feed = FeedData::fromDataBaseWithUser($feed, $purchased_subscriptions_by_users);
if($feed['entity']){
$feed['entity']->tags->transform(function ($item) {
return [
'id' => $item->id,
'name' => $item->name,
'slug' => $item->slug,
];
});
}
$feed_collect[] = $feed;
}
if(auth()->check()){
$subscription_purchased = SubscriptionService::activeSubscription();
if($subscription_purchased == false){
$adsMedia = Feed::where('is_ads', true)->with('media')->inRandomOrder()->first();
if($adsMedia && $this->is_ads){
$adsMediaData = FeedData::fromAds($adsMedia);
$feed_collect->splice(4, 0, [$adsMediaData]);
}
}
}
return $feed_collect;
}
public function build()
{
$this
->withFeedable()
->withUser()
->withTags()
->getData();
return $this;
}
public function transformGet()
{
return $this
->withFeedable()
->withUser()
->withTags()
->getData()->transformData();
}
}

View File

@@ -0,0 +1,139 @@
<?php
namespace App\Domain\Feeds\Service;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Feeds\Enums\CollectionMediaEnum;
class FeedMediaTransform
{
public $feed;
public $type;
public $typeUrl = 'web';
public $collection_name;
public function __construct(Feed $feed)
{
$this->feed = $feed;
$this->type = $feed->type;
}
public function getFullPath()
{
$this->typeUrl = 'disk';
return $this;
}
public function paid()
{
return $this->addCollectionMediaName(CollectionMediaEnum::PAID());
}
public function default()
{
return $this->addCollectionMediaName(CollectionMediaEnum::COMMON());
}
public function addCollectionMediaName($collection_name)
{
$this->collection_name = $collection_name;
return $this;
}
public function spot()
{
if($this->type === 'images'){
return $this->images();
}
if($this->type === 'videos'){
return $this->videos();
}
if($this->type === 'musics'){
return $this->musics();
}
}
public function videos()
{
$collection = [];
$medias = $this->feed->getMedia($this->collection_name);
$medias->each(function ($item) use (&$collection) {
$collection[] = [
'url' => $this->typeUrl === 'web' ? $item->getFullUrl() : $item->getPath(),
'id' => $item->id,
];
});
return [
'preview' => $this->getPreview(),
'medias' => $collection,
];
}
public function images()
{
$collection = [];
$medias = $this->feed->getMedia($this->collection_name);
$medias->each(function ($item) use (&$collection) {
$collection[] = [
'url' => $this->typeUrl === 'web' ? $item->getFullUrl() : $item->getPath(),
'id' => $item->id,
];
});
return [
'preview' => $this->getPreview(),
'medias' => $collection,
];
}
public function musics()
{
$collection = [];
$medias = $this->feed->getMedia($this->collection_name);
$medias->each(function ($item) use (&$collection) {
$collection[] = [
'url' => $this->typeUrl === 'web' ? $item->getFullUrl() : $item->getPath(),
'name' => $item->name,
'playing' => false,
'liked' => $item->likes_count ?? false,
'time' => $item->getCustomProperty('time'),
'id' => $item->id,
];
});
return [
'preview' => $this->getPreview(),
'medias' => $collection,
];
}
public function getPreview($type = 0)
{
if($this->type === 'images'){
$img_preview = $this->feed->getMedia($this->collection_name)->first();
if($img_preview){
if($type){
return $img_preview;
}
return $img_preview->getFullUrl();
}
}
$preview = $this->feed->getMedia(CollectionMediaEnum::PREVIEW());
if($type){
return $preview->count() ? $preview->first() : null;
}
return $preview->count() ? $preview->first()->getFullUrl() : null;
}
public function getPreviewObject()
{
$preview = $this->getPreview(1);
if($preview){
return [ 'id'=> $preview->id, 'url' => $preview->getFullUrl() ];
}
return null;
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Domain\Feeds\Service;
use App\Domain\Feeds\DataTransferObjects\FeedData;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Images\Models\Image;
use App\Domain\Musics\Models\Music;
use App\Domain\Videos\Models\Video;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Builder;
class FeedService
{
public static function list($users, $where = null, $only = null)
{
$users_id = $users->pluck('id')->toArray();
$feeds = Feed::query();
if ($where) {
$feeds = $feeds->where('id', '<', $where);
}
if($only){
if($only == 'image'){
//$feeds = $feeds->whereHasMorph('feedable', [Image::class]);
$feeds = $feeds->where('type', 'images');
}
if($only == 'video'){
//$feeds = $feeds->whereHasMorph('feedable', [Video::class]);
$feeds = $feeds->where('type', 'videos');
}
if($only == 'music'){
//$feeds = $feeds->whereHasMorph('feedable', [Music::class]);
$feeds = $feeds->where('type', 'musics');
}
}
$feeds = $feeds->whereIn('user_id', $users_id)
->orderBy('id', 'desc')
->limit(10)
->withCount([ 'comments', 'likes', 'likes as liked' => function (Builder $query) {
$query->where('user_id', auth()->user()->id);
}])
->withCasts(['liked' => 'boolean'])
->with('tags', 'media')->get();
$feed_collect = collect();
foreach ($feeds as $feed) {
$feed = FeedData::fromDataBase($feed, $users);
$feed['entity']->tags->transform(function ($item) {
return [
'id' => $item->id,
'name' => $item->name,
'slug' => $item->slug,
];
});
$feed_collect[] = $feed;
}
return $feed_collect;
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Domain\Feeds\Service;
use DB;
class LiveFeed
{
public static function addBySub($user)
{
$userID = $user->id;
$userFeeds = $user->feeds()->pluck('created_at', 'id')->transform(function ($item) {
return ['times' => $item->getTimestamp()];
})->toArray();
$add_posts = [];
foreach ($userFeeds as $feedID => $userFeed) {
$add_posts[] = [
'feed_id' => $feedID,
'user_id' => auth()->user()->id,
'home_user_id' => $userID,
'times' => $userFeed['times'],
];
}
DB::table('users_live_feeds')->insertOrIgnore($add_posts);
}
public static function removeBySub($user)
{
$userID = $user->id;
DB::table('users_live_feeds')
->where('home_user_id', $userID)
->where('user_id', auth()->user()->id)
->delete();
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace App\Domain\Feeds;
interface ToFeedAction
{
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Domain\Images\Action;
use DB;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Feeds\ToFeedAction;
use App\Domain\Images\DataTransferObjects\ImageData;
class CreateImageAction implements ToFeedAction
{
public function __invoke(ImageData $imageData)
{
DB::beginTransaction();
$imageFeed = Feed::create([
'title' => $imageData->title,
'body' => $imageData->body,
'price' => $imageData->price,
'is_paid' => $imageData->is_paid,
'user_id' => $imageData->user->id,
'is_ads' => false,
'type' => 'images',
]);
foreach ($imageData->photos as $photo) {
$imageFeed->addMedia($photo)->toMediaCollection('common');
}
if($imageData->is_loaded_photos_paid){
foreach ($imageData->photos_paid as $photo) {
$imageFeed->addMedia($photo)->toMediaCollection('paid');
}
}
DB::commit();
return $imageFeed;
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace App\Domain\Images\Action;
use DB;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Feeds\ToFeedAction;
use App\Domain\Feeds\Enums\StatusEnum;
use App\Domain\Images\DataTransferObjects\ImageData;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
class UpdateImageAction implements ToFeedAction
{
public $imageFeed;
public function __construct(Feed $imageFeed)
{
$this->imageFeed = $imageFeed;
}
public function __invoke(ImageData $imageData)
{
$status = $this->imageFeed->status;
if($status === StatusEnum::BANNED()){
$status = StatusEnum::EDITABLE();
}
if($status === StatusEnum::APPROVED()){
$status = StatusEnum::EDITABLE();
}
DB::beginTransaction();
$this->imageFeed->fill([
'title' => $imageData->title,
'body' => $imageData->body,
'price' => $imageData->price,
'is_paid' => $imageData->is_paid,
'status' => $status,
'is_ads' => false,
])->save();
if($imageData->is_loaded_photos){
foreach ($imageData->photos as $photo) {
$this->imageFeed->addMedia($photo)->toMediaCollection('common');
}
}
if($imageData->is_loaded_photos_paid){
foreach ($imageData->photos_paid as $photo) {
$this->imageFeed->addMedia($photo)->toMediaCollection('paid');
}
}
if(count($imageData->removedItems)){
foreach ($imageData->removedItems as $removedItem) {
if($media = Media::find($removedItem)){
$media->delete();
}
}
}
DB::commit();
return $this->imageFeed->refresh();
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Domain\Images\DataTransferObjects;
use App\Http\Requests\ImageFormRequest;
use Spatie\DataTransferObject\DataTransferObject;
class ImageData extends DataTransferObject
{
public $title;
public $body;
public $user;
public $photos;
public $price;
public $tags;
public $is_paid;
public $is_loaded_photos_paid;
public $is_loaded_photos;
public $photos_paid;
public $removedItems;
public static function fromRequest(ImageFormRequest $request)
{
return new self([
'title' => $request->input('title'),
'body' => $request->input('body'),
'price' => $request->input('price'),
'is_paid' => $request->input('is_paid'),
'user' => auth()->user(),
'tags' => $request->input('tags') ?? [],
'photos' => $request->file('photos'),
'is_loaded_photos' => $request->hasFile('photos'),
'photos_paid' => $request->file('photos_paid'),
'is_loaded_photos_paid' => $request->hasFile('photos_paid'),
'removedItems' => $request->input('removedItems') ?? [],
]);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Domain\Images\Models;
use App\Domain\Complaints\Models\Complaint;
use App\Domain\Feeds\Models\Feed;
use App\Models\Model;
use App\Models\User;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
class Image extends Model implements HasMedia
{
use InteractsWithMedia;
public function feed()
{
return $this->morphOne(Feed::class, 'feedable');
}
public function complaints()
{
return $this->morphMany(Complaint::class, 'complaintable');
}
public function user()
{
return $this->belongsTo(User::class);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Domain\Images\Observers;
use App\Domain\Images\Models\Image;
class ImageObserver
{
public function creating(Image $image)
{
$image->slug = 'image_' . uniqid();
}
public function deleting(Image $image)
{
$image->feed()->delete();
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Domain\Medias\Models;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
class TeaserMedia extends Media
{
protected $table = 'media';
public function likes()
{
return $this->belongsToMany(\App\Models\User::class, 'user_audio_like', 'media_id', 'user_id');
}
}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Domain\Messenger\Models;
use App\Models\User;
use App\Models\Model;
class ChatRoom extends Model
{
public function messsages()
{
return $this->hasMany(Message::class)->orderBy('created_at', 'desc');
}
public function latestMessage()
{
return $this->hasOne(Message::class)->latestOfMany();
}
public function users()
{
return $this->belongsToMany(User::class, 'user_chat_room');
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Domain\Messenger\Models;
use App\Models\User;
use App\Models\Model;
use App\Domain\Messenger\Models\ChatRoom;
class Message extends Model
{
// protected $touches = ['room'];
public function user()
{
return $this->belongsTo(User::class);
}
public function room()
{
return $this->belongsTo(ChatRoom::class, 'chat_room_id');
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace App\Domain\Musics\Action;
use DB;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Feeds\ToFeedAction;
use App\Domain\Musics\DataTransferObjects\MusicData;
class CreateMusicAction implements ToFeedAction
{
public function __invoke(MusicData $musicData)
{
DB::beginTransaction();
if(empty($musicData->title)){
$file_count = count($musicData->musics);
$first_file = $musicData->musics[0]->getClientOriginalName();
$filename = pathinfo($first_file, PATHINFO_FILENAME);
$musicData->title = $filename . ' (' . $file_count . ')';
}
$musicFeed = Feed::create([
'title' => $musicData->title,
'body' => $musicData->body,
'price' => $musicData->price,
'is_paid' => $musicData->is_paid,
'user_id' => $musicData->user->id,
'is_ads' => false,
'type' => 'musics',
]);
$result_time_common = $this->calcTimeFile($musicData->times);
foreach ($musicData->musics as $music) {
$name = $music->getClientOriginalName();
$time = @$result_time_common[$name];
$musicFeed->addMedia($music)
->withCustomProperties(['time' => $time])
->toMediaCollection('common');
}
if($musicData->is_loaded_preview){
$musicFeed->addMedia($musicData->preview)->toMediaCollection('preview');
}
if($musicData->is_loaded_paid_music){
$result_time_paids = $this->calcTimeFile($musicData->times_paid);
foreach ($musicData->musics_paid as $music) {
$name = $music->getClientOriginalName();
$time = @$result_time_paids[$name];
$musicFeed->addMedia($music)
->withCustomProperties(['time' => $time])
->toMediaCollection('paid');
}
}
DB::commit();
return $musicFeed;
}
protected function calcTimeFile($time_musics)
{
$times = array_map(function($line){
$line = explode(',', $line);
return [$line[0] => $line[1]];
}, $time_musics);
return array_merge(...$times);
}
}

View File

@@ -0,0 +1,95 @@
<?php
namespace App\Domain\Musics\Action;
use DB;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Feeds\ToFeedAction;
use App\Domain\Feeds\Enums\StatusEnum;
use App\Domain\Musics\DataTransferObjects\MusicData;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
class UpdateMusicAction implements ToFeedAction
{
public $musicFeed;
public function __construct(Feed $musicFeed)
{
$this->musicFeed = $musicFeed;
}
public function __invoke(MusicData $musicData)
{
$status = $this->musicFeed->status;
if($status === StatusEnum::BANNED()){
$status = StatusEnum::EDITABLE();
}
if($status === StatusEnum::APPROVED()){
$status = StatusEnum::EDITABLE();
}
DB::beginTransaction();
$this->musicFeed->fill([
'title' => $musicData->title,
'body' => $musicData->body,
'price' => $musicData->price,
'is_paid' => $musicData->is_paid,
'is_ads' => false,
'status' => $status,
])->save();
if($musicData->is_loaded_preview){
if($existPreview = $this->musicFeed->getMedia('preview')->first()){
$existPreview->delete();
}
$this->musicFeed->addMedia($musicData->preview)->toMediaCollection('preview');
}
if($musicData->is_loaded_music){
$result_time_common = $this->calcTimeFile($musicData->times);
foreach ($musicData->musics as $music) {
$name = $music->getClientOriginalName();
$time = @$result_time_common[$name];
$this->musicFeed->addMedia($music)
->withCustomProperties(['time' => $time])
->toMediaCollection('common');
}
}
if($musicData->is_loaded_paid_music){
$result_time_paids = $this->calcTimeFile($musicData->times_paid);
foreach ($musicData->musics_paid as $music) {
$name = $music->getClientOriginalName();
$time = @$result_time_paids[$name];
$this->musicFeed->addMedia($music)
->withCustomProperties(['time' => $time])
->toMediaCollection('paid');
}
}
if(count($musicData->removedItems)){
foreach ($musicData->removedItems as $removedItem) {
if($media = Media::find($removedItem)){
$media->delete();
}
}
}
DB::commit();
return $this->musicFeed->refresh();
}
protected function calcTimeFile($time_musics)
{
$times = array_map(function($line){
$line = explode(',', $line);
return [$line[0] => $line[1]];
}, $time_musics);
return array_merge(...$times);
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace App\Domain\Musics\DataTransferObjects;
use App\Http\Requests\MusicFormRequest;
use Spatie\DataTransferObject\DataTransferObject;
class MusicData extends DataTransferObject
{
public $title;
public $body;
public $user;
public $musics;
public $musics_paid;
public $preview;
public $is_loaded_music;
public $is_loaded_paid_music;
public $is_loaded_preview;
public $price;
public $times;
public $times_paid;
public $is_paid;
public $tags;
public $removedItems;
public static function fromRequest(MusicFormRequest $request)
{
return new self([
'title' => $request->input('title'),
'body' => $request->input('body'),
'price' => $request->input('price'),
'is_paid' => $request->input('is_paid'),
'user' => auth()->user(),
'tags' => $request->input('tags') ?? [],
'preview' => $request->file('preview'),
'is_loaded_preview' => $request->hasFile('preview'),
'musics' => $request->file('musics'),
'is_loaded_music' => $request->hasFile('musics'),
'musics_paid' => $request->file('musics_paid'),
'is_loaded_paid_music' => $request->hasFile('musics_paid'),
'times' => $request->input('times'),
'times_paid' => $request->input('times_paid'),
'removedItems' => $request->input('removedItems') ?? [],
]);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace App\Domain\Musics\Models;
use App\Domain\Complaints\Models\Complaint;
use App\Domain\Feeds\Models\Feed;
use App\Models\Model;
use App\Models\User;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
class Music extends Model implements HasMedia
{
use InteractsWithMedia;
protected $table = 'musics';
public function complaints()
{
return $this->morphMany(Complaint::class, 'complaintable');
}
public function feed()
{
return $this->morphOne(Feed::class, 'feedable');
}
public function user()
{
return $this->belongsTo(User::class);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Domain\Musics\Observers;
use App\Domain\Musics\Models\Music;
class MusicObserver
{
public function creating(Music $music)
{
$music->slug = 'music_' . uniqid();
}
public function deleting(Music $music)
{
$music->feed()->delete();
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace App\Domain\PaymentGateway\Models;
use App\Models\User;
use App\Models\Model;
use Illuminate\Support\Str;
class PaymentGatewayOrder extends Model
{
const TYPE_INTERKASSA_NAME = "interkassa";
const TYPE_UNITPAY_NAME = "unitpay";
const TYPE_QIWI_NAME = "qiwi";
const TYPE_YOO_NAME = "yookassa";
public function user()
{
return $this->belongsTo(User::class);
}
public static function interkassa($amount)
{
$paymentGatewayOrder = new PaymentGatewayOrder;
$paymentGatewayOrder->user_id = auth()->user()->id;
$paymentGatewayOrder->amount = $amount;
$paymentGatewayOrder->status = 0; // 0 - created/ 1- success/ 2-error/ 3-pending
$paymentGatewayOrder->type = self::TYPE_INTERKASSA_NAME;
$paymentGatewayOrder->save();
return $paymentGatewayOrder;
}
public static function unitpay($amount)
{
$paymentGatewayOrder = new PaymentGatewayOrder;
$paymentGatewayOrder->user_id = auth()->user()->id;
$paymentGatewayOrder->amount = $amount;
$paymentGatewayOrder->status = 0; // 0 - created/ 1- success/ 2-error/ 3-pending
$paymentGatewayOrder->type = self::TYPE_UNITPAY_NAME;
$paymentGatewayOrder->save();
return $paymentGatewayOrder;
}
public static function qiwi($amount)
{
$paymentGatewayOrder = new PaymentGatewayOrder;
$paymentGatewayOrder->user_id = auth()->user()->id;
$paymentGatewayOrder->amount = $amount;
$paymentGatewayOrder->number = (string) Str::uuid();
$paymentGatewayOrder->status = 0; // 0 - created/ 1- success/ 2-error/ 3-pending
$paymentGatewayOrder->type = self::TYPE_QIWI_NAME;
$paymentGatewayOrder->save();
return $paymentGatewayOrder;
}
public static function yookassa($amount)
{
$paymentGatewayOrder = new PaymentGatewayOrder;
$paymentGatewayOrder->user_id = auth()->user()->id;
$paymentGatewayOrder->amount = $amount;
$paymentGatewayOrder->number = (string) Str::uuid();
$paymentGatewayOrder->status = 0; // 0 - created/ 1- success/ 2-error/ 3-pending
$paymentGatewayOrder->type = self::TYPE_YOO_NAME;
$paymentGatewayOrder->save();
return $paymentGatewayOrder;
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Domain\PaymentGateway\Services;
class InterkassaService
{
public static function payments_link($amount, $order_id)
{
$configuration = new \Interkassa\Helper\Config();
$configuration->setCheckoutSecretKey(env('INTERKASSA_SECRET_KEY'));
$configuration->setAuthorizationKey(env('INTERKASSA_AUTH_KEY'));
$configuration->setAccountId(env('INTERKASSA_ACCOUNT_ID'));
$SDKClient = new \Interkassa\Interkassa($configuration);
$invoiceRequest = new \Interkassa\Request\GetInvoiceRequest();
$invoiceRequest
->setCheckoutId(env('INTERKASSA_ID'))
->setPaymentNumber($order_id)
->setAmount($amount)
->setCurrency('RUB')
->setDescription('Пополнение баланса');
return $SDKClient->makeInvoiceSciLink($invoiceRequest);
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Domain\PaymentGateway\Services;
class QiwiService
{
public static function payments_link($amount, $order, $user)
{
$publicKey = env('QIWI_PUBLIC');
$SECRET_KEY = env('QIWI_SECRET');
$billPayments = new \Qiwi\Api\BillPayments($SECRET_KEY);
$success_url = env('APP_URL') . '/qiwi-to-payments/status/' . $order->number;
$params = [
'publicKey' => $publicKey,
'amount' => $amount,
'billId' => $order->number,
'successUrl' => $success_url,
'email' => $user->email,
'comment' => 'Пополнение баланса',
];
return $billPayments->createPaymentForm($params);
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Domain\PaymentGateway\Services;
class QiwiService
{
public static function payments_link($amount, $order, $user)
{
$publicKey = '48e7qUxn9T7RyYE1MVZswX1FRSbE6iyCj2gCRwwF3Dnh5XrasNTx3BGPiMsyXQFNKQhvukniQG8RTVhYm3iPvros6VXmW3DSrABXJ5twJd5AUuZNxHcF4mREk3SV8dCpRwUz5wXBCEYnwDxM2E6ABmYnifP7VWAeUs639FSpb7BApdN8giv9qiN3Pfa9a';
$SECRET_KEY = 'eyJ2ZXJzaW9uIjoiUDJQIiwiZGF0YSI6eyJwYXlpbl9tZXJjaGFudF9zaXRlX3VpZCI6InAwOGxmMS0wMCIsInVzZXJfaWQiOiI3OTAyOTI0MDM2NCIsInNlY3JldCI6ImE1MmJhZWEwZDBiMGVlMzI2ZTU4OWU1MGNiZDY1YzRkYjE0MTFhMmViYWJjNGVlNDA3ZjMwYjE1NGY3NzI0ZGYifX0=';
$billPayments = new \Qiwi\Api\BillPayments($SECRET_KEY);
$success_url = env('APP_URL') . '/qiwi-to-payments/status/' . $order->number;
$params = [
'publicKey' => $publicKey,
'amount' => $amount,
'billId' => $order->number,
'successUrl' => $success_url,
'email' => $user->email,
'comment' => 'Пополнение баланса',
];
return $billPayments->createPaymentForm($params);
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace App\Domain\PaymentGateway\Services;
use UnitPay;
use CashItem;
class UnitpayService
{
public static function payments_link($amount, $order_id)
{
// Project Data
$domain = 'unitpay.ru';// Your working domain: unitpay.ru or address provided by unitpay support service
$secretKey = '72449d551500fb99bb66499203ed1ccb';// Project secret key
$publicId = 'demo';
// $publicId = '438925-9eafe';
// My item Info
$itemName = 'Пополнение баланса';
// My Order Data
$orderId = $order_id;
$orderSum = $amount;
$orderDesc = 'Payment for item "' . $itemName . '"';
$orderCurrency = 'RUB';
$unitpay = new UnitPay($domain, $secretKey);
// ->setCustomerEmail('customer@domain.com')
// ->setCustomerPhone('79001235555')
$unitpay
->setBackUrl('https://teeaseer.com')
->setCashItems([
new CashItem($itemName, 1, $orderSum)
]);
$redirectUrl = $unitpay->form(
$publicId,
$orderSum,
$orderId,
$orderDesc,
$orderCurrency
);
return $redirectUrl;
// $configuration = new \Interkassa\Helper\Config();
// $configuration->setCheckoutSecretKey(env('INTERKASSA_SECRET_KEY'));
// $configuration->setAuthorizationKey(env('INTERKASSA_AUTH_KEY'));
// $configuration->setAccountId(env('INTERKASSA_ACCOUNT_ID'));
// $SDKClient = new \Interkassa\Interkassa($configuration);
// $invoiceRequest = new \Interkassa\Request\GetInvoiceRequest();
// $invoiceRequest
// ->setCheckoutId(env('INTERKASSA_ID'))
// ->setPaymentNumber($order_id)
// ->setAmount($amount)
// ->setCurrency('RUB')
// ->setDescription('Пополнение баланса');
// return $SDKClient->makeInvoiceSciLink($invoiceRequest);
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Domain\PaymentGateway\Services;
use YooKassa\Client;
class YookassaService
{
public static function payments_link($amount, $order, $user)
{
$YOOKASSA_SHOP_ID = env('YOOKASSA_SHOP_ID');
$YOOKASSA_KEY = env('YOOKASSA_KEY');
$idempotenceKey = $order->number;
$client = new Client();
$client->setAuth($YOOKASSA_SHOP_ID, $YOOKASSA_KEY);
$success_url = env('APP_URL') . '/payments/status/' . $order->number;
$response = $client->createPayment(
[
'amount' => [
'value' => $amount,
'currency' => 'RUB',
],
'capture' => true,
'payment_method_data' => [
'type' => 'sbp',
],
'confirmation' => [
'type' => 'redirect',
'return_url' => $success_url,
],
'receipt' => [
'customer' => [
'full_name' => $user->name ?? $user->username,
'phone' => $user->phone,
"email" => $user->email
],
'items' => [
[
'description' => 'оплата бонусов тизер',
'quantity' => 1.00,
'amount' => [
'value' => $amount,
'currency' => 'RUB',
],
'vat_code' => 1,
'payment_mode' => 'full_payment'
]
]
],
'description' => 'Заказ №' . $order->id,
],
$idempotenceKey
);
$order->system_payment_id = $response->getId();
$order->save();
$confirmationUrl = $response->getConfirmation()->getConfirmationUrl();
return $confirmationUrl;
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Domain\Payments\Models;
use App\Models\Model;
use App\Models\User;
class BankRequisites extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function requisites()
{
return $this->morphOne(Requisites::class, 'requisiteable');
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Domain\Payments\Models;
use App\Models\Model;
use App\Models\User;
class Requisites extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function requisiteable()
{
return $this->morphTo();
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace App\Domain\Payments\Models;
use App\Models\User;
use App\Models\Model;
use App\Domain\Points\Models\Point;
class Withdrawal extends Model
{
public function getUserPhoneAttribute()
{
return $this->user->phone;
}
public function getUserTypeAttribute()
{
return $this->user->type;
}
public function getRequisitesAttribute()
{
return 'ИНН: ' . $this->user->inn . ' ' .
'БИК: ' . $this->user->bik . ' ' .
'Счет: ' . $this->user->checking_account;
}
public static function getTotalAmountForUserInCurrentMonth($userId)
{
return self::where('user_id', $userId)
->where('status', '<>', 'cancel')
->where('created_at', '>=', now()->startOfMonth())
->where('created_at', '<', now()->startOfMonth()->addMonth())
->sum('amount');
}
public static function canRequestWithdrawalPhysical($userId, $requestedAmount)
{
$totalAmount = self::getTotalAmountForUserInCurrentMonth($userId);
return ($totalAmount + $requestedAmount) <= 12000;
}
public static function canRequestWithdrawalLegal($userId, $requestedAmount)
{
$totalAmount = self::getTotalAmountForUserInCurrentMonth($userId);
return ($totalAmount + $requestedAmount) <= 150000;
}
public function user()
{
return $this->belongsTo(User::class);
}
public function requisites()
{
return $this->belongsTo(Requisites::class);
}
public function point()
{
return $this->belongsTo(Point::class);
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Domain\Payments\Observers;
use App\Domain\Points\Models\Point;
use App\Domain\Payments\Models\Withdrawal;
class WithdrawalObserver
{
public function updated(Withdrawal $withdrawal)
{
$status = $withdrawal->status;
$point_id = $withdrawal->point_id;
if($status === 'cancel'){
Point::destroy($point_id);
}
if($status === 'success'){
$point = Point::find($point_id);
$point->type = "Вывод средств";
$point->save();
}
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Domain\Points\Enums;
use Spatie\Enum\Laravel\Enum;
/**
* @method static self COMING()
* @method static self EXPENSE()
* @method static self PENDING()
*/
final class DirectionEnum extends Enum
{
protected static function values(): array
{
return [
'COMING' => 0, // приход
'EXPENSE' => 1, //расход
'PENDING' => 2, //ожидание
];
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace App\Domain\Points\Models;
use App\Models\Model;
use App\Models\User;
class Point extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace App\Domain\Subscriptions\Models;
use App\Models\Model;
class Package extends Model
{
public $timestamps = false;
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Domain\Subscriptions\Models;
use App\Models\Model;
use App\Models\User;
class Subscription extends Model
{
protected $casts = [
'ends_at' => 'datetime',
];
public function user()
{
return $this->belongsTo(User::class);
}
public function package()
{
return $this->belongsTo(Package::class);
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace App\Domain\Subscriptions\Service;
use Carbon\Carbon;
use App\Models\User;
use App\Domain\Points\Models\Point;
use App\Domain\Subscriptions\Models\Subscription;
class SubscriptionService
{
public static function amount()
{
$subscriptions = Subscription::where('ends_at', '>', Carbon::now())
->where('status', 'complete')->get();
return $subscriptions->sum('price');
}
public static function hasSubscription()
{
return auth()->user()->subscription()->count();
}
public static function activeSubscription()
{
$last = auth()->user()->subscription()->first();
if (empty($last)) {
return false;
}
if ($last->ends_at > Carbon::now()) {
return true;
}
return false;
}
public static function freeLeaders()
{
$leader_count = nova_get_setting('vote_leader_count');
$users = \DB::table('users_subscribers')->get();
$users = $users->groupBy('subscriber_id');
$leaders = collect();
$users = $users->map(function ($item) {
return $item->sum('leader');
})->sortDesc()->take($leader_count);
foreach ($users as $user_id => $leader) {
$lUser = User::find($user_id);
$lUser->name = $lUser->name;
$lUser->countVote = $leader;
$leaders[] = $lUser;
}
return $leaders;
}
public static function leaders()
{
$leaders = \DB::select("SELECT vote.subscriber_id as user_id, SUM(vote.leader) as vote_count FROM
(
SELECT friends.subscriber_id, friends.leader
FROM users_subscribers friends,
(
SELECT user_id,ends_at FROM subscriptions
WHERE ends_at > CURRENT_TIMESTAMP
)user_active,
(
SELECT user_id,ends_at FROM subscriptions
WHERE ends_at > CURRENT_TIMESTAMP
)user_active2
where
friends.user_id = user_active.user_id
and friends.subscriber_id = user_active2.user_id
) vote
GROUP BY vote.subscriber_id ORDER BY vote_count DESC");
return $leaders;
}
public static function calculate($user_id)
{
$balance = \DB::select("SELECT T_IN.user_id, T_IN.in-T_OUT.out as balance FROM
(SELECT user_id, sum(point) as out FROM points WHERE user_id = {$user_id} AND direction = 1 GROUP BY user_id) T_OUT,
(SELECT user_id, sum(point) as in FROM points WHERE user_id = {$user_id} AND direction = 0 GROUP BY user_id) T_IN
where T_IN.user_id = T_OUT.user_id");
$balance = @$balance[0]->balance;
if (empty($balance)) {
$points = Point::where('user_id', $user_id)->get();
$in = $points->where('direction', 0)->sum('point');
$out = $points->where('direction', 1)->sum('point');
$sum = $in-$out;
if ($sum <= 0) {
return 0;
}
return $sum;
}
return $balance;
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace App\Domain\Tags\Action;
use Illuminate\Support\Str;
use App\Domain\Tags\Models\Tag;
class CreateTagAction
{
public function __invoke(Array $tags)
{
$tagIds = [];
$tags = array_map(function($tag){
$tag = trim(strip_tags($tag));
//$tag = mb_strtolower($tag);
//$tag = mb_ucfirst($tag);
return $tag;
}, $tags);
$tags = array_unique($tags);
foreach ($tags as $tag) {
$slug = Str::slug($tag, '-');
$tagDB = Tag::firstOrCreate(
['slug' => $slug],
['name' => $tag]
);
$tagIds[] = $tagDB->id;
}
return $tagIds;
}
protected function create()
{
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Domain\Tags\Models;
use App\Models\Model;
use App\Domain\Feeds\Models\Feed;
class Tag extends Model
{
public function feeds()
{
return $this->belongsToMany(Feed::class, 'feed_tags');
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Domain\Texts\Action;
use App\Domain\Texts\DataTransferObjects\TextData;
use App\Domain\Texts\Models\Text;
class CreateTextAction
{
public function __invoke(TextData $textData)
{
$textFeed = Text::create([
'title' => $textData->title,
'body' => $textData->body,
'user_id' => $textData->user->id,
]);
return $textFeed;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Domain\Texts\DataTransferObjects;
use App\Http\Requests\TextFormRequest;
use Spatie\DataTransferObject\DataTransferObject;
class TextData extends DataTransferObject
{
public $title;
public $body;
public $user;
public static function fromRequest(TextFormRequest $request)
{
return new self([
'title' => $request->input('title'),
'body' => $request->input('body'),
'user' => auth()->user(),
]);
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Domain\Texts\Models;
use App\Domain\Complaints\Models\Complaint;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Texts\Observers\TextObserver;
use App\Models\Model;
use App\Models\User;
class Text extends Model
{
protected $fillable = ['title', 'body', 'user_id'];
protected static function boot()
{
parent::boot();
self::observe(TextObserver::class);
}
public function feed()
{
return $this->morphOne(Feed::class, 'feedable');
}
public function complaints()
{
return $this->morphMany(Complaint::class, 'complaintable');
}
public function user()
{
return $this->belongsTo(User::class);
}
}

View File

@@ -0,0 +1,28 @@
<?php
namespace App\Domain\Texts\Observers;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Texts\Models\Text;
class TextObserver
{
public function creating(Text $text)
{
$text->slug = 'text_' . uniqid();
}
public function created(Text $text)
{
$feed = new Feed;
$feed->time = time();
$feed->user()->associate(auth()->user());
$text->feed()->save($feed);
}
public function deleting(Text $text)
{
$text->feed()->delete();
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Domain\Users\DataTransferObjects;
use App\Models\User;
use Spatie\DataTransferObject\DataTransferObject;
class SubscribedData extends DataTransferObject
{
public $id;
public $full_name;
public $username;
public $photo_path;
public $leader;
public static function fromModel(User $user)
{
return new self([
'id' => $user->id,
'full_name' => $user->name,
'username' => $user->username,
'photo_path' => $user->photo_path,
'leader' => $user->pivot->leader,
]);
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace App\Domain\Users\DataTransferObjects;
use App\Models\User;
use Spatie\DataTransferObject\DataTransferObject;
class UserData extends DataTransferObject
{
public $id;
public $name;
public $user_char;
public $color;
public $photo_path;
public $banner_path;
public $username;
public $private;
public $is_auth_user;
public static function fromModel(User $user)
{
$idCheck = auth()->user() ? $user->id === auth()->user()->id : false;
return new self([
'id' => $user->id,
'name' => $user->name,
'user_char' => $user->user_char,
'color' => $user->color,
'photo_path' => $user->photo_path,
'banner_path' => $user->banner_path,
'username' => $user->username,
'private' => $user->private,
'is_auth_user' => $idCheck,
]);
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace App\Domain\Users\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use App\Models\Model;
class UserPackage extends Model
{
use HasFactory;
}

View File

@@ -0,0 +1,54 @@
<?php
namespace App\Domain\Users\Observers;
use App\Models\User;
use Illuminate\Support\Arr;
// use App\Domain\Points\Models\Point;
// use App\Domain\Points\Enums\DirectionEnum;
class UserObserver
{
public function creating(User $user)
{
$user->color = $this->generateColors();
if(!$user->username){
$user->username = 'id_' . uniqid();
}
}
public function created(User $user)
{
// if($user->username != 'inner_systemuser_api'){
// $point = new Point;
// $point->user_id = $user->id;
// $point->point = 100;
// $point->type = 'Тестовое пополнение'; //YSV ENUM!
// $point->direction = DirectionEnum::COMING();
// $point->save();
// }
}
public function saving(User $user)
{
$user->user_char = $this->getChar($user);
}
private function generateColors()
{
$colors = ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5', '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4caf50', '#8bc34a', '#ffc107', '#ff9800', '#ff5722', '#795548', '#9e9e9e', '#607d8b', '#f44331', '#e91e61', '#9c27b1', '#673ab1', '#3f51b1', '#2196f1', '#03a9f1', '#00bcd1', '#009681', '#4caf51', '#8bc341', '#ffc101', '#ff9801', '#ff5721', '#795541', '#9e9e91', '#607d81'];
return Arr::random($colors);
}
private function getChar($user)
{
$fname = mb_strtoupper($user->first_name);
$lname = @$user->last_name;
if($lname){
$lname = mb_strtoupper($lname);
return mb_substr($fname, 0, 1) . mb_substr($lname, 0, 1);
}
return mb_substr($fname, 0, 1) . mb_substr($fname, 1, 1);
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace App\Domain\Users\Service;
use Illuminate\Database\Eloquent\Builder;
class ProfileDataService
{
public static function get($user)
{
$gues = auth()->user();
if($gues){
$gues = auth()->user()->id;
}else{
$gues = null;
}
$user->loadCount(['subscriber_reverse as is_sub' => function (Builder $query) use($gues) {
$query->where('user_id', $gues);
},'subscribers as is_reader' => function (Builder $query) use($gues) {
$query->where('subscriber_id', $gues);
}])->withCasts(['is_sub' => 'boolean', 'is_reader' => 'boolean']);
$is_leader = false;
if($user->is_sub && auth()->user()){
$leader = auth()->user()->subscribers()->where('subscriber_id', $user->id)->first();
if($leader){
$is_leader = (boolean)$leader->pivot->leader;
}
}
$count_feeds = $user->feeds()->count();
$count_readable = $user->subscribers()->count();
$count_subscribers = $user->subscriber_reverse()->count();
$is_auth_user = $user->id === $gues;
if($is_auth_user){
$close_account = false;
}else{
$close_account = $user->private == true && ($user->is_sub == 0 || $user->is_reader == 0);
}
$object = new \stdClass();
$object->user = $user;
$object->count_feeds = $count_feeds;
$object->count_readable = $count_readable;
$object->count_subscribers = $count_subscribers;
$object->close_account = $close_account;
$object->is_leader = $is_leader;
return $object;
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Domain\Videos\Action;
use App\Domain\Feeds\Models\Feed;
use DB;
use App\Domain\Feeds\ToFeedAction;
use App\Domain\Videos\DataTransferObjects\VideoData;
class CreateVideoAction implements ToFeedAction
{
public function __invoke(VideoData $videoData)
{
DB::beginTransaction();
//$youtube_code = $videoData->youtube ? $this->getCodeYoutube($videoData->youtube) : '';
$videoFeed = Feed::create([
'title' => $videoData->title,
'body' => $videoData->body,
'price' => $videoData->price,
'is_paid' => $videoData->is_paid,
'user_id' => $videoData->user->id,
'type' => 'videos',
'is_ads' => false,
//'iframe_code' => $youtube_code,
]);
foreach ($videoData->videos as $video) {
$videoFeed->addMedia($video)->toMediaCollection('common');
}
if($videoData->is_loaded_preview){
$videoFeed->addMedia($videoData->preview)->toMediaCollection('preview');
}
if($videoData->is_loaded_videos_paid){
foreach ($videoData->videos_paid as $video) {
$videoFeed->addMedia($video)->toMediaCollection('paid');
}
}
DB::commit();
return $videoFeed;
}
private function getCodeYoutube($video)
{
$youtuberegexp = '/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/i';
preg_match($youtuberegexp, $video, $matches);
return @$matches[1];
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace App\Domain\Videos\Action;
use DB;
use App\Domain\Feeds\Models\Feed;
use App\Domain\Feeds\ToFeedAction;
use App\Domain\Feeds\Enums\StatusEnum;
use App\Domain\Videos\DataTransferObjects\VideoData;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
class UpdateVideoAction implements ToFeedAction
{
public $videoFeed;
public function __construct(Feed $videoFeed)
{
$this->videoFeed = $videoFeed;
}
public function __invoke(VideoData $videoData)
{
$status = $this->videoFeed->status;
if($status === StatusEnum::BANNED()){
$status = StatusEnum::EDITABLE();
}
if($status === StatusEnum::APPROVED()){
$status = StatusEnum::EDITABLE();
}
DB::beginTransaction();
$this->videoFeed->fill([
'title' => $videoData->title,
'body' => $videoData->body,
'price' => $videoData->price,
'is_paid' => $videoData->is_paid,
'status' => $status,
'is_ads' => false,
])->save();
if($videoData->is_loaded_video){
foreach ($videoData->videos as $video) {
$this->videoFeed->addMedia($video)->toMediaCollection('common');
}
}
if($videoData->is_loaded_preview){
if($existPreview = $this->videoFeed->getMedia('preview')->first()){
$existPreview->delete();
}
$this->videoFeed->addMedia($videoData->preview)->toMediaCollection('preview');
}
if($videoData->is_loaded_videos_paid){
foreach ($videoData->videos_paid as $video) {
$this->videoFeed->addMedia($video)->toMediaCollection('paid');
}
}
if(count($videoData->removedItems)){
foreach ($videoData->removedItems as $removedItem) {
if($media = Media::find($removedItem)){
$media->delete();
}
}
}
DB::commit();
return $this->videoFeed->refresh();
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace App\Domain\Videos\DataTransferObjects;
use App\Http\Requests\VideoFormRequest;
use Spatie\DataTransferObject\DataTransferObject;
class VideoData extends DataTransferObject
{
public $title;
public $body;
public $user;
public $videos;
public $videos_paid;
public $preview;
public $is_loaded_video;
public $is_loaded_preview;
public $is_loaded_videos_paid;
public $price;
public $is_paid;
public $tags;
public $removedItems;
public static function fromRequest(VideoFormRequest $request)
{
return new self([
'title' => $request->input('title'),
'body' => $request->input('body'),
'price' => $request->input('price'),
'is_paid' => $request->input('is_paid'),
'user' => auth()->user(),
'tags' => $request->input('tags') ?? [],
'preview' => $request->file('preview'),
'is_loaded_preview' => $request->hasFile('preview'),
'videos' => $request->file('videos'),
'is_loaded_video' => $request->hasFile('videos'),
'videos_paid' => $request->file('videos_paid'),
'is_loaded_videos_paid' => $request->hasFile('videos_paid'),
'removedItems' => $request->input('removedItems') ?? [],
]);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Domain\Videos\Models;
use App\Domain\Complaints\Models\Complaint;
use App\Domain\Feeds\Models\Feed;
use App\Models\Model;
use App\Models\User;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
class Video extends Model implements HasMedia
{
use InteractsWithMedia;
public function complaints()
{
return $this->morphMany(Complaint::class, 'complaintable');
}
public function feed()
{
return $this->morphOne(Feed::class, 'feedable');
}
public function user()
{
return $this->belongsTo(User::class);
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace App\Domain\Videos\Observers;
use App\Domain\Videos\Models\Video;
class VideoObserver
{
public function creating(Video $video)
{
$video->slug = 'video_' . uniqid();
}
public function deleting(Video $video)
{
$video->feed()->delete();
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace App\Domain\Votes\Models;
use App\Models\Model;
use App\Models\User;
class Vote extends Model
{
public function users()
{
return $this->belongsToMany(User::class)->withPivot('payment');
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Domain\Votes\Observers;
use App\Domain\Votes\Models\Vote;
use App\Domain\Votes\Services\VoteService;
class VoteObserver
{
public function created(Vote $vote)
{
$mode = nova_get_setting('vote_paid_mode');
// Платный режим
if($mode){
(new VoteService($vote))->accrualPoints();
}else{
(new VoteService($vote))->freeMode();
}
}
}

View File

@@ -0,0 +1,180 @@
<?php
namespace App\Domain\Votes\Services;
use DB;
use Carbon\Carbon;
use App\Models\User;
use App\Domain\Points\Models\Point;
use App\Domain\Points\Enums\DirectionEnum;
use App\Domain\Subscriptions\Models\Subscription;
use App\Domain\Subscriptions\Service\SubscriptionService;
class VoteService
{
public $vote;
public $leaders;
public function __construct($vote)
{
$leader_count = nova_get_setting('vote_leader_count');
$leaders = SubscriptionService::leaders();
$leaders = array_column(array_slice($leaders, 0, $leader_count), 'user_id');
$this->leaders = $leaders;
$this->vote = $vote;
}
public function accrualPoints()
{
DB::beginTransaction();
$procent_site = (int)nova_get_setting('vote_procent_site');
$procent_site = $procent_site / 100;
$procent_top = (int)nova_get_setting('vote_procent_leader');
$procent_top = $procent_top / 100;
$procent_local = (int)nova_get_setting('vote_procent_local_leader');
$procent_local = $procent_local / 100;
$subscriptions = Subscription::with('user.subscribers.subscription')->where('ends_at', '>', Carbon::now())
->where('status', 'complete')->get();
$sum_site = 0;
$sdr_leader_pay = 0;
$sdr_leader_for_all_pay = [];
foreach ($subscriptions as $subscription) {
$user = $subscription->user;
$subscribers = $this->activeSubs($user->subscribers);
// Фильтр лидеров
$subscribersLeader = $subscribers->filter(function ($subscriber) {
return $subscriber->pivot->leader === 1;
});
// Фильтр простых пользователей
$subscribersSimple = $subscribers->filter(function ($subscriber) {
return $subscriber->pivot->leader === 0;
});
$price = $subscription->price;
$to_site = round($price * $procent_site);
$sum_site += $to_site;
$sdr = round($price - $to_site); // сумма для распределения
$sdr_leader_global = round($sdr * $procent_top);
$sdr_leader_local = round($sdr * $procent_local);
$sdr_simple = $sdr - $sdr_leader_global - $sdr_leader_local;
// добавляем лидерам
$sdr_leader_pay += $sdr_leader_global;
//если 0 подписок, но куплена подписка на сайт
// отдаем лидеру 40%, а 60% сайту
if($subscribers->isEmpty()){
$sum_site += ($sdr - $sdr_leader_global); // 20%сайту(вместо локальных) и 40%сайту (вместо простых)
}else {
if ($subscribersLeader->isNotEmpty()) {
//Выплачиваем каждому локальному лидеру
$sdr_parts_local = round($sdr_leader_local / $subscribersLeader->count());
//сохраняем транзакции локальных лидеров
foreach ($subscribersLeader as $subs) {
$sdr_leader_for_all_pay[$subs->id][] = $sdr_parts_local;
}
}else{
$sum_site += $sdr_leader_local; //если у пользователя есть подписки, но он не выбрал лидеров
}
if ($subscribersSimple->isNotEmpty()) {
//Выплачиваем каждому юзеру
$sdr_parts = round($sdr_simple / $subscribersSimple->count());
//сохраняем транзакции простых пользователей
foreach ($subscribersSimple as $subs) {
$sdr_leader_for_all_pay[$subs->id][] = $sdr_parts;
}
}else{
$sum_site += $sdr_simple;
}
}
$this->updateSubs($subscription);
}
$part_for_leader = round($sdr_leader_pay/count($this->leaders));
foreach ($this->leaders as $leader) {
$sdr_leader_for_all_pay[$leader][] = $part_for_leader;
}
$this->payUsers($sdr_leader_for_all_pay);
$this->payForSystemUser($sum_site);
DB::commit();
}
private function payUsers($sdr)
{
$sdr_users_pay = array_map(function ($lines) {
return array_sum($lines);
}, $sdr);
foreach ($sdr_users_pay as $user_pay_id => $sdr_user) {
$this->addPoint($user_pay_id, $sdr_user);
}
}
private function payForSystemUser($sum_site)
{
$system_user_id = User::system()->id;
$this->addPoint($system_user_id, $sum_site);
}
private function addPoint($user_id, $amount)
{
$point = new Point;
$point->user_id = $user_id;
$point->point = $amount;
$point->type = 'votes'; //YSV ENUM!
$point->direction = DirectionEnum::COMING();
$point->save();
$this->vote->users()->attach($user_id, ['payment' => $amount]);
}
private function updateSubs($sub)
{
$sub->status = 'end'; //YSV ENUM!
$sub->save();
}
//проверка на акт. подписки
private function activeSubs($subscribers)
{
return $subscribers->filter(function ($subscriber) {
return optional($subscriber->subscription->first())->ends_at > Carbon::now();
});
}
public function freeMode()
{
$users = SubscriptionService::freeLeaders();
foreach ($users as $leader) {
$this->vote->users()->attach($leader->id, ['payment' => $leader->countVote]);
}
}
}

View File

@@ -0,0 +1,155 @@
<?php
namespace App\Domain\Votes\Services;
use DB;
use Carbon\Carbon;
use App\Models\User;
use App\Domain\Points\Models\Point;
use App\Domain\Points\Enums\DirectionEnum;
use App\Domain\Subscriptions\Models\Subscription;
use App\Domain\Subscriptions\Service\SubscriptionService;
class VoteServiceOld
{
public $vote;
public $leaders;
public function __construct($vote)
{
$leaders = SubscriptionService::leaders();
$leaders = array_column(array_slice($leaders, 0, 2), 'user_id');
$this->leaders = $leaders;
$this->vote = $vote;
}
public function accrualPoints()
{
DB::beginTransaction();
$procent_site = (int)$this->vote->procent_site;
$procent_site = $procent_site / 100;
$procent_top = (int)$this->vote->procent_top;
$procent_top = $procent_top / 100;
$subscriptions = Subscription::with('user.subscribers.subscription')->where('ends_at', '>', Carbon::now())
->where('status', 'complete')->get();
$sum_site = 0;
$sdr_leader_pay = 0;
$sdr_users_pay = [];
foreach ($subscriptions as $subscription) {
$subscribers_simple = collect([]);
$user = $subscription->user;
$subscribers = $this->activeSubs($user->subscribers);
$one_sub_is_leader = $this->oneLeaders($subscribers);
if (! $one_sub_is_leader) {
$subscribers_simple = $subscribers->filter(function ($subscriber) {
return ! in_array($subscriber->id, $this->leaders);
});
}
$price = $subscription->price;
$to_site = $price * $procent_site;
$sum_site += $to_site;
$sdr = round($price - $to_site);
$sdr_leader = round($sdr * $procent_top);
$sdr_simple = $sdr - $sdr_leader;
if ($one_sub_is_leader) {
//выплачиваем весь sdr если чел. подписан на лидеров, и у него больше нет простых
$sdr_leader_pay += $sdr;
} else {
$sdr_leader_pay += $sdr_leader;
}
if ($subscribers_simple->isNotEmpty()) {
//Выплачиваем каждому юзеру
$sdr_parts = round($sdr_simple / $subscribers_simple->count());
//сохраняем транзакции простых пользователей
foreach ($subscribers_simple as $subs) {
$sdr_users_pay[$subs->id][] = $sdr_parts;
}
}
$this->updateSubs($subscription);
}
$this->payForSimpleUser($sdr_users_pay);
$this->payForLeaderUser($sdr_leader_pay);
$this->payForSystemUser($sum_site);
DB::commit();
}
public function payForSystemUser($sum_site)
{
$system_user_id = User::system()->id;
$this->addPoint($system_user_id, $sum_site);
}
//оплата лидеров
public function payForLeaderUser($sdr_leader_pay)
{
$part_for_leader = round($sdr_leader_pay/count($this->leaders));
foreach ($this->leaders as $leader) {
$this->addPoint($leader, $part_for_leader);
}
}
//оплата обычных
public function payForSimpleUser($sdr_users_pay)
{
$sdr_users_pay = array_map(function ($lines) {
return array_sum($lines);
}, $sdr_users_pay);
foreach ($sdr_users_pay as $user_pay_id => $sdr_users) {
$this->addPoint($user_pay_id, $sdr_users);
}
}
public function addPoint($user_id, $amount)
{
$point = new Point;
$point->user_id = $user_id;
$point->point = $amount;
$point->type = 'votes'; //YSV ENUM!
$point->direction = DirectionEnum::COMING();
$point->save();
$this->vote->users()->attach($user_id, ['payment' => $amount]);
}
public function updateSubs($sub)
{
$sub->status = 'end'; //YSV ENUM!
$sub->save();
}
// есть в списке только лидеры
public function oneLeaders($subscribers)
{
if ($subscribers->count() <= count($this->leaders)) {
$contains = $subscribers->filter(function ($subscriber) {
return in_array($subscriber->id, $this->leaders);
});
if ($contains->count() === $subscribers->count()) {
return true;
}
}
return false;
}
//проверка на акт. подписки
public function activeSubs($subscribers)
{
return $subscribers->filter(function ($subscriber) {
return optional($subscriber->subscription->first())->ends_at > Carbon::now();
});
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Events;
use App\Domain\Feeds\Models\Feed;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class FeedAddProcessed
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $feed;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Feed $feed)
{
$this->feed = $feed;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('add-feed-for-readers');
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Events;
use App\Domain\Feeds\Models\Feed;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class FeedRemoveProcessed
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $feed;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Feed $feed)
{
$this->feed = $feed;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('remove-feed-for-readers');
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace App\Events;
use App\Domain\Feeds\Models\Feed;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class FeedUpdateProcessed
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $feed;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Feed $feed)
{
$this->feed = $feed;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('update-feed-for-readers');
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
//
}
public function render($request, Throwable $e)
{
$response = parent::render($request, $e);
if ($response->status() === 419) {
return back()->with([
'message' => 'The page expired, please try again.',
]);
}
return $response;
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\LoginRequest;
use App\Providers\RouteServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Inertia\Inertia;
class AuthenticatedSessionController extends Controller
{
/**
* Display the login view.
*
* @return \Inertia\Response
*/
public function create()
{
return Inertia::render('Auth/Login');
}
/**
* Handle an incoming authentication request.
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(RouteServiceProvider::HOME);
}
/**
* Destroy an authenticated session.
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Request $request)
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Http\Controllers\Auth;
use Inertia\Inertia;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
class EmailVerificationPromptController extends Controller
{
/**
* Display the email verification prompt.
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function __invoke(Request $request)
{
if($request->user()->hasVerifiedEmail()){
return redirect()->intended(RouteServiceProvider::HOME);
}
return Inertia::render('Auth/VerifyEmail');
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace App\Http\Controllers\Auth;
use Inertia\Inertia;
use Illuminate\View\View;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Validation\Rules;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Password;
use Illuminate\Auth\Events\PasswordReset;
class NewPasswordController extends Controller
{
/**
* Display the password reset view.
*/
public function create(Request $request)
{
return Inertia::render('Auth/ResetPassword', [
'token' => $request->route('token'),
]);
}
/**
* Handle an incoming new password request.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'token' => ['required'],
'email' => ['required', 'email'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function ($user) use ($request) {
$user->forceFill([
'password' => Hash::make($request->password),
'remember_token' => Str::random(60),
])->save();
event(new PasswordReset($user));
}
);
// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
return $status == Password::PASSWORD_RESET
? redirect()->route('login')->with('status', __($status))
: back()->with('status', __($status));
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Http\Controllers\Auth;
use Inertia\Inertia;
use Illuminate\View\View;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Password;
class PasswordResetLinkController extends Controller
{
/**
* Display the password reset link request view.
*/
public function create()
{
return Inertia::render('Auth/ForgotPassword');
}
/**
* Handle an incoming password reset link request.
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'email' => ['required', 'email'],
]);
// We will send the password reset link to this user. Once we have attempted
// to send the link, we will examine the response then see the message we
// need to show to the user. Finally, we'll send out a proper response.
$status = Password::sendResetLink(
$request->only('email')
);
return back()->with('status', __($status));
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Models\User;
use Inertia\Inertia;
use Illuminate\Http\Request;
use Illuminate\Validation\Rules;
use App\Mail\AfterReigsterToAdmin;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Auth\Events\Registered;
use App\Providers\RouteServiceProvider;
class RegisteredUserController extends Controller
{
/**
* Display the registration view.
*
* @return \Illuminate\View\View
*/
public function create()
{
return Inertia::render('Auth/Register');
}
/**
* Handle an incoming registration request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request)
{
$request->validate([
'first_name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => ['required', Rules\Password::defaults()],
]);
$user = User::create([
'first_name' => $request->first_name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new Registered($user));
Auth::login($user);
Mail::to(env('MAIL_ADMIN_EMAIL'))->send(new AfterReigsterToAdmin($user));
return redirect(RouteServiceProvider::HOME);
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
class VerifyEmailController extends Controller
{
/**
* Mark the authenticated user's email address as verified.
*
* @param \Illuminate\Foundation\Auth\EmailVerificationRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function __invoke(EmailVerificationRequest $request)
{
if ($request->user()->hasVerifiedEmail()) {
return redirect()->intended(
config('app.frontend_url').RouteServiceProvider::HOME.'?verified=1'
);
}
if ($request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
return redirect()->intended(
config('app.frontend_url').RouteServiceProvider::HOME.'?verified=1'
);
}
}

Some files were not shown because too many files have changed in this diff Show More