CollectionOrNull::class, 'datetime' => 'datetime:Y-m-d H:i:s', 'desc' => CompressedString::class, 'ldesc' => CompressedString::class, 'rogue_seenby' => CollectionOrNull::class, 'rogue_path' => CollectionOrNull::class, 'size' => 'int', ]; private const cast_utf8 = [ 'desc', 'ldesc', ]; public function __set($key,$value) { switch ($key) { case 'fullname': case 'replaces': case 'no_export': case 'set_path': case 'set_seenby': $this->{$key} = $value; break; default: parent::__set($key,$value); } } public static function boot() { parent::boot(); static::creating(function($model) { Log::info(sprintf('%s:- Storing file [%s] in [%s]',self::LOGKEY,$model->fullname,$model->full_storage_path)); // Store file if (Storage::put($model->full_storage_path,Storage::disk('local')->get($model->fullname),'public')) { unlink(Storage::disk('local')->path($model->fullname)); } else { throw new \Exception(sprintf('Unable to move file [%s] to [%s]',$model->fullname,$model->full_storage_path)); } // Delete anything being replaced // @todo implement replace }); // @todo if the file is updated with new SEEN-BY's from another route, we'll delete the pending export for systems (if there is one) static::created(function($model) { if (! $model->filearea_id) { Log::alert(sprintf('%s:- File has no filearea, not exporting',self::LOGKEY,$model->id)); return; } $so = Setup::findOrFail(config('app.id')); // Our address $ftns = $so ->system ->match($model->fftn->zone); // Add our address to the seenby; $model->set_seenby = $model->set_seenby->merge($ftns->pluck('id'))->unique(); $model->set_path = $model->set_path->merge([[ 'address'=>$ftns->first(), 'datetime'=>$x=Carbon::now(), 'extra'=>sprintf('%s %s (%s)',$x->toRfc7231String(),$so::PRODUCT_NAME,$so->version), ]]); // Make sure all the path is in the seenby $model->set_seenby = $model->set_seenby->merge($model->set_path->pluck('address.id'))->unique()->filter(); // Save the seenby $model->seenby()->sync($model->set_seenby); // Save the Path $ppoid = NULL; foreach ($model->set_path as $path) { $po = DB::select('INSERT INTO file_path (file_id,address_id,parent_id,datetime,extra) VALUES (?,?,?,?,?) RETURNING id',[ $model->id, $path['address']->id, $ppoid, Carbon::createFromTimestamp($path['datetime']), $path['extra'], ]); $ppoid = $po[0]->id; } // See if we need to export this file. if ($model->filearea->sec_read) { $exportto = $model ->filearea ->addresses ->filter(function($item) use ($model) { return $item->security >= $model->filearea->sec_read; }) ->pluck('id') ->diff($model->set_seenby); if ($exportto->count()) { if ($model->no_export) { Log::alert(sprintf('%s:- NOT processing exporting of message by configuration [%s] to [%s]',self::LOGKEY,$model->id,$exportto->join(','))); return; } Log::info(sprintf('%s:- Exporting file [%s] to [%s]',self::LOGKEY,$model->id,$exportto->join(','))); // Save the seenby for the exported systems $model->seenby()->syncWithPivotValues($exportto,['export_at'=>Carbon::now()],FALSE); } } }); } /* RELATIONS */ public function filearea() { return $this->belongsTo(Filearea::class); } public function fftn() { return $this->belongsTo(Address::class) ->withTrashed(); } public function seenby() { return $this->belongsToMany(Address::class,'file_seenby') ->ftnOrder(); } public function path() { return $this->belongsToMany(Address::class,'file_path') ->withPivot(['id','parent_id','datetime','extra']); } /* ATTRIBUTES */ /** * Return the relative path to Storage::disk() in the store * * @return string */ public function getFullStoragePathAttribute(): string { return sprintf('%04X/%s',$this->filearea_id,$this->name); } /** * Return the relative path to Storage::disk() in the inbound; * * @return string */ public function getRelNameAttribute(): string { return sprintf('%s/%s',config('fido.dir'),$this->prefix_name); } public function getPrefixNameAttribute(): string { return sprintf('%s%s',$this->prefix ? $this->prefix.'-' : '',$this->name); } /* METHODS */ public function jsonSerialize(): array { return $this->encode(); } }