summaryrefslogblamecommitdiffstats
path: root/app/class/mesg.class.php
blob: 6c84d4f8bb879e9ca3afd75f9c18a66461a4e292 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                                                         

                                     







                                                                        




                                                     


























































































































































































































                                                                                           






                                                                             
     
























                                                                         


  
<?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;
    }
}

?>