summaryrefslogtreecommitdiffstats
path: root/app/class/mesg.class.php
diff options
context:
space:
mode:
authorMalf Furious <m@lfurio.us>2018-10-27 18:28:22 -0400
committerMalf Furious <m@lfurio.us>2018-10-27 18:28:22 -0400
commit0421aa1b60f4fe6bf140888159c58059c1013588 (patch)
treec3285276f6c53b6789e2f6dc82cb3b0fd17b38a4 /app/class/mesg.class.php
parent495157341d60522084dcc9f6219877b6ba497312 (diff)
parent6512655aee73d3d295daa4de0e4ef25c08cfec9e (diff)
downloadscrott-0.1.tar.gz
scrott-0.1.zip
Merge branch 'rel/v0.1'v0.1
Diffstat (limited to 'app/class/mesg.class.php')
-rw-r--r--app/class/mesg.class.php341
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;
+ }
+}
+
+?>