/** * Add a reply to an existing conversation. Assumes the creator is the currently logged in user. * * @param array $conversation The conversation to add the reply to. The conversation's details will * be updated (post count, last post time, etc.) * @param string $content The post content. * @return int|bool The new post's ID, or false if there was an error. */ public function addReply(&$conversation, $content) { // We can't do this if we're not logged in. if (!ET::$session->user) { return false; } // Flood control! if (ET::$session->isFlooding()) { $this->error("flooding", sprintf(T("message.waitToReply"), C("esoTalk.conversation.timeBetweenPosts"))); return false; } // Start a notification group. This means that for all notifications sent out until endNotifcationGroup // is called, each individual user will receive a maximum of one. ET::activityModel()->startNotificationGroup(); // Create the post. If there were validation errors, get them from the post model and add them to this model. $postModel = ET::postModel(); $postId = $postModel->create($conversation["conversationId"], ET::$session->userId, $content, $conversation["title"]); if (!$postId) { $this->error($postModel->errors()); } // Did we encounter any errors? Don't continue. if ($this->errorCount()) { return false; } // Update the conversations table with the new post count, last post/action times, and last post member. $time = time(); $update = array("countPosts" => ET::raw("countPosts + 1"), "lastPostMemberId" => ET::$session->userId, "lastPostTime" => $time); // Also update the conversation's start time if this is the first post. if ($conversation["countPosts"] == 0) { $update["startTime"] = $time; } $this->updateById($conversation["conversationId"], $update); // If the user had a draft saved in this conversation before adding this reply, erase it now. // Also, if the user has the "star on reply" option checked, star the conversation. $update = array(); if ($conversation["draft"]) { $update["draft"] = null; } if (ET::$session->preference("starOnReply")) { $update["starred"] = true; } if (count($update)) { $this->setStatus($conversation["conversationId"], ET::$session->userId, $update); } // Send out notifications to people who have starred this conversation. // We get all members who have starred the conversation and have no unread posts in it. $sql = ET::SQL()->from("member_conversation s", "s.conversationId=:conversationId AND s.type='member' AND s.id=m.memberId AND s.starred=1 AND s.lastRead>=:posts AND s.id!=:userId", "inner")->bind(":conversationId", $conversation["conversationId"])->bind(":posts", $conversation["countPosts"])->bind(":userId", ET::$session->userId); $members = ET::memberModel()->getWithSQL($sql); $data = array("conversationId" => $conversation["conversationId"], "postId" => $postId, "title" => $conversation["title"]); $emailData = array("content" => $content); foreach ($members as $member) { ET::activityModel()->create("post", $member, ET::$session->user, $data, $emailData); } // Update the conversation details. $conversation["countPosts"]++; $conversation["lastPostTime"] = $time; $conversation["lastPostMemberId"] = ET::$session->userId; // If this is the first reply (ie. the conversation was a draft and now it isn't), send notifications to // members who are in the membersAllowed list. if ($conversation["countPosts"] == 1 and !empty($conversation["membersAllowed"])) { $memberIds = array(); foreach ($conversation["membersAllowed"] as $member) { if ($member["type"] == "member") { $memberIds[] = $member["id"]; } } $this->privateAddNotification($conversation, $memberIds, true); } $this->trigger("addReplyAfter", array($conversation, $postId, $content)); ET::activityModel()->endNotificationGroup(); return $postId; }