/// <summary>
        /// Determines if the content item should be shown to the current site visitor, based on the personalisation groups associated with it.
        /// </summary>
        /// <param name="pickedGroups">List of IPublishedContent items that are the groups you want to check against.</param>
        /// <param name="showIfNoGroupsDefined">Indicates the response to return if groups cannot be found on the content</param>
        /// <returns>True if content should be shown to visitor</returns>
        private static bool ShowToVisitor(IList <IPublishedContent> pickedGroups, bool showIfNoGroupsDefined = true)
        {
            if (!pickedGroups.Any())
            {
                // No personalisation groups picked or no property for picker, so we return the provided default
                return(showIfNoGroupsDefined);
            }

            // Check each personalisation group assigned for a match with the current site visitor
            foreach (var group in pickedGroups)
            {
                var definition = group.GetPropertyValue <PersonalisationGroupDefinition>(AppConstants.PersonalisationGroupDefinitionPropertyAlias);
                if (IsStickyMatch(definition, group.Id))
                {
                    return(true);
                }

                var matchCount = PersonalisationGroupMatcher.CountMatchingDefinitionDetails(definition);

                // If matching any and matched at least one, or matching all and matched all - we've matched one of the definitions
                // associated with a selected personalisation group
                if ((definition.Match == PersonalisationGroupDefinitionMatch.Any && matchCount > 0) ||
                    (definition.Match == PersonalisationGroupDefinitionMatch.All && matchCount == definition.Details.Count()))
                {
                    MakeStickyMatch(definition, group.Id);
                    return(true);
                }
            }

            // If we've got here, we haven't found a match
            return(false);
        }
コード例 #2
0
        internal static int ScoreGroups(IList <IPublishedContent> pickedGroups)
        {
            // Package is disabled, return default
            if (PersonalisationGroupsConfig.Value.DisablePackage)
            {
                return(0);
            }

            // Check each personalisation group assigned for a match with the current site visitor
            var score = 0;

            foreach (var group in pickedGroups)
            {
                var definition = group.GetPropertyValue <PersonalisationGroupDefinition>(AppConstants.PersonalisationGroupDefinitionPropertyAlias);
                if (GroupMatchingHelper.IsStickyMatch(definition, group.Id))
                {
                    score += definition.Score;
                    continue;
                }

                var matchCount = PersonalisationGroupMatcher.CountMatchingDefinitionDetails(definition);

                // If matching any and matched at least one, or matching all and matched all - we've matched one of the definitions
                // associated with a selected personalisation group
                if ((definition.Match == PersonalisationGroupDefinitionMatch.Any && matchCount > 0) ||
                    (definition.Match == PersonalisationGroupDefinitionMatch.All && matchCount == definition.Details.Count()))
                {
                    GroupMatchingHelper.MakeStickyMatch(definition, group.Id);
                    score += definition.Score;
                }
            }

            return(score);
        }
        /// <summary>
        /// Scores the content item for the current site visitor, based on the personalisation groups associated with it.
        /// </summary>
        /// <param name="pickedGroups">List of IPublishedContent items that are the groups you want to check against.</param>
        /// <returns>True if content should be shown to visitor</returns>
        private static int ScoreForVisitor(IList <IPublishedContent> pickedGroups)
        {
            if (!pickedGroups.Any())
            {
                // No personalisation groups picked or no property for picker, so we score zero
                return(0);
            }

            // Check each personalisation group assigned for a match with the current site visitor
            var score = 0;

            foreach (var group in pickedGroups)
            {
                var definition = group.GetPropertyValue <PersonalisationGroupDefinition>(AppConstants.PersonalisationGroupDefinitionPropertyAlias);
                if (IsStickyMatch(definition, group.Id))
                {
                    score += definition.Score;
                }

                var matchCount = PersonalisationGroupMatcher.CountMatchingDefinitionDetails(definition);

                // If matching any and matched at least one, or matching all and matched all - we've matched one of the definitions
                // associated with a selected personalisation group
                if ((definition.Match == PersonalisationGroupDefinitionMatch.Any && matchCount > 0) ||
                    (definition.Match == PersonalisationGroupDefinitionMatch.All && matchCount == definition.Details.Count()))
                {
                    MakeStickyMatch(definition, group.Id);
                    score += definition.Score;
                }
            }

            return(score);
        }
コード例 #4
0
        /// <summary>
        /// Adapted IsMatch from https://github.com/AndyButland/UmbracoPersonalisationGroups/blob/master/Zone.UmbracoPersonalisationGroups/ExtensionMethods/PublishedContentExtensions.cs
        /// </summary>
        public bool VisitorInSegment(string segmentKey)
        {
            var helper  = new UmbracoHelper(UmbracoContext.Current);
            var segment = helper.TypedContent(segmentKey);

            if (segment == null)
            {
                return(false); //something went wrong, we didn't find the segment!
            }

            var definition = segment.GetPropertyValue <PersonalisationGroupDefinition>(AppConstants.PersonalisationGroupDefinitionPropertyAlias);

            if (IsStickyMatch(definition, segment.Id))
            {
                return(true);
            }

            var matchCount = PersonalisationGroupMatcher.CountMatchingDefinitionDetails(definition);

            // If matching any and matched at least one, or matching all and matched all - we've matched one of the definitions
            // associated with a selected personalisation group
            if ((definition.Match == PersonalisationGroupDefinitionMatch.Any && matchCount > 0) ||
                (definition.Match == PersonalisationGroupDefinitionMatch.All && matchCount == definition.Details.Count()))
            {
                MakeStickyMatch(definition, segment.Id);
                return(true);
            }


            // If we've got here, we haven't found a match
            return(false);
        }
コード例 #5
0
        internal static bool MatchGroups(IList <IPublishedContent> pickedGroups)
        {
            // Package is disabled, return default
            if (UmbracoConfig.For.PersonalisationGroups().DisablePackage)
            {
                return(true);
            }

            // Check each personalisation group assigned for a match with the current site visitor
            foreach (var group in pickedGroups)
            {
                var definition = group.GetPropertyValue <PersonalisationGroupDefinition>(AppConstants.PersonalisationGroupDefinitionPropertyAlias);
                if (IsStickyMatch(definition, group.Id))
                {
                    return(true);
                }

                var matchCount = PersonalisationGroupMatcher.CountMatchingDefinitionDetails(definition);

                // If matching any and matched at least one, or matching all and matched all - we've matched one of the definitions
                // associated with a selected personalisation group
                if ((definition.Match == PersonalisationGroupDefinitionMatch.Any && matchCount > 0) ||
                    (definition.Match == PersonalisationGroupDefinitionMatch.All && matchCount == definition.Details.Count()))
                {
                    MakeStickyMatch(definition, group.Id);
                    return(true);
                }
            }

            // If we've got here, we haven't found a match
            return(false);
        }
コード例 #6
0
        /// <summary>
        /// When overridden in a derived class, returns a read-only stream to the virtual resource.
        /// </summary>
        /// <returns>
        /// A read-only stream to the virtual file.
        /// </returns>
        public Stream Open()
        {
            string resourceName;

            // Get this assembly.
            Assembly assembly = typeof(ResourceController).Assembly;
            Stream   output   = EmbeddedResourceHelper.GetResource(assembly, this.virtualPath, out resourceName);

            if (output == null)
            {
                // We need to loop through the loaded criteria and check each one.
                Assembly localAssembly = assembly;
                IEnumerable <IPersonalisationGroupCriteria> criteria =
                    PersonalisationGroupMatcher
                    .GetAvailableCriteria().Where(a => a.GetType().Assembly != localAssembly);

                foreach (IPersonalisationGroupCriteria criterion in criteria)
                {
                    string resource = EmbeddedResourceHelper.SanitizeCriteriaResourceName(this.virtualPath);

                    assembly     = criterion.GetType().Assembly;
                    resourceName = assembly.GetManifestResourceNames().FirstOrDefault(r => r.InvariantEndsWith(resource));

                    if (!string.IsNullOrWhiteSpace(resourceName))
                    {
                        return(EmbeddedResourceHelper.GetResource(assembly, resource, out resourceName));
                    }
                }
            }

            return(output);
        }
コード例 #7
0
        /// <summary>
        /// Adds an extension method to UmbracoHelper to calculate a hash for the current visitor for all visitor groups
        /// </summary>
        /// <param name="helper">Instance of UmbracoHelper</param>
        /// <param name="personalisationGroupsRootNode">Root node for the personalisation groups</param>
        /// <param name="cacheUserIdentifier">Identifier for the user to use in the cache key (likely the session Id)</param>
        /// <param name="cacheForSeconds">Length of time in seconds to cache the generated personalisation group hash for the visitor</param>
        /// <returns>Has for the visitor for all groups</returns>
        public static string GetPersonalisationGroupsHashForVisitor(this UmbracoHelper helper, IPublishedContent personalisationGroupsRootNode,
                                                                    string cacheUserIdentifier, int cacheForSeconds)
        {
            Mandate.ParameterNotNull(personalisationGroupsRootNode, "personalisationGroupsRootNode");

            var cacheKey = $"{cacheUserIdentifier}-{AppConstants.CacheKeys.PersonalisationGroupsVisitorHash}";

            return((string)UmbracoContext.Current.Application.ApplicationCache.RuntimeCache
                   .GetCacheItem(cacheKey,
                                 () =>
            {
                var groups = personalisationGroupsRootNode.Descendants(AppConstants.DocumentTypeAliases.PersonalisationGroup);
                var sb = new StringBuilder();
                foreach (var group in groups)
                {
                    var definition = group.GetPropertyValue <PersonalisationGroupDefinition>(AppConstants.PersonalisationGroupDefinitionPropertyAlias);
                    var matchCount = PersonalisationGroupMatcher.CountMatchingDefinitionDetails(definition);
                    var matched = ((definition.Match == PersonalisationGroupDefinitionMatch.Any && matchCount > 0) ||
                                   (definition.Match == PersonalisationGroupDefinitionMatch.All && matchCount == definition.Details.Count()));

                    if (sb.Length > 0)
                    {
                        sb.Append(",");
                    }

                    sb.AppendFormat("{0}={1}", group.Name, matched);
                }

                return sb.ToString().GetHashCode().ToString();
            }, timeout: TimeSpan.FromSeconds(cacheForSeconds)));
        }
        public void PersonalisationGroupMatcher_IsMatch_WithMatchingCriteria_ReturnsTrue()
        {
            // Arrange
            var definitionDetail = TestHelpers.Definitions.MatchingDayOfWeekDefinition();

            // Act
            var result = PersonalisationGroupMatcher.IsMatch(definitionDetail);

            // Arrange
            Assert.IsTrue(result);
        }
        public void PersonalisationGroupMatcher_IsMatch_WithMissingCritieria_ThrowsException()
        {
            // Arrange
            var definitionDetail = new PersonalisationGroupDefinitionDetail
            {
                Alias      = "invalidAlias",
                Definition = string.Empty,
            };

            // Act
            PersonalisationGroupMatcher.IsMatch(definitionDetail);
        }
コード例 #10
0
        public static void AppendMatchedGroupDetailToVisitorHashString(StringBuilder sb, PersonalisationGroupDefinition definition, string name)
        {
            var matchCount = PersonalisationGroupMatcher.CountMatchingDefinitionDetails(definition);
            var matched    = (definition.Match == PersonalisationGroupDefinitionMatch.Any && matchCount > 0) ||
                             (definition.Match == PersonalisationGroupDefinitionMatch.All && matchCount == definition.Details.Count());

            if (sb.Length > 0)
            {
                sb.Append(",");
            }

            sb.AppendFormat("{0}={1}", name, matched);
        }
        /// <summary>
        /// Returns a value indicating whether the given resource exists.
        /// </summary>
        /// <param name="resource">The resource name.</param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public static bool ResourceExists(string resource)
        {
            // Sanitize the resource request.
            string resourceRoot = Constants.ResourceRoot;
            string criteriaRoot = Constants.ResourceForCriteriaRoot;
            string extension    = Constants.ResourceExtension;

            if (resource.StartsWith(resourceRoot))
            {
                resource = resource.TrimStart(resourceRoot).Replace("/", ".").TrimEnd(extension);
            }
            else if (resource.StartsWith(criteriaRoot))
            {
                resource = resource.TrimStart(criteriaRoot).Replace("/", ".").TrimEnd(extension);
            }
            else if (resource.EndsWith(extension))
            {
                resource = resource.TrimEnd(extension);
            }

            // Check this assembly first.
            Assembly assembly = typeof(ResourceController).Assembly;

            // Find the resource name; not case sensitive.
            string resourceName = assembly.GetManifestResourceNames().FirstOrDefault(r => r.InvariantEndsWith(resource));

            if (string.IsNullOrWhiteSpace(resourceName))
            {
                // We need to loop through the loaded criteria and check each one.
                Assembly localAssembly = assembly;
                IEnumerable <IPersonalisationGroupCriteria> criteria =
                    PersonalisationGroupMatcher
                    .GetAvailableCriteria().Where(a => a.GetType().Assembly != localAssembly);

                foreach (IPersonalisationGroupCriteria criterion in criteria)
                {
                    assembly     = criterion.GetType().Assembly;
                    resourceName = assembly.GetManifestResourceNames().FirstOrDefault(r => r.InvariantEndsWith(resource));

                    if (!string.IsNullOrWhiteSpace(resourceName))
                    {
                        return(true);
                    }
                }
            }

            return(!string.IsNullOrWhiteSpace(resourceName));
        }
        public void PersonalisationGroupMatcher_IsMatch_WithMatchingCriteria_ReturnsTrue()
        {
            // Arrange
            var definitionDetail = new PersonalisationGroupDefinitionDetail
            {
                Alias      = "dayOfWeek",
                Definition = string.Format("[ {0} ]",
                                           (int)(DateTime.Now.DayOfWeek) + 1),
            };

            // Act
            var result = PersonalisationGroupMatcher.IsMatch(definitionDetail);

            // Arrange
            Assert.IsTrue(result);
        }
        public void PersonalisationGroupMatcher_CountMatchingDefinitionDetails_WithDefinitonForMatchAll_AndMatchesAll_ReturnsCount()
        {
            // Arrange
            var definition = new PersonalisationGroupDefinition
            {
                Match   = PersonalisationGroupDefinitionMatch.All,
                Details = new List <PersonalisationGroupDefinitionDetail>
                {
                    TestHelpers.Definitions.MatchingDayOfWeekDefinition(),
                TestHelpers.Definitions.MatchingTimeOfDayDefinition(),
                }
            };

            // Act
            var result = PersonalisationGroupMatcher.CountMatchingDefinitionDetails(definition);

            // Assert
            Assert.AreEqual(2, result);
        }
        public void PersonalisationGroupMatcher_CountMatchingDefinitionDetails_WithDefinitonForMatchAny_AndMatchingFirst_ReturnsShortCutCount()
        {
            // Arrange
            var definition = new PersonalisationGroupDefinition
            {
                Match   = PersonalisationGroupDefinitionMatch.All,
                Details = new List <PersonalisationGroupDefinitionDetail>
                {
                    Definitions.MatchingDayOfWeekDefinition(),
                Definitions.NonMatchingDayOfWeekDefinition(),
                Definitions.MatchingTimeOfDayDefinition(),
                }
            };

            // Act
            var result = PersonalisationGroupMatcher.CountMatchingDefinitionDetails(definition);

            // Assert
            Assert.AreEqual(1, result);
        }
コード例 #15
0
        /// <summary>
        /// Gets an embedded resource for a given criteria, that may be from the main assembly or another one
        /// </summary>
        /// <param name="criteriaAlias">Alias of criteria</param>
        /// <param name="fileName">Name of resource</param>
        /// <returns>File stream of resource</returns>
        public ActionResult GetResourceForCriteria(string criteriaAlias, string fileName)
        {
            Mandate.ParameterNotNullOrEmpty(criteriaAlias, "criteriaAlias");
            Mandate.ParameterNotNullOrEmpty(fileName, "fileName");

            var criteria = PersonalisationGroupMatcher.GetAvailableCriteria()
                           .SingleOrDefault(x => x.Alias.InvariantEquals(criteriaAlias));

            if (criteria != null)
            {
                string resourceName;
                var    resourceStream = EmbeddedResourceHelper.GetResource(criteria.GetType().Assembly, criteriaAlias + "." + fileName, out resourceName);

                if (resourceStream != null)
                {
                    return(new FileStreamResult(resourceStream, GetMimeType(resourceName)));
                }
            }

            return(HttpNotFound());
        }
        /// <summary>
        /// Gets a count of the number of the definition details for a given personalisation group definition that matches
        /// the current site visitor
        /// </summary>
        /// <param name="definition">Personalisation group definition</param>
        /// <returns>Number of definition details that match</returns>
        private static int CountMatchingDefinitionDetails(PersonalisationGroupDefinition definition)
        {
            var matchCount = 0;

            foreach (var detail in definition.Details)
            {
                var isMatch = PersonalisationGroupMatcher.IsMatch(detail);
                if (isMatch)
                {
                    matchCount++;
                }

                // We can short-cut here if matching any and found one match, or matching all and found one mismatch
                if ((isMatch && definition.Match == PersonalisationGroupDefinitionMatch.Any) ||
                    (!isMatch && definition.Match == PersonalisationGroupDefinitionMatch.All))
                {
                    break;
                }
            }

            return(matchCount);
        }
コード例 #17
0
        /// <summary>
        /// Gets a JSON list of the available criteria
        /// </summary>
        /// <returns>JSON response of available criteria</returns>
        /// <remarks>Using ContentResult so can serialize with camel case for consistency in client-side code</remarks>
        public ContentResult Index()
        {
            var criteria = PersonalisationGroupMatcher.GetAvailableCriteria();

            return(CamelCasedJsonResult(criteria));
        }