'json', 'rogue_seenby' => 'json', 'rogue_path' => 'json', ]; private const cast_utf8 = [ 'to', 'from', 'subject', 'msg', 'msg_src', 'origin', 'tearline', 'tagline', ]; protected $dates = ['datetime']; public function __set($key, $value) { switch ($key) { case 'no_export': case 'set_path': case 'set_packet': case 'set_seenby': $this->{$key} = $value; break; default: parent::__set($key,$value); } } public static function boot() { parent::boot(); // @todo if the message 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->echoarea_id) { Log::alert(sprintf('%s:- Message has no echo area, not exporting',self::LOGKEY,$model->id)); return; } // Our address $ftns = Setup::findOrFail(config('app.id'))->system->match($model->fftn->zone,Address::NODE_ACTIVE|Address::NODE_PVT|Address::NODE_HOLD); // Add our address to the seenby; $model->set_seenby = array_merge($model->set_seenby,$ftns->pluck('id')->toArray()); $model->set_path = array_merge($model->set_path,$ftns->pluck('id')->toArray()); // Save the seenby foreach ($model->set_seenby as $aoid) { DB::insert('INSERT INTO echomail_seenby (echomail_id,address_id,packet) VALUES (?,?,?)',[ $model->id, $aoid, $model->set_packet, ]); } // Save the Path $ppoid = NULL; foreach ($model->set_path as $aoid) { $po = DB::select('INSERT INTO echomail_path (echomail_id,address_id,parent_id) VALUES (?,?,?) RETURNING id',[ $model->id, $aoid, $ppoid, ]); $ppoid = $po[0]->id; } // See if we need to export this message. $exportto = $model->echoarea->addresses->pluck('id')->diff($model->set_seenby); if ($exportto->count()) { if ($model->no_export) { Log::debug(sprintf('%s:- NOT processing exporting of message by configuration [%s] to [%s]',self::LOGKEY,$model->id,$exportto->join(','))); return; } Log::debug(sprintf('%s:- Exporting message [%s] to [%s]',self::LOGKEY,$model->id,$exportto->join(','))); // Save the seenby for the exported systems $export_at = Carbon::now(); foreach ($exportto as $aoid) { DB::insert('INSERT INTO echomail_seenby (echomail_id,address_id,export_at) VALUES (?,?,?)',[ $model->id, $aoid, $export_at, ]); } } }); } /* RELATIONS */ public function echoarea() { return $this->belongsTo(Echoarea::class); } public function fftn() { return $this->belongsTo(Address::class) ->withTrashed(); } public function seenby() { return $this->belongsToMany(Address::class,'echomail_seenby') ->ftnOrder(); } public function path() { return $this->belongsToMany(Address::class,'echomail_path') ->withPivot(['id','parent_id']); } /* METHODS */ public function jsonSerialize(): array { return $this->encode(); } /** * Return this model as a packet */ public function packet(Address $ao): Message { Log::debug(sprintf('%s:Bundling [%s]',self::LOGKEY,$this->id)); // @todo Dont bundle mail to nodes that have been disabled, or addresses that have been deleted $o = new Message; $o->header = [ 'onode' => $this->fftn->node_id, 'dnode' => $ao->node_id, 'onet' => $this->fftn->host_id, 'dnet' => $ao->host_id, 'flags' => 0, // @todo? 'cost' => 0, 'date'=>$this->datetime->format('d M y H:i:s'), ]; $o->tzutc = $this->datetime->utcOffset($this->tzoffset)->getOffsetString(''); $o->user_to = $this->to; $o->user_from = $this->from; $o->subject = $this->subject; $o->echoarea = $this->echoarea->name; $o->flags = $this->flags; if ($this->kludges) $o->kludge = collect($this->kludges); $o->kludge->put('dbid',$this->id); $o->msgid = $this->msgid; if ($this->replyid) $o->replyid = $this->replyid; $o->message = $this->msg; if ($this->tagline) $o->tagline = $this->tagline; if ($this->tearline) $o->tearline = $this->tearline; if ($this->origin) $o->origin = $this->origin; $o->seenby = $this->seenby->pluck('ftn2d'); $o->path = $this->pathorder(); $o->packed = TRUE; return $o; } public function pathorder(string $display='ftn2d',int $start=NULL): Collection { $result = collect(); if ($x=$this->path->firstWhere('pivot.parent_id',$start)) { $result->push($x->$display); $result->push($this->pathorder($display,$x->pivot->id)); }; return $result->flatten()->filter(); } }