function WriteDiscussion($Discussion, &$Sender, &$Session, $Alt) { $CssClass = 'Item'; $CssClass .= $Discussion->Bookmarked == '1' ? ' Bookmarked' : ''; $CssClass .= $Alt . ' '; $CssClass .= $Discussion->Announce == '1' ? ' Announcement' : ''; $CssClass .= $Discussion->Closed == '1' ? ' Closed' : ''; $CssClass .= $Discussion->InsertUserID == $Session->UserID ? ' Mine' : ''; $CssClass .= $Discussion->CountUnreadComments > 0 && $Session->IsValid() ? ' New' : ''; $Sender->EventArguments['Discussion'] =& $Discussion; $Sender->FireEvent('BeforeDiscussionName'); $DiscussionName = Gdn_Format::Text($Discussion->Name); if ($DiscussionName == '') { $DiscussionName = T('Blank Discussion Topic'); } static $FirstDiscussion = TRUE; if (!$FirstDiscussion) { $Sender->FireEvent('BetweenDiscussion'); } else { $FirstDiscussion = FALSE; } ?> <li class="<?php echo $CssClass; ?> "> <?php if ($Discussion->FirstPhoto != '') { if (strtolower(substr($Discussion->FirstPhoto, 0, 7)) == 'http://' || strtolower(substr($Discussion->FirstPhoto, 0, 8)) == 'https://') { $PhotoUrl = $Discussion->FirstPhoto; } else { $PhotoUrl = 'uploads/' . ChangeBasename($Discussion->FirstPhoto, 'n%s'); } echo Img($PhotoUrl, array('alt' => $Discussion->FirstName)); } ?> <div class="ItemContent Discussion"> <?php echo Anchor($DiscussionName, '/discussion/' . $Discussion->DiscussionID . '/' . Gdn_Format::Url($Discussion->Name) . ($Discussion->CountCommentWatch > 0 && C('Vanilla.Comments.AutoOffset') ? '/#Item_' . $Discussion->CountCommentWatch : ''), 'Title'); ?> <?php $Sender->FireEvent('AfterDiscussionTitle'); ?> <div class="Meta"> <span class="Author"><?php echo $Discussion->FirstName; ?> </span> <?php echo '<span class="Counts' . ($Discussion->CountUnreadComments > 0 ? ' NewCounts' : '') . '">' . ($Discussion->CountUnreadComments > 0 ? $Discussion->CountUnreadComments . '/' : '') . $Discussion->CountComments . '</span>'; if ($Discussion->LastCommentID != '') { echo '<span class="LastCommentBy">' . sprintf(T('Latest %1$s'), $Discussion->LastName) . '</span> '; } echo '<span class="LastCommentDate">' . Gdn_Format::Date($Discussion->FirstDate) . '</span> '; ?> </div> </div> </li> <?php }
public function Index($Offset = 0, $Limit = NULL) { $this->AddJsFile('/js/library/jquery.gardenmorepager.js'); $this->AddJsFile('search.js'); $this->Title(T('Search')); if (!is_numeric($Limit)) { $Limit = Gdn::Config('Garden.Search.PerPage', 20); } $Search = $this->Form->GetFormValue('Search'); $ResultSet = $this->SearchModel->Search($Search, $Offset, $Limit); $this->SetData('SearchResults', $ResultSet, TRUE); $this->SetData('SearchTerm', Gdn_Format::Text($Search), TRUE); if ($ResultSet) { $NumResults = $ResultSet->NumRows(); } else { $NumResults = 0; } if ($NumResults == $Offset + $Limit) { $NumResults++; } // Build a pager $PagerFactory = new Gdn_PagerFactory(); $Pager = $PagerFactory->GetPager('MorePager', $this); $Pager->MoreCode = 'More Results'; $Pager->LessCode = 'Previous Results'; $Pager->ClientID = 'Pager'; $Pager->Configure($Offset, $Limit, $NumResults, 'dashboard/search/%1$s/%2$s/?Search=' . Gdn_Format::Url($Search)); $this->SetData('Pager', $Pager, TRUE); if ($this->_DeliveryType != DELIVERY_TYPE_ALL) { $this->SetJson('LessRow', $this->Pager->ToString('less')); $this->SetJson('MoreRow', $this->Pager->ToString('more')); $this->View = 'results'; } $this->Render(); }
/** * Award a badge to a user and record some activity * * @param int $BadgeID * @param int $UserID This is the user that should get the award * @param int $InsertUserID This is the user that gave the award * @param string $Reason This is the reason the giver gave with the award */ public function Award($BadgeID, $UserID, $InsertUserID = NULL, $Reason = '') { $Badge = Yaga::BadgeModel()->GetByID($BadgeID); if (!empty($Badge)) { if (!$this->Exists($UserID, $BadgeID)) { $this->SQL->Insert('BadgeAward', array('BadgeID' => $BadgeID, 'UserID' => $UserID, 'InsertUserID' => $InsertUserID, 'Reason' => $Reason, 'DateInserted' => date(DATE_ISO8601))); // Record the points for this badge UserModel::GivePoints($UserID, $Badge->AwardValue, 'Badge'); // Increment the user's badge count $this->SQL->Update('User')->Set('CountBadges', 'CountBadges + 1', FALSE)->Where('UserID', $UserID)->Put(); if (is_null($InsertUserID)) { $InsertUserID = Gdn::Session()->UserID; } // Record some activity $ActivityModel = new ActivityModel(); $Activity = array('ActivityType' => 'BadgeAward', 'ActivityUserID' => $UserID, 'RegardingUserID' => $InsertUserID, 'Photo' => $Badge->Photo, 'RecordType' => 'Badge', 'RecordID' => $BadgeID, 'Route' => '/badges/detail/' . $Badge->BadgeID . '/' . Gdn_Format::Url($Badge->Name), 'HeadlineFormat' => T('Yaga.Badge.EarnedHeadlineFormat'), 'Data' => array('Name' => $Badge->Name), 'Story' => $Badge->Description); // Create a public record $ActivityModel->Queue($Activity, FALSE); // TODO: enable the grouped notifications after issue #1776 is resolved , array('GroupBy' => 'Route')); // Notify the user of the award $Activity['NotifyUserID'] = $UserID; $ActivityModel->Queue($Activity, 'BadgeAward', array('Force' => TRUE)); // Actually save the activity $ActivityModel->SaveQueue(); $this->EventArguments['UserID'] = $UserID; $this->FireEvent('AfterBadgeAward'); } } }
public function AddLabel($Name, $Code = '', $Url = '') { if ($Code == '') { $Code = Gdn_Format::Url(ucwords(trim(Gdn_Format::PlainText($Name)))); } $this->_Labels[] = array('Name' => $Name, 'Code' => $Code, 'Url' => $Url); }
public function Search($Search, $Offset = 0, $Limit = 20) { $BaseUrl = C('Plugins.Solr.SearchUrl', 'http://localhost:8983/solr/select/?'); if (!$BaseUrl) { throw new Gdn_UserException("The search url has not been configured."); } if (!$Search) { return array(); } // Escepe the search. $Search = preg_replace('`([][+&|!(){}^"~*?:\\\\-])`', "\\\\\$1", $Search); // Add the category watch. $Categories = CategoryModel::CategoryWatch(); if ($Categories === FALSE) { return array(); } elseif ($Categories !== TRUE) { $Search = 'CategoryID:(' . implode(' ', $Categories) . ') AND ' . $Search; } // Build the search url. $BaseUrl .= strpos($BaseUrl, '?') === FALSE ? '?' : '&'; $Query = array('q' => $Search, 'start' => $Offset, 'rows' => $Limit); $Url = $BaseUrl . http_build_query($Query); // Grab the data. $Curl = curl_init($Url); curl_setopt($Curl, CURLOPT_RETURNTRANSFER, 1); $CurlResult = curl_exec($Curl); curl_close($Curl); // Parse the result into the form that the search controller expects. $Xml = new SimpleXMLElement($CurlResult); $Result = array(); if (!isset($Xml->result)) { return array(); } foreach ($Xml->result->children() as $Doc) { $Row = array(); foreach ($Doc->children() as $Field) { $Name = (string) $Field['name']; $Row[$Name] = (string) $Field; } // Add the url. switch ($Row['DocType']) { case 'Discussion': $Row['Url'] = '/discussion/' . $Row['PrimaryID'] . '/' . Gdn_Format::Url($Row['Title']); break; case 'Comment': $Row['Url'] = "/discussion/comment/{$Row['PrimaryID']}/#Comment_{$Row['PrimaryID']}"; break; } // Fix the time. $Row['DateInserted'] = strtotime($Row['DateInserted']); $Result[] = $Row; } // Join the users into the result. Gdn_DataSet::Join($Result, array('table' => 'User', 'parent' => 'UserID', 'prefix' => '', 'Name', 'Photo')); return $Result; }
public function ProfileController_AfterAddSideMenu_Handler($Sender) { if (!Gdn::Session()->CheckPermission('Garden.SignIn.Allow')) { return; } $SideMenu = $Sender->EventArguments['SideMenu']; $ViewingUserID = Gdn::Session()->UserID; if ($Sender->User->UserID == $ViewingUserID) { $SideMenu->AddLink('Options', T('Quote Settings'), '/profile/quotes', FALSE, array('class' => 'Popup')); } else { $SideMenu->AddLink('Options', T('Quote Settings'), '/profile/quotes/' . $Sender->User->UserID . '/' . Gdn_Format::Url($Sender->User->Name), 'Garden.Users.Edit', array('class' => 'Popup')); } }
public function ProfileController_AfterAddSideMenu_Handler($Sender) { if (!Gdn::Session()->CheckPermission('Garden.Users.Edit') && $Sender->User->UserID !== Gdn::Session()->UserID) { return; } $SideMenu = $Sender->EventArguments['SideMenu']; $SessionUserID = Gdn::Session()->UserID; if ($Sender->User->UserID == $SessionUserID) { $SideMenu->AddLink('Options', T('My Profile Edit'), '/profile/myprofileedit/' . $Sender->User->UserID . '/' . Gdn_Format::Url($Sender->User->Name), FALSE, array('class' => 'Popup')); } else { $SideMenu->AddLink('Options', T('My Profile Edit'), '/profile/myprofileedit/' . $Sender->User->UserID . '/' . Gdn_Format::Url($Sender->User->Name), 'Garden.Users.Edit', array('class' => 'Popup')); } }
public function ProfileController_AfterAddSideMenu_Handler(&$Sender) { if (!C('Plugins.Signatures.Enabled')) { return; } $SideMenu = $Sender->EventArguments['SideMenu']; $Session = Gdn::Session(); $ViewingUserID = $Session->UserID; if ($Sender->User->UserID == $ViewingUserID) { $SideMenu->AddLink('Options', T('Signature Settings'), '/profile/signature', FALSE, array('class' => 'aaaaa')); } else { $SideMenu->AddLink('Options', T('Signature Settings'), '/profile/signature/' . $Sender->User->UserID . '/' . Gdn_Format::Url($Sender->User->Name), 'Garden.Users.Edit', array('class' => 'Popup')); } }
public function ToString() { echo '<div class="Box DonateBox">'; echo Wrap(T('Donation Box'), 'h4'); echo '<ul class="PanelInfo">'; echo '<p></p>'; echo T("Your Donations will help keep this forum afloat"); echo '<p></p>'; echo Anchor(Gdn_Format::Text("My donation link"), Gdn_Format::Url("/donations")); // edit the links above to the appropriate paypal or whatever donate links and image echo Wrap(T('Item 1'), 'li'); echo Wrap(T('Item 2'), 'li'); echo "</ul>"; echo "</div>"; }
public function DiscussionController_AutoExpire_Create($Sender, $Args) { $DiscussionID = intval($Args[0]); $DiscussionModel = new DiscussionModel(); $Discussion = $DiscussionModel->GetID($DiscussionID); if (!Gdn::Session()->CheckPermission('Vanilla.Discussions.Close', TRUE, 'Category', $Discussion->PermissionCategoryID)) { throw PermissionException('Vanilla.Discussions.Close'); } if (strtolower($Args[1]) == 'reset') { Gdn::SQL()->Put('Discussion', array('AutoExpire' => 1, 'Closed' => 0, 'DateReOpened' => Gdn_Format::ToDateTime()), array('DiscussionID' => $DiscussionID)); } else { $Expire = strtolower($Args[1]) == 'on' ? 1 : 0; Gdn::SQL()->Put('Discussion', array('AutoExpire' => $Expire), array('DiscussionID' => $DiscussionID)); } Redirect('discussion/' . $DiscussionID . '/' . Gdn_Format::Url($Discussion->Name)); }
public function Index() { $Session = Gdn::Session(); $categories = array(); $discussionsPerCategory = 4; $DiscussionModel = new DiscussionModel(); $this->CategoryData = $this->CategoryModel->GetFull(); $this->CategoryDiscussionData = array(); foreach ($this->CategoryData->Result() as $Category) { $this->Category = $Category; if ($Session->CheckPermission('Vanilla.Discussions.View', $this->Category->CategoryID)) { //TODO be nice if options could be passed to filter // discussions that are closed, sunk, etc etc... $this->DiscussionData = $DiscussionModel->Get(0, $discussionsPerCategory, array('d.CategoryID' => $Category->CategoryID)); $category = array(); foreach ($Category as $key => $value) { $category[$key] = $value; } #$category["CategoryURL"] = Gdn::Config('Garden.Domain')."/categories/".$Category->UrlCode; $category["CategoryURL"] = Gdn::Request()->Domain() . "/categories/" . $Category->UrlCode; if ($this->DiscussionData->NumRows() > 0) { $count = 0; $discussion = array(); $category["discussions"] = array(); foreach ($this->DiscussionData->Result() as $Discussion) { foreach ($Discussion as $key => $value) { $discussion[$key] = $value; } //$discussion["DiscussionURL"] = Gdn::Config('Garden.Domain').'/discussion/'.$Discussion->DiscussionID.'/'.Gdn_Format::Url($Discussion->Name); $discussion["DiscussionURL"] = Gdn::Request()->Domain() . '/discussion/' . $Discussion->DiscussionID . '/' . Gdn_Format::Url($Discussion->Name); if ($count++ < $discussionsPerCategory) { $category["discussions"][] = $discussion; } else { break; } } } $categories[] = $category; } } $this->SetJSON("categories", $categories); $this->Render(); }
<?php if (!defined('APPLICATION')) { exit; } // An individual discussion record for all panel modules to use when rendering a discussion list. ?> <li id="<?php echo 'Bookmark_' . $Discussion->DiscussionID; ?> "> <strong><?php echo Anchor($Discussion->Name, '/discussion/' . $Discussion->DiscussionID . '/' . Gdn_Format::Url($Discussion->Name) . ($Discussion->CountCommentWatch > 0 ? '/#Item_' . $Discussion->CountCommentWatch : ''), 'DiscussionLink'); ?> </strong> <div class="Meta"> <?php echo '<span>' . $Discussion->CountComments . '</span>'; $CountUnreadComments = $Discussion->CountComments - $Discussion->CountCommentWatch; // Logic for incomplete comment count. if ($Discussion->CountCommentWatch == 0 && ($DateLastViewed = GetValue('DateLastViewed', $Discussion))) { if (Gdn_Format::ToTimestamp($DateLastViewed) >= Gdn_Format::ToTimestamp($Discussion->LastDate)) { $CountUnreadComments = 0; $Discussion->CountCommentWatch = $Discussion->CountComments; } else { $CountUnreadComments = ''; } } if ($CountUnreadComments > 0 || $CountUnreadComments === '') { echo '<strong>' . trim(sprintf('%s new', $CountUnreadComments)) . '</strong>'; }
<?php if (!defined('APPLICATION')) exit(); $Session = Gdn::Session(); $CancelUrl = '/vanilla/discussions'; if (C('Vanilla.Categories.Use') && is_object($this->Category)) $CancelUrl = '/vanilla/discussions/0/'.$this->Category->CategoryID.'/'.Gdn_Format::Url($this->Category->Name); ?> <div id="DiscussionForm"> <h1><?php echo $this->Data('Title'); ?></h1> <?php echo $this->Form->Open(); echo $this->Form->Errors(); $this->FireEvent('BeforeFormInputs'); echo '<div class="P">'; echo $this->Form->Label('Discussion Title', 'Name'); echo Wrap($this->Form->TextBox('Name', array('maxlength' => 100, 'class' => 'InputBox BigInput')), 'div', array('class' => 'TextBoxWrapper')); echo '</div>'; if ($this->ShowCategorySelector === TRUE) { echo '<div class="P">'; echo '<div class="Category">'; echo $this->Form->Label('Category', 'CategoryID'), ' '; echo $this->Form->DropDown('CategoryID', $this->CategoryData, array('TextField' => 'Name', 'ValueField' => 'CategoryID')); echo '</div>'; echo '</div>'; } $this->FireEvent('BeforeBodyInput'); echo '<div class="P">'; echo Wrap($this->Form->TextBox('Body', array('MultiLine' => TRUE)), 'div', array('class' => 'TextBoxWrapper')); echo '</div>';
/** * Build the user profile: Set the page title, add data to page modules & add * modules to assets, Add tabs to tab menu. $this->User must be defined, * or this method will throw an exception. */ public function BuildProfile() { if (!is_object($this->User)) { throw new Exception(T('Cannot build profile information if user is not defined.')); } $Session = Gdn::Session(); $this->CssClass = 'Profile'; $this->Title(Gdn_Format::Text($this->User->Name)); if ($this->_DeliveryType != DELIVERY_TYPE_VIEW) { $UserInfoModule = new UserInfoModule($this); $UserInfoModule->User = $this->User; $UserInfoModule->Roles = $this->Roles; $this->AddModule($UserInfoModule); $this->AddJsFile('jquery.jcrop.pack.js'); $this->AddJsFile('profile.js'); $this->AddJsFile('activity.js'); $ActivityUrl = 'profile/activity/'; if ($this->User->UserID != $Session->UserID) { $ActivityUrl .= $this->User->UserID . '/' . Gdn_Format::Url($this->User->Name); } $this->AddProfileTab(T('Activity'), $ActivityUrl); if ($this->User->UserID == $Session->UserID) { $Notifications = T('Notifications'); $CountNotifications = $Session->User->CountNotifications; if (is_numeric($CountNotifications) && $CountNotifications > 0) { $Notifications .= '<span>' . $CountNotifications . '</span>'; } $this->AddProfileTab(array($Notifications => 'profile/notifications')); } $this->FireEvent('AddProfileTabs'); } return TRUE; }
/** * Add a method to the ModerationController to handle merging discussions. * @param Gdn_Controller $Sender */ public function ModerationController_MergeDiscussions_Create($Sender) { $Session = Gdn::Session(); $Sender->Form = new Gdn_Form(); $Sender->Title(T('Merge Discussions')); $DiscussionModel = new DiscussionModel(); $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array()); if (!is_array($CheckedDiscussions)) { $CheckedDiscussions = array(); } $DiscussionIDs = $CheckedDiscussions; $Sender->SetData('DiscussionIDs', $DiscussionIDs); $CountCheckedDiscussions = count($DiscussionIDs); $Sender->SetData('CountCheckedDiscussions', $CountCheckedDiscussions); $Discussions = $DiscussionModel->SQL->WhereIn('DiscussionID', $DiscussionIDs)->Get('Discussion')->ResultArray(); $Sender->SetData('Discussions', $Discussions); // Perform the merge if ($Sender->Form->AuthenticatedPostBack()) { // Create a new discussion record $MergeDiscussion = FALSE; $MergeDiscussionID = $Sender->Form->GetFormValue('MergeDiscussionID'); foreach ($Discussions as $Discussion) { if ($Discussion['DiscussionID'] == $MergeDiscussionID) { $MergeDiscussion = $Discussion; break; } } if ($MergeDiscussion) { $ErrorCount = 0; // Verify that the user has permission to perform the merge. $Category = CategoryModel::Categories($MergeDiscussion['CategoryID']); if ($Category && !$Category['PermsDiscussionsEdit']) { throw PermissionException('Vanilla.Discussions.Edit'); } // Assign the comments to the new discussion record $DiscussionModel->SQL->Update('Comment')->Set('DiscussionID', $MergeDiscussionID)->WhereIn('DiscussionID', $DiscussionIDs)->Put(); $CommentModel = new CommentModel(); foreach ($Discussions as $Discussion) { if ($Discussion['DiscussionID'] == $MergeDiscussionID) { continue; } // Create a comment out of the discussion. $Comment = ArrayTranslate($Discussion, array('Body', 'Format', 'DateInserted', 'InsertUserID', 'InsertIPAddress', 'DateUpdated', 'UpdateUserID', 'UpdateIPAddress', 'Attributes', 'Spam', 'Likes', 'Abuse')); $Comment['DiscussionID'] = $MergeDiscussionID; $CommentModel->Validation->Results(TRUE); $CommentID = $CommentModel->Save($Comment); if ($CommentID) { // Move any attachments (FileUpload plugin awareness) if (class_exists('MediaModel')) { $MediaModel = new MediaModel(); $MediaModel->Reassign($Discussion['DiscussionID'], 'discussion', $CommentID, 'comment'); } // Delete discussion that was merged $DiscussionModel->Delete($Discussion['DiscussionID']); } else { $Sender->InformMessage($CommentModel->Validation->ResultsText()); $ErrorCount++; } } // Update counts on all affected discussions. $CommentModel->UpdateCommentCount($MergeDiscussionID); $CommentModel->RemovePageCache($MergeDiscussionID); // Clear selections Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedDiscussions', FALSE); ModerationController::InformCheckedDiscussions($Sender); if ($ErrorCount == 0) { $Sender->RedirectUrl = Url("/discussion/{$MergeDiscussionID}/" . Gdn_Format::Url($MergeDiscussion['Name'])); } } } $Sender->Render('MergeDiscussions', '', 'plugins/SplitMerge'); }
public function UpdateCounts() { // This option could take a while so set the timeout. set_time_limit(60 * 5); // Define the necessary SQL. $Sqls = array(); if (!$this->ImportExists('Discussion', 'LastCommentID')) { $Sqls['Discussion.LastCommentID'] = $this->GetCountSQL('max', 'Discussion', 'Comment'); } if (!$this->ImportExists('Discussion', 'DateLastComment')) { $Sqls['Discussion.DateLastComment'] = "update :_Discussion d\r\n left join :_Comment c\r\n on d.LastCommentID = c.CommentID\r\n set d.DateLastComment = coalesce(c.DateInserted, d.DateInserted)"; } if (!$this->ImportExists('Discussion', 'CountBookmarks')) { $Sqls['Discussion.CountBookmarks'] = "update :_Discussion d\r\n set CountBookmarks = (\r\n select count(ud.DiscussionID)\r\n from :_UserDiscussion ud\r\n where ud.Bookmarked = 1\r\n and ud.DiscussionID = d.DiscussionID\r\n )"; } if (!$this->ImportExists('Discussion', 'LastCommentUserID')) { $Sqls['Discussion.LastCommentUseID'] = "update :_Discussion d\r\n join :_Comment c\r\n on d.LastCommentID = c.CommentID\r\n set d.LastCommentUserID = c.InsertUserID"; } if (!$this->ImportExists('Discussion', 'Body')) { // Update the body of the discussion if it isn't there. if (!$this->ImportExists('Discussion', 'FirstCommentID')) { $Sqls['Discussion.FirstCommentID'] = $this->GetCountSQL('min', 'Discussion', 'Comment', 'FirstCommentID', 'CommentID'); } $Sqls['Discussion.Body'] = "update :_Discussion d\r\n join :_Comment c\r\n on d.FirstCommentID = c.CommentID\r\n set d.Body = c.Body, d.Format = c.Format"; if ($this->ImportExists('Media') && Gdn::Structure()->TableExists('Media')) { // Comment Media has to go onto the discussion. $Sqls['Media.Foreign'] = "update :_Media m\r\n join :_Discussion d\r\n on d.FirstCommentID = m.ForeignID and m.ForeignTable = 'comment'\r\n set m.ForeignID = d.DiscussionID, m.ForeignTable = 'discussion'"; } $Sqls['Comment.FirstComment.Delete'] = "delete c.*\r\n from :_Comment c\r\n inner join :_Discussion d\r\n on d.FirstCommentID = c.CommentID"; } if (!$this->ImportExists('Discussion', 'CountComments')) { $Sqls['Discussion.CountComments'] = $this->GetCountSQL('count', 'Discussion', 'Comment'); } if ($this->ImportExists('UserDiscussion') && !$this->ImportExists('UserDiscussion', 'CountComments') && $this->ImportExists('UserDiscussion', 'DateLastViewed')) { $Sqls['UserDiscussuion.CountComments'] = "update :_UserDiscussion ud\r\n set CountComments = (\r\n select count(c.CommentID)\r\n from :_Comment c\r\n where c.DiscussionID = ud.DiscussionID\r\n and c.DateInserted <= ud.DateLastViewed)"; } if ($this->ImportExists('Tag') && $this->ImportExists('TagDiscussion')) { $Sqls['Tag.CoundDiscussions'] = $this->GetCountSQL('count', 'Tag', 'TagDiscussion', 'CountDiscussions', 'TagID'); } if ($this->ImportExists('Poll') && Gdn::Structure()->TableExists('Poll')) { $Sqls['PollOption.CountVotes'] = $this->GetCountSQL('count', 'PollOption', 'PollVote', 'CountVotes', 'PollOptionID'); $Sqls['Poll.CountOptions'] = $this->GetCountSQL('count', 'Poll', 'PollOption', 'CountOptions', 'PollID'); $Sqls['Poll.CountVotes'] = $this->GetCountSQL('sum', 'Poll', 'PollOption', 'CountVotes', 'CountVotes', 'PollID'); } if ($this->ImportExists('Activity', 'ActivityType')) { $Sqls['Activity.ActivityTypeID'] = "\r\n update :_Activity a\r\n join :_ActivityType t\r\n on a.ActivityType = t.Name\r\n set a.ActivityTypeID = t.ActivityTypeID"; } if ($this->ImportExists('Tag') && $this->ImportExists('TagDiscussion')) { $Sqls['Tag.CoundDiscussions'] = $this->GetCountSQL('count', 'Tag', 'TagDiscussion', 'CountDiscussions', 'TagID'); } $Sqls['Category.CountDiscussions'] = $this->GetCountSQL('count', 'Category', 'Discussion'); $Sqls['Category.CountComments'] = $this->GetCountSQL('sum', 'Category', 'Discussion', 'CountComments', 'CountComments'); if (!$this->ImportExists('Category', 'PermissionCategoryID')) { $Sqls['Category.PermissionCategoryID'] = "update :_Category set PermissionCategoryID = -1"; } if ($this->ImportExists('Conversation') && $this->ImportExists('ConversationMessage')) { $Sqls['Conversation.FirstMessageID'] = $this->GetCountSQL('min', 'Conversation', 'ConversationMessage', 'FirstMessageID', 'MessageID'); if (!$this->ImportExists('Conversation', 'CountMessages')) { $Sqls['Conversation.CountMessages'] = $this->GetCountSQL('count', 'Conversation', 'ConversationMessage', 'CountMessages', 'MessageID'); } if (!$this->ImportExists('Conversation', 'LastMessageID')) { $Sqls['Conversation.LastMessageID'] = $this->GetCountSQL('max', 'Conversation', 'ConversationMessage', 'LastMessageID', 'MessageID'); } if (!$this->ImportExists('Conversation', 'DateUpdated')) { $Sqls['Converstation.DateUpdated'] = "update :_Conversation c join :_ConversationMessage m on c.LastMessageID = m.MessageID set c.DateUpdated = m.DateInserted"; } if ($this->ImportExists('UserConversation')) { if (!$this->ImportExists('UserConversation', 'LastMessageID')) { if ($this->ImportExists('UserConversation', 'DateLastViewed')) { // Get the value from the DateLastViewed. $Sqls['UserConversation.LastMessageID'] = "update :_UserConversation uc\r\n set LastMessageID = (\r\n select max(MessageID)\r\n from :_ConversationMessage m\r\n where m.ConversationID = uc.ConversationID\r\n and m.DateInserted >= uc.DateLastViewed)"; } else { // Get the value from the conversation. // In this case just mark all of the messages read. $Sqls['UserConversation.LastMessageID'] = "update :_UserConversation uc\r\n join :_Conversation c\r\n on c.ConversationID = uc.ConversationID\r\n set uc.CountReadMessages = c.CountMessages,\r\n uc.LastMessageID = c.LastMessageID"; } } elseif (!$this->ImportExists('UserConversation', 'DateLastViewed')) { // We have the last message so grab the date from that. $Sqls['UserConversation.DateLastViewed'] = "update :_UserConversation uc\r\n join :_ConversationMessage m\r\n on m.ConversationID = uc.ConversationID\r\n and m.MessageID = uc.LastMessageID\r\n set uc.DateLastViewed = m.DateInserted"; } } } // User counts. if (!$this->ImportExists('User', 'DateFirstVisit')) { $Sqls['User.DateFirstVisit'] = 'update :_User set DateFirstVisit = DateInserted'; } if (!$this->ImportExists('User', 'CountDiscussions')) { $Sqls['User.CountDiscussions'] = $this->GetCountSQL('count', 'User', 'Discussion', 'CountDiscussions', 'DiscussionID', 'UserID', 'InsertUserID'); } if (!$this->ImportExists('User', 'CountComments')) { $Sqls['User.CountComments'] = $this->GetCountSQL('count', 'User', 'Comment', 'CountComments', 'CommentID', 'UserID', 'InsertUserID'); } if (!$this->ImportExists('User', 'CountBookmarks')) { $Sqls['User.CountBookmarks'] = "update :_User u\r\n set CountBookmarks = (\r\n select count(ud.DiscussionID)\r\n from :_UserDiscussion ud\r\n where ud.Bookmarked = 1\r\n and ud.UserID = u.UserID\r\n )"; } // if (!$this->ImportExists('User', 'CountUnreadConversations')) { // $Sqls['User.CountUnreadConversations'] = // 'update :_User u // set u.CountUnreadConversations = ( // select count(c.ConversationID) // from :_Conversation c // inner join :_UserConversation uc // on c.ConversationID = uc.ConversationID // where uc.UserID = u.UserID // and uc.CountReadMessages < c.CountMessages // )'; // } // The updates start here. $CurrentSubstep = GetValue('CurrentSubstep', $this->Data, 0); // $Sqls2 = array(); // $i = 1; // foreach ($Sqls as $Name => $Sql) { // $Sqls2[] = "/* $i. $Name */\n" // .str_replace(':_', $this->Database->DatabasePrefix, $Sql) // .";\n"; // $i++; // } // throw new Exception(implode("\n", $Sqls2)); // Execute the SQL. $Keys = array_keys($Sqls); for ($i = $CurrentSubstep; $i < count($Keys); $i++) { $this->Data['CurrentStepMessage'] = sprintf(T('%s of %s'), $CurrentSubstep + 1, count($Keys)); $Sql = $Sqls[$Keys[$i]]; $this->Query($Sql); if ($this->Timer->ElapsedTime() > $this->MaxStepTime) { $this->Data['CurrentSubstep'] = $i + 1; return FALSE; } } if (isset($this->Data['CurrentSubstep'])) { unset($this->Data['CurrentSubstep']); } $this->Data['CurrentStepMessage'] = ''; // Update the url codes of categories. if (!$this->ImportExists('Category', 'UrlCode')) { $Categories = CategoryModel::Categories(); $TakenCodes = array(); foreach ($Categories as $Category) { $UrlCode = urldecode(Gdn_Format::Url($Category['Name'])); if (strlen($UrlCode) > 50) { $UrlCode = $Category['CategoryID']; } if (in_array($UrlCode, $TakenCodes)) { $ParentCategory = CategoryModel::Categories($Category['ParentCategoryID']); if ($ParentCategory && $ParentCategory['CategoryID'] != -1) { $UrlCode = Gdn_Format::Url($ParentCategory['Name']) . '-' . $UrlCode; } if (in_array($UrlCode, $TakenCodes)) { $UrlCode = $Category['CategoryID']; } } $TakenCodes[] = $UrlCode; Gdn::SQL()->Put('Category', array('UrlCode' => $UrlCode), array('CategoryID' => $Category['CategoryID'])); } } // Rebuild the category tree. $CategoryModel = new CategoryModel(); $CategoryModel->RebuildTree(); $this->SetCategoryPermissionIDs(); return TRUE; }
public function PostController_Reply_Create($Sender, $EventArguments = '') { $Sender->View = $this->GetView('vanilla_post_reply.php'); $ReplyCommentID = 0; if (is_array($EventArguments) && array_key_exists(0, $EventArguments)) { $ReplyCommentID = is_numeric($EventArguments[0]) ? $EventArguments[0] : 0; } $ReplyModel = Gdn::Factory('ReplyModel'); $Sender->ReplyCommentID = $ReplyCommentID; // Set the model on the form. $Sender->Form->SetModel($ReplyModel); // Make sure the form knows which comment we're replying to $Sender->Form->AddHidden('ReplyCommentID', $ReplyCommentID); $Sender->ReplyComment = $Sender->CommentModel->GetID($ReplyCommentID); $Discussion = $Sender->DiscussionModel->GetID($Sender->ReplyComment->DiscussionID); $Sender->Permission('Vanilla.Comments.Add', $Discussion->CategoryID); if ($Sender->Form->AuthenticatedPostBack()) { $CommentID = $Sender->Form->Save(); if ($Sender->Form->ErrorCount() == 0) { // Redirect if this is not an ajax request if ($Sender->DeliveryType() == DELIVERY_TYPE_ALL) { $Discussion = $ReplyModel->GetDiscussion($CommentID); Redirect('/vanilla/discussion/' . $Discussion->DiscussionID . '/' . Gdn_Format::Url($Discussion->Name) . '#Comment_' . $CommentID); } // Load all new replies that the user hasn't seen yet $LastCommentID = $Sender->Form->GetFormValue('LastCommentID'); if (!is_numeric($LastCommentID)) { $LastCommentID = $CommentID - 1; } $Sender->ReplyData = $ReplyModel->GetNew($ReplyCommentID, $LastCommentID); $Sender->CurrentReply = is_object($Sender->ReplyData) ? $Sender->ReplyData->NextRow() : FALSE; $Replies = $Sender->ReplyComment->CountReplies + 1; $Sender->SetJson('Replies', sprintf(T(Plural($Replies, '%s Reply', '%s Replies')), $Replies)); $Sender->SetJson('CommentID', $CommentID); $Sender->Discussion = $Sender->DiscussionModel->GetID($Sender->ReplyComment->DiscussionID); $Sender->ControllerName = 'discussion'; $Sender->View = $this->GetView('replies.php'); } else { if ($Sender->DeliveryType() !== DELIVERY_TYPE_ALL) { // Handle ajax-based errors $Sender->StatusMessage = $Sender->Form->Errors(); } } } $Sender->Render(); }
$ScreenName = Gdn_Format::Display(GetValue('Name', $PluginInfo, $PluginName)); $SettingsUrl = $State == 'enabled' ? ArrayValue('SettingsUrl', $PluginInfo, '') : ''; $PluginUrl = ArrayValue('PluginUrl', $PluginInfo, ''); $Author = ArrayValue('Author', $PluginInfo, ''); $AuthorUrl = ArrayValue('AuthorUrl', $PluginInfo, ''); $NewVersion = ArrayValue('NewVersion', $PluginInfo, ''); $Upgrade = $NewVersion != '' && version_compare($NewVersion, $Version, '>'); $RowClass = $Css; if ($Alt) { $RowClass .= ' Alt'; } $IconPath = '/plugins/' . GetValue('Folder', $PluginInfo, '') . '/icon.png'; $IconPath = file_exists(PATH_ROOT . $IconPath) ? $IconPath : 'applications/dashboard/design/images/plugin-icon.png'; ?> <tr <?php echo 'id="' . Gdn_Format::Url(strtolower($PluginName)) . '-plugin"', ' class="More ' . $RowClass . '"'; ?> > <td rowspan="2" class="Less"><?php echo Img($IconPath, array('class' => 'PluginIcon')); ?> </td> <th><?php echo $ScreenName; ?> </th> <td class="Alt"><?php echo Gdn_Format::Html(GetValue('Description', $PluginInfo, '')); ?> </td> </tr>
function DiscussionLink($Discussion, $Extended = TRUE) { $DiscussionID = GetValue('DiscussionID', $Discussion); $DiscussionName = GetValue('Name', $Discussion); $Parts = array( 'discussion', $DiscussionID, Gdn_Format::Url($DiscussionName) ); if ($Extended) { $Parts[] = ($Discussion->CountCommentWatch > 0) ? '#Item_'.$Discussion->CountCommentWatch : ''; } return Url(implode('/',$Parts), TRUE); }
/** * Show activity feed for this user. * * @since 2.0.0 * @access public * @param mixed $UserReference Unique identifier, possible ID or username. * @param string $Username Username. * @param int $UserID Unique ID. * @param int $Offset How many to skip (for paging). */ public function Activity($UserReference = '', $Username = '', $UserID = '', $Page = '') { $this->Permission('Garden.Profiles.View'); $this->EditMode(FALSE); // Object setup $Session = Gdn::Session(); $this->ActivityModel = new ActivityModel(); // Calculate offset. list($Offset, $Limit) = OffsetLimit($Page, 30); // Get user, tab, and comment $this->GetUserInfo($UserReference, $Username, $UserID); $UserID = $this->User->UserID; $Username = $this->User->Name; $this->_SetBreadcrumbs(T('Activity'), UserUrl($this->User, '', 'activity')); $this->SetTabView('Activity'); $Comment = $this->Form->GetFormValue('Comment'); // Load data to display $this->ProfileUserID = $this->User->UserID; $Limit = 30; $NotifyUserIDs = array(ActivityModel::NOTIFY_PUBLIC); if (Gdn::Session()->CheckPermission('Garden.Moderation.Manage')) { $NotifyUserIDs[] = ActivityModel::NOTIFY_MODS; } $Activities = $this->ActivityModel->GetWhere(array('ActivityUserID' => $UserID, 'NotifyUserID' => $NotifyUserIDs), $Offset, $Limit)->ResultArray(); $this->ActivityModel->JoinComments($Activities); $this->SetData('Activities', $Activities); if (count($Activities) > 0) { $LastActivity = $Activities[0]; $LastModifiedDate = Gdn_Format::ToTimestamp($this->User->DateUpdated); $LastActivityDate = Gdn_Format::ToTimestamp($LastActivity['DateInserted']); if ($LastModifiedDate < $LastActivityDate) { $LastModifiedDate = $LastActivityDate; } // Make sure to only query this page if the user has no new activity since the requesting browser last saw it. $this->SetLastModified($LastModifiedDate); } // Set the canonical Url. if (is_numeric($this->User->Name) || Gdn_Format::Url($this->User->Name) != strtolower($this->User->Name)) { $this->CanonicalUrl(Url('profile/' . $this->User->UserID . '/' . Gdn_Format::Url($this->User->Name), TRUE)); } else { $this->CanonicalUrl(Url('profile/' . strtolower($this->User->Name), TRUE)); } $this->Render(); }
/** * Add a method to the ModerationController to handle splitting comments out to a new discussion. */ public function ModerationController_SplitComments_Create($Sender) { $Session = Gdn::Session(); $Sender->Form = new Gdn_Form(); $Sender->Title(T('Split Comments')); $Sender->Category = FALSE; $DiscussionID = GetValue('0', $Sender->RequestArgs, ''); if (!is_numeric($DiscussionID)) { return; } $DiscussionModel = new DiscussionModel(); $Discussion = $DiscussionModel->GetID($DiscussionID); if (!$Discussion) { return; } // Verify that the user has permission to perform the split $Sender->Permission('Vanilla.Discussions.Edit', TRUE, 'Category', $Discussion->PermissionCategoryID); $CheckedComments = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedComments', array()); if (!is_array($CheckedComments)) { $CheckedComments = array(); } $CommentIDs = array(); foreach ($CheckedComments as $DiscID => $Comments) { foreach ($Comments as $Comment) { if ($DiscID == $DiscussionID) { $CommentIDs[] = str_replace('Comment_', '', $Comment); } } } // Load category data. $Sender->ShowCategorySelector = (bool) C('Vanilla.Categories.Use'); $CountCheckedComments = count($CommentIDs); $Sender->SetData('CountCheckedComments', $CountCheckedComments); // Perform the split if ($Sender->Form->AuthenticatedPostBack()) { // Create a new discussion record $Data = $Sender->Form->FormValues(); $Data['Body'] = sprintf(T('This discussion was created from comments split from: %s.'), Anchor(Gdn_Format::Text($Discussion->Name), 'discussion/' . $Discussion->DiscussionID . '/' . Gdn_Format::Url($Discussion->Name) . '/')); $Data['Format'] = 'Html'; $Data['Type'] = 'Discussion'; $NewDiscussionID = $DiscussionModel->Save($Data); $Sender->Form->SetValidationResults($DiscussionModel->ValidationResults()); if ($Sender->Form->ErrorCount() == 0 && $NewDiscussionID > 0) { // Re-assign the comments to the new discussion record $DiscussionModel->SQL->Update('Comment')->Set('DiscussionID', $NewDiscussionID)->WhereIn('CommentID', $CommentIDs)->Put(); // Update counts on both discussions $CommentModel = new CommentModel(); $CommentModel->UpdateCommentCount($DiscussionID); // $CommentModel->UpdateUserCommentCounts($DiscussionID); $CommentModel->UpdateCommentCount($NewDiscussionID); $CommentModel->RemovePageCache($DiscussionID, 1); // Clear selections unset($CheckedComments[$DiscussionID]); Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedComments', $CheckedComments); ModerationController::InformCheckedComments($Sender); $Sender->RedirectUrl = Url('discussion/' . $NewDiscussionID . '/' . Gdn_Format::Url($Data['Name'])); } } else { $Sender->Form->SetValue('CategoryID', GetValue('CategoryID', $Discussion)); } $Sender->Render($this->GetView('splitcomments.php')); }
/** * Queue a notification for sending. */ public function QueueNotification($ActivityID, $Story = '') { $Activity = $this->GetID($ActivityID); if (!is_object($Activity)) { return; } $Story = Gdn_Format::Text($Story == '' ? $Activity->Story : $Story, FALSE); // If this is a comment on another activity, fudge the activity a bit so that everything appears properly. if (is_null($Activity->RegardingUserID) && $Activity->CommentActivityID > 0) { $CommentActivity = $this->GetID($Activity->CommentActivityID); $Activity->RegardingUserID = $CommentActivity->RegardingUserID; $Activity->Route = '/profile/' . $CommentActivity->RegardingUserID . '/' . Gdn_Format::Url($CommentActivity->RegardingName) . '/#Activity_' . $Activity->CommentActivityID; } $User = $this->SQL->Select('UserID, Name, Email, Preferences')->From('User')->Where('UserID', $Activity->RegardingUserID)->Get()->FirstRow(); if ($User) { $Preferences = Gdn_Format::Unserialize($User->Preferences); $Preference = ArrayValue('Email.' . $Activity->ActivityType, $Preferences, Gdn::Config('Preferences.Email.' . $Activity->ActivityType)); if ($Preference) { $ActivityHeadline = Gdn_Format::Text(Gdn_Format::ActivityHeadline($Activity, $Activity->ActivityUserID, $Activity->RegardingUserID), FALSE); $Email = new Gdn_Email(); $Email->Subject(sprintf(T('[%1$s] %2$s'), Gdn::Config('Garden.Title'), $ActivityHeadline)); $Email->To($User->Email, $User->Name); //$Email->From(Gdn::Config('Garden.SupportEmail'), Gdn::Config('Garden.SupportName')); $Email->Message(sprintf(T($Story == '' ? 'EmailNotification' : 'EmailStoryNotification'), $ActivityHeadline, Url($Activity->Route == '' ? '/' : $Activity->Route, TRUE), $Story)); if (!array_key_exists($User->UserID, $this->_NotificationQueue)) { $this->_NotificationQueue[$User->UserID] = array(); } $this->_NotificationQueue[$User->UserID][] = array('ActivityID' => $ActivityID, 'User' => $User, 'Email' => $Email); } } }
if ($FirstCommentIDExists) $Construct->Query("update {$Prefix}Discussion set LastCommentID = null where LastCommentID = FirstCommentID"); // This is the final structure of the discussion table after removed & updated columns. if ($FirstCommentIDExists) { $Construct->Table('Discussion')->DropColumn('FirstCommentID'); $Construct->Reset(); } $Construct->Table('TagDiscussion') ->Column('TagID', 'int', FALSE, 'primary') ->Column('DiscussionID', 'int', FALSE, 'primary') ->Engine('InnoDB') ->Set($Explicit, $Drop); $Construct->Table('Tag') ->Column('CountDiscussions', 'int', 0) ->Set(); $Categories = Gdn::SQL()->Where("coalesce(UrlCode, '') =", "''", FALSE, FALSE)->Get('Category')->ResultArray(); foreach ($Categories as $Category) { $UrlCode = Gdn_Format::Url($Category['Name']); if (strlen($UrlCode) > 50) $UrlCode = $Category['CategoryID']; Gdn::SQL()->Put( 'Category', array('UrlCode' => $UrlCode), array('CategoryID' => $Category['CategoryID'])); }
/** * $Object is either a Comment or the original Discussion. */ function WriteComment($Object, $Sender, $Session, $CurrentOffset) { $Author = UserBuilder($Object, 'Insert'); $Type = property_exists($Object, 'CommentID') ? 'Comment' : 'Discussion'; $Sender->EventArguments['Object'] = $Object; $Sender->EventArguments['Type'] = $Type; $Sender->EventArguments['Author'] = $Author; $CssClass = 'Item Comment'; if ($Type == 'Comment') { $Sender->EventArguments['Comment'] = $Object; $Id = 'Comment_' . $Object->CommentID; $Permalink = '/discussion/comment/' . $Object->CommentID . '/#Comment_' . $Object->CommentID; } else { $Sender->EventArguments['Discussion'] = $Object; $CssClass .= ' FirstComment'; $Id = 'Discussion_' . $Object->DiscussionID; $Permalink = '/discussion/' . $Object->DiscussionID . '/' . Gdn_Format::Url($Object->Name) . '/p1'; } $Sender->Options = ''; $CssClass .= $Object->InsertUserID == $Session->UserID ? ' Mine' : ''; $Sender->FireEvent('BeforeCommentDisplay'); ?> <li class="<?php echo $CssClass; ?> " id="<?php echo $Id; ?> "> <div class="Comment"> <div class="Meta"> <?php $Sender->FireEvent('BeforeCommentMeta'); ?> <span class="Author"> <?php echo UserPhoto($Author); echo UserAnchor($Author); ?> </span> <span class="DateCreated"> <?php echo Gdn_Format::Date($Object->DateInserted); ?> </span> <span class="Permalink"> <?php echo Anchor(T('Permalink'), $Permalink, 'Permalink', array('name' => 'Item_' . ($CurrentOffset + 1), 'rel' => 'nofollow')); ?> </span> <?php WriteOptionList($Object, $Sender, $Session); ?> <?php $Sender->FireEvent('AfterCommentMeta'); ?> </div> <div class="Message"> <?php $Sender->FireEvent('BeforeCommentBody'); ?> <p><?php echo Gdn_Format::To($Object->Body, $Object->Format); ?> </p> </div> <?php $Sender->FireEvent('AfterCommentBody'); ?> </div> </li> <?php $Sender->FireEvent('AfterComment'); }
public function RecordActivity($UserID, $DiscussionID, $DiscussionName) { // Report that the discussion was created AddActivity($UserID, 'NewDiscussion', Anchor(Gdn_Format::Text($DiscussionName), 'vanilla/discussion/' . $DiscussionID . '/' . Gdn_Format::Url($DiscussionName))); // Get the user's discussion count $Data = $this->SQL->Select('DiscussionID', 'count', 'CountDiscussions')->From('Discussion')->Where('InsertUserID', $UserID)->Get(); // Save the count to the user table $this->SQL->Update('User')->Set('CountDiscussions', $Data->NumRows() > 0 ? $Data->FirstRow()->CountDiscussions : 0)->Where('UserID', $UserID)->Put(); }
public function UpdateCounts() { // Define the necessary SQL. $Sqls = array(); if (!$this->ImportExists('Discussion', 'CountComments')) { $Sqls['Discussion.CountComments'] = $this->GetCountSQL('count', 'Discussion', 'Comment'); } if (!$this->ImportExists('Discussion', 'LastCommentID')) { $Sqls['Discussion.LastCommentID'] = $this->GetCountSQL('max', 'Discussion', 'Comment'); } if (!$this->ImportExists('Discussion', 'DateLastComment')) { $Sqls['Discussion.DateLastComment'] = "update :_Discussion d\r\n join :_Comment c\r\n on d.LastCommentID = c.CommentID\r\n set d.DateLastComment = c.DateInserted"; } if (!$this->ImportExists('Discussion', 'CountBookmarks')) { $Sqls['Discussion.CountBookmarks'] = "update :_Discussion d\r\n set CountBookmarks = (\r\n select count(ud.DiscussionID)\r\n from :_UserDiscussion ud\r\n where ud.Bookmarked = 1\r\n and ud.DiscussionID = d.DiscussionID\r\n )"; } if (!$this->ImportExists('Discussion', 'LastCommentUserID')) { $Sqls['Discussion.LastCommentUseID'] = "update :_Discussion d\r\n join :_Comment c\r\n on d.LastCommentID = c.CommentID\r\n set d.LastCommentUserID = c.InsertUserID"; } if (!$this->ImportExists('Discussion', 'Body')) { // Update the body of the discussion if it isn't there. if (!$this->ImportExists('Discussion', 'FirstCommentID')) { $Sqls['Discussion.FirstCommentID'] = $this->GetCountSQL('min', 'Discussion', 'Comment', 'FirstCommentID', 'CommentID'); } $Sqls['Discussion.Body'] = "update :_Discussion d\r\n join :_Comment c\r\n on d.FirstCommentID = c.CommentID\r\n set d.Body = c.Body, d.Format = c.Format"; $Sqls['Comment.FirstComment.Delete'] = "delete :_Comment c\r\n from :_Comment c\r\n inner join :_Discussion d\r\n on d.FirstCommentID = c.CommentID"; } if ($this->ImportExists('UserDiscussion') && !$this->ImportExists('UserDiscussion', 'CountComments') && $this->ImportExists('UserDiscussion', 'DateLastViewed')) { $Sqls['UserDiscussuion.CountComments'] = "update :_UserDiscussion ud\r\n set CountComments = (\r\n select count(c.CommentID)\r\n from :_Comment c\r\n where c.DiscussionID = ud.DiscussionID\r\n and c.DateInserted <= ud.DateLastViewed)"; } $Sqls['Category.CountDiscussions'] = $this->GetCountSQL('count', 'Category', 'Discussion'); if ($this->ImportExists('Conversation') && $this->ImportExists('ConversationMessage')) { $Sqls['Conversation.FirstMessageID'] = $this->GetCountSQL('min', 'Conversation', 'ConversationMessage', 'FirstMessageID', 'MessageID'); if (!$this->ImportExists('Conversation', 'CountMessages')) { $Sqls['Conversation.CountMessages'] = $this->GetCountSQL('count', 'Conversation', 'ConversationMessage', 'CountMessages', 'MessageID'); } if (!$this->ImportExists('Conversation', 'LastMessageID')) { $Sqls['Conversation.LastMessageID'] = $this->GetCountSQL('max', 'Conversation', 'ConversationMessage', 'LastMessageID', 'MessageID'); } if ($this->ImportExists('UserConversation')) { if (!$this->ImportExists('UserConversation', 'LastMessageID')) { if ($this->ImportExists('UserConversation', 'DateLastViewed')) { // Get the value from the DateLastViewed. $Sqls['UserConversation.LastMessageID'] = "update :_UserConversation uc\r\n set LastMessageID = (\r\n select max(MessageID)\r\n from :_ConversationMessage m\r\n where m.ConversationID = uc.ConversationID\r\n and m.DateInserted >= uc.DateLastViewed)"; } else { // Get the value from the conversation. // In this case just mark all of the messages read. $Sqls['UserConversation.LastMessageID'] = "update :_UserConversation uc\r\n join :_Conversation c\r\n on c.ConversationID = uc.ConversationID\r\n set uc.CountReadMessages = c.CountMessages,\r\n uc.LastMessageID = c.LastMessageID"; } } elseif (!$this->ImportExists('UserConversation', 'DateLastViewed')) { // We have the last message so grab the date from that. $Sqls['UserConversation.DateLastViewed'] = "update :_UserConversation uc\r\n join :_ConversationMessage m\r\n on m.ConversationID = uc.ConversationID\r\n and m.MessageID = uc.LastMessageID\r\n set uc.DateLastViewed = m.DateInserted"; } } } // User counts. if (!$this->ImportExists('User', 'CountDiscussions')) { $Sqls['User.CountDiscussions'] = $this->GetCountSQL('count', 'User', 'Discussion', 'CountDiscussions', 'DiscussionID', 'UserID', 'InsertUserID'); } if (!$this->ImportExists('User', 'CountComments')) { $Sqls['User.CountComments'] = $this->GetCountSQL('count', 'User', 'Comment', 'CountComments', 'CommentID', 'UserID', 'InsertUserID'); } if (!$this->ImportExists('User', 'CountBookmarks')) { $Sqls['User.CountBookmarks'] = "update :_User u\r\n set CountBookmarks = (\r\n select count(ud.DiscussionID)\r\n from :_UserDiscussion ud\r\n where ud.Bookmarked = 1\r\n and ud.UserID = u.UserID\r\n )"; } if (!$this->ImportExists('User', 'CountUnreadConversations')) { $Sqls['User.CountUnreadConversations'] = 'update :_User u set u.CountUnreadConversations = ( select count(c.ConversationID) from :_Conversation c inner join :_UserConversation uc on c.ConversationID = uc.ConversationID where uc.UserID = u.UserID and uc.CountReadMessages < c.CountMessages )'; } // The updates start here. $CurrentSubstep = GetValue('CurrentSubstep', $this->Data, 0); if ($CurrentSubstep == 0) { // Add the FirstCommentID to the discussion table. Gdn::Structure()->Table('Discussion')->Column('FirstCommentID', 'int', NULL)->Set(FALSE, FALSE); } // Execute the SQL. $Keys = array_keys($Sqls); for ($i = $CurrentSubstep; $i < count($Keys); $i++) { $this->Data['CurrentStepMessage'] = sprintf(T('%s of %s'), $CurrentSubstep + 1, count($Keys)); $Sql = $Sqls[$Keys[$i]]; $this->Query($Sql); if ($this->Timer->ElapsedTime() > $this->MaxStepTime) { $this->Data['CurrentSubstep'] = $i + 1; return FALSE; } } if (isset($this->Data['CurrentSubstep'])) { unset($this->Data['CurrentSubstep']); } // Remove the FirstCommentID from the discussion table. Gdn::Structure()->Table('Discussion')->DropColumn('FirstCommentID'); $this->Data['CurrentStepMessage'] = ''; // Update the url codes of categories. if (!$this->ImportExists('Category', 'UrlCode')) { $Categories = Gdn::SQL()->Get('Category')->ResultArray(); foreach ($Categories as $Category) { Gdn::SQL()->Put('Category', array('UrlCode' => Gdn_Format::Url($Category['Name'])), array('CategoryID' => $Category['CategoryID'])); } } return TRUE; }
public function Index($DiscussionID = '', $DiscussionStub = '', $Offset = '', $Limit = '') { $this->AddCssFile('vanilla.css'); $Session = Gdn::Session(); $this->AddJsFile('jquery.resizable.js'); $this->AddJsFile('jquery.ui.packed.js'); $this->AddJsFile('jquery.autogrow.js'); // $this->AddJsFile('jquery.gardenmorepager.js'); $this->AddJsFile('options.js'); $this->AddJsFile('bookmark.js'); $this->AddJsFile('discussion.js'); $this->AddJsFile('autosave.js'); // Load the discussion record $DiscussionID = is_numeric($DiscussionID) && $DiscussionID > 0 ? $DiscussionID : 0; $this->SetData('Discussion', $this->DiscussionModel->GetID($DiscussionID), TRUE); if (!is_object($this->Discussion)) { return Gdn::Dispatcher()->Dispatch('Default404'); } // Check Permissions $this->Permission('Vanilla.Discussions.View', TRUE, 'Category', $this->Discussion->CategoryID); $this->SetData('CategoryID', $this->CategoryID = $this->Discussion->CategoryID, TRUE); // Setup $this->Title($this->Discussion->Name); // Actual number of comments, excluding the discussion itself $ActualResponses = $this->Discussion->CountComments - 1; // Define the query offset & limit if (!is_numeric($Limit) || $Limit < 0) { $Limit = C('Vanilla.Comments.PerPage', 50); } $OffsetProvided = $Offset != ''; list($Offset, $Limit) = OffsetLimit($Offset, $Limit); // If $Offset isn't defined, assume that the user has not clicked to // view a next or previous page, and this is a "view" to be counted. if ($Offset == '') { $this->DiscussionModel->AddView($DiscussionID); } $this->Offset = $Offset; if (C('Vanilla.Comments.AutoOffset')) { if (!is_numeric($this->Offset) || $this->Offset < 0 || !$OffsetProvided) { // Round down to the appropriate offset based on the user's read comments & comments per page $CountCommentWatch = $this->Discussion->CountCommentWatch > 0 ? $this->Discussion->CountCommentWatch : 0; if ($CountCommentWatch > $ActualResponses) { $CountCommentWatch = $ActualResponses; } // (((67 comments / 10 perpage) = 6.7) rounded down = 6) * 10 perpage = offset 60; $this->Offset = floor($CountCommentWatch / $Limit) * $Limit; } if ($ActualResponses <= $Limit) { $this->Offset = 0; } if ($this->Offset == $ActualResponses) { $this->Offset -= $Limit; } } else { if ($this->Offset == '') { $this->Offset = 0; } } if ($this->Offset < 0) { $this->Offset = 0; } // Set the canonical url to have the proper page title. $this->CanonicalUrl(Url(ConcatSep('/', 'discussion/' . $this->Discussion->DiscussionID . '/' . Gdn_Format::Url($this->Discussion->Name), PageNumber($this->Offset, $Limit, TRUE)), TRUE)); // Make sure to set the user's discussion watch records $this->CommentModel->SetWatch($this->Discussion, $Limit, $this->Offset, $this->Discussion->CountComments); // Load the comments $this->SetData('CommentData', $this->CommentModel->Get($DiscussionID, $Limit, $this->Offset), TRUE); $this->SetData('Comments', $this->CommentData); // Build a pager $PagerFactory = new Gdn_PagerFactory(); $this->Pager = $PagerFactory->GetPager('Pager', $this); $this->Pager->ClientID = 'Pager'; $this->Pager->Configure($this->Offset, $Limit, $ActualResponses, 'discussion/' . $DiscussionID . '/' . Gdn_Format::Url($this->Discussion->Name) . '/%1$s'); // $this->Pager->MoreCode = '%1$s more comments'; // $this->Pager->LessCode = '%1$s older comments'; // $this->Pager->ClientID = 'Pager'; // $this->Pager->Configure( // $this->Offset, // $Limit, // $ActualResponses, // 'discussion/'.$DiscussionID.'/'.Gdn_Format::Url($this->Discussion->Name).'/%1$s/%2$s/' // ); // Define the form for the comment input $this->Form = Gdn::Factory('Form', 'Comment'); $this->Form->Action = Url('/vanilla/post/comment/'); $this->DiscussionID = $this->Discussion->DiscussionID; $this->Form->AddHidden('DiscussionID', $this->DiscussionID); $this->Form->AddHidden('CommentID', ''); // Retrieve & apply the draft if there is one: $DraftModel = new DraftModel(); $Draft = $DraftModel->Get($Session->UserID, 0, 1, $this->Discussion->DiscussionID)->FirstRow(); $this->Form->AddHidden('DraftID', $Draft ? $Draft->DraftID : ''); if ($Draft) { $this->Form->SetFormValue('Body', $Draft->Body); } // Deliver json data if necessary if ($this->_DeliveryType != DELIVERY_TYPE_ALL) { $this->SetJson('LessRow', $this->Pager->ToString('less')); $this->SetJson('MoreRow', $this->Pager->ToString('more')); $this->View = 'comments'; } // Add Modules $this->AddModule('NewDiscussionModule'); $this->AddModule('CategoriesModule'); $BookmarkedModule = new BookmarkedModule($this); $BookmarkedModule->GetData(); $this->AddModule($BookmarkedModule); $this->FireEvent('BeforeDiscussionRender'); $this->Render(); }
/** * Alternate version of Index that uses the embed master view. * * @param int $DiscussionID Unique identifier, if discussion has been created. * @param string $DiscussionStub Deprecated. * @param int $Offset * @param int $Limit */ public function Embed($DiscussionID = '', $DiscussionStub = '', $Offset = '', $Limit = '') { $this->Title(T('Comments')); // Add theme data $this->Theme = C('Garden.CommentsTheme', $this->Theme); Gdn_Theme::Section('Comments'); // Force view options $this->MasterView = 'empty'; $this->CanEditComments = FALSE; // Don't show the comment checkboxes on the embed comments page // Add some css to help with the transparent bg on embedded comments if ($this->Head) { $this->Head->AddString('<style type="text/css"> body { background: transparent !important; } </style>'); } // Javascript files & options $this->AddJsFile('jquery.gardenmorepager.js'); $this->AddJsFile('jquery.autogrow.js'); $this->RemoveJsFile('autosave.js'); $this->AddJsFile('discussion.js'); $this->AddDefinition('DoInform', '0'); // Suppress inform messages on embedded page. $this->AddDefinition('SelfUrl', Gdn::Request()->PathAndQuery()); $this->AddDefinition('Embedded', TRUE); // Define incoming variables (prefer querystring parameters over method parameters) $DiscussionID = is_numeric($DiscussionID) && $DiscussionID > 0 ? $DiscussionID : 0; $DiscussionID = GetIncomingValue('vanilla_discussion_id', $DiscussionID); $Offset = GetIncomingValue('Offset', $Offset); $Limit = GetIncomingValue('Limit', $Limit); $vanilla_identifier = GetIncomingValue('vanilla_identifier', ''); // Only allow vanilla identifiers of 32 chars or less - md5 if larger if (strlen($vanilla_identifier) > 32) { $vanilla_identifier = md5($vanilla_identifier); } $vanilla_type = GetIncomingValue('vanilla_type', 'page'); $vanilla_url = GetIncomingValue('vanilla_url', ''); $vanilla_category_id = GetIncomingValue('vanilla_category_id', ''); $ForeignSource = array('vanilla_identifier' => $vanilla_identifier, 'vanilla_type' => $vanilla_type, 'vanilla_url' => $vanilla_url, 'vanilla_category_id' => $vanilla_category_id); $this->SetData('ForeignSource', $ForeignSource); // Set comment sorting $SortComments = C('Garden.Embed.SortComments') == 'desc' ? 'desc' : 'asc'; $this->SetData('SortComments', $SortComments); // Retrieve the discussion record $Discussion = FALSE; if ($DiscussionID > 0) { $Discussion = $this->DiscussionModel->GetID($DiscussionID); } else { if ($vanilla_identifier != '' && $vanilla_type != '') { $Discussion = $this->DiscussionModel->GetForeignID($vanilla_identifier, $vanilla_type); } } // Set discussion data if we have one for this page if ($Discussion) { $this->Permission('Vanilla.Discussions.View', TRUE, 'Category', $Discussion->PermissionCategoryID); $this->SetData('Discussion', $Discussion, TRUE); $this->SetData('DiscussionID', $Discussion->DiscussionID, TRUE); $this->Title($Discussion->Name); // Actual number of comments, excluding the discussion itself $ActualResponses = $Discussion->CountComments; // Define the query offset & limit if (!is_numeric($Limit) || $Limit < 0) { $Limit = C('Garden.Embed.CommentsPerPage', 30); } $OffsetProvided = $Offset != ''; list($Offset, $Limit) = OffsetLimit($Offset, $Limit); $this->Offset = $Offset; if (C('Vanilla.Comments.AutoOffset')) { if ($ActualResponses <= $Limit) { $this->Offset = 0; } if ($this->Offset == $ActualResponses) { $this->Offset -= $Limit; } } else { if ($this->Offset == '') { $this->Offset = 0; } } if ($this->Offset < 0) { $this->Offset = 0; } // Set the canonical url to have the proper page title. $this->CanonicalUrl(DiscussionUrl($Discussion, PageNumber($this->Offset, $Limit))); // Load the comments. $CurrentOrderBy = $this->CommentModel->OrderBy(); if (StringBeginsWith(GetValueR('0.0', $CurrentOrderBy), 'c.DateInserted')) { $this->CommentModel->OrderBy('c.DateInserted ' . $SortComments); } // allow custom sort $this->SetData('Comments', $this->CommentModel->Get($Discussion->DiscussionID, $Limit, $this->Offset), TRUE); if (count($this->CommentModel->Where()) > 0) { $ActualResponses = FALSE; } $this->SetData('_Count', $ActualResponses); // Build a pager $PagerFactory = new Gdn_PagerFactory(); $this->EventArguments['PagerType'] = 'MorePager'; $this->FireEvent('BeforeBuildPager'); $this->Pager = $PagerFactory->GetPager($this->EventArguments['PagerType'], $this); $this->Pager->ClientID = 'Pager'; $this->Pager->MoreCode = 'More Comments'; $this->Pager->Configure($this->Offset, $Limit, $ActualResponses, 'discussion/embed/' . $Discussion->DiscussionID . '/' . Gdn_Format::Url($Discussion->Name) . '/%1$s'); $this->Pager->CurrentRecords = $this->Comments->NumRows(); $this->FireEvent('AfterBuildPager'); } // Define the form for the comment input $this->Form = Gdn::Factory('Form', 'Comment'); $this->Form->Action = Url('/vanilla/post/comment/'); $this->Form->AddHidden('CommentID', ''); $this->Form->AddHidden('Embedded', 'true'); // Tell the post controller that this is an embedded page (in case there are custom views it needs to pick up from a theme). $this->Form->AddHidden('DisplayNewCommentOnly', 'true'); // Only load/display the new comment after posting (don't load all new comments since the page last loaded). // Grab the page title if ($this->Request->Get('title')) { $this->Form->SetValue('Name', $this->Request->Get('title')); } // Set existing DiscussionID for comment form if ($Discussion) { $this->Form->AddHidden('DiscussionID', $Discussion->DiscussionID); } foreach ($ForeignSource as $Key => $Val) { // Drop the foreign source information into the form so it can be used if creating a discussion $this->Form->AddHidden($Key, $Val); // Also drop it into the definitions so it can be picked up for stashing comments $this->AddDefinition($Key, $Val); } // Retrieve & apply the draft if there is one: $Draft = FALSE; if (Gdn::Session()->UserID && $Discussion) { $DraftModel = new DraftModel(); $Draft = $DraftModel->Get(Gdn::Session()->UserID, 0, 1, $Discussion->DiscussionID)->FirstRow(); $this->Form->AddHidden('DraftID', $Draft ? $Draft->DraftID : ''); } if ($Draft) { $this->Form->SetFormValue('Body', $Draft->Body); } else { // Look in the session stash for a comment $StashComment = Gdn::Session()->Stash('CommentForForeignID_' . $ForeignSource['vanilla_identifier'], '', FALSE); if ($StashComment) { $this->Form->SetValue('Body', $StashComment); $this->Form->SetFormValue('Body', $StashComment); } } // Deliver JSON data if necessary if ($this->_DeliveryType != DELIVERY_TYPE_ALL) { if ($this->Discussion) { $this->SetJson('LessRow', $this->Pager->ToString('less')); $this->SetJson('MoreRow', $this->Pager->ToString('more')); } $this->View = 'comments'; } // Ordering note for JS if ($SortComments == 'desc') { $this->AddDefinition('PrependNewComments', '1'); } // Report the discussion id so js can use it. if ($Discussion) { $this->AddDefinition('DiscussionID', $Discussion->DiscussionID); } $this->FireEvent('BeforeDiscussionRender'); $this->Render(); }
/** * Create 'Flag' link for comments in a discussion. */ public function DiscussionController_CommentOptions_Handler($Sender) { if (!C('Plugins.Flagging.Enabled')) { return; } // Signed in users only. No guest reporting! if (!Gdn::Session()->UserID) { return; } $Context = strtolower($Sender->EventArguments['Type']); $ElementID = $Context == 'comment' ? $Sender->EventArguments['Comment']->CommentID : $Sender->EventArguments['Discussion']->DiscussionID; if (!is_object($Sender->EventArguments['Author'])) { $ElementAuthorID = 0; $ElementAuthor = 'Unknown'; } else { $ElementAuthorID = $Sender->EventArguments['Author']->UserID; $ElementAuthor = $Sender->EventArguments['Author']->Name; } switch ($Context) { case 'comment': $URL = "/discussion/comment/{$ElementID}/#Comment_{$ElementID}"; break; case 'discussion': $URL = "/discussion/{$ElementID}/" . Gdn_Format::Url($Sender->EventArguments['Discussion']->Name); break; default: return; } $EncodedURL = str_replace('=', '-', base64_encode($URL)); $Sender->Options .= '<span>' . Anchor(T('Flag'), "discussion/flag/{$Context}/{$ElementID}/{$ElementAuthorID}/" . Gdn_Format::Url($ElementAuthor) . "/{$EncodedURL}", 'FlagContent Popup') . '</span>'; }
function WriteClassic($Results, $WriteText, $CssClass) { if (sizeof($Results) == 0) { //make sure there is something here return ''; } ob_start(); ?> <div class="SphinxSearch"> <ul class="DataList"> <?php foreach ($Results as $Row) { ?> <?php $Author->Photo = $Row->UserPhoto; $Author->Name = $Row->UserName; $Author->UserID = $Row->UserID; $TitleURL = $Row->IsComment ? 'discussion/comment/' . $Row->CommentID . '/#Comment_' . $Row->CommentID : DiscussionLink($Row, FALSE); //if the comment is from the orignal discussion poster, simply link to the front page of that ?> <li class="Item"> <div class="ItemContent"> <h4 class="Title"><?php echo Anchor($Row->Title . Wrap(htmlspecialchars(SliceString($Row->DiscussionBody, SS_PREVIEW_BODY_LIMIT)), 'span', array('class' => 'ToolTip')), $TitleURL, FALSE, array('class' => 'HasToolTip')); ?> </h4> <?php if ($WriteText) { ?> <div class="Message Excerpt"> <?php //echo nl2br(SliceString($Row->Body, SS_BODY_LIMIT)); This seemed to make MARKDOWN posts look correct - JJB ?> <?php echo SliceString($Row->Body, SS_BODY_LIMIT); ?> </div> <?php } ?> <div class="Meta"> <span class="MItem"><?php echo UserPhoto($Author, array('LinkClass' => '', 'ImageClass' => 'ProfilePhotoSmall PhotoWrap')); ?> </span> <span class="MItem"><?php echo Anchor($Row->UserName, UserUrl($Author)); ?> </span> <span class="MItem"><?php echo Anchor(Gdn_Format::Date($Row->DateInserted), 'discussion/' . $Row->DiscussionID . '/' . Gdn_Format::Url($Row->Title) . '/p1'); ?> </span> <span class="MItem"><?php echo Anchor($Row->CatName, 'discussion/' . $Row->DiscussionID . '/' . Gdn_Format::Url($Row->Title) . '/p1'); ?> </span> </div> </div> </li> <?php } ?> </ul> </div> <?php $String = ob_get_contents(); @ob_end_clean(); return $String; }