diff options
author | Malf Furious <m@lfurio.us> | 2017-06-04 22:28:09 -0400 |
---|---|---|
committer | Malf Furious <m@lfurio.us> | 2017-06-04 22:28:09 -0400 |
commit | 2376aabe74528b018189982224d61a643325b114 (patch) | |
tree | 3aa16bc3dd40b1a7dd1a1f524d71a6c16055e716 /app | |
parent | 6b69e5a8f85ebdf92b84e3330bea306d4a90a115 (diff) | |
parent | a8e79321426b1436f46ba5b7c5dee390c94bdb8b (diff) | |
download | scrott-2376aabe74528b018189982224d61a643325b114.tar.gz scrott-2376aabe74528b018189982224d61a643325b114.zip |
Merge branch 'feature/mesgs' into dev
Diffstat (limited to 'app')
-rw-r--r-- | app/class/issue.class.php | 18 | ||||
-rw-r--r-- | app/class/mesg.class.php | 287 | ||||
-rw-r--r-- | app/class/object.class.php | 18 | ||||
-rw-r--r-- | app/df.php | 16 | ||||
-rw-r--r-- | app/dynmic/attach/.gitignore | 3 |
5 files changed, 321 insertions, 21 deletions
diff --git a/app/class/issue.class.php b/app/class/issue.class.php index 3127a87..6056457 100644 --- a/app/class/issue.class.php +++ b/app/class/issue.class.php @@ -63,24 +63,6 @@ class issue extends object } /* - * Get all activity for this issue. Messages are sorted by date - * created. - */ - public function getMesgs_ordByDatetime() : array - { - $query = "SELECT guid FROM objects WHERE objtype = 'mesg' AND " . - "parent = '" . database::esc($this->guid) . "' ORDER BY created"; - $res = database::query($query); - - $mesgs = array(); - - foreach ($res as $m) - $mesgs[] = new mesg($m['guid']); - - return $mesgs; - } - - /* * Reset the seen flag and reassign this issue. */ public function assignTo(user $assignee) : void diff --git a/app/class/mesg.class.php b/app/class/mesg.class.php new file mode 100644 index 0000000..6c84d4f --- /dev/null +++ b/app/class/mesg.class.php @@ -0,0 +1,287 @@ +<?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/object.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 object +{ + /* + * 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, object $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, object $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(array $file) : bool + { + $path = "dynmic/attach/" . $this->guid; + $origName = ""; + + $ret = saveFile($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; + } +} + +?> diff --git a/app/class/object.class.php b/app/class/object.class.php index 7c80b5b..461f1b1 100644 --- a/app/class/object.class.php +++ b/app/class/object.class.php @@ -163,6 +163,24 @@ class object extends table } /* + * Get all messages on this object. Messages are sorted by date + * created. + */ + public function getMesgs_ordByDatetime() : array + { + $query = "SELECT guid FROM objects WHERE objtype = 'mesg' AND " . + "parent = '" . database::esc($this->guid) . "' ORDER BY created"; + $res = database::query($query); + + $mesgs = array(); + + foreach ($res as $m) + $mesgs[] = new mesg($m['guid']); + + return $mesgs; + } + + /* * Get the URL to the head image resource for this object */ public function getHeadImg() : string @@ -13,6 +13,7 @@ */ require_once "class/user.class.php"; +require_once "class/mesg.class.php"; /* * This file is a proxy script for fetching resources from the /dynmic @@ -31,15 +32,19 @@ require_once "class/user.class.php"; * request. When finished, this function will exit PHP and terminate * this script. */ -function serveResource(string $uri) : void +function serveResource(string $uri, ?string $filename = NULL) : void { $f = fopen($uri, "rb"); if (!$f) exit; - header("Content-type: " . mime_content_type($uri)); - header("Content-length: " . filesize($uri)); + header("Content-Type: " . mime_content_type($uri)); + header("Content-Length: " . filesize($uri)); + + if ($filename) + header("Content-Disposition: attachment; filename=\"" . $filename . "\""); + fpassthru($f); fclose($f); @@ -89,6 +94,11 @@ function main(string $dir, string $guid) : void case "bgs": serveResource("dynmic/bgs/" . $guid); break; + + case "attach": + $mesg = new mesg($guid); + serveResource("dynmic/attach/" . $guid, $mesg->attachment); + break; } } catch (Exception $e) diff --git a/app/dynmic/attach/.gitignore b/app/dynmic/attach/.gitignore new file mode 100644 index 0000000..e38384e --- /dev/null +++ b/app/dynmic/attach/.gitignore @@ -0,0 +1,3 @@ +# Track empty directory +* +!.gitignore |