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

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();
});
}
}