<?php namespace App\Models; use AgliPanci\LaravelCase\Facades\CaseBuilder; use Carbon\Carbon; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; use App\Casts\CompressedStringOrNull; use App\Traits\{QueryCacheableConfig,ScopeActive}; class Domain extends Model { use HasFactory,QueryCacheableConfig,ScopeActive; private const CACHE_TIME = 3600; private const STATS_MONTHS = 6; protected $casts = [ 'homepage' => CompressedStringOrNull::class, ]; /* SCOPES */ /** * Only query active records */ public function scopePublic($query) { $user = Auth::user(); return $query ->when(((! $user) || (! $user->isAdmin())),function($query) { return $query->where('public',TRUE)->active(); }); } /* RELATIONS */ public function echoareas() { return $this->hasMany(Echoarea::class); } public function fileareas() { return $this->hasMany(Filearea::class); } public function nodelist_filearea() { return $this->belongsTo(Filearea::class); } public function nodestatusarea() { return $this->belongsTo(Echoarea::class,'nodestatus_id'); } public function zones() { return $this->hasMany(Zone::class) ->select(['id','zone_id','domain_id','active']); } /* ATTRIBUTES */ public function getCanAcceptAppAttribute(): bool { return ($x=our_address($this)) && $x->count() && $this->active && $this->accept_app && Auth::id() && $this->userHasSystemsNotInNet(Auth::user())->count(); } public function getHomePageAttribute(?string $value): string { //0xFD2FB528 return $this->castAttribute('homepage',$value) ?: 'No available information at the moment.'; } /* METHODS */ public function echoarea_stats(): Collection { $dt = Carbon::now()->startOfday(); $case = CaseBuilder::whenRaw("datetime >= '?'",$dt->subDay()->format('Y-m-d'))->thenRaw("'day'") ->whenRaw("datetime >= '?'",$dt->subDays(7)->format('Y-m-d'))->thenRaw("'week'") ->whenRaw("datetime >= '?'",$dt->subMonth()->format('Y-m-d'))->thenRaw("'month'") ->elseRaw("'all'"); return Echoarea::select(['echoareas.id','name','description','active',DB::raw('count(echomails.id) AS count'),DB::raw('min(datetime) as first_message'),DB::raw('max(datetime) as last_message')]) ->selectRaw($case->toRaw().' AS stats') ->join('echomails',['echomails.echoarea_id'=>'echoareas.id'],NULL,NULL,'left outer') ->where('domain_id',$this->id) ->groupBy('echoareas.id') ->groupBy('echoareas.name') ->groupBy('stats') ->orderBy('echoareas.name') ->orderBy('last_message','DESC') ->get(); } public function echoarea_total_daily(Collection $systems=NULL): Collection { return Cache::remember(md5(sprintf('%d-%s',$this->id,$systems?->pluck('id')->join(','))),self::CACHE_TIME,function() use ($systems) { return DB::query() ->select(['echoareas.name','echoareas.show',DB::raw('COUNT(echoareas.name) AS count'),DB::raw('datetime::date AS date')]) ->from($this->getTable()) ->join('echoareas',['echoareas.domain_id'=>'domains.id']) ->join('echomails',['echomails.echoarea_id'=>'echoareas.id']) ->where('domains.id',$this->id) ->where('echomails.datetime','>=',Carbon::now()->subMonths(self::STATS_MONTHS)->startOfMonth()) ->when($systems?->count(),function($query) use ($systems) { return $query->whereIn('echomails.fftn_id',$systems->pluck('addresses')->flatten()->pluck('id')); }) ->groupBy(['echoareas.name','echoareas.show','date']) ->orderBy('echoareas.name') ->orderBy('date') ->get(); }); } /** * Determine if this zone is managed by this host * * @return bool * @throws \Exception */ public function isManaged(): bool { return ($x=our_address()) && $x->pluck('zone.domain') ->pluck('id') ->contains($this->id); } /** * Work out which of the users systems are not in this domain * * @param User $o * @return Collection */ public function userHasSystemsNotInNet(User $o): Collection { $o->load('systems.akas.zone'); $result = collect(); foreach ($o->systems->filter(function($item) { return $item->active; }) as $so) { if (! $so->akas->pluck('zone')->unique('domain_id')->pluck('domain_id')->contains($this->id)) $result->push($so); } return $result; } }