Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
gilour
/
foundation
/
src
/
Channels
:
BaseChannel.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php namespace Common\Channels; use App\Models\User; use Carbon\Carbon; use Common\Core\BaseModel; use Common\Database\Datasource\Datasource; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Pagination\AbstractPaginator; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; abstract class BaseChannel extends BaseModel { const MODEL_TYPE = 'channel'; protected $guarded = ['id']; protected $appends = ['model_type']; protected $hidden = ['pivot', 'internal']; protected $casts = [ 'id' => 'integer', 'public' => 'boolean', 'internal' => 'boolean', 'user_id' => 'integer', ]; protected static function booted(): void { // touch parent channels static::updated(function (self $channel) { $parentIds = DB::table('channelables') ->where('channelable_type', static::MODEL_TYPE) ->where('channelable_id', $channel->id) ->pluck('channel_id'); static::withoutEvents(function () use ($parentIds) { static::whereIn('id', $parentIds)->update([ 'updated_at' => Carbon::now(), ]); }); }); } public function user(): BelongsTo { return $this->belongsTo(User::class); } public function getRouteKeyName(): string { return 'slug'; } public function users(): MorphToMany { return $this->morphedByMany(User::class, 'channelable')->withPivot([ 'id', 'channelable_id', 'order', ]); } public function allChannels( array $params, $builder = null, ): AbstractPaginator { $datasource = new Datasource( ($builder ?? static::query())->where( 'channels.id', '!=', $this->id, ), $params, ); return $datasource->paginate(); } public function channels(): MorphToMany { return $this->morphedByMany(static::class, 'channelable')->withPivot([ 'id', 'channelable_id', 'order', ]); } public function getConfigAttribute(): ?array { return isset($this->attributes['config']) ? json_decode($this->attributes['config'], true) : []; } public function setConfigAttribute($value) { $this->attributes['config'] = is_array($value) ? json_encode($value) : $value; } public function toNormalizedArray(): array { return [ 'id' => $this->id, 'name' => $this->name, 'image' => $this->image, 'description' => $this->description ? $this->description : Arr::get($this->attributes, 'config.seoDescription'), 'model_type' => static::MODEL_TYPE, ]; } public function toSearchableArray(): array { return [ 'id' => $this->id, 'name' => $this->name, 'slug' => $this->slug, ]; } public static function filterableFields(): array { return ['id', 'created_at', 'updated_at']; } public static function getModelTypeAttribute(): string { return static::MODEL_TYPE; } public function loadRestrictionModel(string $urlParam = null) { $restriction = null; $modelName = $this->config['restriction']; $modelId = $this->config['restrictionModelId'] ?? null; $model = app(modelTypeToNamespace($modelName))->select([ 'id', 'name', 'display_name', ]); if ($modelId === 'urlParam' && $urlParam) { $restriction = $model->where('name', $urlParam)->first(); } elseif (isset($modelId) && $modelId !== 'urlParam') { $restriction = $model->find($modelId); } if ($restriction && !$restriction->display_name) { $restriction->display_name = ucwords($restriction->name); } return $restriction; } public function loadContent(array $params = [], self $parent = null): static { $channelContent = (new LoadChannelContent())->execute( $this, $params, $parent, ); if (Arr::get($params, 'normalizeContent') && $channelContent) { $channelContent->transform(function ($item) { $normalized = $item->toNormalizedArray(); // needed in order to preserve "created_at" date when updating items if (isset($item->pivot)) { $normalized['created_at'] = $item->pivot->created_at; } return $normalized; }); } $this->setRelation('content', $channelContent); return $this; } public function updateContentFromExternal( string $autoUpdateMethod = null, ): void { $method = $autoUpdateMethod ?? Arr::get($this->config, 'autoUpdateMethod'); if ( !$method || Arr::get($this->config, 'contentType') !== 'autoUpdate' ) { return; } $content = $this->loadContentFromExternal($method); // bail if we could not fetch any content if (!$content || $content->isEmpty()) { return; } // detach all channel items from the channel DB::table('channelables') ->where(['channel_id' => $this->id]) ->delete(); // group content by model type (track, album, playlist etc) // and attach each group via its own separate relation $groupedContent = $content->groupBy('model_type'); $groupedContent->each(function (Collection $contentGroup, $modelType) { $pivots = $contentGroup->mapWithKeys( fn($item, $index) => [$item['id'] => ['order' => $index]], ); // track => tracks $relation = Str::plural($modelType); $this->$relation()->syncWithoutDetaching($pivots->toArray()); }); // clear channel cache, it's based on updated_at timestamp $this->touch(); } public function shouldRestrictContent() { // when channel is set to auto update, content will be filtered when auto updating return Arr::get($this->config, 'contentType') !== 'autoUpdate' && Arr::get($this->config, 'restriction'); } abstract protected function loadContentFromExternal( string $autoUpdateMethod, ): Collection|array|null; public function resolveRouteBinding($value, $field = null) { $type = request('channelType'); if (ctype_digit($value)) { $channel = $this->when( $type, fn($q) => $q->where('type', $type), )->findOrFail($value); } else { $channel = $this->where('slug', $value) ->when($type, fn($q) => $q->where('type', $type)) ->firstOrFail(); } return $channel; } }