/**
  * Deny access to private support discussions.
  */
 public function DiscussionController_Render_Before($Sender, $Args)
 {
     // Get category & discussion data
     $Category = CategoryModel::Categories($Sender->Data('CategoryID'));
     $Discussion = CategoryModel::Categories($Sender->Data('CategoryID'));
     // Evaluate conditions
     $Private = GetValue('PrivateSupport', $Category) ? TRUE : FALSE;
     $Mine = GetValue('InsertUserID', $Discussion) == Gdn::Session()->UserID ? TRUE : FALSE;
     // Deny access to private support discussions
     if (!$Mine && $Private) {
         $Sender->Permission('Garden.Moderation.Manage');
     }
 }
 /**
  * Render the module.
  *
  * @return string
  */
 public function ToString()
 {
     // Set CategoryID if we have one.
     if ($this->CategoryID === NULL) {
         $this->CategoryID = Gdn::Controller()->Data('Category.CategoryID', FALSE);
     }
     // Allow plugins and themes to modify parameters.
     Gdn::Controller()->EventArguments['NewDiscussionModule'] =& $this;
     Gdn::Controller()->FireEvent('BeforeNewDiscussionButton');
     // Make sure the user has the most basic of permissions first.
     $PermissionCategory = CategoryModel::PermissionCategory($this->CategoryID);
     if ($this->CategoryID) {
         $Category = CategoryModel::Categories($this->CategoryID);
         $HasPermission = Gdn::Session()->CheckPermission('Vanilla.Discussions.Add', TRUE, 'Category', GetValue('CategoryID', $PermissionCategory));
     } else {
         $HasPermission = Gdn::Session()->CheckPermission('Vanilla.Discussions.Add', TRUE, 'Category', 'any');
     }
     // Determine if this is a guest & we're using "New Discussion" button as call to action.
     $PrivilegedGuest = $this->ShowGuests && !Gdn::Session()->IsValid();
     // No module for you!
     if (!$HasPermission && !$PrivilegedGuest) {
         return '';
     }
     // Grab the allowed discussion types.
     $DiscussionTypes = CategoryModel::AllowedDiscussionTypes($PermissionCategory);
     foreach ($DiscussionTypes as $Key => $Type) {
         if (isset($Type['AddPermission']) && !Gdn::Session()->CheckPermission($Type['AddPermission'])) {
             unset($DiscussionTypes[$Key]);
             continue;
         }
         // If user !$HasPermission, they are $PrivilegedGuest so redirect to $GuestUrl.
         $Url = $HasPermission ? GetValue('AddUrl', $Type) : $this->GuestUrl;
         if (!$Url) {
             continue;
         }
         if (isset($Category) && $HasPermission) {
             $Url .= '/' . rawurlencode(GetValue('UrlCode', $Category));
         }
         $this->AddButton(T(GetValue('AddText', $Type)), $Url);
     }
     // Add QueryString to URL if one is defined.
     if ($this->QueryString && $HasPermission) {
         foreach ($this->Buttons as &$Row) {
             $Row['Url'] .= (strpos($Row['Url'], '?') !== FALSE ? '&' : '?') . $this->QueryString;
         }
     }
     return parent::ToString();
 }
 public function __construct($Sender = '', $ApplicationFolder = '')
 {
     $this->Data = FALSE;
     $NoFollowing = TRUE;
     if (C('Vanilla.Categories.Use') == TRUE) {
         // Load categories with respect to view permissions
         $Categories = CategoryModel::Categories();
         $Categories2 = $Categories;
         foreach ($Categories2 as $i => $Category) {
             if (!$Category['PermsDiscussionsView']) {
                 unset($Categories[$i]);
             } elseif (!$Category['Following']) {
                 $NoFollowing = FALSE;
             }
         }
         // delete view filter if no categories are hidden
         $Session = Gdn::Session();
         if ($NoFollowing && $Session->IsValid()) {
             $Session->SetPreference('ShowAllCategories', TRUE);
         }
         // set categories to data
         $Data = new Gdn_DataSet($Categories);
         $Data->DatasetType(DATASET_TYPE_ARRAY);
         $Data->DatasetType(DATASET_TYPE_OBJECT);
         $this->Data['Categories'] = $Data;
         // calculate additional needed data
         $this->Data['CategoryID'] = isset($Sender->CategoryID) ? $Sender->CategoryID : '';
         $this->Data['OnCategories'] = strtolower($Sender->ControllerName) == 'categoriescontroller' && !is_numeric($this->Data['CategoryID']);
         $this->Data['ShowAllCategoriesPref'] = $Session->GetPreference('ShowAllCategories');
         $this->Data['Url'] = Gdn::Request()->Path();
         if ($this->Data['Url'] == '') {
             $this->Data['Url'] = '/';
         }
         $this->Data['ShowAllCategoriesUrl'] = Gdn::Request()->Url('categories/settoggle?ShowAllCategories=true&Target=' . $this->Data['Url']);
         $this->Data['ShowFollowedCategoriesUrl'] = Gdn::Request()->Url('categories/settoggle?ShowAllCategories=false&Target=' . $this->Data['Url']);
         $this->Data['TKey'] = urlencode(Gdn::Session()->TransientKey());
         $this->Data['ValidSession'] = $Session->UserID > 0 && $Session->ValidateTransientKey($this->Data['TKey']);
         $this->Data['MaxDepth'] = C('Vanilla.Categories.MaxDisplayDepth');
         $this->Data['DoHeadings'] = C('Vanilla.Categories.DoHeadings');
     }
     parent::__construct($Sender, $ApplicationFolder);
 }
 public function __construct($Sender = '')
 {
     // Load categories
     $this->Data = FALSE;
     if (C('Vanilla.Categories.Use') == TRUE && !C('Vanilla.Categories.HideModule')) {
         $Categories = CategoryModel::Categories();
         $Categories2 = $Categories;
         // Filter out the categories we aren't watching.
         foreach ($Categories2 as $i => $Category) {
             if (!$Category['PermsDiscussionsView'] || !$Category['Following']) {
                 unset($Categories[$i]);
             }
         }
         $Data = new Gdn_DataSet($Categories);
         $Data->DatasetType(DATASET_TYPE_ARRAY);
         $Data->DatasetType(DATASET_TYPE_OBJECT);
         $this->Data = $Data;
     }
     parent::__construct($Sender);
 }
 public function ToString()
 {
     if ($this->CategoryID === NULL) {
         $this->CategoryID = Gdn::Controller()->Data('Category.CategoryID', FALSE);
     }
     Gdn::Controller()->EventArguments['NewDiscussionModule'] =& $this;
     Gdn::Controller()->FireEvent('BeforeNewDiscussionButton');
     // Make sure the user has the most basic of permissions first.
     $PermissionCategory = CategoryModel::PermissionCategory($this->CategoryID);
     if ($this->CategoryID) {
         $Category = CategoryModel::Categories($this->CategoryID);
         $HasPermission = Gdn::Session()->CheckPermission('Vanilla.Discussions.Add', TRUE, 'Category', GetValue('CategoryID', $PermissionCategory));
     } else {
         $HasPermission = Gdn::Session()->CheckPermission('Vanilla.Discussions.Add', TRUE, 'Category', 'any');
     }
     if (!$HasPermission) {
         return '';
     }
     // Grab the allowed discussion types.
     $DiscussionTypes = CategoryModel::AllowedDiscussionTypes($PermissionCategory);
     foreach ($DiscussionTypes as $Key => $Type) {
         if (isset($Type['AddPermission']) && !Gdn::Session()->CheckPermission($Type['AddPermission'])) {
             unset($DiscussionTypes[$Key]);
             continue;
         }
         $Url = GetValue('AddUrl', $Type);
         if (!$Url) {
             continue;
         }
         if (isset($Category)) {
             $Url .= '/' . rawurlencode(GetValue('UrlCode', $Category));
         }
         $this->AddButton(T(GetValue('AddText', $Type)), $Url);
     }
     if ($this->QueryString) {
         foreach ($this->Buttons as &$Row) {
             $Row['Url'] .= (strpos($Row['Url'], '?') !== FALSE ? '&' : '?') . $this->QueryString;
         }
     }
     return parent::ToString();
 }
 protected function InCategory($NeedleCategoryID, $HaystackCategoryID, $IncludeSubcategories = FALSE)
 {
     if (!$HaystackCategoryID) {
         return TRUE;
     }
     if ($NeedleCategoryID == $HaystackCategoryID) {
         return TRUE;
     }
     if ($IncludeSubcategories) {
         $Cat = CategoryModel::Categories($NeedleCategoryID);
         for ($i = 0; $i < 10; $i++) {
             if (!$Cat) {
                 break;
             }
             if ($Cat['CategoryID'] == $HaystackCategoryID) {
                 return TRUE;
             }
             $Cat = CategoryModel::Categories($Cat['ParentCategoryID']);
         }
     }
     return FALSE;
 }
示例#7
0
 public function PostController_BeforeBodyInput_Handler($Sender)
 {
     # If the script ID is passed in, it will be hardcoded to category 4.
     if ($this->ScriptIDPassed($Sender)) {
         return;
     }
     echo '<div class="P">';
     echo '<div class="Category">';
     echo $Sender->Form->Label('Category', 'CategoryID'), ' ';
     echo '<br>';
     $SelectedCategory = GetValue('CategoryID', $Sender->Category);
     foreach (CategoryModel::Categories() as $c) {
         # -1 is the root
         if ($c['CategoryID'] != -1) {
             #4 is Style Reviews, which should only by used when script id is passed (and skips this anyway) or by mods
             if ($c['CategoryID'] != 4 || Gdn::Session()->CheckPermission('Vanilla.Discussions.Edit')) {
                 echo '<input name="CategoryID" id="category-' . $c['CategoryID'] . '" type="radio" value="' . $c['CategoryID'] . '"' . ($SelectedCategory == $c['CategoryID'] ? ' checked' : '') . '><label for="category-' . $c['CategoryID'] . '">' . $c['Name'] . ' - ' . $c['Description'] . '</label><br>';
             }
         }
     }
     #echo $Sender->Form->CategoryDropDown('CategoryID', array('Value' => GetValue('CategoryID', $this->Category)));
     echo '</div>';
     echo '</div>';
 }
 /**
  * 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;
             }
         }
         $RedirectLink = $Sender->Form->GetFormValue('RedirectLink');
         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');
             }
             $DiscussionModel->DefineSchema();
             $MaxNameLength = GetValue('Length', $DiscussionModel->Schema->GetField('Name'));
             // 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');
                     }
                     if ($RedirectLink) {
                         // The discussion needs to be changed to a moved link.
                         $RedirectDiscussion = array('Name' => SliceString(sprintf(T('Merged: %s'), $Discussion['Name']), $MaxNameLength), 'Type' => 'redirect', 'Body' => FormatString(T('This discussion has been <a href="{url,html}">merged</a>.'), array('url' => DiscussionUrl($MergeDiscussion))), 'Format' => 'Html');
                         $DiscussionModel->SetField($Discussion['DiscussionID'], $RedirectDiscussion);
                         $CommentModel->UpdateCommentCount($Discussion['DiscussionID']);
                         $CommentModel->RemovePageCache($Discussion['DiscussionID']);
                     } else {
                         // 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->JsonTarget('', '', 'Refresh');
             }
         }
     }
     $Sender->Render('MergeDiscussions', '', 'plugins/SplitMerge');
 }
示例#9
0
    /**
     * Writes a discussion in table row format.
     */
    function WriteDiscussionRow($Discussion, &$Sender, &$Session, $Alt2)
    {
        if (!property_exists($Sender, 'CanEditDiscussions')) {
            $Sender->CanEditDiscussions = GetValue('PermsDiscussionsEdit', CategoryModel::Categories($Discussion->CategoryID)) && C('Vanilla.AdminCheckboxes.Use');
        }
        $CssClass = CssClass($Discussion);
        $DiscussionUrl = $Discussion->Url;
        if ($Session->UserID) {
            $DiscussionUrl .= '#latest';
        }
        $Sender->EventArguments['DiscussionUrl'] =& $DiscussionUrl;
        $Sender->EventArguments['Discussion'] =& $Discussion;
        $Sender->EventArguments['CssClass'] =& $CssClass;
        $First = UserBuilder($Discussion, 'First');
        if ($Discussion->LastUserID) {
            $Last = UserBuilder($Discussion, 'Last');
        } else {
            $Last = $First;
        }
        //   $Sender->EventArguments['FirstUser'] = &$First;
        //   $Sender->EventArguments['LastUser'] = &$Last;
        //
        //   $Sender->FireEvent('BeforeDiscussionName');
        $DiscussionName = $Discussion->Name;
        if ($DiscussionName == '') {
            $DiscussionName = T('Blank Discussion Topic');
        }
        $Sender->EventArguments['DiscussionName'] =& $DiscussionName;
        $Discussion->CountPages = ceil($Discussion->CountComments / $Sender->CountCommentsPerPage);
        $FirstPageUrl = DiscussionUrl($Discussion, 1);
        $LastPageUrl = DiscussionUrl($Discussion, FALSE) . '#latest';
        ?>
<tr id="Discussion_<?php 
        echo $Discussion->DiscussionID;
        ?>
" class="<?php 
        echo $CssClass;
        ?>
">
   <?php 
        echo AdminCheck($Discussion, array('<td class="CheckBoxColumn"><div class="Wrap">', '</div></td>'));
        ?>
	<td class="DiscussionName">
		<div class="Wrap">
         <span class="Options">
            <?php 
        echo OptionsList($Discussion);
        echo BookmarkButton($Discussion);
        ?>
         </span>
			<?php 
        echo Anchor($DiscussionName, $DiscussionUrl, 'Title') . ' ';
        $Sender->FireEvent('AfterDiscussionTitle');
        WriteMiniPager($Discussion);
        echo NewComments($Discussion);
        if ($Sender->Data('_ShowCategoryLink', TRUE)) {
            echo CategoryLink($Discussion, ' ' . T('in') . ' ');
        }
        // Other stuff that was in the standard view that you may want to display:
        echo '<div class="Meta Meta-Discussion">';
        WriteTags($Discussion);
        echo '</div>';
        //			if ($Source = GetValue('Source', $Discussion))
        //				echo ' '.sprintf(T('via %s'), T($Source.' Source', $Source));
        //
        ?>
		</div>
	</td>
	<td class="BlockColumn BlockColumn-User FirstUser">
		<div class="Block Wrap">
			<?php 
        echo UserPhoto($First, array('Size' => 'Small'));
        echo UserAnchor($First, 'UserLink BlockTitle');
        echo '<div class="Meta">';
        echo Anchor(Gdn_Format::Date($Discussion->FirstDate, 'html'), $FirstPageUrl, 'CommentDate MItem');
        echo '</div>';
        ?>
		</div>
   </td>
	<td class="BigCount CountComments">
      <div class="Wrap">
         <?php 
        // Exact Number
        // echo number_format($Discussion->CountComments);
        // Round Number
        echo BigPlural($Discussion->CountComments, '%s comment');
        ?>
      </div>
	</td>
	<td class="BigCount CountViews">
      <div class="Wrap">
         <?php 
        // Exact Number
        // echo number_format($Discussion->CountViews);
        // Round Number
        echo BigPlural($Discussion->CountViews, '%s view');
        ?>
      </div>
	</td>
	<td class="BlockColumn BlockColumn-User LastUser">
		<div class="Block Wrap">
			<?php 
        if ($Last) {
            echo UserPhoto($Last, array('Size' => 'Small'));
            echo UserAnchor($Last, 'UserLink BlockTitle');
            echo '<div class="Meta">';
            echo Anchor(Gdn_Format::Date($Discussion->LastDate, 'html'), $LastPageUrl, 'CommentDate MItem');
            echo '</div>';
        } else {
            echo '&nbsp;';
        }
        ?>
		</div>
	</td>
</tr>
<?php 
    }
示例#10
0
//               $CommentOptions = array('MultiLine' => TRUE, 'format' => GetValueR('Comment.Format', $this));
$this->FireEvent('BeforeBodyField');
echo $this->Form->BodyBox('Body', array('Table' => 'Comment', 'tabindex' => 1));
$this->FireEvent('AfterBodyField');
echo "<div class=\"Buttons\">\n";
$this->FireEvent('BeforeFormButtons');
$CancelText = T('Home');
$CancelClass = 'Back';
if (!$NewOrDraft || $Editing) {
    $CancelText = T('Cancel');
    $CancelClass = 'Cancel';
}
echo '<span class="' . $CancelClass . '">';
echo Anchor($CancelText, '/');
if ($CategoryID = $this->Data('Discussion.CategoryID')) {
    $Category = CategoryModel::Categories($CategoryID);
    if ($Category) {
        echo ' <span class="Bullet">•</span> ' . Anchor($Category['Name'], $Category['Url']);
    }
}
echo '</span>';
$ButtonOptions = array('class' => 'Button Primary CommentButton');
$ButtonOptions['tabindex'] = 2;
/*
Caused non-root users to not be able to add comments. Must take categories
into account. Look at CheckPermission for more information.
if (!Gdn::Session()->CheckPermission('Vanilla.Comment.Add'))
   $ButtonOptions['Disabled'] = 'disabled';
*/
if (!$Editing && $Session->IsValid()) {
    echo Anchor(T('Preview'), '#', 'PreviewButton') . "\n";
示例#11
0
 /**
  * Load discussions for a specific tag.
  * @param DiscussionsController $Sender
  */
 public function DiscussionsController_Tagged_Create($Sender)
 {
     Gdn_Theme::Section('DiscussionList');
     $Args = $Sender->RequestArgs;
     $Get = array_change_key_case($Sender->Request->Get());
     if ($UseCategories = C('Plugins.Tagging.UseCategories')) {
         // The url is in the form /category/tag/p1
         $CategoryCode = GetValue(0, $Args);
         $Tag = GetValue(1, $Args);
         $Page = GetValue(2, $Args);
     } else {
         // The url is in the form /tag/p1
         $CategoryCode = '';
         $Tag = GetValue(0, $Args);
         $Page = GetValue(1, $Args);
     }
     // Look for explcit values.
     $CategoryCode = GetValue('category', $Get, $CategoryCode);
     $Tag = GetValue('tag', $Get, $Tag);
     $Page = GetValue('page', $Get, $Page);
     $Category = CategoryModel::Categories($CategoryCode);
     $Tag = StringEndsWith($Tag, '.rss', TRUE, TRUE);
     list($Offset, $Limit) = OffsetLimit($Page, C('Vanilla.Discussions.PerPage', 30));
     $MultipleTags = strpos($Tag, ',') !== FALSE;
     $Sender->SetData('Tag', $Tag, TRUE);
     $TagModel = TagModel::instance();
     $RecordCount = FALSE;
     if (!$MultipleTags) {
         $Tags = $TagModel->GetWhere(array('Name' => $Tag))->ResultArray();
         if (count($Tags) == 0) {
             throw NotFoundException('Page');
         }
         if (count($Tags) > 1) {
             foreach ($Tags as $TagRow) {
                 if ($TagRow['CategoryID'] == GetValue('CategoryID', $Category)) {
                     break;
                 }
             }
         } else {
             $TagRow = array_pop($Tags);
         }
         $Tags = $TagModel->getRelatedTags($TagRow);
         $RecordCount = $TagRow['CountDiscussions'];
         $Sender->SetData('CountDiscussions', $RecordCount);
         $Sender->SetData('Tags', $Tags);
         $Sender->SetData('Tag', $TagRow);
         $ChildTags = $TagModel->getChildTags($TagRow['TagID']);
         $Sender->SetData('ChildTags', $ChildTags);
     }
     $Sender->Title(htmlspecialchars($TagRow['FullName']));
     $UrlTag = rawurlencode($Tag);
     if (urlencode($Tag) == $Tag) {
         $Sender->CanonicalUrl(Url(ConcatSep('/', "/discussions/tagged/{$UrlTag}", PageNumber($Offset, $Limit, TRUE)), TRUE));
         $FeedUrl = Url(ConcatSep('/', "/discussions/tagged/{$UrlTag}/feed.rss", PageNumber($Offset, $Limit, TRUE, FALSE)), '//');
     } else {
         $Sender->CanonicalUrl(Url(ConcatSep('/', 'discussions/tagged', PageNumber($Offset, $Limit, TRUE)) . '?Tag=' . $UrlTag, TRUE));
         $FeedUrl = Url(ConcatSep('/', 'discussions/tagged', PageNumber($Offset, $Limit, TRUE, FALSE), 'feed.rss') . '?Tag=' . $UrlTag, '//');
     }
     if ($Sender->Head) {
         $Sender->AddJsFile('discussions.js');
         $Sender->Head->AddRss($FeedUrl, $Sender->Head->Title());
     }
     if (!is_numeric($Offset) || $Offset < 0) {
         $Offset = 0;
     }
     // Add Modules
     $Sender->AddModule('NewDiscussionModule');
     $Sender->AddModule('DiscussionFilterModule');
     $Sender->AddModule('BookmarkedModule');
     $Sender->SetData('Category', FALSE, TRUE);
     $Sender->AnnounceData = FALSE;
     $Sender->SetData('Announcements', array(), TRUE);
     $DiscussionModel = new DiscussionModel();
     $TagModel->SetTagSql($DiscussionModel->SQL, $Tag, $Limit, $Offset, $Sender->Request->Get('op', 'or'));
     $Sender->DiscussionData = $DiscussionModel->Get($Offset, $Limit, array('Announce' => 'all'));
     $Sender->SetData('Discussions', $Sender->DiscussionData, TRUE);
     $Sender->SetJson('Loading', $Offset . ' to ' . $Limit);
     // Build a pager.
     $PagerFactory = new Gdn_PagerFactory();
     $Sender->Pager = $PagerFactory->GetPager('Pager', $Sender);
     $Sender->Pager->ClientID = 'Pager';
     $Sender->Pager->Configure($Offset, $Limit, $RecordCount, '');
     $Sender->View = C('Vanilla.Discussions.Layout');
     /*
           // If these don't equal, then there is a category that should be inserted.
           if ($UseCategories && $Category && $TagRow['FullName'] != GetValue('Name', $Category)) {
              $Sender->Data['Breadcrumbs'][] = array('Name' => $Category['Name'], 'Url' => TagUrl($TagRow));
           }
           $Sender->Data['Breadcrumbs'][] = array('Name' => $TagRow['FullName'], 'Url' => '');
     */
     // Render the controller.
     $this->View = C('Vanilla.Discussions.Layout') == 'table' ? 'table' : 'index';
     $Sender->Render($this->View, 'discussions', 'vanilla');
 }
示例#12
0
 /**
  * Grab and update the category cache
  *
  * @since 2.0.18
  * @access public
  * @param int $ID
  * @param array $Data
  */
 public static function setCache($ID = false, $Data = false)
 {
     self::instance()->collection->refreshCache((int) $ID);
     $Categories = Gdn::cache()->get(self::CACHE_KEY);
     self::$Categories = null;
     if (!$Categories) {
         return;
     }
     // Extract actual category list, remove key if malformed
     if (!$ID || !is_array($Categories) || !array_key_exists('categories', $Categories)) {
         Gdn::cache()->remove(self::CACHE_KEY);
         return;
     }
     $Categories = $Categories['categories'];
     // Check for category in list, otherwise remove key if not found
     if (!array_key_exists($ID, $Categories)) {
         Gdn::cache()->remove(self::CACHE_KEY);
         return;
     }
     $Category = $Categories[$ID];
     $Category = array_merge($Category, $Data);
     $Categories[$ID] = $Category;
     // Update memcache entry
     self::$Categories = $Categories;
     unset($Categories);
     self::BuildCache($ID);
     self::JoinUserData(self::$Categories, true);
 }
示例#13
0
 /**
  * Delete a comment.
  *
  * This is a hard delete that completely removes it from the database.
  * Events: DeleteComment.
  * 
  * @since 2.0.0
  * @access public
  *
  * @param int $CommentID Unique ID of the comment to be deleted.
  * @param array $Options Additional options for the delete.
  * @param bool Always returns TRUE.
  */
 public function Delete($CommentID, $Options = array())
 {
     $this->EventArguments['CommentID'] = $CommentID;
     $Comment = $this->GetID($CommentID, DATASET_TYPE_ARRAY);
     if (!$Comment) {
         return FALSE;
     }
     $Discussion = $this->SQL->GetWhere('Discussion', array('DiscussionID' => $Comment['DiscussionID']))->FirstRow(DATASET_TYPE_ARRAY);
     // Decrement the UserDiscussion comment count if the user has seen this comment
     $Offset = $this->GetOffset($CommentID);
     $this->SQL->Update('UserDiscussion')->Set('CountComments', 'CountComments - 1', FALSE)->Where('DiscussionID', $Comment['DiscussionID'])->Where('CountComments >', $Offset)->Put();
     $this->FireEvent('DeleteComment');
     // Log the deletion.
     $Log = GetValue('Log', $Options, 'Delete');
     LogModel::Insert($Log, 'Comment', $Comment, GetValue('LogOptions', $Options, array()));
     // Delete the comment.
     $this->SQL->Delete('Comment', array('CommentID' => $CommentID));
     // Update the comment count
     $this->UpdateCommentCount($Discussion);
     // Update the user's comment count
     $this->UpdateUser($Comment['InsertUserID']);
     // Update the category.
     $Category = CategoryModel::Categories(GetValue('CategoryID', $Discussion));
     if ($Category && $Category['LastCommentID'] == $CommentID) {
         $CategoryModel = new CategoryModel();
         $CategoryModel->SetRecentPost($Category['CategoryID']);
     }
     // Clear the page cache.
     $this->RemovePageCache($Comment['DiscussionID']);
     return TRUE;
 }
示例#14
0
 /**
  * Grab and update the category cache
  * 
  * @since 2.0.18
  * @access public
  * @param int $ID
  * @param array $Data
  */
 public static function SetCache($ID = FALSE, $Data = FALSE)
 {
     $Categories = Gdn::Cache()->Get(self::CACHE_KEY);
     self::$Categories = NULL;
     if (!$Categories) {
         return;
     }
     if (!$ID || !is_array($Categories)) {
         Gdn::Cache()->Remove(self::CACHE_KEY);
         return;
     }
     if (!array_key_exists($ID, $Categories)) {
         Gdn::Cache()->Remove(self::CACHE_KEY);
         return;
     }
     $Category = $Categories[$ID];
     $Category = array_merge($Category, $Data);
     $Categories[$ID] = $Category;
     self::$Categories = $Categories;
     unset($Categories);
     self::BuildCache();
     self::JoinUserData(self::$Categories, TRUE);
 }
 /**
  * Editing a category.
  *
  * @since 2.0.0
  * @access public
  *
  * @param int $CategoryID Unique ID of the category to be updated.
  */
 public function EditCategory($CategoryID = '')
 {
     // Check permission
     $this->Permission('Garden.Settings.Manage');
     // Set up models
     $RoleModel = new RoleModel();
     $PermissionModel = Gdn::PermissionModel();
     $this->Form->SetModel($this->CategoryModel);
     if (!$CategoryID && $this->Form->IsPostBack()) {
         if ($ID = $this->Form->GetFormValue('CategoryID')) {
             $CategoryID = $ID;
         }
     }
     // Get category data
     $this->Category = $this->CategoryModel->GetID($CategoryID);
     $this->Category->CustomPermissions = $this->Category->CategoryID == $this->Category->PermissionCategoryID;
     // Set up head
     $this->AddJsFile('jquery.alphanumeric.js');
     $this->AddJsFile('categories.js');
     $this->AddJsFile('jquery.gardencheckboxgrid.js');
     $this->Title(T('Edit Category'));
     $this->AddSideMenu('vanilla/settings/managecategories');
     // Make sure the form knows which item we are editing.
     $this->Form->AddHidden('CategoryID', $CategoryID);
     $this->SetData('CategoryID', $CategoryID);
     // Load all roles with editable permissions
     $this->RoleArray = $RoleModel->GetArray();
     $this->FireEvent('AddEditCategory');
     if ($this->Form->IsPostBack() == FALSE) {
         $this->Form->SetData($this->Category);
         $this->SetupDiscussionTypes($this->Category);
         $this->Form->SetValue('CustomPoints', $this->Category->PointsCategoryID == $this->Category->CategoryID);
     } else {
         $this->SetupDiscussionTypes($this->Category);
         $Upload = new Gdn_Upload();
         $TmpImage = $Upload->ValidateUpload('PhotoUpload', FALSE);
         if ($TmpImage) {
             // Generate the target image name
             $TargetImage = $Upload->GenerateTargetName(PATH_UPLOADS);
             $ImageBaseName = pathinfo($TargetImage, PATHINFO_BASENAME);
             // Save the uploaded image
             $Parts = $Upload->SaveAs($TmpImage, $ImageBaseName);
             $this->Form->SetFormValue('Photo', $Parts['SaveName']);
         }
         $this->Form->SetFormValue('CustomPoints', (bool) $this->Form->GetFormValue('CustomPoints'));
         if ($this->Form->Save()) {
             $Category = CategoryModel::Categories($CategoryID);
             $this->SetData('Category', $Category);
             if ($this->DeliveryType() == DELIVERY_TYPE_ALL) {
                 Redirect('vanilla/settings/managecategories');
             }
         }
     }
     // Get all of the currently selected role/permission combinations for this junction.
     $Permissions = $PermissionModel->GetJunctionPermissions(array('JunctionID' => $CategoryID), 'Category', '', array('AddDefaults' => !$this->Category->CustomPermissions));
     $Permissions = $PermissionModel->UnpivotPermissions($Permissions, TRUE);
     if ($this->DeliveryType() == DELIVERY_TYPE_ALL) {
         $this->SetData('PermissionData', $Permissions, TRUE);
     }
     // Render default view
     $this->Render();
 }
示例#16
0
 /**
  * @param Gdn_Controller $Sender
  * @param type $Args 
  */
 public function UtilityController_SiteMapIndex_Create($Sender)
 {
     // Clear the session to mimic a crawler.
     Gdn::Session()->Start(0, FALSE, FALSE);
     $Sender->DeliveryMethod(DELIVERY_METHOD_XHTML);
     $Sender->DeliveryType(DELIVERY_TYPE_VIEW);
     $Sender->SetHeader('Content-Type', 'text/xml');
     $SiteMaps = array();
     if (class_exists('CategoryModel')) {
         $Categories = CategoryModel::Categories();
         foreach ($Categories as $Category) {
             if (!$Category['PermsDiscussionsView'] || $Category['CategoryID'] < 0 || $Category['CountDiscussions'] == 0) {
                 continue;
             }
             $SiteMap = array('Loc' => Url('/sitemap-category-' . rawurlencode($Category['UrlCode'] ? $Category['UrlCode'] : $Category['CategoryID']) . '.xml', TRUE), 'LastMod' => $Category['DateLastComment'], 'ChangeFreq' => '', 'Priority' => '');
             $SiteMaps[] = $SiteMap;
         }
     }
     $Sender->SetData('SiteMaps', $SiteMaps);
     $Sender->Render('SiteMapIndex', '', 'plugins/Sitemaps');
 }
示例#17
0
 /**
  * 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');
 }
示例#18
0
 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;
 }
示例#19
0
 /**
  * Check whether a user has access to view discussions in a particular category.
  *
  * @since 2.0.18
  * @example $UserModel->GetCategoryViewPermission($UserID, $CategoryID).
  *
  * @param $Sender UserModel.
  * @return bool Whether user has permission.
  */
 public function UserModel_GetCategoryViewPermission_Create($Sender)
 {
     static $PermissionModel = NULL;
     $UserID = ArrayValue(0, $Sender->EventArguments, '');
     $CategoryID = ArrayValue(1, $Sender->EventArguments, '');
     if ($UserID && $CategoryID) {
         if ($PermissionModel === NULL) {
             $PermissionModel = new PermissionModel();
         }
         $Category = CategoryModel::Categories($CategoryID);
         if ($Category) {
             $PermissionCategoryID = $Category['PermissionCategoryID'];
         } else {
             $PermissionCategoryID = -1;
         }
         $Result = $PermissionModel->GetUserPermissions($UserID, 'Vanilla.Discussions.View', 'Category', 'PermissionCategoryID', 'CategoryID', $PermissionCategoryID);
         return GetValue('Vanilla.Discussions.View', GetValue(0, $Result), FALSE) ? TRUE : FALSE;
     }
     return FALSE;
 }
示例#20
0
 /**
  *
  * @param type $Discussion
  * @param type $NotifiedUsers
  * @param ActivityModel $ActivityModel 
  */
 public function NotifyNewDiscussion($Discussion, $ActivityModel, $Activity)
 {
     if (is_numeric($Discussion)) {
         $Discussion = $this->GetID($Discussion);
     }
     $CategoryID = GetValue('CategoryID', $Discussion);
     // Figure out the category that governs this notification preference.
     $i = 0;
     $Category = CategoryModel::Categories($CategoryID);
     if (!$Category) {
         return;
     }
     while ($Category['Depth'] > 2 && $i < 20) {
         if (!$Category || $Category['Archived']) {
             return;
         }
         $i++;
         $Category = CategoryModel::Categories($Category['ParentCategoryID']);
     }
     // Grab all of the users that need to be notified.
     $Data = $this->SQL->WhereIn('Name', array('Preferences.Email.NewDiscussion.' . $Category['CategoryID'], 'Preferences.Popup.NewDiscussion.' . $Category['CategoryID']))->Get('UserMeta')->ResultArray();
     //      decho($Data, 'Data');
     $NotifyUsers = array();
     foreach ($Data as $Row) {
         if (!$Row['Value']) {
             continue;
         }
         $UserID = $Row['UserID'];
         $Name = $Row['Name'];
         if (strpos($Name, '.Email.') !== FALSE) {
             $NotifyUsers[$UserID]['Emailed'] = ActivityModel::SENT_PENDING;
         } elseif (strpos($Name, '.Popup.') !== FALSE) {
             $NotifyUsers[$UserID]['Notified'] = ActivityModel::SENT_PENDING;
         }
     }
     //      decho($NotifyUsers);
     $InsertUserID = GetValue('InsertUserID', $Discussion);
     foreach ($NotifyUsers as $UserID => $Prefs) {
         if ($UserID == $InsertUserID) {
             continue;
         }
         $Activity['NotifyUserID'] = $UserID;
         $Activity['Emailed'] = GetValue('Emailed', $Prefs, FALSE);
         $Activity['Notified'] = GetValue('Notified', $Prefs, FALSE);
         $ActivityModel->Queue($Activity);
         //         decho($Activity, 'die');
     }
     //      die();
 }
示例#21
0
 /**
  * Return a url for a category. This function is in here and not functions.general so that plugins can override.
  *
  * @param array $Category
  * @return string
  */
 function categoryUrl($Category, $Page = '', $WithDomain = true)
 {
     if (is_string($Category)) {
         $Category = CategoryModel::Categories($Category);
     }
     $Category = (array) $Category;
     $Result = '/categories/' . rawurlencode($Category['UrlCode']);
     if ($Page && $Page > 1) {
         $Result .= '/p' . $Page;
     }
     return Url($Result, $WithDomain);
 }
示例#22
0
function WriteDiscussion($Discussion, &$Sender, &$Session, $Alt2)
{
    static $Alt = FALSE;
    $CssClass = 'Item';
    $CssClass .= $Discussion->Bookmarked == '1' ? ' Bookmarked' : '';
    $CssClass .= $Alt ? ' Alt ' : '';
    $Alt = !$Alt;
    $CssClass .= $Discussion->Announce == '1' ? ' Announcement' : '';
    $CssClass .= $Discussion->Dismissed == '1' ? ' Dismissed' : '';
    $CssClass .= $Discussion->InsertUserID == $Session->UserID ? ' Mine' : '';
    $CssClass .= $Discussion->CountUnreadComments > 0 && $Session->IsValid() ? ' New' : '';
    $DiscussionUrl = '/discussion/' . $Discussion->DiscussionID . '/' . Gdn_Format::Url($Discussion->Name) . ($Discussion->CountCommentWatch > 0 && C('Vanilla.Comments.AutoOffset') && $Session->UserID > 0 ? '/#Item_' . $Discussion->CountCommentWatch : '');
    //   $DiscussionUrl = $Discussion->Url;
    $Sender->EventArguments['DiscussionUrl'] =& $DiscussionUrl;
    $Sender->EventArguments['Discussion'] =& $Discussion;
    $Sender->EventArguments['CssClass'] =& $CssClass;
    $First = UserBuilder($Discussion, 'First');
    $Last = UserBuilder($Discussion, 'Last');
    $Sender->FireEvent('BeforeDiscussionName');
    $DiscussionName = $Discussion->Name;
    if ($DiscussionName == '') {
        $DiscussionName = T('Blank Discussion Topic');
    }
    $Sender->EventArguments['DiscussionName'] =& $DiscussionName;
    static $FirstDiscussion = TRUE;
    if (!$FirstDiscussion) {
        $Sender->FireEvent('BetweenDiscussion');
    } else {
        $FirstDiscussion = FALSE;
    }
    ?>
<li class="<?php 
    echo $CssClass;
    ?>
">
   <?php 
    if (!property_exists($Sender, 'CanEditDiscussions')) {
        $Sender->CanEditDiscussions = GetValue('PermsDiscussionsEdit', CategoryModel::Categories($Discussion->CategoryID)) && C('Vanilla.AdminCheckboxes.Use');
    }
    $Sender->FireEvent('BeforeDiscussionContent');
    WriteOptions($Discussion, $Sender, $Session);
    ?>
   <div class="ItemContent Discussion">
      <?php 
    echo Anchor($DiscussionName, $DiscussionUrl, 'Title');
    ?>
      <?php 
    $Sender->FireEvent('AfterDiscussionTitle');
    ?>
      <div class="Meta">
         <?php 
    $Sender->FireEvent('BeforeDiscussionMeta');
    ?>
         <?php 
    if ($Discussion->Announce == '1') {
        ?>
         <span class="Tag Announcement"><?php 
        echo T('Announcement');
        ?>
</span>
         <?php 
    }
    ?>
         <?php 
    if ($Discussion->Closed == '1') {
        ?>
         <span class="Tag Closed"><?php 
        echo T('Closed');
        ?>
</span>
         <?php 
    }
    ?>
         <span class="MItem CommentCount"><?php 
    printf(Plural($Discussion->CountComments, '%s comment', '%s comments'), $Discussion->CountComments);
    if ($Session->IsValid() && $Discussion->CountUnreadComments > 0) {
        echo ' <strong class="HasNew">' . Plural($Discussion->CountUnreadComments, '%s new', '%s new plural') . '</strong>';
    }
    ?>
</span>
         <?php 
    $Sender->FireEvent('AfterCountMeta');
    if ($Discussion->LastCommentID != '') {
        echo ' <span class="MItem LastCommentBy">' . sprintf(T('Most recent by %1$s'), UserAnchor($Last)) . '</span> ';
        echo ' <span class="MItem LastCommentDate">' . Gdn_Format::Date($Discussion->LastDate) . '</span>';
    } else {
        echo ' <span class="MItem LastCommentBy">' . sprintf(T('Started by %1$s'), UserAnchor($First)) . '</span> ';
        echo ' <span class="MItem LastCommentDate">' . Gdn_Format::Date($Discussion->FirstDate);
        if ($Source = GetValue('Source', $Discussion)) {
            echo ' ' . sprintf(T('via %s'), T($Source . ' Source', $Source));
        }
        echo '</span> ';
    }
    if (C('Vanilla.Categories.Use') && $Discussion->CategoryUrlCode != '') {
        echo ' ' . Wrap(Anchor($Discussion->Category, '/categories/' . rawurlencode($Discussion->CategoryUrlCode)), 'span', array('class' => 'Tag Category'));
    }
    $Sender->FireEvent('DiscussionMeta');
    ?>
      </div>
   </div>
</li>
<?php 
}
示例#23
0
 public static function CategoryUrl($Category, $Page = '', $WithDomain = TRUE)
 {
     if (function_exists('CategoryUrl')) {
         return CategoryUrl($Category, $Page, $WithDomain);
     }
     if (is_string($Category)) {
         $Category = CategoryModel::Categories($Category);
     }
     $Category = (array) $Category;
     $Result = '/categories/' . rawurlencode($Category['UrlCode']);
     if ($Page && $Page > 1) {
         $Result .= '/p' . $Page;
     }
     return Url($Result, $WithDomain);
 }
示例#24
0
			<div class="Excerpt"><?php 
        echo Anchor(nl2br(SliceString(Gdn_Format::Text($Row->Summary, FALSE), 250)), $Row->Url);
        ?>
</div>
			<div class="Meta">
				<span><?php 
        printf(T('by %s'), UserAnchor($Row));
        ?>
</span>
				<span><?php 
        echo Gdn_Format::Date($Row->DateInserted);
        ?>
</span>
            <?php 
        if (isset($Row->CategoryID)) {
            $Category = CategoryModel::Categories($Row->CategoryID);
            if ($Category !== NULL) {
                $Url = Url('categories/' . $Category['UrlCode']);
                echo "<span><a class='Category' href='{$Url}'>{$Category['Name']}</a></span>";
            }
        }
        ?>
				<span><?php 
        echo Anchor(T('permalink'), $Row->Url);
        ?>
</span>
			</div>
		</div>
	</li>
<?php 
    }
 /**
  * Form to edit an existing message.
  *
  * @since 2.0.0
  * @access public
  */
 public function Edit($MessageID = '')
 {
     $this->AddJsFile('jquery.autosize.min.js');
     $this->AddJsFile('messages.js');
     $this->Permission('Garden.Messages.Manage');
     $this->AddSideMenu('dashboard/message');
     // Generate some Controller & Asset data arrays
     $this->SetData('Locations', $this->_GetLocationData());
     $this->AssetData = $this->_GetAssetData();
     // Set the model on the form.
     $this->Form->SetModel($this->MessageModel);
     $this->Message = $this->MessageModel->GetID($MessageID);
     $this->Message = $this->MessageModel->DefineLocation($this->Message);
     // Make sure the form knows which item we are editing.
     if (is_numeric($MessageID) && $MessageID > 0) {
         $this->Form->AddHidden('MessageID', $MessageID);
     }
     $CategoriesData = CategoryModel::Categories();
     $Categories = array();
     foreach ($CategoriesData as $Row) {
         if ($Row['CategoryID'] < 0) {
             continue;
         }
         $Categories[$Row['CategoryID']] = str_repeat('&nbsp;&nbsp;&nbsp;', max(0, $Row['Depth'] - 1)) . $Row['Name'];
     }
     $this->SetData('Categories', $Categories);
     // If seeing the form for the first time...
     if (!$this->Form->AuthenticatedPostBack()) {
         $this->Form->SetData($this->Message);
     } else {
         if ($MessageID = $this->Form->Save()) {
             // Reset the message cache
             $this->MessageModel->SetMessageCache();
             // Redirect
             $this->InformMessage(T('Your changes have been saved.'));
             //$this->RedirectUrl = Url('dashboard/message');
         }
     }
     $this->Render();
 }
示例#26
0
 /**
  * Pre-populate the form with values from the query string.
  *
  * @param Gdn_Form $Form
  * @param bool $LimitCategories Whether to turn off the category dropdown if there is only one category to show.
  */
 protected function PopulateForm($Form)
 {
     $Get = $this->Request->Get();
     $Get = array_change_key_case($Get);
     $Values = ArrayTranslate($Get, array('name' => 'Name', 'tags' => 'Tags', 'body' => 'Body'));
     foreach ($Values as $Key => $Value) {
         $Form->SetValue($Key, $Value);
     }
     if (isset($Get['category'])) {
         $Category = CategoryModel::Categories($Get['category']);
         if ($Category && $Category['PermsDiscussionsAdd']) {
             $Form->SetValue('CategoryID', $Category['CategoryID']);
         }
     }
 }
示例#27
0
 /**
  * Adds email notification options to profiles.
  * 
  * @since 2.0.0
  * @package Vanilla
  * 
  * @param ProfileController $Sender
  */
 public function ProfileController_AfterPreferencesDefined_Handler($Sender)
 {
     $Sender->Preferences['Notifications']['Email.DiscussionComment'] = T('Notify me when people comment on my discussions.');
     $Sender->Preferences['Notifications']['Email.BookmarkComment'] = T('Notify me when people comment on my bookmarked discussions.');
     $Sender->Preferences['Notifications']['Email.Mention'] = T('Notify me when people mention me.');
     $Sender->Preferences['Notifications']['Popup.DiscussionComment'] = T('Notify me when people comment on my discussions.');
     $Sender->Preferences['Notifications']['Popup.BookmarkComment'] = T('Notify me when people comment on my bookmarked discussions.');
     $Sender->Preferences['Notifications']['Popup.Mention'] = T('Notify me when people mention me.');
     //      if (Gdn::Session()->CheckPermission('Garden.AdvancedNotifications.Allow')) {
     //         $Sender->Preferences['Notifications']['Email.NewDiscussion'] = array(T('Notify me when people start new discussions.'), 'Meta');
     //         $Sender->Preferences['Notifications']['Email.NewComment'] = array(T('Notify me when people comment on a discussion.'), 'Meta');
     ////      $Sender->Preferences['Notifications']['Popup.NewDiscussion'] = T('Notify me when people start new discussions.');
     //      }
     if (Gdn::Session()->CheckPermission('Garden.AdvancedNotifications.Allow')) {
         $PostBack = $Sender->Form->IsPostBack();
         $Set = array();
         // Add the category definitions to for the view to pick up.
         $DoHeadings = C('Vanilla.Categories.DoHeadings');
         // Grab all of the categories.
         $Categories = array();
         $Prefixes = array('Email.NewDiscussion', 'Popup.NewDiscussion', 'Email.NewComment', 'Popup.NewComment');
         foreach (CategoryModel::Categories() as $Category) {
             if (!$Category['PermsDiscussionsView'] || $Category['Depth'] <= 0 || $Category['Depth'] > 2 || $Category['Archived']) {
                 continue;
             }
             $Category['Heading'] = $DoHeadings && $Category['Depth'] <= 1;
             $Categories[] = $Category;
             if ($PostBack) {
                 foreach ($Prefixes as $Prefix) {
                     $FieldName = "{$Prefix}.{$Category['CategoryID']}";
                     $Value = $Sender->Form->GetFormValue($FieldName, NULL);
                     if (!$Value) {
                         $Value = NULL;
                     }
                     $Set[$FieldName] = $Value;
                 }
             }
         }
         $Sender->SetData('CategoryNotifications', $Categories);
         if ($PostBack) {
             UserModel::SetMeta($Sender->User->UserID, $Set, 'Preferences.');
         }
     }
 }
 /**
  * Show all discussions in a particular category.
  * 
  * @since 2.0.0
  * @access public
  * 
  * @param string $CategoryIdentifier Unique category slug or ID.
  * @param int $Offset Number of discussions to skip.
  */
 public function Index($CategoryIdentifier = '', $Page = '0')
 {
     if ($CategoryIdentifier == '') {
         // Figure out which category layout to choose (Defined on "Homepage" settings page).
         $Layout = C('Vanilla.Categories.Layout');
         switch ($Layout) {
             case 'mixed':
                 $this->View = 'discussions';
                 $this->Discussions();
                 break;
             case 'table':
                 $this->Table();
                 break;
             default:
                 $this->View = 'all';
                 $this->All();
                 break;
         }
         return;
     } else {
         Gdn_Theme::Section('DiscussionList');
         // Figure out which discussions layout to choose (Defined on "Homepage" settings page).
         $Layout = C('Vanilla.Discussions.Layout');
         switch ($Layout) {
             case 'table':
                 if ($this->SyndicationMethod == SYNDICATION_NONE) {
                     $this->View = 'table';
                 }
                 break;
             default:
                 // $this->View = 'index';
                 break;
         }
         $Category = CategoryModel::Categories($CategoryIdentifier);
         if (empty($Category)) {
             if ($CategoryIdentifier) {
                 throw NotFoundException();
             }
         }
         $Category = (object) $Category;
         Gdn_Theme::Section($Category->CssClass);
         // Load the breadcrumbs.
         $this->SetData('Breadcrumbs', CategoryModel::GetAncestors(GetValue('CategoryID', $Category)));
         $this->SetData('Category', $Category, TRUE);
         // Load the subtree.
         if (C('Vanilla.ExpandCategories')) {
             $Categories = CategoryModel::GetSubtree($CategoryIdentifier);
         } else {
             $Categories = array($Category);
         }
         $this->SetData('Categories', $Categories);
         // Setup head
         $this->AddCssFile('vanilla.css');
         $this->Menu->HighlightRoute('/discussions');
         if ($this->Head) {
             $this->AddJsFile('discussions.js');
             $this->AddJsFile('bookmark.js');
             $this->AddJsFile('options.js');
             $this->Head->AddRss($this->SelfUrl . '/feed.rss', $this->Head->Title());
         }
         $this->Title(GetValue('Name', $Category, ''));
         $this->Description(GetValue('Description', $Category), TRUE);
         // Set CategoryID
         $CategoryID = GetValue('CategoryID', $Category);
         $this->SetData('CategoryID', $CategoryID, TRUE);
         // Add modules
         $this->AddModule('NewDiscussionModule');
         $this->AddModule('DiscussionFilterModule');
         $this->AddModule('CategoriesModule');
         $this->AddModule('BookmarkedModule');
         // Get a DiscussionModel
         $DiscussionModel = new DiscussionModel();
         $CategoryIDs = ConsolidateArrayValuesByKey($this->Data('Categories'), 'CategoryID');
         $Wheres = array('d.CategoryID' => $CategoryIDs);
         $this->SetData('_ShowCategoryLink', count($CategoryIDs) > 1);
         // Check permission
         $this->Permission('Vanilla.Discussions.View', TRUE, 'Category', GetValue('PermissionCategoryID', $Category));
         // Set discussion meta data.
         $this->EventArguments['PerPage'] = C('Vanilla.Discussions.PerPage', 30);
         $this->FireEvent('BeforeGetDiscussions');
         list($Offset, $Limit) = OffsetLimit($Page, $this->EventArguments['PerPage']);
         if (!is_numeric($Offset) || $Offset < 0) {
             $Offset = 0;
         }
         $CountDiscussions = $DiscussionModel->GetCount($Wheres);
         $this->SetData('CountDiscussions', $CountDiscussions);
         $this->SetData('_Limit', $Limit);
         // We don't wan't child categories in announcements.
         $Wheres['d.CategoryID'] = $CategoryID;
         $AnnounceData = $Offset == 0 ? $DiscussionModel->GetAnnouncements($Wheres) : new Gdn_DataSet();
         $this->SetData('AnnounceData', $AnnounceData, TRUE);
         $Wheres['d.CategoryID'] = $CategoryIDs;
         $this->DiscussionData = $this->SetData('Discussions', $DiscussionModel->GetWhere($Wheres, $Offset, $Limit));
         // Build a pager
         $PagerFactory = new Gdn_PagerFactory();
         $this->Pager = $PagerFactory->GetPager('Pager', $this);
         $this->Pager->ClientID = 'Pager';
         $this->Pager->Configure($Offset, $Limit, $CountDiscussions, array('CategoryUrl'));
         $this->Pager->Record = $Category;
         PagerModule::Current($this->Pager);
         $this->SetData('_Page', $Page);
         // Set the canonical Url.
         $this->CanonicalUrl(CategoryUrl($Category, PageNumber($Offset, $Limit)));
         // Change the controller name so that it knows to grab the discussion views
         $this->ControllerName = 'DiscussionsController';
         // Pick up the discussions class
         $this->CssClass = 'Discussions';
         // 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 = 'discussions';
         }
         // Render default view.
         $this->FireEvent('BeforeCategoriesRender');
         $this->Render();
     }
 }
示例#29
0
 /**
  * Returns XHTML for a select list containing categories that the user has
  * permission to use.
  *
  * @param array $FieldName An array of category data to render.
  * @param array $Options An associative array of options for the select. Here
  * is a list of "special" options and their default values:
  *
  *   Attribute     Options                        Default
  *   ------------------------------------------------------------------------
  *   Value         The ID of the category that    FALSE
  *                 is selected.
  *   IncludeNull   Include a blank row?           TRUE
  *   CategoryData  Custom set of categories to    CategoryModel::Categories()
  *                 display.
  *
  * @return string
  */
 public function CategoryDropDown($FieldName = 'CategoryID', $Options = FALSE)
 {
     $Value = ArrayValueI('Value', $Options);
     // The selected category id
     $CategoryData = GetValue('CategoryData', $Options, CategoryModel::Categories());
     // Sanity check
     if (is_object($CategoryData)) {
         $CategoryData = (array) $CategoryData;
     } else {
         if (!is_array($CategoryData)) {
             $CategoryData = array();
         }
     }
     $Permission = GetValue('Permission', $Options, 'add');
     // Respect category permissions (remove categories that the user shouldn't see).
     $SafeCategoryData = array();
     foreach ($CategoryData as $CategoryID => $Category) {
         if ($Permission == 'add' && !$Category['PermsDiscussionsAdd']) {
             continue;
         }
         if ($Value != $CategoryID) {
             if ($Category['CategoryID'] <= 0 || !$Category['PermsDiscussionsView']) {
                 continue;
             }
             if ($Category['Archived']) {
                 continue;
             }
         }
         $SafeCategoryData[$CategoryID] = $Category;
     }
     // Opening select tag
     $Return = '<select';
     $Return .= $this->_IDAttribute($FieldName, $Options);
     $Return .= $this->_NameAttribute($FieldName, $Options);
     $Return .= $this->_AttributesToString($Options);
     $Return .= ">\n";
     // Get value from attributes
     if ($Value === FALSE) {
         $Value = $this->GetValue($FieldName);
     }
     if (!is_array($Value)) {
         $Value = array($Value);
     }
     // Prevent default $Value from matching key of zero
     $HasValue = $Value !== array(FALSE) && $Value !== array('') ? TRUE : FALSE;
     // Start with null option?
     $IncludeNull = GetValue('IncludeNull', $Options);
     if ($IncludeNull === TRUE) {
         $Return .= '<option value="">' . T('Select a category...') . '</option>';
     } elseif (is_array($IncludeNull)) {
         $Return .= "<option value=\"{$IncludeNull[0]}\">{$IncludeNull[1]}</option>\n";
     } elseif ($IncludeNull) {
         $Return .= "<option value=\"\">{$IncludeNull}</option>\n";
     } elseif (!$HasValue) {
         $Return .= '<option value=""></option>';
     }
     // Show root categories as headings (ie. you can't post in them)?
     $DoHeadings = GetValue('Headings', $Options, C('Vanilla.Categories.DoHeadings'));
     // If making headings disabled and there was no default value for
     // selection, make sure to select the first non-disabled value, or the
     // browser will auto-select the first disabled option.
     $ForceCleanSelection = $DoHeadings && !$HasValue && !$IncludeNull;
     // Write out the category options
     if (is_array($SafeCategoryData)) {
         foreach ($SafeCategoryData as $CategoryID => $Category) {
             $Depth = GetValue('Depth', $Category, 0);
             $Disabled = $Depth == 1 && $DoHeadings;
             $Selected = in_array($CategoryID, $Value) && $HasValue;
             if ($ForceCleanSelection && $Depth > 1) {
                 $Selected = TRUE;
                 $ForceCleanSelection = FALSE;
             }
             $Return .= '<option value="' . $CategoryID . '"';
             if ($Disabled) {
                 $Return .= ' disabled="disabled"';
             } else {
                 if ($Selected) {
                     $Return .= ' selected="selected"';
                 }
             }
             // only allow selection if NOT disabled
             $Name = htmlspecialchars(GetValue('Name', $Category, 'Blank Category Name'));
             if ($Depth > 1) {
                 $Name = str_repeat('&#160;', 4 * ($Depth - 1)) . $Name;
                 //               $Name = str_replace(' ', '&#160;', $Name);
             }
             $Return .= '>' . $Name . "</option>\n";
         }
     }
     return $Return . '</select>';
 }
 /**
  * Allows user to announce or unannounce a discussion.
  *
  * If the discussion isn't announced, this announces it.
  * If it is already announced, this unannounces it.
  * Announced discussions stay at the top of the discussions
  * list regardless of how long ago the last comment was.
  *
  * @since 2.0.0
  * @access public
  *
  * @param int $DiscussionID Unique discussion ID.
  * @param string $TransientKey Single-use hash to prove intent.
  */
 public function Announce($DiscussionID = '', $Target = '')
 {
     $Discussion = $this->DiscussionModel->GetID($DiscussionID);
     if (!$Discussion) {
         throw NotFoundException('Discussion');
     }
     $this->Permission('Vanilla.Discussions.Announce', TRUE, 'Category', $Discussion->PermissionCategoryID);
     if ($this->Form->AuthenticatedPostBack()) {
         // Save the property.
         $CacheKeys = array('Announcements', 'Announcements_' . GetValue('CategoryID', $Discussion));
         $this->DiscussionModel->SQL->Cache($CacheKeys);
         $this->DiscussionModel->SetProperty($DiscussionID, 'Announce', (int) $this->Form->GetFormValue('Announce', 0));
         if ($Target) {
             $this->RedirectUrl = Url($Target);
         }
     } else {
         if (!$Discussion->Announce) {
             $Discussion->Announce = 2;
         }
         $this->Form->SetData($Discussion);
     }
     $Discussion = (array) $Discussion;
     $Category = CategoryModel::Categories($Discussion['CategoryID']);
     $this->SetData('Discussion', $Discussion);
     $this->SetData('Category', $Category);
     $this->Title(T('Announce'));
     $this->Render();
 }