Exemple #1
0
        /// <summary>
        /// Builds a strongly typed Page Model from a given DXA R2 Data Model.
        /// </summary>
        /// <param name="pageModel">The strongly typed Page Model to build. Is <c>null</c> for the first Page Model Builder in the pipeline.</param>
        /// <param name="pageModelData">The DXA R2 Data Model.</param>
        /// <param name="includePageRegions">Indicates whether Include Page Regions should be included.</param>
        /// <param name="localization">The context <see cref="Localization"/>.</param>
        public void BuildPageModel(ref PageModel pageModel, PageModelData pageModelData, bool includePageRegions, ILocalization localization)
        {
            using (new Tracer(pageModel, pageModelData, includePageRegions, localization))
            {
                if ((pageModel == null) || !pageModel.Regions.OfType <SmartTargetRegion>().Any())
                {
                    Log.Debug("No SmartTarget Regions on Page.");
                    return;
                }

                // "Upgrade" the PageModel to a SmartTargetPageModel, so we can store AllowDuplicates in the Page Model.
                SmartTargetPageModel smartTargetPageModel = new SmartTargetPageModel(pageModel)
                {
                    AllowDuplicates = GetAllowDuplicatesOnSamePage(pageModelData, localization),
                    NoCache         = true // Don't cache the Page Model, because its contents are dynamic.
                };
                pageModel = smartTargetPageModel;

                // Set SmartTargetRegionModel.MaxItem based on the Region Metadata
                foreach (SmartTargetRegion smartTargetRegion in pageModel.Regions.OfType <SmartTargetRegion>())
                {
                    string          regionName      = smartTargetRegion.Name;
                    RegionModelData regionModelData = pageModelData.Regions.First(r => r.Name == regionName);

                    int maxItems = 100; // Default
                    if ((regionModelData.Metadata != null) && regionModelData.Metadata.ContainsKey("maxItems"))
                    {
                        maxItems = GetInt(regionModelData.Metadata["maxItems"]);
                    }
                    smartTargetRegion.MaxItems = maxItems;
                }

                PopulateSmartTargetRegions(smartTargetPageModel, localization);
            }
        }
Exemple #2
0
        /// <summary>
        /// Post-processes the Page Model constructed by the <see cref="DefaultModelBuilder"/>.
        /// </summary>
        /// <remarks>
        /// This implementation relies on the <see cref="DefaultModelBuilder"/> already having constructed Region Models of type <see cref="SmartTargetRegion"/>.
        /// We "upgrade" the Page Model to type <see cref="SmartTargetPageModel"/> and populate the ST Regions <see cref="SmartTargetPromotion"/> Entities.
        /// </remarks>
        public void BuildPageModel(ref PageModel pageModel, IPage page, IEnumerable <IPage> includes, ILocalization localization)
        {
            using (new Tracer(pageModel, page, includes, localization))
            {
                if ((pageModel == null) || !pageModel.Regions.OfType <SmartTargetRegion>().Any())
                {
                    Log.Debug("No SmartTarget Regions on Page.");
                    return;
                }

                if ((page?.PageTemplate?.MetadataFields == null) || !page.PageTemplate.MetadataFields.ContainsKey("regions"))
                {
                    Log.Debug("No Regions metadata found.");
                    return;
                }

                // "Upgrade" the PageModel to a SmartTargetPageModel, so we can store AllowDuplicates in the Page Model.
                SmartTargetPageModel smartTargetPageModel = new SmartTargetPageModel(pageModel)
                {
                    AllowDuplicates = GetAllowDuplicatesOnSamePage(page.PageTemplate, localization),
                    NoCache         = true // Don't cache the Page Model, because its contents are dynamic.
                };
                pageModel = smartTargetPageModel;

                // Set SmartTargetRegionModel.MaxItem based on the Region Metadata in the Page Template.
                foreach (IFieldSet smartTargetRegionField in page.PageTemplate.MetadataFields["regions"].EmbeddedValues)
                {
                    string regionName;
                    IField regionNameField;
                    if (smartTargetRegionField.TryGetValue("name", out regionNameField) && !string.IsNullOrEmpty(regionNameField.Value))
                    {
                        regionName = regionNameField.Value;
                    }
                    else
                    {
                        regionName = new MvcData(smartTargetRegionField["view"].Value).ViewName;
                    }

                    SmartTargetRegion smartTargetRegion = smartTargetPageModel.Regions[regionName] as SmartTargetRegion;
                    if (smartTargetRegion != null)
                    {
                        int    maxItems = 100; // Default
                        IField maxItemsField;
                        if (smartTargetRegionField.TryGetValue("maxItems", out maxItemsField))
                        {
                            maxItems = Convert.ToInt32(maxItemsField.NumericValues[0]);
                        }
                        smartTargetRegion.MaxItems = maxItems;
                    }
                }

                PopulateSmartTargetRegions(smartTargetPageModel, localization);
            }
        }
        private static ResultSet ExecuteSmartTargetQuery(SmartTargetPageModel smartTargetPageModel, Localization localization)
        {
            using (new Tracer(smartTargetPageModel, localization))
            {
                TcmUri pageUri        = new TcmUri(String.Format("tcm:{0}-{1}-64", localization.LocalizationId, smartTargetPageModel.Id));
                TcmUri publicationUri = new TcmUri(0, pageUri.PublicationId, 1);

                ClaimStore claimStore = AmbientDataContext.CurrentClaimStore;
                string     triggers   = AmbientDataHelper.GetTriggers(claimStore);

                QueryBuilder queryBuilder = new QueryBuilder();
                queryBuilder.Parse(triggers);
                queryBuilder.AddCriteria(new PublicationCriteria(publicationUri));
                queryBuilder.AddCriteria(new PageCriteria(pageUri));

                // Adding all the page regions to the query for having only 1 query a page
                foreach (SmartTargetRegion region in smartTargetPageModel.Regions.OfType <SmartTargetRegion>())
                {
                    queryBuilder.AddCriteria(new RegionCriteria(region.Name));
                }

                return(queryBuilder.Execute());
            }
        }
        /// <summary>
        /// Post-processes the Page Model constructed by the <see cref="DefaultModelBuilder"/>.
        /// </summary>
        /// <remarks>
        /// This implementation relies on the <see cref="DefaultModelBuilder"/> already having constructed Region Models of type <see cref="SmartTargetRegion"/>.
        /// We "upgrade" the Page Model to type <see cref="SmartTargetPageModel"/> and populate the ST Regions <see cref="SmartTargetPromotion"/> Entities.
        /// </remarks>
        public void BuildPageModel(ref PageModel pageModel, IPage page, IEnumerable <IPage> includes, Localization localization)
        {
            using (new Tracer(pageModel, page, includes, localization))
            {
                if (pageModel == null || !pageModel.Regions.OfType <SmartTargetRegion>().Any())
                {
                    Log.Debug("No SmartTarget Regions on Page.");
                    return;
                }

                if (page == null || page.PageTemplate == null || page.PageTemplate.MetadataFields == null || !page.PageTemplate.MetadataFields.ContainsKey("regions"))
                {
                    Log.Debug("No Regions metadata found.");
                    return;
                }

                // "Upgrade" the PageModel to a SmartTargetPageModel, so we can store AllowDuplicates in the Page Model.
                SmartTargetPageModel smartTargetPageModel = new SmartTargetPageModel(pageModel)
                {
                    AllowDuplicates = GetAllowDuplicatesOnSamePage(page.PageTemplate, localization)
                };
                pageModel = smartTargetPageModel;

                // Set SmartTargetRegionModel.MaxItem based on the Region Metadata in the Page Template.
                foreach (IFieldSet smartTargetRegionField in page.PageTemplate.MetadataFields["regions"].EmbeddedValues)
                {
                    string regionName;
                    IField regionNameField;
                    if (smartTargetRegionField.TryGetValue("name", out regionNameField) && !String.IsNullOrEmpty(regionNameField.Value))
                    {
                        regionName = regionNameField.Value;
                    }
                    else
                    {
                        regionName = new MvcData(smartTargetRegionField["view"].Value).ViewName;
                    }

                    SmartTargetRegion smartTargetRegion = smartTargetPageModel.Regions[regionName] as SmartTargetRegion;
                    if (smartTargetRegion != null)
                    {
                        int maxItems = smartTargetRegionField.ContainsKey("maxItems") ? Convert.ToInt32(smartTargetRegionField["maxItems"].Value) : 100;
                        smartTargetRegion.MaxItems = maxItems;
                    }
                }

                // Execute a ST Query for all SmartTargetRegions on the Page.
                ResultSet resultSet = ExecuteSmartTargetQuery(smartTargetPageModel, localization);
                Log.Debug("SmartTarget query returned {0} Promotions.", resultSet.Promotions.Count);

                string promotionViewName = localization.GetConfigValue(PromotionViewNameConfig);
                if (String.IsNullOrEmpty(promotionViewName))
                {
                    Log.Warn("No View name for SmartTarget Promotions is configured on CM-side ({0})", PromotionViewNameConfig);
                    promotionViewName = "SmartTarget:Entity:Promotion";
                }
                Log.Debug("Using Promotion View '{0}'", promotionViewName);

                List <string>     itemsAlreadyOnPage        = new List <string>();
                ExperimentCookies existingExperimentCookies = CookieProcessor.GetExperimentCookies(HttpContext.Current.Request); // TODO: we shouldn't access HttpContext in a Model Builder.

                // Filter the Promotions for each SmartTargetRegion
                foreach (SmartTargetRegion smartTargetRegion in smartTargetPageModel.Regions.OfType <SmartTargetRegion>())
                {
                    string regionName = smartTargetRegion.Name;

                    List <string>        itemsOutputInRegion  = new List <string>();
                    ExperimentCookies    newExperimentCookies = new ExperimentCookies();
                    ExperimentDimensions experimentDimensions;

                    List <Promotion> promotions = new List <Promotion>(resultSet.Promotions);
                    ResultSet.FilterPromotions(promotions, regionName, smartTargetRegion.MaxItems, smartTargetPageModel.AllowDuplicates, itemsOutputInRegion,
                                               itemsAlreadyOnPage, ref existingExperimentCookies, ref newExperimentCookies,
                                               out experimentDimensions);

                    if (localization.IsStaging)
                    {
                        // The SmartTarget API provides the entire XPM markup tag; put it in XpmMetadata["Query"]. See SmartTargetRegion.GetStartQueryXpmMarkup.
                        smartTargetRegion.XpmMetadata = new Dictionary <string, object>
                        {
                            { "Query", ResultSet.GetExperienceManagerMarkup(smartTargetRegion.Name, smartTargetRegion.MaxItems, promotions) }
                        };
                    }

                    // Create SmartTargetPromotion Entity Models for visible Promotions in the current SmartTargetRegion.
                    // It seems that ResultSet.FilterPromotions doesn't really filter on Region name, so we do post-filtering here.
                    foreach (Promotion promotion in promotions.Where(promotion => promotion.Visible && promotion.Region.Contains(regionName)))
                    {
                        SmartTargetPromotion smartTargetPromotion = CreatePromotionEntity(promotion, promotionViewName, smartTargetRegion.Name, localization);

                        if (!smartTargetRegion.HasSmartTargetContent)
                        {
                            // Discard any fallback content coming from Content Manager
                            smartTargetRegion.Entities.Clear();
                            smartTargetRegion.HasSmartTargetContent = true;
                        }

                        smartTargetRegion.Entities.Add(smartTargetPromotion);
                    }
                }
            }
        }
Exemple #5
0
        private void PopulateSmartTargetRegions(SmartTargetPageModel smartTargetPageModel, ILocalization localization)
        {
            // Execute a ST Query for all SmartTargetRegions on the Page.
            ResultSet resultSet = ExecuteSmartTargetQuery(smartTargetPageModel, localization);

            Log.Debug($"SmartTarget query returned {resultSet.Promotions.Count} Promotions.");

            string promotionViewName = localization.GetConfigValue(PromotionViewNameConfig);

            if (String.IsNullOrEmpty(promotionViewName))
            {
                Log.Warn($"No View name for SmartTarget Promotions is configured on CM-side ({PromotionViewNameConfig})");
                promotionViewName = "SmartTarget:Entity:Promotion";
            }
            Log.Debug($"Using Promotion View '{promotionViewName}'");

            // TODO: we shouldn't access HttpContext in a Model Builder.
            HttpContext httpContext = HttpContext.Current;

            if (httpContext == null)
            {
                throw new DxaException("HttpContext is not available.");
            }

            List <string>     itemsAlreadyOnPage        = new List <string>();
            ExperimentCookies existingExperimentCookies = CookieProcessor.GetExperimentCookies(httpContext.Request);
            ExperimentCookies newExperimentCookies      = new ExperimentCookies();

            // Filter the Promotions for each SmartTargetRegion
            foreach (SmartTargetRegion smartTargetRegion in smartTargetPageModel.Regions.OfType <SmartTargetRegion>())
            {
                string regionName = smartTargetRegion.Name;

                List <string>        itemsOutputInRegion = new List <string>();
                ExperimentDimensions experimentDimensions;
                List <Promotion>     promotions = new List <Promotion>(resultSet.Promotions);
                ResultSet.FilterPromotions(promotions, regionName, smartTargetRegion.MaxItems, smartTargetPageModel.AllowDuplicates, itemsOutputInRegion,
                                           itemsAlreadyOnPage, ref existingExperimentCookies, ref newExperimentCookies,
                                           out experimentDimensions);

                if (experimentDimensions != null)
                {
                    // The SmartTarget API doesn't set all ExperimentDimensions properties, but they are required by the ExperimentTrackingHandler (see CRQ-1667).
                    experimentDimensions.PublicationId = localization.GetCmUri();
                    experimentDimensions.PageId        = localization.GetCmUri(smartTargetPageModel.Id, (int)ItemType.Page);
                    experimentDimensions.Region        = smartTargetRegion.Name;
                }

                if (localization.IsXpmEnabled)
                {
                    // The SmartTarget API provides the entire XPM markup tag; put it in XpmMetadata["Query"]. See SmartTargetRegion.GetStartQueryXpmMarkup.
                    smartTargetRegion.XpmMetadata = new Dictionary <string, object>
                    {
                        { "Query", ResultSet.GetExperienceManagerMarkup(smartTargetRegion.Name, smartTargetRegion.MaxItems, promotions) }
                    };
                }

                // Create SmartTargetPromotion Entity Models for visible Promotions in the current SmartTargetRegion.
                // It seems that ResultSet.FilterPromotions doesn't really filter on Region name, so we do post-filtering here.
                foreach (Promotion promotion in promotions.Where(promotion => promotion.Visible && promotion.Regions.Contains(regionName)))
                {
                    SmartTargetPromotion smartTargetPromotion = CreatePromotionEntity(promotion, promotionViewName, smartTargetRegion.Name, localization, experimentDimensions);

                    if (!smartTargetRegion.HasSmartTargetContent)
                    {
                        // Discard any fallback content coming from Content Manager
                        smartTargetRegion.Entities.Clear();
                        smartTargetRegion.HasSmartTargetContent = true;
                    }

                    smartTargetRegion.Entities.Add(smartTargetPromotion);
                }
            }

            if (newExperimentCookies.Count > 0)
            {
                smartTargetPageModel.ExperimentCookies = newExperimentCookies;
            }
        }