using System; using System.Collections.Generic; using System.Data; using System.Text; using System.Web.UI; using System.Web.UI.WebControls; using CMS.CMSHelper; using CMS.ExtendedControls; using CMS.FormControls; using CMS.GlobalHelper; using CMS.Polls; using CMS.PortalEngine; using CMS.SettingsProvider; using CMS.SiteProvider; using CMS.DocumentEngine; using CMS.UIControls; using CMS.WebAnalytics; public partial class CMSModules_Polls_Controls_View_PollView : CMSUserControl { #region "Events" public event EventHandler OnAfterVoted; #endregion #region "Variables" protected bool mShowGraph = true; protected CountTypeEnum mCodeType = CountTypeEnum.Absolute; protected bool mShowResultsAfterVote = true; protected bool mCheckVoted = true; protected bool mCheckPermissions = true; protected bool mCheckOpen = true; protected bool mHideWhenNotAuthorized = false; protected bool mHideWhenNotOpened = false; protected string mButtonText = null; protected int mCacheMinutes = 0; protected string errMessage = null; protected bool hasPermission = false; protected bool isOpened = false; protected DataSet answers = null; private PollInfo pi = null; #endregion #region "Properties" /// /// Gets or sets the code name of the poll, which should be displayed. /// public string PollCodeName { get { return ValidationHelper.GetString(ViewState["PollCodeName"], null); } set { ViewState["PollCodeName"] = value; } } /// /// Gets or sets the site ID of the poll (optional). /// public int PollSiteID { get { return ValidationHelper.GetInteger(ViewState["PollSiteID"], 0); } set { ViewState["PollSiteID"] = value; } } /// /// Gets or sets the group ID of the poll (optional). /// public int PollGroupID { get { return ValidationHelper.GetInteger(ViewState["PollGroupID"], 0); } set { ViewState["PollGroupID"] = value; } } /// /// Gets or sets the value that indicates whether the graph of the poll is displayed. /// public bool ShowGraph { get { return mShowGraph; } set { mShowGraph = value; } } /// /// Gets or sets the type of the representation of the answers' count in the graph. /// public CountTypeEnum CountType { get { return mCodeType; } set { mCodeType = value; } } /// /// Gets or sets the value that indicates whether graph is displayed after answering the poll. /// public bool ShowResultsAfterVote { get { return mShowResultsAfterVote; } set { mShowResultsAfterVote = value; } } /// /// Gets or sets the value that indicates whether current user has voted is checked. /// public bool CheckVoted { get { return mCheckVoted; } set { mCheckVoted = value; } } /// /// Gets or sets the value that indicates whether permissions are checked. /// public bool CheckPermissions { get { return mCheckPermissions; } set { mCheckPermissions = value; } } /// /// Gets or stes the value that indicates whether open from/to time is checked /// public bool CheckOpen { get { return mCheckOpen; } set { mCheckOpen = value; } } /// /// If true, the control hides when not authorized, /// otherwise the control displays the message and does not allow to vote. /// public bool HideWhenNotAuthorized { get { return mHideWhenNotAuthorized; } set { mHideWhenNotAuthorized = value; } } /// /// If true, the control hides when not opened, /// otherwise the control does not allow to vote. /// public bool HideWhenNotOpened { get { return mHideWhenNotOpened; } set { mHideWhenNotOpened = value; } } /// /// Gets or sets the text of the vote button. /// public string ButtonText { get { return ValidationHelper.GetString(mButtonText, GetString("Polls.Vote")); } set { mButtonText = value; } } /// /// Vote button. /// public LocalizedButton VoteButton { get { return btnVote; } } /// /// Gets or sets the WebPart cache minutes. /// public int CacheMinutes { get { return mCacheMinutes; } set { mCacheMinutes = value; } } /// /// Gets or sets the poll answers dataset. /// public DataSet Answers { get { if (DataHelper.DataSourceIsEmpty(answers)) { // Try to get data from cache using (CachedSection cs = new CachedSection(ref answers, CacheMinutes, true, null, "pollanswers", PollCodeName)) { if (cs.LoadData) { // Get from database if (pi != null) { answers = PollAnswerInfoProvider.GetAnswers(pi.PollID, -1, "AnswerID, AnswerText, AnswerCount, AnswerEnabled, AnswerForm, AnswerAlternativeForm, AnswerHideForm"); } if (cs.Cached) { // Prepare cache dependency cs.CacheDependency = CacheHelper.GetCacheDependency("polls.pollanswer|all"); } // Add to the cache cs.Data = answers; } } } return answers; } set { // Remove the data from cache if (CacheMinutes > 0) { string useCacheItemName = CacheHelper.GetCacheItemName(null, "pollanswers", PollCodeName); CacheHelper.Remove(useCacheItemName); } answers = null; } } #endregion #region "Methods" /// /// Page load. /// protected void Page_Load(object sender, EventArgs e) { if (Visible) { ReloadData(false); } } protected void Page_PreRender(object sender, EventArgs e) { // Display info messages if not empty lblInfo.Visible = !string.IsNullOrEmpty(lblInfo.Text); lblResult.Visible = !string.IsNullOrEmpty(lblResult.Text); } /// /// Loads data. /// public void ReloadData(bool forceReload) { if (!StopProcessing) { SetContext(); lblInfo.Text = string.Empty; lblInfo.Visible = false; if (pi == null) { pi = PollInfoProvider.GetPollInfo(PollCodeName, PollSiteID, PollGroupID); hasPermission = HasPermission(); isOpened = IsOpened(); } // Show poll if current user has permission or if poll should be displayed even if user is not authorized // and if poll is opened or if poll should be opened even if it is not opened // ... and show group poll if it is poll of current group bool showPoll = (pi != null) && (hasPermission || !HideWhenNotAuthorized) && (isOpened || !HideWhenNotOpened); // Show site poll only if it is poll of current site if (showPoll && (pi.PollSiteID > 0) && (pi.PollSiteID != CMSContext.CurrentSiteID)) { showPoll = false; } // Show global poll only if it is allowed for current site if (showPoll && (pi.PollSiteID == 0)) { showPoll = SettingsKeyProvider.GetBoolValue(CMSContext.CurrentSiteName + ".CMSPollsAllowGlobal"); } if (showPoll) { Visible = true; // Load title lblTitle.Text = HTMLHelper.HTMLEncode(pi.PollTitle); // Load question lblQuestion.Text = HTMLHelper.HTMLEncode(pi.PollQuestion); if ((!forceReload) || ((forceReload) && (ShowResultsAfterVote))) { // Add answer section CreateAnswerSection(forceReload, CheckVoted && PollInfoProvider.HasVoted(pi.PollID)); } else { // Hide answer panel pnlAnswer.Visible = false; } if ((forceReload) && (isOpened)) { // Hide footer with vote button pnlFooter.Visible = false; // Add poll response after voting if ((errMessage != null) && (errMessage.Trim() != "")) { // Display message if error occurs lblInfo.Text = errMessage; lblInfo.CssClass = "ErrorMessage"; } else { // Display poll response message lblResult.Text = HTMLHelper.HTMLEncode(pi.PollResponseMessage); } } else if (isOpened) { if (hasPermission && !(CheckVoted && (PollInfoProvider.HasVoted(pi.PollID)))) { // Display footer wiht vote button pnlFooter.Visible = true; btnVote.Text = ButtonText; } else { pnlFooter.Visible = false; } } else { pnlFooter.Visible = false; lblInfo.Text = GetString("Polls.Closed"); } } else { Visible = false; } ReleaseContext(); } } /// /// Creates poll answer section. /// /// Indicates postback /// Indicates if user has voted protected void CreateAnswerSection(bool reload, bool hasVoted) { pnlAnswer.Controls.Clear(); if (pi != null) { // Get poll's answers DataSet ds = Answers; if (!DataHelper.DataSourceIsEmpty(ds)) { int count = 0; int maxCount = 0; long sumCount = 0; bool hideSomeForm = false; foreach (DataRow row in ds.Tables[0].Rows) { // Sum answer counts and get highest if (ValidationHelper.GetBoolean(row["AnswerEnabled"], true)) { count = ValidationHelper.GetInteger(row["AnswerCount"], 0); sumCount += count; if (count > maxCount) { maxCount = count; } } // Check if any open-ended answer form should be hidden if (ValidationHelper.GetBoolean(row["AnswerHideForm"], false)) { hideSomeForm = true; } } LocalizedCheckBox chkItem = null; LocalizedRadioButton radItem = null; LocalizedLabel lblItem = null; BizForm viewBiz = null; string formName = null; int index = 0; bool enabled = false; bool bizFormsAvailable = ModuleEntry.IsModuleLoaded(ModuleEntry.BIZFORM) && ResourceSiteInfoProvider.IsResourceOnSite(ModuleEntry.BIZFORM, CMSContext.CurrentSiteName); pnlAnswer.Controls.Add(new LiteralControl("")); // Create the answers foreach (DataRow row in ds.Tables[0].Rows) { enabled = ValidationHelper.GetBoolean(row["AnswerEnabled"], true); if (enabled) { pnlAnswer.Controls.Add(new LiteralControl("")); if (ShowGraph || (hasVoted || reload) && ShowResultsAfterVote) { // Create graph under the answer CreateGraph(maxCount, ValidationHelper.GetInteger(row["AnswerCount"], 0), sumCount, index); } index++; } } pnlAnswer.Controls.Add(new LiteralControl("
")); if (((reload) && (ShowResultsAfterVote)) || (!hasPermission && !HideWhenNotAuthorized) || (!isOpened && !HideWhenNotOpened) || (CheckVoted && PollInfoProvider.HasVoted(pi.PollID))) { // Add label lblItem = new LocalizedLabel(); lblItem.ID = "lbl" + ValidationHelper.GetInteger(row["AnswerID"], 0); lblItem.EnableViewState = false; lblItem.Text = HTMLHelper.HTMLEncode(ValidationHelper.GetString(row["AnswerText"], string.Empty)); lblItem.CssClass = "PollAnswerText"; pnlAnswer.Controls.Add(lblItem); } else { if (pi.PollAllowMultipleAnswers) { // Add checkboxes for multiple answers chkItem = new LocalizedCheckBox(); chkItem.ID = "chk" + ValidationHelper.GetInteger(row["AnswerID"], 0); chkItem.AutoPostBack = false; chkItem.Text = HTMLHelper.HTMLEncode(ValidationHelper.GetString(row["AnswerText"], string.Empty)); chkItem.Checked = false; chkItem.CssClass = "PollAnswerCheck"; if (hideSomeForm) { chkItem.AutoPostBack = true; chkItem.CheckedChanged += AnswerSelectionChanged; } pnlAnswer.Controls.Add(chkItem); } else { // Add radiobuttons radItem = new LocalizedRadioButton(); radItem.ID = "rad" + ValidationHelper.GetInteger(row["AnswerID"], 0); radItem.AutoPostBack = false; radItem.GroupName = pi.PollCodeName + "Group"; radItem.Text = HTMLHelper.HTMLEncode(ValidationHelper.GetString(row["AnswerText"], string.Empty)); radItem.Checked = false; radItem.CssClass = "PollAnswerRadio"; if (hideSomeForm) { radItem.AutoPostBack = true; radItem.CheckedChanged += AnswerSelectionChanged; } pnlAnswer.Controls.Add(radItem); } formName = ValidationHelper.GetString(row["AnswerForm"], string.Empty); if (!string.IsNullOrEmpty(formName) && bizFormsAvailable) { // Add forms for open ended answers viewBiz = new BizForm(); viewBiz.FormName = formName; viewBiz.SiteName = CMSContext.CurrentSiteName; viewBiz.AlternativeFormFullName = ValidationHelper.GetString(row["AnswerAlternativeForm"], string.Empty); viewBiz.ID = "frm" + ValidationHelper.GetInteger(row["AnswerID"], 0); viewBiz.IsLiveSite = IsLiveSite; viewBiz.OnAfterDataLoad += Form_AfterDataLoad; viewBiz.CssClass = "PollAnswerForm"; viewBiz.Visible = !ValidationHelper.GetBoolean(row["AnswerHideForm"], false); viewBiz.FormClearAfterSave = true; viewBiz.FormRedirectToUrl = String.Empty; viewBiz.FormDisplayText = String.Empty; pnlAnswer.Controls.Add(viewBiz); } } pnlAnswer.Controls.Add(new LiteralControl("
")); } } } /// /// Creates graph bar for the answer. /// /// Max answers' count /// Current answer count /// Count summary of all answers /// Index protected void CreateGraph(int maxValue, int currentValue, long countSummary, int index) { long ratio = 0; if (maxValue != 0) { ratio = Math.BigMul(100, currentValue) / (long)maxValue; } // Begin PollAnswerGraph pnlAnswer.Controls.Add(new LiteralControl("
")); if (ratio != 0) { // PollAnswerItemGraph pnlAnswer.Controls.Add(new LiteralControl("
 
")); } else { pnlAnswer.Controls.Add(new LiteralControl(" ")); } // End PollAnswerGraph pnlAnswer.Controls.Add(new LiteralControl("
")); // Create lable with answer count if (CountType == CountTypeEnum.Absolute) { // Absolute count pnlAnswer.Controls.Add(new LiteralControl(currentValue.ToString())); } else if (CountType == CountTypeEnum.Percentage) { // Percentage count long percent = 0; if (countSummary != 0) { percent = Math.BigMul(100, currentValue) / countSummary; } pnlAnswer.Controls.Add(new LiteralControl(percent.ToString() + "%")); } // End PollAnswerGraph pnlAnswer.Controls.Add(new LiteralControl("")); } /// /// On btnVote click event handler. /// protected void btnVote_OnClick(object sender, EventArgs e) { // Check banned ip if (!BannedIPInfoProvider.IsAllowed(CMSContext.CurrentSiteName, BanControlEnum.AllNonComplete)) { lblInfo.CssClass = "ErrorMessage"; lblInfo.Text = GetString("General.BannedIP"); return; } if (pi != null) { // Indicates whether user voted or not bool voted = false; // Indicates wheter all forms of all open-ended answers can be saved bool formsAreValid = true; List selectedAnswers = new List(); // List of poll answers (in case of multiple answers) for activity logging StringBuilder pollAnswerIDs = new StringBuilder(); // Check if user has already voted if ((CheckVoted) && (PollInfoProvider.HasVoted(pi.PollID))) { errMessage = GetString("Polls.UserHasVoted"); voted = true; } else if (isOpened) { // Get poll answers DataSet ds = Answers; if (!DataHelper.DataSourceIsEmpty(ds)) { DataRowCollection rows = ds.Tables[0].Rows; LocalizedCheckBox chkItem = null; LocalizedRadioButton radItem = null; bool selected = false; PollAnswerInfo pai = null; BizForm bizItem = null; foreach (DataRow row in rows) { pai = new PollAnswerInfo(row); if ((pai != null) && (pai.AnswerEnabled)) { selected = false; // Find specific controls and update pollanswerinfo if controls are checked if (pi.PollAllowMultipleAnswers) { // Find checkbox chkItem = (LocalizedCheckBox)pnlAnswer.FindControl("chk" + pai.AnswerID); if (chkItem != null) { selected = chkItem.Checked; } } else { // Find radiobutton radItem = (LocalizedRadioButton)pnlAnswer.FindControl("rad" + pai.AnswerID); if (radItem != null) { selected = radItem.Checked; } } if ((selected) && (pai.AnswerCount < Int32.MaxValue)) { bool canBeSaved = false; bizItem = (BizForm)pnlAnswer.FindControl("frm" + pai.AnswerID); if (bizItem == null) { canBeSaved = true; } else if (bizItem.BasicForm != null) { // Validate form data canBeSaved = bizItem.BasicForm.ValidateData(); } if (canBeSaved) { selectedAnswers.Add(pai.AnswerID); } else { formsAreValid = false; } } } } if (formsAreValid) { if (selectedAnswers.Count > 0) { foreach (int aid in selectedAnswers) { // Set the vote PollAnswerInfoProvider.Vote(aid); // Save the bizform data bizItem = (BizForm)pnlAnswer.FindControl("frm" + aid); if (bizItem != null) { if (bizItem.BasicForm != null) { bizItem.BasicForm.SaveData(null, false); } } // Save all selected answers (for activity logging) pollAnswerIDs.Append(aid); pollAnswerIDs.Append(ActivityLogProvider.POLL_ANSWER_SEPARATOR); } voted = true; } else { // Set error message if no answer selected lblInfo.CssClass = "ErrorMessage"; lblInfo.Text = GetString("Polls.DidNotVoted"); } } if (voted) { LogActivity(pi, pollAnswerIDs.ToString()); } if ((CheckVoted) && (voted)) { // Create cookie about user's voting PollInfoProvider.SetVoted(pi.PollID); } } } if (voted) { // Clear cache if it's used Answers = null; // Reload poll control ReloadData(true); if (OnAfterVoted != null) { OnAfterVoted(this, EventArgs.Empty); } } } } /// /// Returns true if user has permissions. /// protected bool HasPermission() { if ((!CheckPermissions) || (CMSContext.CurrentUser.IsGlobalAdministrator)) { return true; } bool toReturn = false; if (pi != null) { // Access to all users if (pi.PollAccess == SecurityAccessEnum.AllUsers) { toReturn = true; } // Access to authenticated user if ((pi.PollAccess == SecurityAccessEnum.AuthenticatedUsers) && (CMSContext.CurrentUser.IsAuthenticated())) { toReturn = true; } // Access to group members if ((pi.PollAccess == SecurityAccessEnum.GroupMembers) && (CMSContext.CurrentUser.IsGroupMember(PollGroupID))) { toReturn = true; } // Access to roles if ((pi.PollAccess == SecurityAccessEnum.AuthorizedRoles) && (CMSContext.CurrentUser != null)) { foreach (String role in pi.AllowedRoles.Keys) { if (CMSContext.CurrentUser.IsInRole(role, CMSContext.CurrentSiteName)) { toReturn = true; break; } } } } return toReturn; } /// /// Return true if actual time is inside the poll's opening time or the poll's open from/to are not set. /// protected bool IsOpened() { if (!CheckOpen) { return true; } bool toReturn = false; if (pi != null) { DateTime now = DateTime.Now; if ((pi.PollOpenFrom == DataHelper.DATETIME_NOT_SELECTED) && (pi.PollOpenTo == DataHelper.DATETIME_NOT_SELECTED)) { toReturn = true; } else if ((pi.PollOpenFrom != DataHelper.DATETIME_NOT_SELECTED) && (pi.PollOpenTo == DataHelper.DATETIME_NOT_SELECTED) && (pi.PollOpenFrom < now)) { toReturn = true; } else if ((pi.PollOpenFrom == DataHelper.DATETIME_NOT_SELECTED) && (pi.PollOpenTo != DataHelper.DATETIME_NOT_SELECTED) && (pi.PollOpenTo > now)) { toReturn = true; } else if ((pi.PollOpenFrom != DataHelper.DATETIME_NOT_SELECTED) && (pi.PollOpenTo != DataHelper.DATETIME_NOT_SELECTED) && (pi.PollOpenFrom < now) && (pi.PollOpenTo > now)) { toReturn = true; } } return toReturn; } /// /// Logs activity /// /// Poll /// Answers private void LogActivity(PollInfo pi, string answers) { if ((CMSContext.ViewMode == ViewModeEnum.LiveSite) && IsLiveSite) { Activity activity = new ActivityPollVoting(pi, CMSContext.CurrentDocument, answers, CMSContext.ActivityEnvironmentVariables); activity.Log(); } } private void Form_AfterDataLoad(object sender, EventArgs e) { BizForm bizForm = sender as BizForm; if ((bizForm != null) && (bizForm.BasicForm != null)) { bizForm.BasicForm.SubmitButton.Visible = false; bizForm.BasicForm.SubmitImageButton.Visible = false; } } /// /// Shows answer form for selected answer. /// private void AnswerSelectionChanged(object sender, EventArgs e) { WebControl control = sender as WebControl; if (control != null) { // Find the appropriate bizform BizForm bizItem = (BizForm)pnlAnswer.FindControl("frm" + control.ID.Substring(3)); if (bizItem != null) { bizItem.Visible = true; } } } #endregion }