diff options
Diffstat (limited to 'app/class/mesg.class.php')
-rw-r--r-- | app/class/mesg.class.php | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/app/class/mesg.class.php b/app/class/mesg.class.php new file mode 100644 index 0000000..2e5c9d6 --- /dev/null +++ b/app/class/mesg.class.php @@ -0,0 +1,341 @@ +<?php + +/* + * SCROTT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to UNLICENSE + */ + +require_once "class/obj.class.php"; +require_once "class/user.class.php"; +require_once "class/pad.class.php"; +require_once "class/stage.class.php"; +require_once "class/issue.class.php"; + +/* + * This class models issue activity, private messaging, pad discussions, + * and system and object log messages. + */ +class mesg extends obj +{ + /* + * Constants used for uploading attachments + */ + public const ATTACH_MAXSIZE = 536870912; // 512Mb + + /* + * Constructor + */ + public function __construct(?string $guid = NULL) + { + $this->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 (<br />) + * 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; + } +} + +?> |