/** * * * @param $Name * @param string $Code * @param string $Url */ 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); }
/** * * * @param string $ID * @param string $ServeFile */ public function index($ID = '', $ServeFile = '0') { $this->addJsFile('jquery.js'); // Define the item being downloaded if (strtolower($ID) == 'vanilla') { $ID = 'vanilla-core'; } $UrlFilename = Gdn::request()->filename(); $PathInfo = pathinfo($UrlFilename); $Ext = val('extension', $PathInfo); if ($Ext == 'zip') { $ServeFile = '1'; $ID = $Ext = val('filename', $PathInfo); } // Find the requested addon $this->Addon = $this->AddonModel->getSlug($ID, true); $this->setData('Addon', $this->Addon); if (!is_array($this->Addon) || !val('File', $this->Addon)) { $this->Addon = array('Name' => 'Not Found', 'Version' => 'undefined', 'File' => ''); } else { $AddonID = $this->Addon['AddonID']; if ($ServeFile != '1') { $this->addJsFile('get.js'); } if ($ServeFile == '1') { // Record this download $this->Database->sql()->insert('Download', array('AddonID' => $AddonID, 'DateInserted' => Gdn_Format::toDateTime(), 'RemoteIp' => @$_SERVER['REMOTE_ADDR'])); $this->AddonModel->setProperty($AddonID, 'CountDownloads', $this->Addon['CountDownloads'] + 1); if (val('Slug', $this->Addon)) { $Filename = $this->Addon['Slug']; } else { $Filename = "{$this->Addon['Name']}-{$this->Addon['Version']}"; } $Filename = Gdn_Format::url($Filename) . '.zip'; $File = $this->Addon['File']; $Url = Gdn_Upload::url($File); Gdn_FileSystem::serveFile($Url, $Filename); } } $this->addModule('AddonHelpModule'); $this->render(); }
/** * Output Flag link. */ protected function addFlagButton($Sender, $Args, $Context = 'comment') { $ElementID = $Context == 'comment' ? $Args['Comment']->CommentID : $Args['Discussion']->DiscussionID; if (!is_object($Args['Author']) || !isset($Args['Author']->UserID)) { $ElementAuthorID = 0; $ElementAuthor = 'Unknown'; } else { $ElementAuthorID = $Args['Author']->UserID; $ElementAuthor = $Args['Author']->Name; } switch ($Context) { case 'comment': $URL = "/discussion/comment/{$ElementID}/#Comment_{$ElementID}"; break; case 'discussion': $URL = "/discussion/{$ElementID}/" . Gdn_Format::url($Args['Discussion']->Name); break; default: return; } $EncodedURL = str_replace('=', '-', base64_encode($URL)); $FlagLink = anchor(t('Flag'), "discussion/flag/{$Context}/{$ElementID}/{$ElementAuthorID}/" . Gdn_Format::url($ElementAuthor) . "/{$EncodedURL}", 'FlagContent Popup'); echo wrap($FlagLink, 'span', array('class' => 'MItem CommentFlag')); }
/** * Default search functionality. * * @since 2.0.0 * @access public * @param int $Page Page number. */ public function index($Page = '') { $this->addJsFile('search.js'); $this->title(t('Search')); saveToConfig('Garden.Format.EmbedSize', '160x90', false); Gdn_Theme::section('SearchResults'); list($Offset, $Limit) = offsetLimit($Page, c('Garden.Search.PerPage', 20)); $this->setData('_Limit', $Limit); $Search = $this->Form->getFormValue('Search'); $Mode = $this->Form->getFormValue('Mode'); if ($Mode) { $this->SearchModel->ForceSearchMode = $Mode; } try { $ResultSet = $this->SearchModel->Search($Search, $Offset, $Limit); } catch (Gdn_UserException $Ex) { $this->Form->addError($Ex); $ResultSet = array(); } catch (Exception $Ex) { LogException($Ex); $this->Form->addError($Ex); $ResultSet = array(); } Gdn::userModel()->joinUsers($ResultSet, array('UserID')); // Fix up the summaries. $SearchTerms = explode(' ', Gdn_Format::text($Search)); foreach ($ResultSet as &$Row) { $Row['Summary'] = SearchExcerpt(Gdn_Format::plainText($Row['Summary'], $Row['Format']), $SearchTerms); $Row['Summary'] = Emoji::instance()->translateToHtml($Row['Summary']); $Row['Format'] = 'Html'; } $this->setData('SearchResults', $ResultSet, true); $this->setData('SearchTerm', Gdn_Format::text($Search), true); if ($ResultSet) { $NumResults = count($ResultSet); } else { $NumResults = 0; } if ($NumResults == $Offset + $Limit) { $NumResults++; } // Build a pager $PagerFactory = new Gdn_PagerFactory(); $this->Pager = $PagerFactory->GetPager('MorePager', $this); $this->Pager->MoreCode = 'More Results'; $this->Pager->LessCode = 'Previous Results'; $this->Pager->ClientID = 'Pager'; $this->Pager->configure($Offset, $Limit, $NumResults, 'dashboard/search/%1$s/%2$s/?Search=' . Gdn_Format::url($Search)); // if ($this->_DeliveryType != DELIVERY_TYPE_ALL) { // $this->setJson('LessRow', $this->Pager->toString('less')); // $this->setJson('MoreRow', $this->Pager->toString('more')); // $this->View = 'results'; // } $this->canonicalUrl(url('search', true)); $this->render(); }
private function handleAddonToggle($addonName, $addonInfo, $type, $isEnabled, $filter = '', $action = '') { require_once $this->fetchViewLocation('helper_functions'); if ($this->Form->errorCount() > 0) { $this->informMessage($this->Form->errors()); } else { if ($action === 'SlideUp') { $this->jsonTarget('#' . Gdn_Format::url($addonName) . '-addon', '', 'SlideUp'); } else { ob_start(); writeAddonMedia($addonName, $addonInfo, $isEnabled, $type, $filter); $row = ob_get_clean(); $this->jsonTarget('#' . Gdn_Format::url($addonName) . '-addon', $row, 'ReplaceWith'); } } $this->render('blank', 'utility', 'dashboard'); }
if (!$LastCommentIDExists || !$LastCommentUserIDExists) { $Construct->query("update {$Prefix}Discussion d\n inner join {$Prefix}Comment c\n on c.DiscussionID = d.DiscussionID\n inner join (\n select max(c2.CommentID) as CommentID\n from {$Prefix}Comment c2\n group by c2.DiscussionID\n ) c2\n on c.CommentID = c2.CommentID\n set d.LastCommentID = c.CommentID,\n d.LastCommentUserID = c.InsertUserID\nwhere d.LastCommentUserID is null"); } if (!$CountBookmarksExists) { $Construct->query("update {$Prefix}Discussion d\n set CountBookmarks = (\n select count(ud.DiscussionID)\n from {$Prefix}UserDiscussion ud\n where ud.Bookmarked = 1\n and ud.DiscussionID = d.DiscussionID\n )"); } $Construct->table('TagDiscussion'); $DateInsertedExists = $Construct->columnExists('DateInserted'); $Construct->column('TagID', 'int', false, 'primary')->column('DiscussionID', 'int', false, 'primary')->column('CategoryID', 'int', false, 'index')->column('DateInserted', 'datetime', !$DateInsertedExists)->Engine('InnoDB')->set($Explicit, $Drop); if (!$DateInsertedExists) { $SQL->update('TagDiscussion td')->join('Discussion d', 'td.DiscussionID = d.DiscussionID')->set('td.DateInserted', 'd.DateInserted', false, false)->put(); } $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'])); } // Moved this down here because it needs to run after GDN_Comment is created if (!$LastDiscussionIDExists) { $SQL->update('Category c')->join('Comment cm', 'c.LastCommentID = cm.CommentID')->set('c.LastDiscussionID', 'cm.DiscussionID', false, false)->put(); } // Add stub content include PATH_APPLICATIONS . DS . 'vanilla' . DS . 'settings' . DS . 'stub.php'; // Set current Vanilla.Version $ApplicationInfo = array(); include CombinePaths(array(PATH_APPLICATIONS . DS . 'vanilla' . DS . 'settings' . DS . 'about.php')); $Version = val('Version', val('Vanilla', $ApplicationInfo, array()), 'Undefined');
/** * Find the requested plugin and redirect to it. * * @param string $PluginName */ public function find($PluginName = '') { $Data = $this->Database->sql()->select('AddonID, Name')->from('Addon')->where('Name', $PluginName)->get()->firstRow(); if ($Data) { safeRedirect('/addon/' . $Data->AddonID . '/' . Gdn_Format::url($Data->Name)); } else { safeRedirect('/addon/notfound/'); } }
$ScreenName = Gdn_Format::Display(val('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(t(val('Name', $PluginInfo, $PluginName) . ' Description', val('Description', $PluginInfo, ''))); ?> </td> </tr>
/** * * * @return bool */ 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\n left join :_Comment c\n on d.LastCommentID = c.CommentID\n set d.DateLastComment = coalesce(c.DateInserted, d.DateInserted)"; } if (!$this->importExists('Discussion', 'LastCommentUserID')) { $Sqls['Discussion.LastCommentUseID'] = "update :_Discussion d\n join :_Comment c\n on d.LastCommentID = c.CommentID\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\n join :_Comment c\n on d.FirstCommentID = c.CommentID\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\n join :_Discussion d\n on d.FirstCommentID = m.ForeignID and m.ForeignTable = 'comment'\n set m.ForeignID = d.DiscussionID, m.ForeignTable = 'discussion'"; } $Sqls['Comment.FirstComment.Delete'] = "delete c.*\n from :_Comment c\n inner join :_Discussion d\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\n set CountComments = (\n select count(c.CommentID)\n from :_Comment c\n where c.DiscussionID = ud.DiscussionID\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'] = "\n update :_Activity a\n join :_ActivityType t\n on a.ActivityType = t.Name\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\n set LastMessageID = (\n select max(MessageID)\n from :_ConversationMessage m\n where m.ConversationID = uc.ConversationID\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\n join :_Conversation c\n on c.ConversationID = uc.ConversationID\n set uc.CountReadMessages = c.CountMessages,\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\n join :_ConversationMessage m\n on m.ConversationID = uc.ConversationID\n and m.MessageID = uc.LastMessageID\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\n set CountBookmarks = (\n select count(ud.DiscussionID)\n from :_UserDiscussion ud\n where ud.Bookmarked = 1\n and ud.UserID = u.UserID\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 = val('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 = 'c' . $Category['CategoryID']; } elseif (is_numeric($UrlCode)) { $UrlCode = 'c' . $UrlCode; } 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; }
/** * Show a message when the discussion is related to an addon. * * @param $AddonID * @param $AddonName * @param $AttachID * @return string */ function renderDiscussionAddonWarning($AddonID, $AddonName, $AttachID) { $DeleteOption = ''; if (Gdn::session()->checkPermission('Addons.Addon.Manage')) { $DeleteOption = anchor('x', 'addon/detachfromdiscussion/' . $AttachID, array('class' => 'Dismiss')); } $String = wrap($DeleteOption . sprintf(t('This discussion is related to the %s addon.'), anchor($AddonName, 'addon/' . $AddonID . '/' . Gdn_Format::url($AddonName))), 'div', array('class' => 'Warning AddonAttachment DismissMessage')); return $String; }
/** * 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 = reset($Activities); $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(); }
echo t('Comments'); ?> </td> <!-- <td><?php echo t('PageViews'); ?> </td> --> </tr> </thead> <tbody> <?php foreach ($this->Data['UserData'] as $User) { ?> <tr> <th><?php echo anchor($User->Name, 'profile/' . $User->UserID . '/' . Gdn_Format::url($User->Name)); ?> </th> <td><?php echo number_format($User->CountComments); ?> </td> <!-- <td><?php // echo number_format($Discussion->CountViews); ?> </td> --> </tr> <?php } ?> </tbody>
/** * * * @param $Addon * @param bool|true $IncludeVersion * @return string */ public static function slug($Addon, $IncludeVersion = true) { if (val('AddonKey', $Addon) && (val('Version', $Addon) || !$IncludeVersion)) { $Key = val('AddonKey', $Addon); $Type = val('Type', $Addon); if (!$Type) { $Type = val(val('AddonTypeID', $Addon), array_flip(self::$Types)); } //$Slug = strtolower(val('AddonKey', $Data).'-'.val('Type', $Data).'-'.val('Version', $Data)); $Slug = strtolower($Key) . '-' . strtolower($Type); if ($IncludeVersion === true) { $Slug .= '-' . val('Version', $Addon, ''); } elseif (is_string($IncludeVersion)) { $Slug .= '-' . $IncludeVersion; } elseif (is_array($IncludeVersion)) { $Slug .= '-' . $IncludeVersion['Version']; } return urlencode($Slug); } else { return val('AddonID', $Addon) . '-' . Gdn_Format::url(val('Name', $Addon)); } }
/** * * * @param $Str * @return string */ public static function tagSlug($Str) { return rawurldecode(Gdn_Format::url($Str)); }
public function fixUrlCodes($Table, $Column) { $Model = $this->createModel($Table); // Get the data to decode. $Data = $this->SQL->select($Model->PrimaryKey)->select($Column)->from($Table)->get()->resultArray(); foreach ($Data as $Row) { $Value = $Row[$Column]; $Encoded = Gdn_Format::url($Value); if (!$Value || $Value != $Encoded) { $Model->setField($Row[$Model->PrimaryKey], $Column, $Encoded); Gdn::controller()->Data['Encoded'][$Row[$Model->PrimaryKey]] = $Encoded; } } return array('Complete' => true); }
} $Session = Gdn::session(); if ($Session->isValid() && c('Garden.Modules.ShowSignedInModule')) { $Name = $Session->User->Name; if (c('EnabledApplications.Conversations')) { $CountInbox = $Session->User->CountUnreadConversations; $CountInbox = is_numeric($CountInbox) && $CountInbox > 0 ? $CountInbox : 0; } $CountNotifications = $Session->User->CountNotifications; $CountNotifications = is_numeric($CountNotifications) && $CountNotifications > 0 ? $CountNotifications : 0; ?> <div class="Box ProfileBox"> <h4>My Profile</h4> <ul class="PanelInfo"> <li><?php echo anchor($Name, 'profile/' . $Session->User->UserID . '/' . Gdn_Format::url($Name)); ?> </li> <?php if (c('EnabledApplications.Conversations')) { ?> <li><?php echo anchor(t('Inbox'), '/messages/all'); ?> <span class="Aside"><span class="Count"><?php echo $CountInbox; ?> </span></span></li> <?php }
/** * 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 = val('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', val('CategoryID', $Discussion)); } $Sender->render($this->getView('splitcomments.php')); }
/** * 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.autosize.min.js'); $this->addJsFile('discussion.js'); $this->removeJsFile('autosave.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); } elseif ($vanilla_identifier != '' && $vanilla_type != '') { $Discussion = $this->DiscussionModel->GetForeignID($vanilla_identifier, $vanilla_type); } // Set discussion data if we have one for this page if ($Discussion) { // Allow Vanilla.Comments.View to be defined to limit access to embedded comments only. // Otherwise, go with normal discussion view permissions. Either will do. $this->permission(array('Vanilla.Discussions.View', 'Vanilla.Comments.View'), false, '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; } } elseif ($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('/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()->getPublicStash('CommentForForeignID_' . $ForeignSource['vanilla_identifier']); 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(); }
</language> <atom:link href="<?php echo url('discussions/tagged' . urlencode($this->data('Tag')) . '/feed.rss'); ?> " rel="self" type="application/rss+xml"/> <?php foreach ($this->DiscussionData->Result() as $Discussion) { ?> <item> <title><?php echo Gdn_Format::text($Discussion->Name); ?> </title> <link><?php echo htmlspecialchars(url('/discussion/' . $Discussion->DiscussionID . '/' . Gdn_Format::url($Discussion->Name), true)); ?> </link> <pubDate><?php echo date(DATE_RSS, Gdn_Format::ToTimeStamp($Discussion->DateInserted)); ?> </pubDate> <dc:creator><?php echo Gdn_Format::text($Discussion->FirstName); ?> </dc:creator> <guid isPermaLink="false"><?php echo $Discussion->DiscussionID . '@' . Url('/discussions'); ?> </guid> <description><![CDATA[<?php
function discussionLink($Discussion, $Extended = true) { $DiscussionID = val('DiscussionID', $Discussion); $DiscussionName = val('Name', $Discussion); $Parts = array('discussion', $DiscussionID, Gdn_Format::url($DiscussionName)); if ($Extended) { $Parts[] = $Discussion->CountCommentWatch > 0 ? '#Item_' . $Discussion->CountCommentWatch : ''; } return url(implode('/', $Parts), true); }
/** * Converts addon info into a media item. * * @param $addonName * @param $addonInfo * @param $isEnabled * @param $addonType * @param $filter */ function writeAddonMedia($addonName, $addonInfo, $isEnabled, $addonType, $filter) { $capitalCaseSheme = new \Vanilla\Utility\CapitalCaseScheme(); $addonInfo = $capitalCaseSheme->convertArrayKeys($addonInfo, ['RegisterPermissions']); $screenName = Gdn_Format::display(val('Name', $addonInfo, $addonName)); $description = Gdn_Format::html(t(val('Name', $addonInfo, $addonName) . ' Description', val('Description', $addonInfo, ''))); $id = Gdn_Format::url($addonName) . '-addon'; $media = new MediaItemModule($screenName, '', $description, 'li', ['id' => $id]); $media->setView('media-addon'); // Icon $addon = Gdn::addonManager()->lookupAddon($addonName); $iconPath = ''; if ($addon) { $iconPath = $addon->getIcon(); } if (!$iconPath) { $iconPath = val('IconUrl', $addonInfo, 'applications/dashboard/design/images/addon-placeholder.png'); } $media->setImage($iconPath); // Settings button $settingsUrl = $isEnabled ? val('SettingsUrl', $addonInfo, '') : ''; $settingsPopupClass = val('UsePopupSettings', $addonInfo, true) ? ' js-modal' : ''; if ($settingsUrl != '') { $attr['class'] = 'btn btn-icon-border' . $settingsPopupClass; $attr['aria-label'] = sprintf(t('Settings for %s'), $screenName); $attr['data-reload-page-on-save'] = false; $media->addButton(dashboardSymbol('settings'), $settingsUrl, $attr); } // Toggle if ($addonType === 'locales') { $action = $isEnabled ? 'disable' : 'enable'; } else { $action = $filter; } if ($isEnabled) { $label = sprintf(t('Disable %s'), $screenName); } else { $label = sprintf(t('Enable %s'), $screenName); } $url = '/settings/' . $addonType . '/' . $action . '/' . $addonName; $media->setToggle(slugify($addonName), $isEnabled, $url, $label); // Meta $info = []; // Requirements $requiredApplications = val('RequiredApplications', $addonInfo, false); $requiredPlugins = val('RequiredPlugins', $addonInfo, false); $requirements = []; if (is_array($requiredApplications)) { foreach ($requiredApplications as $requiredApplication => $versionInfo) { $requirements[] = sprintf(t('%1$s Version %2$s'), $requiredApplication, $versionInfo); } } if (is_array($requiredPlugins)) { foreach ($requiredPlugins as $requiredPlugin => $versionInfo) { $requirements[] = sprintf(t('%1$s Version %2$s'), $requiredPlugin, $versionInfo); } } if (!empty($requirements)) { $requirementsMeta = sprintf(t('Requires: %s'), implode(', ', $requirements)); $info[] = $requirementsMeta; } // Authors $author = val('Author', $addonInfo, ''); $authors = []; // Check if singular author is set if ($author) { $authorUrl = val('AuthorUrl', $addonInfo, ''); if ($authorUrl) { $authors[] = anchor($author, $authorUrl); } else { $authors[] = $author; } } // Check for multiple authors foreach (val('Authors', $addonInfo, []) as $author) { if (val('Homepage', $author)) { $authors[] = anchor(val('Name', $author), val('Homepage', $author)); } else { $authors[] = val('Name', $author); } } if ($authors) { $authors = implode(', ', $authors); $info[] = sprintf(t('Created by %s'), $authors); } // Version Info $version = Gdn_Format::display(val('Version', $addonInfo, '')); $newVersion = val('NewVersion', $addonInfo, ''); $upgrade = $newVersion != '' && version_compare($newVersion, $version, '>'); if ($version != '') { $info[] = sprintf(t('Version %s'), $version); } $pluginUrl = val('PluginUrl', $addonInfo, ''); if ($upgrade && $pluginUrl) { $info[] = anchor(printf(t('%1$s version %2$s is available.'), $screenName, $newVersion), combinePaths(array($pluginUrl, 'find', urlencode($screenName)), '/')); } if ($pluginUrl != '') { $info[] = anchor(t('Visit Site'), $pluginUrl); } // Extra meta in addon array if ($meta = val('Meta', $addonInfo)) { foreach ($meta as $key => $value) { if (is_numeric($key)) { $info[] = $value; } else { $info[] = t($key) . ': ' . $value; } } } $media->setMeta($info); echo $media; }