using System;
using System.Data;
using System.Collections;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using CMS.CMSHelper;
using CMS.Forums;
using CMS.GlobalHelper;
using CMS.IO;
using CMS.SettingsProvider;
using CMS.UIControls;
using CMS.ExtendedControls;
public partial class CMSModules_Forums_Controls_PostTree : ForumViewer
{
#region "Variables"
///
/// Forum Post tree provider.
///
private ForumPostTreeProvider mForumPostTreeProvider = null;
private bool mAllowReply = true;
private string mPostPath = "/%";
private bool mAdministrationMode = false;
private int mSelected = 0;
private bool mSelectOnlyApproved = false;
private bool mRegularLoad = false;
private int mMaxPostNodes = 0;
private bool mUseMaxPostNodes = false;
private ForumPostInfo mSelectedPost = null;
private string mMaxTreeNodeText = null;
private bool? mCanBeModerated = null;
private bool? mUserIsModerator = null;
///
/// If is true unapproved post is higlighted.
///
protected bool mHighlightUnApproved = false;
///
/// Item CSS class.
///
protected string mItemCssClass = "ThreadPost";
///
/// Selcted item CSS class.
///
protected string mSelectedItemCssClass = "ThreadPostSelected";
#endregion
#region "Public events and delegates"
///
/// Image delegate.
///
public delegate string GetIconEventHandler(ForumPostTreeNode node);
///
/// Gets image Url.
///
public event GetIconEventHandler OnGetPostIconUrl;
#endregion
#region "Public properties"
///
/// If is true unapproved post is higlighted.
///
public bool HighlightUnApprove
{
get
{
return mHighlightUnApproved;
}
set
{
mHighlightUnApproved = value;
}
}
///
/// Enable subscription.
///
public bool AllowReply
{
get
{
return mAllowReply;
}
set
{
mAllowReply = value;
}
}
///
/// Path.
///
public string PostPath
{
get
{
return mPostPath;
}
set
{
mPostPath = value;
}
}
///
/// Select only approved.
///
public bool SelectOnlyApproved
{
get
{
return mSelectOnlyApproved;
}
set
{
mSelectOnlyApproved = value;
}
}
///
/// Selected post id.
///
public int Selected
{
get
{
return mSelected;
}
set
{
mSelected = value;
}
}
///
/// Selected post info.
///
public ForumPostInfo SelectedPost
{
get
{
if ((mSelectedPost == null) && (Selected > 0))
{
mSelectedPost = ForumPostInfoProvider.GetForumPostInfo(Selected);
}
return mSelectedPost;
}
set
{
mSelectedPost = value;
}
}
///
/// Maximum number of forum post nodes displayed within one level of the tree.
/// Setting CMSForumMaxPostNode is used by default.
/// Note: UseMaxPostNodes property can suppress use of MaxPostNodes
///
public int MaxPostNodes
{
get
{
if (mMaxPostNodes <= 0)
{
mMaxPostNodes = SettingsKeyProvider.GetIntValue(SiteName + ".CMSForumMaxPostNode");
}
return mMaxPostNodes;
}
set
{
mMaxPostNodes = value;
MapProvider.MaxPostNodes = value + 1;
}
}
///
/// Enables or disables use of MaxPostNodes property, which limits maximum number of posts
/// displayed in tree.
///
public bool UseMaxPostNodes
{
get
{
return mUseMaxPostNodes;
}
set
{
mUseMaxPostNodes = value;
}
}
///
/// Enables or disables administration mode.
///
public bool AdministrationMode
{
get
{
return mAdministrationMode;
}
set
{
mAdministrationMode = value;
}
}
///
/// Post tree provider that the tree uses.
///
public ForumPostTreeProvider MapProvider
{
get
{
if (mForumPostTreeProvider == null)
{
mForumPostTreeProvider = new ForumPostTreeProvider();
// Set Map provider values
mForumPostTreeProvider.BindNodeData = true;
mForumPostTreeProvider.Path = PostPath;
if (ExpandTree || DetailModeIE)
{
// Load all posts
mForumPostTreeProvider.MaxRelativeLevel = ForumPostTreeProvider.ALL_LEVELS;
}
else
{
// Load only first level
mForumPostTreeProvider.MaxRelativeLevel = 1;
}
mForumPostTreeProvider.SelectOnlyApproved = SelectOnlyApproved;
mForumPostTreeProvider.ForumID = ForumID;
mForumPostTreeProvider.WhereCondition = WhereCondition;
mForumPostTreeProvider.Columns = GetColumns();
// Limit number of displayed posts, usually in CMSDesk
if (UseMaxPostNodes)
{
mForumPostTreeProvider.MaxPostNodes = MaxPostNodes + 1;
}
}
return mForumPostTreeProvider;
}
}
///
/// Provides acces to treeElem property.
///
public TreeView TreeView
{
get
{
return treeElem;
}
}
///
/// Item CSS class.
///
public string ItemCssClass
{
get
{
return mItemCssClass;
}
set
{
mItemCssClass = value;
}
}
///
/// Selected item CSS class.
///
public string SelectedItemCssClass
{
get
{
return mSelectedItemCssClass;
}
set
{
mSelectedItemCssClass = value;
}
}
///
/// Text to appear within the latest node when max tree nodes applied.
///
public string MaxTreeNodeText
{
get
{
if (mMaxTreeNodeText == null)
{
mMaxTreeNodeText = GetString("general.seelisting");
}
return mMaxTreeNodeText;
}
set
{
mMaxTreeNodeText = value;
}
}
///
/// Indicates whether posts can be moderated in current context,
/// therefore unapproved post could be displayed.
///
public bool CanBeModerated
{
get
{
if (!mCanBeModerated.HasValue)
{
ForumInfo fi = ForumContext.CurrentForum;
mCanBeModerated = ((fi != null) && EnableOnSiteManagement && fi.ForumModerated && UserIsModerator);
}
return mCanBeModerated.Value;
}
}
///
/// Indicates whether the current user is a moderator. That means: forum moderator or group admin or global admin.
///
private bool UserIsModerator
{
get
{
if (!mUserIsModerator.HasValue)
{
bool result = false;
ForumInfo fi = ForumContext.CurrentForum;
result = (fi != null) && ForumContext.UserIsModerator(fi.ForumID, CommunityGroupID);
if (!result && (CommunityGroupID > 0))
{
result = CMSContext.CurrentUser.IsAuthorizedPerResource("cms.groups", CMSAdminControl.PERMISSION_MANAGE);
}
mUserIsModerator = result;
}
return mUserIsModerator.Value;
}
}
///
/// Indicates if special mode for treating (dynamic) detail mode in IE should be used.
/// The cause is that, IE can't handle too long parameters of TreeView_PopulateNode javascript function
///
private bool DetailModeIE
{
get
{
return (((ShowMode == ShowModeEnum.DetailMode) || (ShowMode == ShowModeEnum.DynamicDetailMode)) && BrowserHelper.IsIE());
}
}
#endregion
#region "Helper methods and properties"
///
/// Gets or sets the value that indicates whether data has been loaded or current load is
/// called on demand
///
protected bool RegularLoad
{
get
{
return mRegularLoad;
}
set
{
mRegularLoad = value;
}
}
///
/// Returns list of required columns if current mode is tree, otherwise returns null => load all columns
///
protected string GetColumns()
{
if (ShowMode == ShowModeEnum.TreeMode)
{
return "PostSubject, PostIDPath, PostParentID, PostApproved, PostID, PostThreadPosts, PostThreadPostsAbsolute, PostLevel";
}
return null;
}
///
/// Returns node text for dynamic mode.
///
/// Forum post data row
private string CreateDetailModeNode(DataRow postRow)
{
StringBuilder sbRendered = null;
// Render forum post control
string forumPostControlId = DynamicForumPostRender(postRow, out sbRendered);
string nodeText = String.Format("
{1}
",
forumPostControlId, sbRendered.ToString());
return nodeText;
}
///
/// Returns node text for dynamic details mode.
///
/// Forum post data row
/// CSS class
/// Image tag
/// Post subject
private string CreateDynamicDetailModeNode(DataRow postRow, string cssClass, string imageTag, string postSubject)
{
StringBuilder sbRendered = null;
// Render forum post control
string forumPostControlId = DynamicForumPostRender(postRow, out sbRendered);
string nodeText = String.Format(
""
+ "{2}{3}" + //imagetag + postsubject
"{4}
",
forumPostControlId, cssClass, imageTag, HTMLHelper.HTMLEncode(postSubject), sbRendered.ToString());
return nodeText;
}
///
/// Renders ForumPost control for specified node.
///
/// Forum post data row
/// String builder instance containing rendered text of control
private string DynamicForumPostRender(DataRow postRow, out StringBuilder sbRendered)
{
// Create detail of post to string
sbRendered = new StringBuilder();
string mId = "";
ForumPostInfo fpi = new ForumPostInfo(postRow);
if (ShowMode != ShowModeEnum.TreeMode)
{
StringWriter sw = new StringWriter(sbRendered);
Html32TextWriter writer = new Html32TextWriter(sw);
CMSModules_Forums_Controls_Posts_ForumPost post = (CMSModules_Forums_Controls_Posts_ForumPost)Page.LoadUserControl("~/CMSModules/Forums/Controls/Posts/ForumPost.ascx");
post.ID = "forumPost" + fpi.PostId;
CopyValues(post);
post.PostInfo = fpi;
post.ReloadData();
post.RenderControl(writer);
mId = ClientID + fpi.PostId;
}
return mId;
}
#endregion
#region "Methods"
///
/// Page load.
///
protected void Page_Load(object sender, EventArgs e)
{
ForumContext.ForumID = ForumID;
treeElem.ImageSet = TreeViewImageSet.Custom;
if ((IsLiveSite && CultureHelper.IsPreferredCultureRTL()) || (!IsLiveSite && CultureHelper.IsUICultureRTL()))
{
treeElem.LineImagesFolder = GetImageUrl("RTL/Design/Controls/Tree", IsLiveSite, false);
}
else
{
treeElem.LineImagesFolder = GetImageUrl("Design/Controls/Tree", IsLiveSite, false);
}
// Loading image script
string loadingScript = @"
if (TreeView_PopulateNode) { base_TreeView_PopulateNode = TreeView_PopulateNode };
TreeView_PopulateNode = function(data, index, node, selectNode, selectImageNode, lineType, text, path, databound, datapath, parentIsLast) {
if (!data) { return; }
if (!node.blur) { node = node[0]; }
node.blur();
node.firstChild.src = '" + GetImageUrl("Design/Preloaders/preload16pad.gif") + "';" + @"
if (base_TreeView_PopulateNode) {
base_TreeView_PopulateNode(data, index, node, selectNode, selectImageNode, lineType, text, path, databound, datapath, parentIsLast); } }";
ltlScript.Text = ScriptHelper.GetScript(loadingScript);
treeElem.ExpandImageToolTip = GetString("ContentTree.Expand");
treeElem.CollapseImageToolTip = GetString("ContentTree.Collapse");
}
///
/// OnPreRender.
///
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (!RequestHelper.IsCallback())
{
ReloadData();
}
}
///
/// Reload data.
///
public override void ReloadData()
{
if (StopProcessing)
{
return;
}
mForumPostTreeProvider = null;
RegularLoad = true;
// Some post should be preselected => load all posts leading to it in one query
if (SelectedPost != null)
{
MapProvider.SelectPostPath = SelectedPost.PostIDPath;
}
if (MapProvider.RootNode != null)
{
TreeNode rootNode = CreateNode((ForumPostTreeNode)MapProvider.RootNode, 0);
// Localize root node
if (rootNode != null)
{
rootNode.Text = ResHelper.LocalizeString(rootNode.Text);
}
// Add root node
treeElem.Nodes.Add(rootNode);
treeElem.EnableViewState = false;
}
}
///
/// Creates tree node.
///
/// Node with source data
protected TreeNode CreateNode(ForumPostTreeNode sourceNode, int index)
{
if (sourceNode == null)
{
return null;
}
// Create tree node
TreeNode newNode = new TreeNode();
DataRow dr = (DataRow)sourceNode.ItemData;
// Check whether item data are defined, if not it is root node
if (dr != null)
{
int sourceNodeId = (int)dr["PostID"];
int nodeLevel = (int)dr["PostLevel"];
// Check on maximum post in tree
if (!UseMaxPostNodes || (index < MaxPostNodes))
{
#region "Set node values and appearance"
newNode.Value = sourceNodeId.ToString();
newNode.SelectAction = TreeNodeSelectAction.None;
bool isApproved = ValidationHelper.GetBoolean(dr["PostApproved"], false);
string postSubject = (string)dr["PostSubject"];
string cssClass = ItemCssClass;
// Add CSS class for unapproved posts
if (HighlightUnApprove && !isApproved)
{
cssClass += " PostUnApproved";
}
string imageTag = "";
if (OnGetPostIconUrl != null)
{
string imageUrl = OnGetPostIconUrl(sourceNode);
imageTag = "
";
}
// Set by display mode
switch (ShowMode)
{
// Dynamic detail mode
case ShowModeEnum.DynamicDetailMode:
newNode.Text = CreateDynamicDetailModeNode(dr, cssClass, imageTag, postSubject);
break;
// Detail mode
case ShowModeEnum.DetailMode:
newNode.Text = CreateDetailModeNode(dr);
break;
// Tree mode
default:
if (Selected == sourceNodeId)
{
cssClass = SelectedItemCssClass;
string spanId = String.Empty;
if (AdministrationMode)
{
spanId = "id=\"treeSelectedNode\"";
}
newNode.Text = String.Format("{3}{4}",
spanId, cssClass, newNode.Value, imageTag, HTMLHelper.HTMLEncode(postSubject));
}
else
{
newNode.Text = String.Format("{2}{3}",
cssClass, newNode.Value, imageTag, HTMLHelper.HTMLEncode(postSubject));
}
break;
}
#endregion
if (!ExpandTree)
{
#region "Populate deeper levels on demand"
// Check if can expand
string childCountColumn = "PostThreadPosts";
// Check if unapproved posts can be included
if (AdministrationMode || UserIsModerator)
{
childCountColumn = "PostThreadPostsAbsolute";
}
int childNodesCount = ValidationHelper.GetInteger(dr[childCountColumn], 0);
// If the post is thread(level = 0) then childnodes count 1 means no real child-post
if ((childNodesCount == 0) || ((childNodesCount == 1) && (nodeLevel == 0)))
{
newNode.PopulateOnDemand = false;
// No children -> expand
newNode.Expanded = true;
}
else
{
if (!sourceNode.ChildNodesLoaded)
{
newNode.PopulateOnDemand = true;
newNode.Expanded = false;
}
}
#endregion
#region "Expand nodes on the current path"
// If preselect is set = first load
if (RegularLoad)
{
string currentNodePath = (string)dr["PostIDPath"];
string currentSelectedPath = String.Empty;
if (SelectedPost != null)
{
currentSelectedPath = SelectedPost.PostIDPath;
}
// Expand if node is on the path
if (currentSelectedPath.StartsWithCSafe(currentNodePath))
{
// Raise OnTreeNodePopulate
newNode.PopulateOnDemand = true;
newNode.Expanded = true;
}
else
{
newNode.Expanded = false;
}
}
#endregion
}
else
{
// Populate will be called on each node
newNode.PopulateOnDemand = true;
newNode.Expanded = true;
}
}
else
{
string parentNodeId = ValidationHelper.GetString(dr["PostParentID"], "");
newNode.Value = sourceNodeId.ToString();
newNode.Text = MaxTreeNodeText.Replace("##PARENTNODEID##", parentNodeId);
newNode.SelectAction = TreeNodeSelectAction.None;
}
}
// Root node populate by default
else
{
// Root node as forum display name
ForumInfo fi = ForumInfoProvider.GetForumInfo(ForumID);
if (fi != null)
{
newNode.Text = "" + HTMLHelper.HTMLEncode(fi.ForumDisplayName) + "";
newNode.Value = "0";
newNode.SelectAction = TreeNodeSelectAction.None;
}
newNode.PopulateOnDemand = true;
newNode.Expanded = true;
}
return newNode;
}
///
/// On populate create child nodes.
///
protected void treeElem_TreeNodePopulate(object sender, TreeNodeEventArgs e)
{
e.Node.ChildNodes.Clear();
e.Node.PopulateOnDemand = false;
int postId = ValidationHelper.GetInteger(e.Node.Value, 0);
// Set the ForumID if not set already
if (ForumContext.ForumID == 0)
{
ForumPostInfo postInfo = ForumPostInfoProvider.GetForumPostInfo(postId);
if (postInfo != null)
{
ForumContext.ForumID = postInfo.PostForumID;
ForumID = postInfo.PostForumID;
}
}
// Get child nodes
SiteMapNodeCollection childNodes = MapProvider.GetChildNodes(postId, RegularLoad);
int index = 0;
foreach (ForumPostTreeNode childNode in childNodes)
{
int childNodeId = (int)((DataRow)childNode.ItemData)["PostID"];
if (childNodeId != postId)
{
TreeNode newNode = CreateNode(childNode, index);
bool? originalExpanded = newNode.Expanded;
// Force node to expand and load child posts
if (DetailModeIE)
{
newNode.PopulateOnDemand = true;
newNode.Expanded = true;
}
e.Node.ChildNodes.Add(newNode);
// Restore original expanded state
if (DetailModeIE)
{
newNode.Expanded = originalExpanded;
}
index++;
}
// Ensure there is only one 'click here for more' item
if (UseMaxPostNodes && (index > MaxPostNodes))
{
break;
}
}
}
///
/// Render
///
protected override void Render(HtmlTextWriter writer)
{
if (!StopProcessing)
{
base.Render(writer);
}
}
#endregion
}