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/TDijk1/erp-apps.eu/wwwroot/CMSModules/Newsletters/Controls/IssueLinks.ascx.cs
using System;
using System.Data;
using System.Linq;
using System.Web.UI.WebControls;

using CMS.DataEngine;
using CMS.ExtendedControls;
using CMS.Helpers;
using CMS.Newsletters;
using CMS.UIControls;
using CMS.UIControls.UniGridConfig;


public partial class CMSModules_Newsletters_Controls_IssueLinks : CMSUserControl
{
    #region "Variables"

    // Default page size 15
    private const int PAGESIZE = 15;
    private int sentOrDeliveredEmails;
    private int issueID;
    private bool isMainABTestIssue;
    private bool isABTest;

    #endregion


    #region "Properties"

    /// <summary>
    /// Newsletter issue ID.
    /// </summary>
    public int IssueID
    {
        get;
        set;
    }


    /// <summary>
    /// Indicates whether click statistics from winner issue (variant + main issue) are included.
    /// </summary>
    public bool IncludeWinnerStatistics
    {
        get;
        set;
    }


    /// <summary>
    /// Indicates whether click statistics from all variants are displayed for the main issue.
    /// </summary>
    public bool IncludeAllVariants
    {
        get;
        set;
    }


    /// <summary>
    /// Indicates whether the user can remove outdated links.
    /// </summary>
    public bool ShowDeleteOutdated
    {
        get;
        set;
    }


    /// <summary>
    /// Indicates whether the filter is displayed above the listing.
    /// </summary>
    public bool ShowFilter
    {
        get;
        set;
    }


    /// <summary>
    /// Selects only N most clicked links.
    /// </summary>
    public int TopN
    {
        get;
        set;
    }


    /// <summary>
    /// Indicates whether the grid displays only clicked links (having ClickLink records).
    /// </summary>
    public bool DisplayOnlyClickedLinks
    {
        get;
        set;
    }


    /// <summary>
    /// Indicates whether the grid displays the Click rate column for AB tested issue.
    /// </summary>
    public bool AllowHidingClickRateColumnForAbTest
    {
        get;
        set;
    }


    /// <summary>
    /// Inner grid control.
    /// </summary>
    public UniGrid UniGrid
    {
        get
        {
            return ugLinks;
        }
    }


    /// <summary>
    /// Text displayed when UniGrid data source is empty.
    /// </summary>
    public string NoDataText
    {
        get;
        set;
    }

    #endregion


    #region "Methods"

    protected void Page_Load(object sender, EventArgs e)
    {
        IssueInfo issue = IssueInfoProvider.GetIssueInfo(IssueID);

        if (issue == null)
        {
            return;
        }

        issueID = IssueID;
        isABTest = issue.IssueIsABTest;

        // Get number of sent or delivered emails according to the "Monitor bounced email" setting
        sentOrDeliveredEmails = GetSentOrDelivered(issue);

        ScriptHelper.RegisterDialogScript(Page);

        string scriptBlock = string.Format(@"
            function OpenTarget(url) {{ window.open(url, 'LinkTarget'); return false; }}
            function ViewClicks(id) {{ modalDialog('{0}?linkid=' + id, 'NewsletterIssueSubscriberClicks', '900px', '700px');  return false; }}",
                                           ResolveUrl(@"~\CMSModules\Newsletters\Tools\Newsletters\Newsletter_Issue_SubscribersClicks.aspx"));
        ScriptHelper.RegisterClientScriptBlock(this, GetType(), "Actions", scriptBlock, true);

        
        // Issue is the main A/B test issue
        isMainABTestIssue = issue.IssueIsABTest && !issue.IssueIsVariant;
        if (isMainABTestIssue)
        {
            // Initialize variant selector in the filter
            fltLinks.IssueId = issue.IssueID;

            // Get current issue ID from variant selector
            issueID = fltLinks.IssueId;

            // Get number of sent emails for selected variant
            var issueVariant = IssueInfoProvider.GetIssueInfo(issueID);
            sentOrDeliveredEmails = CalculateVariantSentEmails(issue, issueVariant);

            // Set the visibility of Click rate column
            ugLinks.OnBeforeDataReload += SetClickRateColumnVisibility;
            ugLinks.OnAfterDataReload += SetClickRateColumnVisibility;

        }

        ugLinks.Pager.DefaultPageSize = PAGESIZE;
        ugLinks.Pager.ShowPageSize = false;
        ugLinks.FilterLimit = 1;
        ugLinks.OnExternalDataBound += UniGrid_OnExternalDataBound;
        ugLinks.OnAction += UniGrid_OnAction;

        ugLinks.OnDataReload += GetLinks;

        // Hide actions column if there is no outdated links
        ugLinks.OnAfterDataReload += () =>
        {
            var dv = ugLinks.GridView.DataSource as DataView;
            if (DataHelper.DataSourceIsEmpty(dv))
            {
                return;
            }

            var outdated = DataHelper.GetValues<Boolean>(dv.Table, "LinkOutdated");
            if (!outdated.Any(x => x) || !ShowDeleteOutdated)
            {
                if (ugLinks.GridActions != null)
                {
                    ugLinks.GridActions.Actions.Clear();
                    ugLinks.GridActions.Actions.Add(new EmptyAction());
                }
            }
        };

        fltLinks.Visible = ShowFilter;
        ugLinks.ZeroRowsText = NoDataText;
    }


    protected DataSet GetLinks(string completeWhere, string currentOrder, int currentTopN, string columns, int currentOffset, int currentPageSize, ref int totalRecords)
    {
        // Default where condition
        WhereCondition whereIssues = new WhereCondition().WhereEquals("LinkIssueID", issueID);
        isMainABTestIssue = isMainABTestIssue && (issueID == IssueID);        
        int winnerIssueId = 0;

        if (IncludeAllVariants && isABTest)
        {
            // Get all variants
            var issueIDs = IssueInfoProvider.GetIssues()
                                            .Column("IssueID")
                                            .WhereEquals("IssueID", IssueID)
                                            .Or()
                                            .WhereEquals("IssueVariantOfIssueID", IssueID).GetListResult<Int32>();

            // Include all links for all variants
            whereIssues = new WhereCondition().WhereIn("LinkIssueID", issueIDs);
        }
        else if (IncludeWinnerStatistics && isMainABTestIssue)
        {
            var test = ABTestInfoProvider.GetABTestInfoForIssue(issueID);

            if (test != null)
            {
                // Get winner variant issue ID
                winnerIssueId = test.TestWinnerIssueID;
            }

            if (winnerIssueId > 0)
            {
                // Include winner issue
                whereIssues = whereIssues.Or().WhereEquals("LinkIssueID", winnerIssueId);
            }
        }

        // Get links with clicks statistics for issue(s)
        var query = LinkInfoProvider.GetLinks()
                        .Columns(
                            new QueryColumn("LinkID"),
                            new QueryColumn("LinkIssueID"),
                            new QueryColumn("LinkTarget"),
                            new QueryColumn("LinkDescription"),
                            new QueryColumn("LinkOutdated"),

                            // Get total and unique clicks
                            new AggregatedColumn(AggregationType.Count, "DISTINCT(ClickedLinkEmail)").As("UniqueClicks"),
                            new AggregatedColumn(AggregationType.Count, "ClickedLinkEmail").As("TotalClicks")
                        )
                        .Where(whereIssues)
                        .And()
                        .Where(fltLinks.WhereCondition)
                        .Source(s => s.LeftJoin<ClickedLinkInfo>("LinkID", "ClickedLinkNewsletterLinkID"))
                        .GroupBy("LinkID", "LinkIssueID", "LinkTarget", "LinkDescription", "LinkOutdated");


        if ((winnerIssueId > 0) || IncludeAllVariants)
        {
            // Aggregate same links (LinkTarget, LinkDescription, LinkOutdated) from various variants (variant + winner OR all variants)
            query = query.AsNested()
                 .Columns(
                     new QueryColumn("LinkTarget"),
                     new QueryColumn("LinkDescription"),
                     new QueryColumn("LinkOutdated"),

                     // Get ID of main issue link (grater than variant link ID)
                     new AggregatedColumn(AggregationType.Max, "LinkID").As("LinkID"),

                     // Get total and unique clicks (sum variants)
                     new AggregatedColumn(AggregationType.Sum, "UniqueClicks").As("UniqueClicks"),
                     new AggregatedColumn(AggregationType.Sum, "TotalClicks").As("TotalClicks")

                 )
                 .GroupBy("LinkTarget", "LinkDescription", "LinkOutdated");
                 
            if (DisplayOnlyClickedLinks)
            {
                query = query.Having(x => x.WhereGreaterThan(new AggregatedColumn(AggregationType.Sum, "UniqueClicks"), 0));
            }
        }
        else if (DisplayOnlyClickedLinks)
        {
            query = query.Having(x => x.WhereGreaterThan(new AggregatedColumn(AggregationType.Count, "DISTINCT(ClickedLinkEmail)").As("UniqueClicks"), 0));
        }

        if (TopN > 0)
        {
            query = query.TopN(TopN);
        }

        query = query.OrderByDescending("UniqueClicks");

        return query.Result;
    }


    protected object UniGrid_OnExternalDataBound(object sender, string sourceName, object parameter)
    {
        int linkID = 0;
        DataRowView dr = parameter as DataRowView;

        if (dr != null)
        {
            linkID = ValidationHelper.GetInteger(DataHelper.GetDataRowViewValue(dr, "LinkID"), 0);
        }

        switch (sourceName)
        {
            case "clickrate":
                {
                    var uniqueClicks = ValidationHelper.GetDouble(GetStatisticsValueForLink((DataRowView)parameter, "UniqueClicks"), 0);

                    if(uniqueClicks == 0)
                    {
                        return "0%";
                    }

                    var rate = (sentOrDeliveredEmails == 0) ? 0 : ((uniqueClicks / sentOrDeliveredEmails) * 100);
                    return GetClickDialogLink(linkID, String.Format("{0:F2}%", rate));
                }
            case "uniqueclicks":
                {
                    var uniqueClicks = GetStatisticsValueForLink((DataRowView)parameter, "UniqueClicks");
                    if (uniqueClicks > 0)
                    {
                        return GetClickDialogLink(linkID, uniqueClicks.ToString());
                    }

                    return uniqueClicks;
                }
            case "totalclicks":
                {
                    var totalClicks = GetStatisticsValueForLink((DataRowView)parameter, "TotalClicks");
                    if (totalClicks > 0)
                    {
                        return GetClickDialogLink(linkID, totalClicks.ToString());
                    }

                    return totalClicks;
                }

            case "linktarget":
                return string.Format(@"<a href=""#"" onclick=""OpenTarget('{0}')"">{1}</a>",
                                     parameter,
                                     HTMLHelper.HTMLEncode(TextHelper.LimitLength(parameter.ToString(), 50)));

            case "linktargettooltip":
                return HTMLHelper.HTMLEncode(parameter.ToString());

            case "linkdescription":
                return HTMLHelper.HTMLEncode(TextHelper.LimitLength(parameter.ToString(), 25));

            case "linkdescriptiontooltip":
                return HTMLHelper.HTMLEncode(parameter.ToString());

            case "deleteoutdated":
                var isOutdated = DataHelper.GetDataRowViewValue((DataRowView)((GridViewRow)parameter).DataItem, "LinkOutdated");
                return ((CMSGridActionButton)sender).Visible = ValidationHelper.GetBoolean(isOutdated, false);

            default:
                return parameter;
        }
    }


    protected void UniGrid_OnAction(string actionName, object actionArgument)
    {
        switch (actionName)
        {
            case "deleteoutdated":
                // Delete link that is not used in current version of the issue
                int linkId = ValidationHelper.GetInteger(actionArgument, 0);
                LinkInfoProvider.DeleteLinkInfo(linkId);
                break;
        }
    }


    /// <summary>
    /// Returns HTML link to link click dialog.
    /// </summary>
    /// <param name="linkID">LinkInfo ID</param>
    /// <param name="text">Link text</param>
    private string GetClickDialogLink(int linkID, string text)
    {
        // Do not show links in Most Click table for ABTestsed issue
        if (isABTest && IncludeAllVariants)
        {
            return text;
        }

        return string.Format(@"<a href=""#"" onclick=""ViewClicks({0})"">{1}</a>", linkID, text);
    }


    /// <summary>
    /// Returns statistics value for the given link.
    /// </summary>
    /// <param name="link">Newsletter link DataRowView</param>
    /// <param name="columnName">Column name</param>
    private int GetStatisticsValueForLink(DataRowView link, string columnName)
    {
        var value = DataHelper.GetIntValue(link.Row, columnName);
        return value;
    }


    /// <summary>
    /// In the parent issue is stored "SentEmail" amount of all variants and the remainder,
    /// so the remainder amount have to be computed by subtraction of all sent amounts
    /// from particular variants.
    /// </summary>
    /// <param name="parentIssue">Parent issue</param>
    /// <param name="variantIssue">Current variant</param>
    /// <returns></returns>
    private int CalculateVariantSentEmails(IssueInfo parentIssue, IssueInfo variantIssue)
    {
        if ((parentIssue == null) || (variantIssue == null))
        {
            return 0;
        }

        if (IncludeAllVariants)
        {
            return GetSentOrDelivered(parentIssue);
        }
        
        // If the winner has not been selected yet, or the selected variant is not the winner
        // return SentEmails of the current variant
        if (parentIssue.IssueID != variantIssue.IssueID)
        {
            return variantIssue.IssueSentEmails;
        }

        var abTest = ABTestInfoProvider.GetABTestInfoForIssue(parentIssue.IssueID);
        if (abTest == null)
        {
            return 0;
        }

        // If variantIssue equals parentIssue it means that winner variant was selected, but the
        // filter has returned the parent variant, and we need winner variant object
        // For the winner variant is returned the sum of variant SentEmail amount and the remainder SentEmail amount.
        // See the "Summary" section for the domain specification.
        var sentSumFromRemainingVariants = IssueInfoProvider.GetIssues()
                                           .Column(new AggregatedColumn(AggregationType.Sum, "IssueSentEmails"))
                                           .WhereEquals("IssueVariantOfIssueID", parentIssue.IssueID)
                                           .And()
                                           .WhereNotEquals("IssueID", abTest.TestWinnerIssueID)
                                           .GetScalarResult(0);

        return parentIssue.IssueSentEmails - sentSumFromRemainingVariants;
    }


    /// <summary>
    /// Returns issue's sent emails amount or delivered emails amount based on 
    /// monitor bounced email setting.
    /// </summary>
    /// <param name="issue">Issue</param>
    private int GetSentOrDelivered(IssueInfo issue)
    {
        if (NewsletterHelper.MonitorBouncedEmails(CurrentSite.SiteName))
        {
            return issue.IssueSentEmails - issue.IssueBounces;
        }

        return issue.IssueSentEmails;
    }


    /// <summary>
    /// Sets the visibility of "Click rate" column according 
    /// to control setting.
    /// </summary>
    private void SetClickRateColumnVisibility()
    {
        ugLinks.NamedColumns["clickrate"].Visible = !AllowHidingClickRateColumnForAbTest;
    }

    #endregion
}