fields['mesgs'] = array( "guid", "author", "mesg", "attachment", ); parent::__construct($guid); try { $this->expectType("log"); } catch (Exception $e) { $this->expectType("mesg"); } } /* * Initialize a new regular message. */ public static function initNew(string $message, user $author, obj $parent) : mesg { $mesg = new mesg(); $mesg->setOwner($author); $mesg->setParent($parent); $mesg->name = "message " . $mesg->guid; $mesg->objtype = "mesg"; $mesg->setAuthor($author); $mesg->mesg = $message; $mesg->saveObj(); return $mesg; } /* * Initialize a new pad discussion thread. */ public static function initNewDiscussion(string $name, string $message, user $author, pad $parent) : mesg { $mesg = new mesg(); $mesg->setOwner($author); $mesg->setParent($parent); $mesg->name = $name; $mesg->objtype = "mesg"; $mesg->setAuthor($author); $mesg->mesg = $message; $mesg->saveObj(); return $mesg; } /* * Initialize a new private message (user-to-user). */ public static function initNewPM(string $name, string $message, user $author, user $rcpt) : mesg { $mesg = new mesg(); $mesg->setOwner($rcpt); $mesg->setParent($rcpt); $mesg->name = $name; $mesg->objtype = "mesg"; $mesg->setAuthor($author); $mesg->mesg = $message; $mesg->saveObj(); return $mesg; } /* * Initialize a new log message. */ public static function initNewLog(string $message, user $author, obj $parent) : mesg { $owner = $parent->getOwner(); if (!$owner) $owner = $parent; $mesg = new mesg(); $mesg->setOwner($owner); $mesg->setParent($parent); $mesg->name = "log " . $mesg->guid; $mesg->objtype = "log"; $mesg->setAuthor($author); $mesg->mesg = $message; $mesg->saveObj(); return $mesg; } /* * Initialize a new admin log message. */ public static function initNewAdminLog(string $message, user $author) : mesg { $mesg = new mesg(); $mesg->saveObj(); // need to get a guid $mesg->name = "admin log " . $mesg->guid; $mesg->objtype = "log"; $mesg->setAuthor($author); $mesg->mesg = $message; $mesg->saveObj(); return $mesg; } /* * Get an array of messages in the admin log, between two timestamps. * With no arguments, the entire log is returned. Results are sorted * in reverse chronological order. */ public static function getAdminLog_ordByDatetime(?string $after = NULL, ?string $before = NULL) : array { $query = "SELECT guid FROM objects WHERE objtype = 'log' AND " . "parent = '' "; if ($after) $query += "AND created >= '" . database::esc($after) . "' "; if ($before) $query += "AND created < '" . database::esc($before) . "' "; $query += "ORDER BY created DESC"; $res = database::query($query); $log = array(); foreach ($res as $l) $log[] = new mesg($l['guid']); return $log; } /* * Get the author of this message. This user either actually wrote * this message, or caused it to be generated. */ public function getAuthor() : user { if (!isset($this->author) || $this->author == "") return NULL; return new user($this->author); } /* * Set the author of this message. This should usually only be done * while constructing a new message or to clear out references to * a user that got removed. */ public function setAuthor(user $author) : void { $this->author = $author->guid; $this->saveObj(); } /* * Check whether this message has been seen by the given user */ public function seenBy(user $viewer) : bool { $query = "SELECT * FROM views WHERE guid = '" . database::esc($this->guid) . "' " . "AND viewer = '" . database::esc($viewer->guid) . "'"; $res = database::query($query); return count($res) > 0; } /* * Mark this message as seen by the given user */ public function markSeen(user $viewer) : void { if (!$this->seenBy($viewer)) { $query = "INSERT INTO views (guid, viewer) VALUES ('" . database::esc($this->guid) . "', '" . database::esc($viewer->guid) . "')"; database::query($query); } } /* * Format message (if auto generated), and insert HTML linebreaks (
) * at message newlines. */ public function renderMesg() : string { if ($this->objtype == "log") $mesg = sprintf($this->mesg, $this->getAuthor()->getDisplayName()); else $mesg = $this->mesg; return nl2br($mesg); } /* * Get the URL to this message's attachment. If no file is attached, * NULL is returned. */ public function getAttachment() : ?string { if (!is_file("dynmic/attach/" . $this->guid)) return NULL; return ar() . "/df.php?d=attach&f=" . $this->guid; } /* * Set the attached file for this message. Should typically be done * during new message creation and not changed afterward. Returns * false if there is a problem saving the attachment. */ public function setAttachment(string $file) : bool { $path = "dynmic/attach/" . $this->guid; $origName = ""; $ret = saveIfFile($file, $path, self::ATTACH_MAXSIZE, NULL, $origName); $this->attachment = $origName; $this->saveObj(); return $ret; } /* * Promote a pad discussion thread to an issue. This message object * must be the top-level message (op) of the discussion thread (ie: * its parent must be a pad). All reply messages to this one are * retained and will be messages left on the new issue. A new issue * object is created and this message object will be destroyed. If * this is not an eligible message for promotion, NULL is returned. */ public function makeIssue(stage $parent) : ?issue { if ($this->getParent()->objtype != "pad") return NULL; $issue = issue::initNew($this->name, $this->getOwner(), $parent); $issue->created = $this->created; $issue->description = $this->mesg; $issue->saveObj(); foreach ($this->getMesgs_ordByDatetime() as $mesg) $mesg->setParent($issue); $this->delObj(); return $issue; } /* * Email this message to parents, owners, members. In the case that * this is an issue message or a reply message, the assignee or original * author is also included. Attachments are included in mailing. Any * duplicates in the rcpt list are removed before sending. Success * or failure is returned. */ public function emailMesg() : bool { $parent = $this->getParent(); if (!$parent) return true; $rcpt = $parent->getMembers(); $rcpt[] = $parent->getOwner(); switch ($parent->objtype) { case "user": $rcpt[] = $parent; $subj = $this->author . " " . $this->getAuthor()->getDisplayName() . " // " . $this->name; break; case "issue": $rcpt[] = $parent->getAssignee(); $pad = $parent->getPad(); $subj = $parent->guid . " " . $pad->name . " [#" . $parent->numb . "] " . $parent->name; break; case "mesg": case "log": $rcpt[] = $parent->getAuthor(); $pad = $parent->getParent(); $subj = $parent->guid . " " . $pad->name . " // " . $parent->name; break; } $rcpt = obj::arrayUnique($rcpt); $author = $this->author; $rcpt = array_filter($rcpt, function ($val) use($author) { return $val->guid != $author; }); $attachPath = ($this->getAttachment() ? "dynmic/attach/" . $this->guid : NULL); $mesg = $this->getAuthor()->getDisplayName() . " wrote on " . $this->created . "\n\n"; $mesg .= $this->renderMesg(); foreach ($rcpt as $r) { if (!$r->sendEmail($subj, $mesg, $attachPath, $this->attachment)) return false; } return true; } } ?>