HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/RMourik/bassol.nl/CMS/CMSModules/Scoring/Controls/UI/Rule/Edit.ascx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;

using CMS.Base;
using CMS.Core;
using CMS.DataEngine;
using CMS.ExtendedControls;
using CMS.ExtendedControls.ActionsConfig;
using CMS.FormControls;
using CMS.FormEngine;
using CMS.Helpers;
using CMS.MacroEngine;
using CMS.OnlineMarketing;
using CMS.Scheduler;
using CMS.SiteProvider;
using CMS.UIControls;
using CMS.WebAnalytics;

using AjaxControlToolkit;

/// <remarks>
/// Both attribute and activity type of rule use additional form for detailed rule setting. On the other hand, 
/// macro uses only one Condition builder. Therefore methods working with macro condition are much simpler and 
/// manipulation with macro rule is quite different from the other types.
/// </remarks>
public partial class CMSModules_Scoring_Controls_UI_Rule_Edit : CMSAdminEditControl
{
    #region "Variables"

    private List<FormFieldInfo> mFields;
    private FormFieldInfo mSelectedAttribute;
    private string mRecalculationNeededResourceString = "om.score.recalculationrequired2";
    private string mNewRuleUrl;
    private string mResourceName = ModuleName.SCORING;

    #endregion


    #region "Properties"

    /// <summary>
    /// Reference to currently edited rule.
    /// </summary>
    private RuleInfo Rule
    {
        get
        {
            return (RuleInfo)editForm.EditedObject;
        }
    }


    /// <summary>
    /// Gets or sets value indicating what item was selected in activity type drop-down list.
    /// </summary>
    private string PreviousSelectedActivity
    {
        get
        {
            return ValidationHelper.GetString(ViewState["PreviousActivityType"], PredefinedActivityType.ABUSE_REPORT);
        }
        set
        {
            ViewState["PreviousActivityType"] = value;
        }
    }


    /// <summary>
    /// Gets or sets value indicating what item was selected in attribute type drop-down list.
    /// </summary>
    private int PreviousSelectedAttribute
    {
        get
        {
            return ValidationHelper.GetInteger(ViewState["PreviousAttributeField"], 0);
        }
        set
        {
            ViewState["PreviousAttributeField"] = value;
        }
    }


    /// <summary>
    /// Gets radio button list containing all types of rule available.
    /// </summary>
    private CMSFormControls_Basic_RadioButtonsControl RadioButtonsListRuleType
    {
        get
        {
            // Currently it is not possible to obtain value directly from Field.EditingObject, thus reference to field from Form fields collection has to be used instead
            return (CMSFormControls_Basic_RadioButtonsControl)editForm.FieldControls["ruletype"];
        }
    }


    /// <summary>
    /// Gets value indicating what rule type was selected within radio button list.
    /// </summary>
    private RuleTypeEnum SelectedRuleType
    {
        get
        {
            return (RuleTypeEnum)ValidationHelper.GetInteger(RadioButtonsListRuleType.Value, 1);
        }
    }


    /// <summary>
    /// ID of parent score.
    /// </summary>
    public int ScoreId
    {
        get;
        set;
    }


    /// <summary>
    /// Specifies path to new rule page. When not set, default value is used.
    /// </summary>
    public string NewRuleUrl
    {
        get
        {
            if (mNewRuleUrl == null)
            {
                return "Tab_Rules_Edit.aspx?scoreid=" + ScoreId;
            }

            return mNewRuleUrl;
        }
        set
        {
            mNewRuleUrl = value;
        }
    }


    /// <summary>
    /// URL page will be redirect after the rule is saved.
    /// </summary>
    public string RedirectUrlAfterCreate
    {
        get
        {
            return editForm.RedirectUrlAfterCreate;
        }
        set
        {
            editForm.RedirectUrlAfterCreate = value;
        }
    }


    /// <summary>
    /// Gets or sets the name of the resource used in permission check. If not set, uses CMS.Scoring by default.
    /// </summary>
    public string ResourceName
    {
        get
        {
            return mResourceName;
        }
        set
        {
            mResourceName = value;
        }
    }


    public UIForm UIForm
    {
        get
        {
            return editForm;
        }
    }

    #endregion


    #region "Page events"

    protected void Page_Init(object sender, EventArgs e)
    {
        editForm.OnBeforeSave += EditForm_OnBeforeSave;
    }


    protected void Page_Load(object sender, EventArgs e)
    {
        var score = ScoreInfoProvider.GetScoreInfo(ScoreId);
        if (score == null)
        {
            RedirectToInformation("Internal error. Unknown score.");
        }

        if (!score.CheckPermissions(PermissionsEnum.Modify, SiteInfoProvider.GetSiteName(score.ScoreSiteID), CurrentUser))
        {
            UIForm.Enabled = false;
            ShowError(GetString("ui.notauthorizemodified"));
            UIForm.StopProcessing = true;
        }

        InitControls();
        InitHeaderActions();

        // Note: controls has to be initialized here with previously selected values to avoid "Must match the control tree" error when loading ViewState
        switch (SelectedRuleType)
        {
            case RuleTypeEnum.Activity:
                InitActivitySettings(PreviousSelectedActivity);
                break;

            case RuleTypeEnum.Attribute:
                InitAttributeSettings(PreviousSelectedAttribute);
                break;
            case RuleTypeEnum.Macro:
                InitMacroSettings();
                break;
        }

        if (QueryHelper.GetBoolean("saved", false))
        {
            InitWarnings();
        }

        // Use mode always to update header actions to show warning info all the time.
        HeaderActions.UpdatePanel.UpdateMode = UpdatePanelUpdateMode.Always;
    }


    protected void Page_PreRender(object sender, EventArgs e)
    {
        // Hide all changing parts
        HideAllPanels();

        switch (SelectedRuleType)
        {
            case RuleTypeEnum.Activity:
                ActivityRuleTypeSelected();
                break;

            case RuleTypeEnum.Attribute:
                AttributeRuleTypeSelected();
                break;

            case RuleTypeEnum.Macro:
                MacroRuleTypeSelected();
                CheckMacros();
                break;
        }
    }

    #endregion


    #region "Control events"

    /// <summary>
    /// UIForm OnBeforeSave event handler.
    /// </summary>
    protected void EditForm_OnBeforeSave(object sender, EventArgs e)
    {
        // Store parent score ID
        editForm.Data["RuleScoreID"] = ScoreId;

        // Store site ID
        if (Rule.Generalized.ObjectID == 0)
        {
            editForm.Data["RuleSiteID"] = SiteContext.CurrentSiteID;
        }

        // Store attribute or activity rule
        editForm.Data["RuleType"] = (int)SelectedRuleType;

        switch (SelectedRuleType)
        {
            case RuleTypeEnum.Activity:
                StoreActivityData();
                return;

            case RuleTypeEnum.Attribute:
                StoreAttributeData();
                return;

            case RuleTypeEnum.Macro:
                StoreMacroData();
                return;
        }
    }


    /// <summary>
    /// Activity drop-down SelectionChanged event handler.
    /// </summary>
    private void ActivitySelectionChanged(object sender, EventArgs e)
    {
        // Init rule condition when changing activity type
        if (Rule != null)
        {
            Rule.RuleCondition = null;
        }

        // Save current selected index to ViewState (needed to avoid "Must match the control tree" error when loading ViewState)
        PreviousSelectedActivity = ucActivityType.SelectedValue;

        // Initialize form using new (current) activity type
        InitActivitySettings(ucActivityType.SelectedValue);
    }


    /// <summary>
    /// Attribute drop-down SelectionChanged event handler.
    /// </summary>
    private void AttributeSelectionChanged(object sender, EventArgs e)
    {
        // Save current selected index to ViewState (needed to avoid "Must match the control tree" error when loading ViewState)
        PreviousSelectedAttribute = drpAttribute.SelectedIndex;

        // Load form specific for currently selected attribute
        LoadAttributeForm(mFields[drpAttribute.SelectedIndex]);
    }


    /// <summary>
    /// Actions handler.
    /// </summary>
    protected void HeaderActions_ActionPerformed(object sender, CommandEventArgs e)
    {
        CheckPermissions(ResourceName, "Modify");
        switch (e.CommandName.ToLowerCSafe())
        {
            // Save rule
            case "save":
                if (ValidateForm())
                {
                    editForm.SaveData(null);
                    InitWarnings();
                }
                break;
        }
    }

    #endregion


    #region "General methods"

    /// <summary>
    /// Checks whether given form control is available. If so, sets it to referring control name.
    /// </summary>
    /// <param name="formControl">Codename of form control</param>
    /// <param name="controlName">Referring control name to which will be set codename of control, if exists</param>
    private void CheckFormControl(string formControl, ref string controlName)
    {
        // Check if user defined control exists
        FormUserControlInfo fui = FormUserControlInfoProvider.GetFormUserControlInfo(formControl);
        if (fui != null)
        {
            controlName = formControl;
        }
    }


    /// <summary>
    /// Clears validity data that could be stored in EditForm data collection.
    /// This data is only needed when Activity type of rule is selected, otherwise it is irrelevant.
    /// </summary>
    private void ClearStoredValidityData()
    {
        editForm.Data["RuleValidity"] = null;
        editForm.Data["RuleValidUntil"] = null;
        editForm.Data["RuleValidFor"] = null;
    }


    /// <summary>
    /// Checks datatype of given form field and return name of control which should be used with fields; sets up form field info 
    /// with DataType related setting.
    /// </summary>
    /// <param name="ffi">Form field to be examined</param>
    /// <returns>Name of appropriate control name</returns>
    private static string GetControlNameForFieldDataType(FormFieldInfo ffi)
    {
        string controlName = null;

        switch (ffi.DataType)
        {
            case FieldDataType.Text:
            case FieldDataType.LongText:
                controlName = "textfilter";
                ffi.Settings["OperatorFieldName"] = ffi.Name + ".operator";
                break;

            case FieldDataType.DateTime:
                controlName = "datetimefilter";
                ffi.Settings["SecondDateFieldName"] = ffi.Name + ".seconddatetime";
                break;

            case FieldDataType.Integer:
            case FieldDataType.LongInteger:
                controlName = "numberfilter";
                ffi.Settings["OperatorFieldName"] = ffi.Name + ".operator";
                break;
        }
        return controlName;
    }


    /// <summary>
    /// Hides all panels with fields specific to rule types.
    /// </summary>
    private void HideAllPanels()
    {
        pnlActivityPlaceHolder.Visible = false;
        plcActivitySettings.Visible = false;

        plcAttributeSettings.Visible = false;

        pnlMacroSettings.Visible = false;
    }


    /// <summary>
    /// Loads basicform with filter controls.
    /// </summary>
    /// <param name="bf">BasicForm control</param>
    /// <param name="fi">Form definition</param>
    /// <param name="activityType">Activity type in case the rule type is activity</param>
    private void LoadForm(BasicForm bf, FormInfo fi, string activityType = null)
    {
        bf.FormInformation = fi;
        bf.Data = RuleHelper.GetDataFromCondition(Rule, fi.GetDataRow().Table, ref activityType);
        bf.SubmitButton.Visible = false;
        bf.SiteName = SiteContext.CurrentSiteName;

        if (Rule != null)
        {
            bf.Mode = FormModeEnum.Update;
        }

        bf.ReloadData();
    }


    /// <summary>
    /// Finds form field by given name and changes its behavior to accepts only digits and negative sign; limits maximal length of field. This changes cannot be done in markup.
    /// </summary>
    /// <param name="name">Name of field</param>
    private void NumbersOnlyTextBox(string name)
    {
        // Get bottom text box object 
        var textbox = editForm.FieldControls[name] as CMSFormControls_Basic_TextBoxControl;
        if (textbox == null)
        {
            return;
        }

        // These settings are propagated to javascript, thus not only wrong data does not pass validation check, but wrong data cannot be inserted in the first place
        textbox.MaxLength = 11;
        textbox.FilterType = FilterTypes.Numbers | FilterTypes.Custom;
        textbox.ValidChars = "-";
    }


    /// <summary>
    /// Displays error message in header section of page.
    /// </summary>
    /// <param name="errorMessage">Error message to be displayed</param>
    private void DisplayError(string errorMessage)
    {
        ShowError(TextHelper.LimitLength(errorMessage, 200), (errorMessage.Length > 200 ? errorMessage : String.Empty));
    }


    /// <summary>
    /// Sets the caption of field, if resource with given caption key is available.
    /// </summary>
    /// <param name="ffi">Form field info</param>
    /// <param name="captionKey">Resource key of caption</param>
    private void SetCaptionToField(FormFieldInfo ffi, string captionKey)
    {
        // Set detailed caption
        string caption = GetString(captionKey);
        if (!caption.EqualsCSafe(captionKey, true))
        {
            ffi.SetPropertyValue(FormFieldPropertyEnum.FieldCaption, caption);
        }
    }


    /// <summary>
    /// Performs custom validation and displays error in top of the page.
    /// </summary>
    /// <returns>Returns true if validation is successful.</returns>
    private bool ValidateForm()
    {
        ScoreInfo info = ScoreInfoProvider.GetScoreInfo(ScoreId);
        if (info.ScoreStatus == ScoreStatusEnum.Recalculating)
        {
            ShowError(GetString("om.score.editrulefailedrecalculating"));
            return false;
        }

        switch (SelectedRuleType)
        {
            case RuleTypeEnum.Activity:
                return ValidateActivityData();

            case RuleTypeEnum.Attribute:
                return ValidateAttributeData();

            case RuleTypeEnum.Macro:
                return ValidateMacroData();
        }

        return true;
    }

    #endregion


    #region "Overriding UI Texts"

    /// <summary>
    /// This class holds information about text displayed on the page which will be displayed instead the default texts.
    /// </summary>
    public class UITexts
    {
        public string DisplayNameTooltipResourceString
        {
            get;
            set;
        }
        public string ScoreValueTooltipResourceString
        {
            get;
            set;
        }
        public string ScoreValueLabelResourceString
        {
            get;
            set;
        }
        public string RecalculationNeededResourceString
        {
            get;
            set;
        }
    }


    /// <summary>
    /// Sets different values for the specified labels and tooltips of the UI form. This method has to be called on the Load phase!
    /// </summary>
    /// <param name="uiTexts">New texts</param>
    public void OverrideUITexts(UITexts uiTexts)
    {
        if (uiTexts == null)
        {
            throw new ArgumentNullException("uiTexts");
        }

        fDisplayName.ToolTipResourceString = uiTexts.DisplayNameTooltipResourceString;
        fValue.ResourceString = uiTexts.ScoreValueLabelResourceString;
        fValue.ToolTipResourceString = uiTexts.ScoreValueTooltipResourceString;

        mRecalculationNeededResourceString = uiTexts.RecalculationNeededResourceString;
    }

    #endregion


    #region "Initialize methods"

    /// <summary>
    /// Initializes controls, preselects items in Activity Validity field set.
    /// </summary>
    private void InitControls()
    {
        // Set validity setting information from edited rule. Because specific form control is used, FFI is not able to set data itself
        if ((!RequestHelper.IsPostBack()) && (Rule != null))
        {
            validity.ValidUntil = Rule.RuleValidUntil;
            validity.Validity = Rule.RuleValidity;
            validity.ValidFor = Rule.RuleValidFor;
        }

        // Sets up fields with specific numbers-only settings
        NumbersOnlyTextBox("rulevalue");
        NumbersOnlyTextBox("rulemaxpoints");

        drpAttribute.SelectedIndexChanged += AttributeSelectionChanged;
        ucActivityType.OnSelectedIndexChanged += ActivitySelectionChanged;

        // Update rule settings panel when changing selected rule type
        RadioButtonsListRuleType.Changed += (s, e) => upnlSettings.Update();
    }


    /// <summary>
    /// Initializes header action control.
    /// </summary>
    private void InitHeaderActions()
    {
        if ((Rule != null) && (Rule.RuleID != 0))
        {
            AddHeaderAction(new HeaderAction
            {
                Text = GetString("om.score.newrule"),
                RedirectUrl = ResolveUrl(NewRuleUrl),
                ButtonStyle = ButtonStyle.Default
            });
        }

        HeaderActions.ActionPerformed += HeaderActions_ActionPerformed;
    }


    /// <summary>
    /// Shows warning message if score needs to be rebuilt.
    /// </summary>
    private void InitWarnings()
    {
        ScoreInfo info = ScoreInfoProvider.GetScoreInfo(ScoreId);

        // Do nothing if recalculation is already scheduled
        if (info.ScoreScheduledTaskID > 0)
        {
            TaskInfo taskInfo = TaskInfoProvider.GetTaskInfo(info.ScoreScheduledTaskID);
            if (taskInfo != null)
            {
                if (taskInfo.TaskEnabled)
                {
                    return;
                }
            }
        }

        if (info.ScoreStatus == ScoreStatusEnum.RecalculationRequired)
        {
            ShowInformation(GetString(mRecalculationNeededResourceString));
        }
    }

    #endregion


    #region "Attribute rule type methods"

    /// <summary>
    /// Handles content tree changes performed when Attribute type of rule is selected.
    /// </summary>
    private void AttributeRuleTypeSelected()
    {
        // Show markup containing controls related to attribute settings
        plcAttributeSettings.Visible = true;

        if (attributeFormCondition.FieldLabels != null)
        {
            // Change visual style of form label
            LocalizedLabel ll = attributeFormCondition.FieldLabels[mSelectedAttribute.Name];
            if (ll != null)
            {
                ll.ResourceString = "om.score.condition";
            }
        }
    }


    /// <summary>
    /// Initializes controls for the Attribute type of rule.
    /// </summary>
    /// <param name="selectedAttribute">Index of selected field in attribute drop-down menu</param>
    private void InitAttributeSettings(int selectedAttribute)
    {
        // This method can be called several times, if mFields are already filled, there is no need to call it again
        if (mFields == null)
        {
            // Load all possible attributes from FormInfo specified for score rules
            FormInfo filterFieldsForm = FormHelper.GetFormInfo(ContactInfo.OBJECT_TYPE + ".ScoringAttributeRule", false);

            var fields = (from formField in filterFieldsForm.GetFields(true, false)
                          let caption = ResHelper.LocalizeString(formField.GetDisplayName(MacroContext.CurrentResolver))
                          orderby caption
                          select new
                          {
                              Caption = caption,
                              formField
                          }).ToList();


            if (drpAttribute.Items.Count == 0)
            {
                // Fill fields to attribute drop-down menu, if not already filled
                fields.ForEach(field => drpAttribute.Items.Add(new ListItem(field.Caption, field.formField.Name)));
            }

            if ((Rule != null) && !RequestHelper.IsPostBack())
            {
                // When editing existing rule, specify selected field in drop-down menu and override the previous selected one
                drpAttribute.SelectedValue = ValidationHelper.GetString(editForm.Data["RuleParameter"], null);
                selectedAttribute = drpAttribute.SelectedIndex;
                PreviousSelectedAttribute = selectedAttribute;
            }

            // Store all available fields for further use in current request
            mFields = fields.Select(c => c.formField).ToList();
        }

        // Loads form for selected attribute
        LoadAttributeForm(mFields[selectedAttribute]);
    }


    /// <summary>
    /// Loads form with specific settings for rule of type Attribute.
    /// </summary>
    /// <param name="selectedAttribute">Reference to field selected in attribute drop-down menu</param>
    private void LoadAttributeForm(FormFieldInfo selectedAttribute)
    {
        // Store current selected attribute for further usage within current request
        mSelectedAttribute = selectedAttribute;

        // Create FormInfo which will be passed to basic form already set in markup
        // According to selected attribute specific fields will be loaded into the basic form
        var fi = new FormInfo();
        fi.AddFormItem(selectedAttribute);
        LoadForm(attributeFormCondition, fi);
    }


    /// <summary>
    /// Stores Attribute form data to main Edit form.
    /// </summary>
    private void StoreAttributeData()
    {
        // For attribute rule don't store validity
        ClearStoredValidityData();

        // Only activity rules can be recurring and have max points
        editForm.Data["RuleIsRecurring"] = false;
        editForm.Data["RuleMaxPoints"] = null;

        // Store contact column for attribute rule
        editForm.Data["RuleParameter"] = mSelectedAttribute.Name;

        // Store xml with where condition
        attributeFormCondition.SaveData(null);
        editForm.Data["RuleCondition"] = RuleHelper.GetAttributeCondition(attributeFormCondition.Data, attributeFormCondition.GetWhereCondition());
    }


    /// <summary>
    /// Validates fields related to Attribute rule type.
    /// </summary>
    /// <returns>True, if validation check was successful, false otherwise</returns>
    private bool ValidateAttributeData()
    {
        // Check the attribute custom form
        if (!attributeFormCondition.ValidateData())
        {
            DisplayError(attributeFormCondition.ValidationErrorMessage);
            return false;
        }

        return true;
    }

    #endregion


    #region "Activity rule type methods"

    /// <summary>
    /// Adds the extra activity fields to the rule settings form.
    /// </summary>
    /// <param name="ignoredColumns">Collection of columns, which shouldn't be added</param>
    /// <param name="fi">Form info used for adding extra fields</param>
    /// <param name="additionalFieldsForm">Collection of extra fields</param>
    private static void AddExtraActivityFields(IEnumerable<string> ignoredColumns, FormInfo fi, FormInfo additionalFieldsForm)
    {
        if (additionalFieldsForm != null)
        {
            IEnumerable<FormFieldInfo> formFields = additionalFieldsForm.GetFields(true, false)
                .Where(f =>
                    !ignoredColumns.Contains(f.Name.ToLowerCSafe())
                );

            foreach (FormFieldInfo ffi in formFields)
            {
                ffi.Settings["controlname"] = GetControlNameForFieldDataType(ffi);
                fi.AddFormItem(ffi);
            }
        }
    }


    /// <summary>
    /// Handles content tree changes performed when Activity type of rule is selected.
    /// </summary>
    private void ActivityRuleTypeSelected()
    {
        pnlActivityPlaceHolder.Visible = true;
        plcActivitySettings.Visible = true;
    }


    /// <summary>
    /// Gets additional fields which should be appended to Activity settings form, if any.
    /// </summary>
    /// <param name="selectedActivity">Activity selected in drop-down menu</param>
    /// <param name="extraFieldsAtEnd">
    /// Determines, whether fields should be appended at end of form or at the beginning
    /// </param>
    /// <returns>FormInfo containing all required additional fields</returns>
    private static FormInfo GetActivityAdditionalFields(string selectedActivity, ref bool extraFieldsAtEnd)
    {
        FormInfo additionalFieldsForm = null;
        switch (selectedActivity)
        {
            case PredefinedActivityType.PAGE_VISIT:
            case PredefinedActivityType.LANDING_PAGE:
                // Page visits
                additionalFieldsForm = FormHelper.GetFormInfo(PageVisitInfo.OBJECT_TYPE, false);
                break;

            case PredefinedActivityType.INTERNAL_SEARCH:
            case PredefinedActivityType.EXTERNAL_SEARCH:
                // Search
                additionalFieldsForm = FormHelper.GetFormInfo(SearchInfo.OBJECT_TYPE, false);
                extraFieldsAtEnd = false;
                break;
        }
        return additionalFieldsForm;
    }


    /// <summary>
    /// Checks form field name and tries to find appropriate form control for field representation.
    /// </summary>
    /// <param name="ffi">Form field info</param>
    /// <param name="ati">Activity type info</param>
    /// <param name="selectedActivity">Activity selected in drop-down menu</param>
    /// <param name="activitiesWithValue">Collection of activities with values</param>
    /// <param name="controlName">Referring control name</param>
    /// <returns>
    /// False, if activity form control is not defined or activity should has value and is not present in given
    /// collection; true otherwise. Sets referring control name, if proper form control is found.
    /// </returns>
    private bool GetControlNameForActivities(FormFieldInfo ffi, ActivityTypeInfo ati, string selectedActivity, IEnumerable<string> activitiesWithValue, ref string controlName)
    {
        string nameToLower = ffi.Name.ToLowerInvariant();
        switch (nameToLower)
        {
            case "activityitemid":
                if (string.IsNullOrEmpty(ati.ActivityTypeMainFormControl))
                {
                    return false;
                }

                CheckFormControl(ati.ActivityTypeMainFormControl, ref controlName);
                SetCaptionToField(ffi, "activityitem." + selectedActivity);
                break;

            case "activityitemdetailid":
                if (string.IsNullOrEmpty(ati.ActivityTypeDetailFormControl))
                {
                    return false;
                }

                CheckFormControl(ati.ActivityTypeDetailFormControl, ref controlName);
                SetCaptionToField(ffi, "activityitemdetail." + selectedActivity);
                break;

            case "activitycreated":
                SetCaptionToField(ffi, "om.activity.createdbetween");
                break;

            case "activitynodeid":
                // Document selector for NodeID
                controlName = "selectdocument";
                break;

            case "activityculture":
                // Culture selector for culture
                controlName = "sitecultureselector";
                break;

            case "activityvalue":
                // Show activity value only for relevant activity types
                if ((!ati.ActivityTypeIsCustom) && (!activitiesWithValue.Contains(selectedActivity)))
                {
                    return false;
                }
                break;
        }

        return true;
    }


    /// <summary>
    /// Initializes controls for activity rule.
    /// </summary>
    /// <param name="selectedActivity">Activity selected in drop-down menu</param>
    private void InitActivitySettings(string selectedActivity)
    {
        // Init activity selector from  edited object if any
        LoadEditedActivityRule(ref selectedActivity);

        string[] ignoredColumns =
        {
            "activitytype",
            "activitysiteid",
            "activityguid",
            "activityactivecontactid",
            "activityoriginalcontactid",
            "pagevisitid",
            "pagevisitactivityid",
            "searchid",
            "searchactivityid"
        };

        string[] activitiesWithValue =
        {
            PredefinedActivityType.PURCHASE,
            PredefinedActivityType.PURCHASEDPRODUCT,
            PredefinedActivityType.RATING,
            PredefinedActivityType.POLL_VOTING,
            PredefinedActivityType.PRODUCT_ADDED_TO_SHOPPINGCART
        };

        // Get columns from OM_Activity (i.e. base table for all activities)
        ActivityTypeInfo ati = ActivityTypeInfoProvider.GetActivityTypeInfo(selectedActivity);
        var fi = new FormInfo();

        // Get columns from additional table (if any) according to selected activity type
        bool extraFieldsAtEnd = true;
        FormInfo additionalFieldsForm = GetActivityAdditionalFields(selectedActivity, ref extraFieldsAtEnd);

        // Get the activity form elements
        FormInfo filterFieldsForm = FormHelper.GetFormInfo(ActivityInfo.OBJECT_TYPE, true);
        IList<IField> elements = filterFieldsForm.GetFormElements(true, false);

        FormCategoryInfo newCategory = null;

        foreach (IField elem in elements)
        {
            if (elem is FormCategoryInfo)
            {
                // Form category
                newCategory = (FormCategoryInfo)elem;
            }
            else if (elem is FormFieldInfo)
            {
                // Form field
                var ffi = (FormFieldInfo)elem;

                // Skip ignored columns
                if (ignoredColumns.Contains(ffi.Name.ToLowerCSafe()))
                {
                    continue;
                }

                if ((!ffi.PrimaryKey) && (fi.GetFormField(ffi.Name) == null))
                {
                    // Skip fields with Guid data type
                    if (ffi.DataType == FieldDataType.Guid)
                    {
                        continue;
                    }

                    // Sets control name based on given datatype of field. Can be overwritten if more proper control is available
                    string controlName = GetControlNameForFieldDataType(ffi);
                    if (!GetControlNameForActivities(ffi, ati, selectedActivity, activitiesWithValue, ref controlName))
                    {
                        continue;
                    }

                    if (controlName != null)
                    {
                        // SKU selector for product
                        ffi.Settings["controlname"] = controlName;
                        ffi.Settings["allowempty"] = controlName.EqualsCSafe("skuselector", true);
                    }

                    // Ensure the category
                    if (newCategory != null)
                    {
                        fi.AddFormCategory(newCategory);
                        newCategory = null;

                        // Extra fields at the beginning
                        if ((!extraFieldsAtEnd) && (additionalFieldsForm != null))
                        {
                            AddExtraActivityFields(ignoredColumns, fi, additionalFieldsForm);
                            additionalFieldsForm = null;
                        }
                    }

                    fi.AddFormItem(ffi);
                }
            }
        }

        // Extra fields at the end
        if ((extraFieldsAtEnd) && (additionalFieldsForm != null))
        {
            // Ensure the category for extra fields
            if (newCategory != null)
            {
                fi.AddFormCategory(newCategory);
            }

            AddExtraActivityFields(ignoredColumns, fi, additionalFieldsForm);
        }

        LoadActivityForm(fi, selectedActivity);
    }


    /// <summary>
    /// Loads form with specific settings for rule of type Activity.
    /// </summary>
    /// <param name="fi">FormInfo containing information about activity</param>
    /// <param name="activityType">Type of activity</param>
    private void LoadActivityForm(FormInfo fi, string activityType)
    {
        LoadForm(activityFormCondition, fi, activityType);
    }


    /// <summary>
    /// Checks if editing already existing rule. If so, and the request is not postback,
    /// preselects proper activity and sets previous selected value to ViewState.
    /// </summary>
    /// <param name="selectedActivity">
    /// Referring selected activity. If editing already existing rule, its value is replaced with the saved one
    /// </param>
    private void LoadEditedActivityRule(ref string selectedActivity)
    {
        if ((Rule != null) && !RequestHelper.IsPostBack())
        {
            // When editing existing rule, specify selected field in drop-down menu and override the previous selected one
            ucActivityType.Value = ValidationHelper.GetString(editForm.Data["RuleParameter"], PredefinedActivityType.ABUSE_REPORT);
            selectedActivity = ucActivityType.SelectedValue;
            PreviousSelectedActivity = selectedActivity;
        }
    }


    /// <summary>
    /// Stores Activity form data to main Edit form.
    /// </summary>
    private void StoreActivityData()
    {
        editForm.Data["RuleValidity"] = (int)validity.Validity;
        editForm.Data["RuleValidUntil"] = null;

        if (validity.Validity == ValidityEnum.Until)
        {
            if (validity.ValidUntil != DateTimeHelper.ZERO_TIME)
            {
                editForm.Data["RuleValidUntil"] = validity.ValidUntil;
            }
        }
        else
        {
            editForm.Data["RuleValidFor"] = validity.ValidFor;
        }

        // Store contact column for attribute rule
        editForm.Data["RuleParameter"] = ucActivityType.SelectedValue;

        // Store xml with Where condition
        activityFormCondition.SaveData(null);
        string whereCond = "ActivityType='" + SqlHelper.EscapeQuotes(ucActivityType.SelectedValue) + "'";
        whereCond = SqlHelper.AddWhereCondition(whereCond, activityFormCondition.GetWhereCondition());
        editForm.Data["RuleCondition"] = RuleHelper.GetActivityCondition(activityFormCondition.Data, whereCond, ucActivityType.SelectedValue);
    }


    /// <summary>
    /// Validates fields related to Activity rule type.
    /// </summary>
    /// <returns>True, is validation check was successful, false otherwise</returns>
    private bool ValidateActivityData()
    {
        bool isValid = true;
        string errorMessage = validity.Validate();
        if (!string.IsNullOrEmpty(errorMessage))
        {
            DisplayError(errorMessage);
            isValid = false;
        }

        // Checks if score value is not outside the boundaries specified in max rule points field
        if (!ValidateMaximumValueField())
        {
            isValid = false;
        }

        // Check the activity custom form
        if (!activityFormCondition.ValidateData())
        {
            DisplayError(activityFormCondition.ValidationErrorMessage);
            isValid = false;
        }

        return isValid;
    }


    /// <summary>
    /// Validates maximum value field, if rule is set to be recurring.
    /// Compares values entered in the Score value and the Max. rule points fields.
    /// </summary>
    /// <returns>True, if rule is not recurring, or if value is between boundaries declared by max value field; false otherwise</returns>
    private bool ValidateMaximumValueField()
    {
        var recurringField = editForm.FieldControls["RuleIsRecurring"];
        var maxValueField = editForm.FieldControls["RuleMaxPoints"];
        var valueField = editForm.FieldControls["RuleValue"];

        // Validate maximum value field
        if (ValidationHelper.GetBoolean(recurringField.Value, false))
        {
            string maxValueStr = maxValueField.Text.Trim();
            if (!String.IsNullOrEmpty(maxValueStr))
            {
                if (!ValidationHelper.IsInteger(maxValueStr))
                {
                    DisplayError(GetString("om.score.enterintegervalue"));
                    return false;
                }

                // Check that maximum value is greater than value
                int value = ValidationHelper.GetInteger(valueField.Text, 0);
                int maxValue = ValidationHelper.GetInteger(maxValueStr, 0);
                if ((value != 0) && (maxValue / value < 1)) // Values can be both negative and positive numbers, this condition ensures value is not outside the boundaries defined by maxValue
                {
                    DisplayError(GetString("om.score.smallmaxvalue"));
                    return false;
                }
            }
        }
        return true;
    }

    #endregion


    #region "Macro rule type methods"

    /// <summary>
    /// Handles content tree changes performed when Macro type of rule is selected.
    /// </summary>
    private void MacroRuleTypeSelected()
    {
        // Show markup containing controls related to macro settings
        pnlMacroSettings.Visible = true;
    }


    /// <summary>
    /// Initializes macro editor for macro rule, loads its default value.
    /// </summary>
    private void InitMacroSettings()
    {
        if ((Rule != null) && !RequestHelper.IsPostBack())
        {
            macroEditor.Text = RuleHelper.GetMacroConditionFromRule(Rule);
        }
    }


    /// <summary>
    /// Stores Macro condition to main Edit form.
    /// </summary>
    private void StoreMacroData()
    {
        // For macro rule don't store validity
        ClearStoredValidityData();

        // Only activity rules can be recurring and have max points
        editForm.Data["RuleIsRecurring"] = false;
        editForm.Data["RuleMaxPoints"] = null;

        // Store null value as rule parameter
        editForm.Data["RuleParameter"] = null;

        // Store xml with macro condition
        editForm.Data["RuleCondition"] = RuleHelper.GetMacroCondition(macroEditor.Text);
    }


    /// <summary>
    /// Validates fields related to Macro rule type.
    /// </summary>
    /// <returns>True, is validation check was successful, false otherwise</returns>
    private bool ValidateMacroData()
    {
        if (string.IsNullOrEmpty(macroEditor.Text))
        {
            editForm.AddError(GetString("om.score.macroisempty"));
            return false;
        }

        return true;
    }


    /// <summary>
    /// Check whether all macros in macro rule are optimized.
    /// Shows warning when not.
    /// </summary>
    private void CheckMacros()
    {
        var macroCondition = RuleHelper.GetMacroConditionFromRule(Rule);
        if (string.IsNullOrEmpty(macroCondition))
        {
            return;
        }

        var macroTree = CachedMacroRuleTrees.GetParsedTree(macroCondition);
        if ((macroTree == null) || !MacroRuleTreeAnalyzer.CanTreeBeTranslated(macroTree))
        {
            ShowWarning(ResHelper.GetString("om.macros.macro.slow"));
        }
    }

    #endregion
}