public function create($values, $wheres = array())
 {
     if (in_array($values["type"], array("select", "radios", "checkboxes"))) {
         $this->validate("options", $values["options"], array($this, "validateOptions"));
     }
     if ($this->errorCount()) {
         return false;
     }
     return parent::create($values);
 }
Пример #2
0
 public function setData($values)
 {
     if (!isset($values["title"])) {
         $values["title"] = "";
     }
     $this->validate("title", $values["title"], array($this, "validateTitle"));
     if (!isset($values["menu"])) {
         $values["menu"] = "user";
     }
     $this->validate("menu", $values["menu"], array($this, "validateMenu"));
     if (!isset($values["slug"])) {
         $values["slug"] = "";
     }
     $this->validate("slug", $values["slug"], array($this, "validateSlug"));
     $values["slug"] = slug($values["slug"]);
     if ($this->errorCount()) {
         return false;
     }
     $pageId = parent::create($values);
     return $pageId;
 }
Пример #3
0
 public function __construct($table = "", $primaryKey = "")
 {
     parent::__construct("conversation_tags", "conversationId");
 }
Пример #4
0
 /**
  * Class constructor. Sets up the inherited model functions to handle data in the search table
  * (used for logging search activity -> flood control.)
  *
  * @return void
  */
 public function __construct()
 {
     parent::__construct("search");
 }
Пример #5
0
 /**
  * Create a new activity entry in the database. If the specified activity type has an email projection
  * handler, this method will also send an email notification where appropriate.
  *
  * @todo Add an unsubscribe link to notification email footers.
  *
  * @param string $type The name of the type of activity to create.
  * @param array $member An array of details for the member to create the activity for.
  * @param array $fromMember An array of details for the member that the activity is from.
  * @param array $data An array of custom data that can be used by the type/projection callback functions.
  * @param array $emailData An array of custom data that can be used only by the EMAIL projection callback function.
  *		(i.e. it is not stored in the database.)
  * @return bool|int The activity ID, or false if there were errors.
  */
 public function create($type, $member, $fromMember = null, $data = null, $emailData = null)
 {
     // Make sure we have a definition for this type of activity.
     if (empty(self::$types[$type])) {
         throw new Exception("Cannot create activity with non-existent type '{$type}'.");
     }
     // Get the projections that are handled by this type.
     $projections = self::$types[$type];
     // Construct an array of information about the new activity.
     $activity = array("type" => $type, "memberId" => $member["memberId"], "fromMemberId" => $fromMember ? $fromMember["memberId"] : null, "conversationId" => isset($data["conversationId"]) ? $data["conversationId"] : null, "postId" => isset($data["postId"]) ? $data["postId"] : null, "time" => time());
     $activityId = null;
     // If this activity type has notification or activity projections, we'll need to insert the activity into the database.
     if (!empty($projections[self::PROJECTION_NOTIFICATION]) or !empty($projections[self::PROJECTION_ACTIVITY])) {
         $activityId = parent::create($activity + array("data" => serialize($data)));
     }
     // Set some more information about the activity.
     $activity["data"] = (array) $data + (array) $emailData;
     $activity["fromMemberName"] = $fromMember ? $fromMember["username"] : null;
     $activity["activityId"] = $activityId;
     // If this activity type has an email projection, the member wants to receive an email notification
     // for this type, and we haven't set sent them one in a previous call of this method, then let's send one!
     if (!empty($projections[self::PROJECTION_EMAIL]) and !empty($member["preferences"]["email.{$type}"]) and !in_array($member["memberId"], $this->membersUsed)) {
         // Log the member as "used", so we don't send them any more email notifications about the same subject.
         $this->membersUsed[] = $member["memberId"];
         // Load the member's language into esoTalk's memory.
         ET::saveLanguageState();
         ET::loadLanguage(@$member["preferences"]["language"]);
         // Get the email content by calling the type's email projection function.
         list($subject, $body) = call_user_func($projections[self::PROJECTION_EMAIL], $activity, $member);
         // Send the email, prepending/appending a common email header/footer.
         sendEmail($member["email"], $subject, sprintf(T("email.header"), $member["username"]) . $body . sprintf(T("email.footer"), URL("settings", true)));
         // Revert back to esoTalk's old language definitions.
         ET::revertLanguageState();
     }
     return $activity["activityId"];
 }
Пример #6
0
 /**
  * Update a member's details.
  *
  * @param array $values An array of fields to update and their values.
  * @param array $wheres An array of WHERE conditions.
  * @return bool|ETSQLResult
  */
 public function update($values, $wheres = array())
 {
     if (isset($values["username"])) {
         $this->validate("username", $values["username"], array($this, "validateUsername"));
     }
     if (isset($values["email"])) {
         $this->validate("email", $values["email"], array($this, "validateEmail"));
     }
     if (isset($values["password"])) {
         $this->validate("password", $values["password"], array($this, "validatePassword"));
         $values["password"] = $this->hashPassword($values["password"]);
     }
     // MD5 the "reset password" hash for storage (for extra safety).
     if (isset($values["resetPassword"])) {
         $values["resetPassword"] = md5($values["resetPassword"]);
     }
     if ($this->errorCount()) {
         return false;
     }
     return parent::update($values, $wheres);
 }
Пример #7
0
 /**
  * Delete a channel and its conversations (or optionally move its conversations to another channel.)
  *
  * @param int $channelId The ID of the channel to delete.
  * @param bool|int $moveToChannelId The ID of the channel to move conversations to, or false to delete them.
  * @return bool true on success, false on error.
  */
 public function deleteById($channelId, $moveToChannelId = false)
 {
     $channelId = (int) $channelId;
     // Do we want to move the conversations to another channel?
     if ($moveToChannelId !== false) {
         // If the channel does exist, move all the conversation over to it.
         if (array_key_exists((int) $moveToChannelId, $this->getAll())) {
             ET::SQL()->update("conversation")->set("channelId", (int) $moveToChannelId)->where("channelId=:channelId")->bind(":channelId", $channelId)->exec();
         } else {
             $this->error("moveToChannelId", "invalidChannel");
         }
     } else {
         ET::conversationModel()->delete(array("channelId" => $channelId));
     }
     if ($this->errorCount()) {
         return false;
     }
     $result = parent::deleteById($channelId);
     // Reset channels in the global cache.
     ET::$cache->remove(self::CACHE_KEY);
     return $result;
 }
Пример #8
0
 /**
  * Start a new converastion. Assumes the creator is the currently logged in user.
  *
  * @param array $data An array of the conversation's details: title, channelId, content.
  * @param array $membersAllowed An array of entities allowed to view the conversation, in the same format
  * 		as the return value of getMembersAllowed()
  * @param bool $isDraft Whether or not the conversation is a draft.
  * @return bool|array An array containing the new conversation ID and the new post ID, or false if
  * 		there was an error.
  */
 public function create($data, $membersAllowed = array(), $isDraft = false)
 {
     // We can't do this if we're not logged in.
     if (!ET::$session->user) {
         return false;
     }
     // If the title is blank but the user is only saving a draft, call it "Untitled conversation."
     if ($isDraft and !$data["title"]) {
         $data["title"] = T("Untitled conversation");
     }
     // Check for errors; validate the title and the post content.
     $this->validate("title", $data["title"], array($this, "validateTitle"));
     $this->validate("content", $data["content"], array(ET::postModel(), "validateContent"));
     $content = $data["content"];
     unset($data["content"]);
     // Flood control!
     if (ET::$session->isFlooding()) {
         $this->error("flooding", "waitToReply");
     }
     // Make sure that we have permission to post in this channel.
     $data["channelId"] = (int) $data["channelId"];
     if (!ET::channelModel()->hasPermission($data["channelId"], "start")) {
         $this->error("channelId", "invalidChannel");
     }
     // Did we encounter any errors? Don't continue.
     if ($this->errorCount()) {
         return false;
     }
     // Add some more data fields to insert into the database.
     $time = time();
     $data["startMemberId"] = ET::$session->userId;
     $data["startTime"] = $time;
     $data["lastPostMemberId"] = ET::$session->userId;
     $data["lastPostTime"] = $time;
     $data["private"] = !empty($membersAllowed);
     $data["countPosts"] = $isDraft ? 0 : 1;
     // Insert the conversation into the database.
     $conversationId = parent::create($data);
     // Update the member's conversation count.
     ET::SQL()->update("member")->set("countConversations", "countConversations + 1", false)->where("memberId", ET::$session->userId)->exec();
     // Update the channel's converastion count.
     ET::SQL()->update("channel")->set("countConversations", "countConversations + 1", false)->where("channelId", $data["channelId"])->exec();
     // Whip up a little array fo conversation details for this model's functions to work with.
     $conversation = array("conversationId" => $conversationId, "title" => $data["title"], "canReply" => true, "labels" => array());
     // Add the first post or save the draft.
     $postId = null;
     if ($isDraft) {
         $this->setDraft($conversation, ET::$session->userId, $content);
     } else {
         $postId = ET::postModel()->create($conversationId, ET::$session->userId, $content);
         // If the conversation is private, send out notifications to the allowed members.
         if (!empty($membersAllowed)) {
             $memberIds = array();
             foreach ($membersAllowed as $member) {
                 if ($member["type"] == "member") {
                     $memberIds[] = $member["id"];
                 }
             }
             ET::conversationModel()->privateAddNotification($conversation, $memberIds, true);
         }
     }
     // If the conversation is private, add the allowed members to the database.
     if (!empty($membersAllowed)) {
         $inserts = array();
         foreach ($membersAllowed as $member) {
             $inserts[] = array($conversationId, $member["type"], $member["id"], 1);
         }
         ET::SQL()->insert("member_conversation")->setMultiple(array("conversationId", "type", "id", "allowed"), $inserts)->setOnDuplicateKey("allowed", 1)->exec();
     }
     return array($conversationId, $postId);
 }
 /**
  * Start a new converastion. Assumes the creator is the currently logged in user.
  *
  * @param array $data An array of the conversation's details: title, channelId, content.
  * @param array $membersAllowed An array of entities allowed to view the conversation, in the same format
  * 		as the return value of getMembersAllowed()
  * @param bool $isDraft Whether or not the conversation is a draft.
  * @return bool|array An array containing the new conversation ID and the new post ID, or false if
  * 		there was an error.
  */
 public function create($data, $membersAllowed = array(), $isDraft = false)
 {
     // We can't do this if we're not logged in.
     if (!ET::$session->user) {
         return false;
     }
     // If the title is blank but the user is only saving a draft, call it "Untitled conversation."
     if ($isDraft and !$data["title"]) {
         $data["title"] = T("Untitled conversation");
     }
     // Check for errors; validate the title and the post content.
     $this->validate("title", $data["title"], array($this, "validateTitle"));
     $this->validate("content", $data["content"], array(ET::postModel(), "validateContent"));
     $content = $data["content"];
     unset($data["content"]);
     // Flood control!
     if (ET::$session->isFlooding()) {
         $this->error("flooding", sprintf(T("message.waitToReply"), C("esoTalk.conversation.timeBetweenPosts")));
     }
     // Make sure that we have permission to post in this channel.
     $data["channelId"] = (int) $data["channelId"];
     if (!ET::channelModel()->hasPermission($data["channelId"], "start")) {
         $this->error("channelId", "invalidChannel");
     }
     // Did we encounter any errors? Don't continue.
     if ($this->errorCount()) {
         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();
     // Add some more data fields to insert into the database.
     $time = time();
     $data["startMemberId"] = ET::$session->userId;
     $data["startTime"] = $time;
     $data["lastPostMemberId"] = ET::$session->userId;
     $data["lastPostTime"] = $time;
     $data["private"] = !empty($membersAllowed);
     $data["countPosts"] = $isDraft ? 0 : 1;
     // Insert the conversation into the database.
     $conversationId = parent::create($data);
     // Update the member's conversation count.
     ET::SQL()->update("member")->set("countConversations", "countConversations + 1", false)->where("memberId", ET::$session->userId)->exec();
     // Update the channel's converastion count.
     ET::SQL()->update("channel")->set("countConversations", "countConversations + 1", false)->where("channelId", $data["channelId"])->exec();
     // Get our newly created conversation.
     $conversation = $this->getById($conversationId);
     // Add the first post or save the draft.
     $postId = null;
     if ($isDraft) {
         $this->setDraft($conversation, ET::$session->userId, $content);
     } else {
         $postId = ET::postModel()->create($conversationId, ET::$session->userId, $content, $conversation["title"]);
         // If the conversation is private, send out notifications to the allowed members.
         if (!empty($membersAllowed)) {
             $memberIds = array();
             foreach ($membersAllowed as $member) {
                 if ($member["type"] == "member") {
                     $memberIds[] = $member["id"];
                 }
             }
             ET::conversationModel()->privateAddNotification($conversation, $memberIds, true, $content);
         }
     }
     // If the conversation is private, add the allowed members to the database.
     if (!empty($membersAllowed)) {
         $inserts = array();
         foreach ($membersAllowed as $member) {
             $inserts[] = array($conversationId, $member["type"], $member["id"], 1);
         }
         ET::SQL()->insert("member_conversation")->setMultiple(array("conversationId", "type", "id", "allowed"), $inserts)->setOnDuplicateKey("allowed", 1)->exec();
     }
     // If the user has the "star on reply" or "star private" preferences checked, star the conversation.
     if (ET::$session->preference("starOnReply") or $conversation["private"] and ET::$session->preference("starPrivate")) {
         $this->setStatus($conversation["conversationId"], ET::$session->userId, array("starred" => true));
     }
     $this->trigger("createAfter", array($conversation, $postId, $content));
     ET::activityModel()->endNotificationGroup();
     return array($conversationId, $postId);
 }
 public function __construct()
 {
     parent::__construct("reputation");
 }
Пример #11
0
 /**
  * Create a post in the specified conversation.
  *
  * This function will go through the post content and notify any members who are @mentioned.
  *
  * @param int $conversationId The ID of the conversation to create the post in.
  * @param int $memberId The ID of the author of the post.
  * @param string $content The post content.
  * @param string $title The title of the conversation (so it can be added alongside the post, for fulltext purposes.)
  * @return bool|int The new post's ID, or false if there were errors.
  */
 public function create($conversationId, $memberId, $content, $title = "")
 {
     // Validate the post content.
     $this->validate("content", $content, array($this, "validateContent"));
     if ($this->errorCount()) {
         return false;
     }
     // Prepare the post details for the query.
     $data = array("conversationId" => $conversationId, "memberId" => $memberId, "time" => time(), "content" => $content, "title" => $title);
     $id = parent::create($data);
     // Update the member's post count.
     ET::SQL()->update("member")->set("countPosts", "countPosts + 1", false)->where("memberId", $memberId)->exec();
     // Update the channel's post count.
     ET::SQL()->update("channel")->set("countPosts", "countPosts + 1", false)->where("channelId", ET::SQL()->select("channelId")->from("conversation")->where("conversationId=:conversationId")->bind(":conversationId", $conversationId)->exec()->result())->exec();
     // Parse the post content for @mentions, and notify any members who were mentioned.
     if (C("esoTalk.format.mentions")) {
         $names = ET::formatter()->getMentions($content);
         if (count($names)) {
             // Get the member details from the database.
             $sql = ET::SQL()->where("m.username IN (:names)")->bind(":names", $names)->where("m.memberId != :userId")->bind(":userId", $memberId);
             $members = ET::memberModel()->getWithSQL($sql);
             $data = array("conversationId" => $conversationId, "postId" => (int) $id, "title" => $title);
             $emailData = array("content" => $content);
             $i = 0;
             foreach ($members as $member) {
                 // Only send notifications to the first 10 members who are mentioned to prevent abuse of the system.
                 if ($i++ > 10) {
                     break;
                 }
                 // Check if this member is allowed to view this conversation before sending them a notification.
                 $sql = ET::SQL()->select("conversationId")->from("conversation c")->where("conversationId", $conversationId);
                 ET::conversationModel()->addAllowedPredicate($sql, $member);
                 if (!$sql->exec()->numRows()) {
                     continue;
                 }
                 ET::activityModel()->create("mention", $member, ET::$session->user, $data, $emailData);
             }
         }
     }
     return $id;
 }
Пример #12
0
 /**
  * Update a member's details.
  *
  * @param array $values An array of fields to update and their values.
  * @param array $wheres An array of WHERE conditions.
  * @return bool|ETSQLResult
  */
 public function update($values, $wheres = array())
 {
     if (isset($values["username"])) {
         $values["username"] = trim($values["username"]);
         $this->validate("username", $values["username"], array($this, "validateUsername"));
     }
     if (isset($values["email"])) {
         $this->validate("email", $values["email"], array($this, "validateEmail"));
     }
     if (isset($values["password"])) {
         $this->validate("password", $values["password"], array($this, "validatePassword"));
         $values["password"] = $this->hashPassword($values["password"]);
     }
     // Serialize preferences.
     if (isset($values["preferences"])) {
         $values["preferences"] = serialize($values["preferences"]);
     }
     if ($this->errorCount()) {
         return false;
     }
     return parent::update($values, $wheres);
 }
Пример #13
0
 /**
  * Class constructor; sets up the base model functions to use the group table.
  *
  * @return void
  */
 public function __construct()
 {
     parent::__construct("group");
 }
 public function __construct()
 {
     parent::__construct("attachment");
 }