public BlogPostComment(Entity entity, string authorName, string authorUrl, string authorEmail,
                               Lazy <ApplicationPath> getEditPath = null, Lazy <ApplicationPath> getDeletePath = null, Lazy <bool> editable = null, IRatingInfo ratingInfo = null,
                               bool ratingEnabled = true)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            if (entity.LogicalName != "feedback")
            {
                throw new ArgumentException(string.Format("Value must have logical name {0}.", entity.LogicalName), "entity");
            }

            Entity = entity;

            Author = new Author(entity.GetAttributeValue <EntityReference>("createdbycontact"), authorName, authorEmail, authorUrl);

            AnchorName = GetAnchorName(entity.Id);

            IsApproved = entity.GetAttributeValue <bool?>("adx_approved").GetValueOrDefault(false);

            RatingInfo = ratingInfo;

            _getEditPath   = getEditPath;
            _getDeletePath = getDeletePath;
            _editable      = editable;
            RatingEnabled  = ratingEnabled;
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="entity">An feedback entity.</param>
        /// <param name="authorName">The name of the author for this comment.</param>
        /// <param name="authorEmail">The email of the author for this comment.</param>
        public IdeaComment(Entity entity, string authorName, string authorEmail, Lazy <ApplicationPath> getEditPath = null,
                           Lazy <ApplicationPath> getDeletePath = null, Lazy <bool> editable = null, IRatingInfo ratingInfo = null,
                           bool ratingEnabled = true)
        {
            entity.ThrowOnNull("entity");
            entity.AssertEntityName("feedback");

            Entity = entity;

            var authorId = entity.GetAttributeValue <EntityReference>(FeedbackMetadataAttributes.UserIdAttributeName) == null ? Guid.Empty : entity.GetAttributeValue <EntityReference>(FeedbackMetadataAttributes.UserIdAttributeName).Id;

            authorName  = entity.GetAttributeValue <string>("adx_createdbycontact") ?? authorName;
            authorEmail = entity.GetAttributeValue <string>("adx_contactemail") ?? authorEmail;
            Author      = authorId != Guid.Empty
                                ? new Author(new EntityReference("contact", authorId), authorName, authorEmail)
                                : new Author(authorName, authorEmail);

            Content  = entity.GetAttributeValue <string>("comments");
            PostedOn = entity.GetAttributeValue <DateTime?>("adx_date") ?? entity.GetAttributeValue <DateTime>("createdon");
            Name     = entity.GetAttributeValue <string>("title");

            RatingInfo = ratingInfo;

            _getEditPath   = getEditPath;
            _getDeletePath = getDeletePath;
            _editable      = editable;
            RatingEnabled  = ratingEnabled;
        }
        public Comment(
            Entity feedback,
            Lazy <ApplicationPath> getEditPath   = null,
            Lazy <ApplicationPath> getDeletePath = null,
            Lazy <bool> editable   = null,
            IRatingInfo ratingInfo = null,
            bool ratingEnabled     = false)
        {
            feedback.ThrowOnNull("entity");
            feedback.AssertEntityName("feedback");

            Entity = feedback;

            var authorReference = feedback.GetAttributeValue <EntityReference>("createdbycontact");

            if (authorReference != null)
            {
                var authorNameAttribute = Localization.LocalizeFullName(
                    feedback.GetAttributeAliasedValue <string>("author.firstname"),
                    feedback.GetAttributeAliasedValue <string>("author.lastname"));
                var authorEmailAttribute = feedback.GetAttributeAliasedValue <string>("author.emailaddress1");
                Author = new Author(authorReference,
                                    authorNameAttribute ?? string.Empty,
                                    authorEmailAttribute ?? string.Empty);
            }
            else
            {
                var authorName = feedback.Contains("adx_createdbycontact") ? feedback["adx_createdbycontact"].ToString() : string.Empty;
                if (!string.IsNullOrWhiteSpace(authorName))
                {
                    var authorUrl            = feedback.Contains("adx_authorurl") ? feedback["adx_authorurl"].ToString() : string.Empty;
                    var authorauthorEmailUrl = feedback.Contains("adx_contactemail") ? feedback["adx_contactemail"].ToString() : string.Empty;
                    Author = new Author(authorName, authorUrl, authorauthorEmailUrl);
                }
            }

            Content    = feedback.GetAttributeValue <string>("comments");
            Date       = feedback.GetAttributeValue <DateTime?>("createdon") ?? feedback.GetAttributeValue <DateTime>("createdon");
            Name       = feedback.GetAttributeValue <string>("title");
            IsApproved = feedback.GetAttributeValue <bool?>("adx_approved").GetValueOrDefault();

            _getEditPath   = getEditPath;
            _getDeletePath = getDeletePath;
            _editable      = editable;
            RatingInfo     = ratingInfo;
            RatingEnabled  = ratingEnabled;

            if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.TelemetryFeatureUsage))
            {
                PortalFeatureTrace.TraceInstance.LogFeatureUsage(FeatureTraceCategory.Feedback, HttpContext.Current, "read_feedback", 1, feedback.ToEntityReference(), "read");
            }
        }
        public BlogPost(Entity entity, ApplicationPath applicationPath, IBlogAuthor author, BlogCommentPolicy commentPolicy,
                        int commentCount, IEnumerable <IBlogPostTag> tags, IRatingInfo ratingInfo = null)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            if (entity.LogicalName != "adx_blogpost")
            {
                throw new ArgumentException(string.Format("Value must have logical name {0}.", entity.LogicalName), "entity");
            }

            if (applicationPath == null)
            {
                throw new ArgumentNullException("applicationPath");
            }

            if (commentCount < 0)
            {
                throw new ArgumentException("Value can't be negative.", "commentCount");
            }

            if (tags == null)
            {
                throw new ArgumentNullException("tags");
            }

            Entity          = entity;
            ApplicationPath = applicationPath;
            Author          = author ?? new NullBlogAuthor();
            CommentPolicy   = commentPolicy;
            CommentCount    = commentCount;
            HasExcerpt      = !string.IsNullOrWhiteSpace(entity.GetAttributeValue <string>("adx_summary"));
            Id              = entity.Id;
            IsPublished     = entity.GetAttributeValue <bool?>("adx_published").GetValueOrDefault(false);
            LastUpdatedTime = entity.GetAttributeValue <DateTime?>("modifiedon").GetValueOrDefault(DateTime.UtcNow);
            PublishDate     = entity.GetAttributeValue <DateTime?>("adx_date").GetValueOrDefault(DateTime.UtcNow);
            Summary         = new HtmlString(entity.GetAttributeValue <string>("adx_summary"));
            Tags            = tags.ToArray();
            Title           = entity.GetAttributeValue <string>("adx_name");

            RatingInfo = ratingInfo;

            var copy = entity.GetAttributeValue <string>("adx_copy");

            Content = new HtmlString(HasExcerpt ? "{0}\n{1}".FormatWith(Summary, copy) : copy);
        }
        /// <summary>
        /// Renders rating for a given entity if the Feedback feature is enabled and the entity is rateable and ratings are enabled for that entity type.
        /// </summary>
        /// <param name="html">Extension method target, provides support for HTML rendering and access to view context/data.</param>
        /// <param name="entityReference">The <see cref="EntityReference"/> of the record for which to display rating.</param>
        /// <param name="ratingInfo">The <see cref="IRatingInfo"/> that provides rating value and count if available. If not provided, it will be dynamically retrieved.</param>
        /// <param name="panel">Indicates whether the rating should be wrapped in a bootstrap panel or not.</param>
        /// <param name="panelTitleSnippetName">If panel is true, this is the name of a content snippet to display a title text in the panel heading.</param>
        /// <param name="isReadonly">Indicates whether the rating is readonly (i.e. not editable).</param>
        /// <param name="resetable">Indicates whether the rating can be reset.</param>
        /// <param name="step">Step size value (default: 1)</param>
        /// <param name="min">Minumum value (default: 0)</param>
        /// <param name="max">Maximum value (default: 5)</param>
        /// <param name="urlSave">The URL to the service to create/update a rating.</param>
        /// <param name="roundNearestHalf">Indicates whether or not to round the rating value to the nearest half. Default is true.</param>
        /// <returns>An HTML encoded string representing rating.</returns>
        public static IHtmlString Rating(this HtmlHelper html, EntityReference entityReference, IRatingInfo ratingInfo = null, bool panel = false, string panelTitleSnippetName = "Rating Heading", bool isReadonly = false, bool resetable = false, string step = "1", string min = "0", string max = "5", string urlSave = null, bool roundNearestHalf = true)
        {
            if (!FeatureCheckHelper.IsFeatureEnabled(FeatureNames.Feedback))
            {
                return(new HtmlString(string.Empty));
            }

            if (entityReference == null)
            {
                return(new HtmlString(string.Empty));
            }

            if (!isReadonly && string.IsNullOrWhiteSpace(urlSave))
            {
                urlSave = html.GetPortalScopedRouteUrlByName("PortalRateit");
            }

            if (string.IsNullOrWhiteSpace(step))
            {
                step = "1";
            }

            if (string.IsNullOrWhiteSpace(min))
            {
                min = "0";
            }

            if (string.IsNullOrWhiteSpace(max))
            {
                max = "5";
            }

            if (ratingInfo == null)
            {
                var portal = PortalCrmConfigurationManager.CreatePortalContext();

                var dataAdapterFactory = new RatingDataAdapterFactory(entityReference);

                var dataAdapter = dataAdapterFactory.GetAdapter(portal, PortalExtensions.GetRequestContext());

                if (!dataAdapter.RatingsEnabled)
                {
                    return(new HtmlString(string.Empty));
                }

                ratingInfo = dataAdapter.GetRatingInfo() ?? new RatingInfo();
            }

            var ratingValue = roundNearestHalf ? ratingInfo.AverageRatingRounded : ratingInfo.AverageRating;

            var ratingCount = ratingInfo.RatingCount;

            var container = new TagBuilder("div");

            container.AddCssClass("rating");

            var rateit = new TagBuilder("div");

            rateit.AddCssClass("rateit");

            rateit.MergeAttribute("data-rateit-resetable", resetable.ToString().ToLower());

            rateit.MergeAttribute("data-rateit-step", step);

            rateit.MergeAttribute("data-rateit-min", min);

            rateit.MergeAttribute("data-rateit-max", max);

            rateit.MergeAttribute("data-rateit-ispreset", "true");

            rateit.MergeAttribute("data-rateit-readonly", isReadonly.ToString().ToLower());

            rateit.MergeAttribute("data-rateit-value", ratingValue.ToString(CultureInfo.InvariantCulture));

            rateit.MergeAttribute("data-logicalname", entityReference.LogicalName);

            rateit.MergeAttribute("data-id", entityReference.Id.ToString());

            if (!isReadonly)
            {
                rateit.MergeAttribute("data-url-save", urlSave);
            }

            var count = new TagBuilder("span");

            count.AddCssClass("rating-count badge");

            count.InnerHtml = ratingCount.ToString();

            if (panel)
            {
                container.AddCssClass("content-panel panel panel-default");

                var heading = new TagBuilder("div");

                heading.AddCssClass("panel-heading");

                var title = new TagBuilder("h4");

                var icon = new TagBuilder("span");

                icon.AddCssClass("fa fa-star-o");

                icon.MergeAttribute("aria-hidden", "true");

                title.InnerHtml += icon.ToString();

                if (string.IsNullOrWhiteSpace(panelTitleSnippetName))
                {
                    panelTitleSnippetName = "Rating Heading";
                }

                var snippet = html.TextSnippet(panelTitleSnippetName, true, "span",
                                               defaultValue: ResourceManager.GetString("Rate_This_Defaulttext"));

                title.InnerHtml += snippet;

                heading.InnerHtml += title;

                var body = new TagBuilder("div");

                body.AddCssClass("panel-body");

                body.InnerHtml += rateit.ToString();

                body.InnerHtml += count.ToString();

                container.InnerHtml += heading.ToString();

                container.InnerHtml += body.ToString();
            }
            else
            {
                container.InnerHtml += rateit.ToString();

                container.InnerHtml += count.ToString();
            }

            return(new HtmlString(container.ToString()));
        }