protected virtual string GetSearchIndexUrl(Localization localization) { // First try the new search.queryURL setting provided by DXA 1.3 TBBs if the Search Query URL can be obtained from Topology Manager. string result = localization.GetConfigValue("search.queryURL"); if (string.IsNullOrEmpty(result)) { result = localization.GetConfigValue("search." + (localization.IsStaging ? "staging" : "live") + "IndexConfig"); } return result; }
/// <summary> /// Gets the rendered XPM markup /// </summary> /// <param name="localization">The context Localization.</param> /// <returns>The XPM markup.</returns> public override string GetXpmMarkup(Localization localization) { if (XpmMetadata == null) { return string.Empty; } string cmsUrl; object cmsUrlValue; if (XpmMetadata.TryGetValue("CmsUrl", out cmsUrlValue)) { cmsUrl = (string) cmsUrlValue; } else { cmsUrl = localization.GetConfigValue("core.cmsurl"); } if (cmsUrl.EndsWith("/")) { // remove trailing slash from cmsUrl if present cmsUrl = cmsUrl.Remove(cmsUrl.Length - 1); } return string.Format( _xpmPageSettingsMarkup, XpmMetadata["PageID"], XpmMetadata["PageModified"], XpmMetadata["PageTemplateID"], XpmMetadata["PageTemplateModified"] ) + string.Format(_xpmPageScript, cmsUrl); }
/// <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), 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; } } // 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); // 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 = string.Format("tcm:0-{0}-1", localization.LocalizationId); experimentDimensions.PageId = string.Format("tcm:{0}-{1}-64", localization.LocalizationId, smartTargetPageModel.Id); experimentDimensions.Region = smartTargetRegion.Name; } 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.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; } } }
/// <summary> /// Determines whether duplicate ST Items are allowed on this page. /// </summary> private static bool GetAllowDuplicatesOnSamePage(IPageTemplate pageTemplate, Localization localization) { const string allowDuplicatesFieldName = "allowDuplicationOnSamePage"; const string allowDuplicatesConfig = "smarttarget.allowDuplicationOnSamePageConfig"; string allowDuplicates = null; if (pageTemplate != null && pageTemplate.MetadataFields != null && pageTemplate.MetadataFields.ContainsKey(allowDuplicatesFieldName)) { allowDuplicates = pageTemplate.MetadataFields[allowDuplicatesFieldName].Value; } if (String.IsNullOrEmpty(allowDuplicates) || allowDuplicates.Equals("Use core configuration", StringComparison.OrdinalIgnoreCase)) { allowDuplicates = localization.GetConfigValue(allowDuplicatesConfig); if (String.IsNullOrEmpty(allowDuplicates)) { allowDuplicates = "true"; } } return Convert.ToBoolean(allowDuplicates); }
protected virtual string GetSearchIndexUrl(Localization localization) { return localization.GetConfigValue("search." + (localization.IsStaging ? "staging" : "live") + "IndexConfig"); }