Beispiel #1
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);
            }
        }
Beispiel #2
0
 /// <summary>
 /// Ensures that the Component Fields of DCPs on the Page are populated.
 /// </summary>
 private static void FullyLoadDynamicComponentPresentations(IPage page, Localization localization)
 {
     using (new Tracer(page, localization))
     {
         foreach (ComponentPresentation dcp in page.ComponentPresentations.Where(cp => cp.IsDynamic).OfType <ComponentPresentation>())
         {
             IComponentFactory componentFactory = DD4TFactoryCache.GetComponentFactory(localization);
             dcp.Component = (Component)componentFactory.GetComponent(dcp.Component.Id, dcp.ComponentTemplate.Id);
         }
     }
 }
Beispiel #3
0
 /// <summary>
 /// Creates a Strongly Typed Page Model for a given DD4T Page and an optional set of include Pages.
 /// </summary>
 /// <param name="page">The DD4T Page object.</param>
 /// <param name="includes">The set of DD4T Page object for include pages. Can be <c>null</c>.</param>
 /// <param name="localization">The context <see cref="Localization"/>.</param>
 /// <returns>The Strongly Typed Page Model (an instance of class <see cref="PageModel"/> or a subclass).</returns>
 public static PageModel CreatePageModel(IPage page, IPage[] includes, Localization localization)
 {
     using (new Tracer(page, includes, localization))
     {
         PageModel pageModel = null;
         foreach (IModelBuilder modelBuilder in ModelBuilders)
         {
             modelBuilder.BuildPageModel(ref pageModel, page, includes, localization);
         }
         return(pageModel);
     }
 }
Beispiel #4
0
 protected virtual IEnumerable <IPage> GetIncludesFromModel(IPage page, Localization localization)
 {
     using (new Tracer(page.Id, localization))
     {
         List <IPage>         result = new List <IPage>();
         string[]             pageTemplateTcmUriParts = page.PageTemplate.Id.Split('-');
         IEnumerable <string> includePageUrls         = localization.GetIncludePageUrls(pageTemplateTcmUriParts[1]);
         foreach (string includePageUrl in includePageUrls)
         {
             IPage includePage = GetPage(localization.GetAbsoluteUrlPath(includePageUrl), localization);
             if (includePage == null)
             {
                 Log.Error("Include Page '{0}' not found.", includePageUrl);
                 continue;
             }
             result.Add(includePage);
         }
         return(result);
     }
 }
Beispiel #5
0
        protected virtual IEnumerable <IPage> GetIncludesFromModel(IPage page, Localization localization)
        {
            List <IPage> result = new List <IPage>();

            string[]             pageTemplateTcmUriParts = page.PageTemplate.Id.Split('-');
            IEnumerable <string> includePageUrls         = SiteConfiguration.GetIncludePageUrls(pageTemplateTcmUriParts[1], localization);

            foreach (string includePageUrl in includePageUrls)
            {
                IPage includePage = GetPage(SiteConfiguration.LocalizeUrl(includePageUrl, localization), localization);
                if (includePage == null)
                {
                    Log.Error("Include Page '{0}' not found.", includePageUrl);
                    continue;
                }
                FullyLoadDynamicComponentPresentations(includePage, localization);
                result.Add(includePage);
            }
            return(result);
        }
Beispiel #6
0
#pragma warning restore 618


        /// <summary>
        /// Gets a Page Model for a given URL.
        /// </summary>
        /// <param name="url">The URL.</param>
        /// <param name="localization">The context Localization.</param>
        /// <param name="addIncludes">Indicates whether include Pages should be expanded.</param>
        /// <returns>The Page Model.</returns>
        /// <exception cref="DxaItemNotFoundException">If no Page Model exists for the given URL.</exception>
        public virtual PageModel GetPageModel(string url, Localization localization, bool addIncludes)
        {
            using (new Tracer(url, localization, addIncludes))
            {
                //We can have a couple of tries to get the page model if there is no file extension on the url request, but it does not end in a slash:
                //1. Try adding the default extension, so /news becomes /news.html
                IPage page = GetPage(url, localization);
                if (page == null && (url == null || (!url.EndsWith("/") && url.LastIndexOf(".", StringComparison.Ordinal) <= url.LastIndexOf("/", StringComparison.Ordinal))))
                {
                    //2. Try adding the default page, so /news becomes /news/index.html
                    page = GetPage(url + "/", localization);
                }
                if (page == null)
                {
                    throw new DxaItemNotFoundException(url);
                }
                FullyLoadDynamicComponentPresentations(page, localization);

                IPage[] includes = addIncludes ? GetIncludesFromModel(page, localization).ToArray() : new IPage[0];

                return(ModelBuilderPipeline.CreatePageModel(page, includes, localization));
            }
        }
        /// <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>
        /// 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);
                    }
                }
            }
        }
        public virtual void BuildPageModel(ref PageModel pageModel, IPage page, IEnumerable<IPage> includes, Localization localization)
        {
            using (new Tracer(pageModel, page, includes, localization))
            {
                pageModel = CreatePageModel(page, localization);
                RegionModelSet regions = pageModel.Regions;

                // Create predefined Regions from Page Template Metadata
                CreatePredefinedRegions(regions, page.PageTemplate);

                // Create Regions/Entities from Component Presentations
                IConditionalEntityEvaluator conditionalEntityEvaluator = SiteConfiguration.ConditionalEntityEvaluator;
                foreach (IComponentPresentation cp in page.ComponentPresentations)
                {
                    MvcData cpRegionMvcData = GetRegionMvcData(cp);
                    RegionModel region;
                    if (regions.TryGetValue(cpRegionMvcData.ViewName, out region))
                    {
                        // Region already exists in Page Model; MVC data should match.
                        if (!region.MvcData.Equals(cpRegionMvcData))
                        {
                            Log.Warn("Region '{0}' is defined with conflicting MVC data: [{1}] and [{2}]. Using the former.", region.Name, region.MvcData, cpRegionMvcData);
                        }
                    }
                    else
                    {
                        // Region does not exist in Page Model yet; create Region Model and add it.
                        region = CreateRegionModel(cpRegionMvcData);
                        regions.Add(region);
                    }

                    EntityModel entity;
                    try
                    {
                        entity = ModelBuilderPipeline.CreateEntityModel(cp, localization);
                    }
                    catch (Exception ex)
                    {
                        //if there is a problem mapping the item, we replace it with an exception entity
                        //and carry on processing - this should not cause a failure in the rendering of
                        //the page as a whole
                        Log.Error(ex);
                        entity = new ExceptionEntity(ex)
                        {
                            MvcData = GetMvcData(cp) // TODO: The regular View won't expect an ExceptionEntity model. Should use an Exception View (?)
                        };
                    }

                    if (conditionalEntityEvaluator == null || conditionalEntityEvaluator.IncludeEntity(entity))
                    {
                        region.Entities.Add(entity);
                    }
                }

                // Create Regions from Include Pages
                if (includes != null)
                {
                    foreach (IPage includePage in includes)
                    {
                        PageModel includePageModel = ModelBuilderPipeline.CreatePageModel(includePage, null, localization);

                        // Model Include Page as Region:
                        RegionModel includePageRegion = GetRegionFromIncludePage(includePage);
                        RegionModel existingRegion;
                        if (regions.TryGetValue(includePageRegion.Name, out existingRegion))
                        {
                            // Region with same name already exists; merge include Page Region.
                            existingRegion.Regions.UnionWith(includePageModel.Regions);

                            if (existingRegion.XpmMetadata != null)
                            {
                                existingRegion.XpmMetadata.Remove(RegionModel.IncludedFromPageIdXpmMetadataKey);
                                existingRegion.XpmMetadata.Remove(RegionModel.IncludedFromPageTitleXpmMetadataKey);
                                existingRegion.XpmMetadata.Remove(RegionModel.IncludedFromPageFileNameXpmMetadataKey);
                            }

                            Log.Info("Merged Include Page [{0}] into Region [{1}]. Note that merged Regions can't be edited properly in XPM (yet).",
                                includePageModel, existingRegion);
                        }
                        else
                        {
                            includePageRegion.Regions.UnionWith(includePageModel.Regions);
                            regions.Add(includePageRegion);
                        }

            #pragma warning disable 618
                        // Legacy WebPage.Includes support:
                        pageModel.Includes.Add(includePage.Title, includePageModel);
            #pragma warning restore 618
                    }

                    if (pageModel.MvcData.ViewName != "IncludePage")
                    {
                        pageModel.Title = ProcessPageMetadata(page, pageModel.Meta, localization);
                    }
                }
            }
        }
Beispiel #10
0
 public void BuildPageModel(ref PageModel pageModel, IPage page, IEnumerable <IPage> includes, Localization localization)
 {
     // Nothing to do here
 }
 public void BuildPageModel(ref PageModel pageModel, IPage page, IEnumerable<IPage> includes, Localization localization)
 {
     // Nothing to do here
 }
Beispiel #12
0
        public void BuildPageModel(ref PageModel pageModel, DD4T.ContentModel.IPage page, IEnumerable <DD4T.ContentModel.IPage> includes, Localization localization)
        {
            var containers = new List <AbstractContainerModel>();

            // Get absolute order of the different container items
            //
            var regionAbsoluteOrder    = new Dictionary <string, IList <int> >();
            var containerAbsoluteOrder = new List <int>();
            int index = 0;

            foreach (var cp in page.ComponentPresentations)
            {
                if (cp.ComponentTemplate.MetadataFields.ContainsKey("regionName"))
                {
                    string      regionName = (string)cp.ComponentTemplate.MetadataFields["regionName"].Values[0];
                    IList <int> orderList  = null;
                    regionAbsoluteOrder.TryGetValue(regionName, out orderList);
                    if (orderList == null)
                    {
                        orderList = new List <int>();
                        regionAbsoluteOrder.Add(regionName, orderList);
                    }
                    orderList.Add(index);
                }
                else if (cp.ComponentTemplate.MetadataFields.ContainsKey("action"))
                {
                    string controllerAction = (string)cp.ComponentTemplate.MetadataFields["action"].Values[0];
                    if (controllerAction.Equals("Container"))
                    {
                        containerAbsoluteOrder.Add(index);
                    }
                }
                index++;
            }

            // Go through the entity list and extract all containers
            //
            index = 1;
            foreach (var region in pageModel.Regions)
            {
                // TODO: Remove container region from the top level? Otherwise XPM drop zones are generated for them as well?

                foreach (var entity in region.Entities)
                {
                    if (entity is AbstractContainerModel)
                    {
                        AbstractContainerModel container = (AbstractContainerModel)entity;

                        // Override region name using MVC route values
                        //
                        string containerRegionName = null;
                        container.MvcData.RouteValues.TryGetValue("containerRegion", out containerRegionName);
                        if (containerRegionName != null)
                        {
                            container.Name = containerRegionName;
                        }
                        // TODO: if no container region name -> should we skip this container then???
                        try
                        {
                            container.Region = new ContainerRegionModel(container);
                        }
                        catch (DxaException e)
                        {
                            throw new DxaException("Could not create empty region for container: " + container.Name, e);
                        }
                        container.Index = index;
                        index++;
                        containers.Add(container);
                    }
                }
            }

            // Move all container items to the containers (to avoid the container items to be rendered outside the container)
            //
            foreach (var container in containers)
            {
                if (containerAbsoluteOrder.Count == 0)
                {
                    break;
                }
                int containerIndex = containerAbsoluteOrder[0];
                containerAbsoluteOrder.RemoveAt(0);
                RegionModel regionWithContainerItems = null;
                pageModel.Regions.TryGetValue(container.Name, out regionWithContainerItems);
                if (regionWithContainerItems == null)
                {
                    // No container items found on the page -> continue
                    //
                    continue;
                }
                IList <int> orderList = null;
                regionAbsoluteOrder.TryGetValue(container.Name, out orderList);
                if (orderList != null && orderList.Count > 0)
                {
                    index = orderList[0];
                    if (containerIndex + 1 == index)
                    {
                        int noOfItems = 0;
                        foreach (var entity in regionWithContainerItems.Entities)
                        {
                            container.Region.Entities.Add(entity);
                            noOfItems++;
                            orderList.RemoveAt(0);
                            if (orderList.Count == 0)
                            {
                                break;
                            }
                            int nextIndex = orderList[0];
                            if (nextIndex != index + 1)
                            {
                                break;
                            }
                            else
                            {
                                index = nextIndex;
                            }
                        }
                        for (int i = 0; i < noOfItems; i++)
                        {
                            regionWithContainerItems.Entities.RemoveAt(0);
                        }
                    }
                }
            }
        }
Beispiel #13
0
 protected virtual Dictionary<string, string> GetPageData(IPage page)
 {
     var res = new Dictionary<string, string>();
     if (page != null)
     {
         res.Add("PageID", page.Id);
         res.Add("PageModified", page.RevisionDate.ToString("s"));
         res.Add("PageTemplateID", page.PageTemplate.Id);
         res.Add("PageTemplateModified", page.PageTemplate.RevisionDate.ToString("s"));
     }
     return res;
 }
 /// <summary>
 /// Creates a Strongly Typed Page Model for a given DD4T Page and an optional set of include Pages.
 /// </summary>
 /// <param name="page">The DD4T Page object.</param>
 /// <param name="includes">The set of DD4T Page object for include pages. Can be <c>null</c>.</param>
 /// <param name="localization">The context <see cref="Localization"/>.</param>
 /// <returns>The Strongly Typed Page Model (an instance of class <see cref="PageModel"/> or a subclass).</returns>
 public static PageModel CreatePageModel(IPage page, IPage[] includes, Localization localization)
 {
     using (new Tracer(page, includes, localization))
     {
         PageModel pageModel = null;
         foreach (IModelBuilder modelBuilder in ModelBuilders)
         {
             modelBuilder.BuildPageModel(ref pageModel, page, includes, localization);
         }
         return pageModel;
     }
 }
        private PageModel CreatePageModel(IPage page, Localization localization)
        {
            MvcData pageMvcData = GetMvcData(page);
            Type pageModelType = ModelTypeRegistry.GetViewModelType(pageMvcData);
            string pageId = GetDxaIdentifierFromTcmUri(page.Id);
            ISchema pageMetadataSchema = page.Schema;

            PageModel pageModel;
            if (pageModelType == typeof(PageModel))
            {
                // Standard Page Model
                pageModel = new PageModel(pageId);
            }
            else if (pageMetadataSchema == null)
            {
                // Custom Page Model but no Page metadata that can be mapped; simply create a Page Model instance of the right type.
                pageModel = (PageModel)Activator.CreateInstance(pageModelType, pageId);
            }
            else
            {
                // Custom Page Model and Page metadata is present; do full-blown model mapping.
                string[] schemaTcmUriParts = pageMetadataSchema.Id.Split('-');
                SemanticSchema semanticSchema = SemanticMapping.GetSchema(schemaTcmUriParts[1], localization);

                MappingData mappingData = new MappingData
                {
                    TargetType = pageModelType,
                    SemanticSchema = semanticSchema,
                    EntityNames = semanticSchema.GetEntityNames(),
                    TargetEntitiesByPrefix = GetEntityDataFromType(pageModelType),
                    Meta = page.MetadataFields,
                    ModelId = pageId,
                    Localization = localization
                };

                pageModel = (PageModel) CreateViewModel(mappingData);
            }

            pageModel.MvcData = pageMvcData;
            pageModel.XpmMetadata = GetXpmMetadata(page);
            pageModel.Title = page.Title;

            // add html classes to model from metadata
            // TODO: move to CreateViewModel so it can be merged with the same code for a Component/ComponentTemplate
            IPageTemplate template = page.PageTemplate;
            if (template.MetadataFields != null && template.MetadataFields.ContainsKey("htmlClasses"))
            {
                // strip illegal characters to ensure valid html in the view (allow spaces for multiple classes)
                pageModel.HtmlClasses = template.MetadataFields["htmlClasses"].Value.StripIllegalCharacters(@"[^\w\-\ ]");
            }

            return pageModel;
        }
        private static RegionModel GetRegionFromIncludePage(IPage page)
        {
            string regionName = page.Title;

            MvcData regionMvcData = new MvcData(regionName);
            InitializeRegionMvcData(regionMvcData);

            return new RegionModel(regionName)
            {
                MvcData = regionMvcData,
                XpmMetadata = new Dictionary<string, string>
                {
                    {RegionModel.IncludedFromPageIdXpmMetadataKey, page.Id},
                    {RegionModel.IncludedFromPageTitleXpmMetadataKey, page.Title},
                    {RegionModel.IncludedFromPageFileNameXpmMetadataKey, page.Filename}
                }
            };
        }
        /// <summary>
        /// Determine MVC data such as view, controller and area name from a Page
        /// </summary>
        /// <param name="page">The DD4T Page object</param>
        /// <returns>MVC data</returns>
        private static MvcData GetMvcData(IPage page)
        {
            IPageTemplate template = page.PageTemplate;
            string viewName = template.Title.RemoveSpaces();

            if (template.MetadataFields != null)
            {
                if (template.MetadataFields.ContainsKey("view"))
                {
                    viewName = template.MetadataFields["view"].Value;
                }
            }

            MvcData mvcData = CreateViewData(viewName);
            // defaults
            mvcData.ControllerName = SiteConfiguration.GetPageController();
            mvcData.ControllerAreaName = SiteConfiguration.GetDefaultModuleName();
            mvcData.ActionName = SiteConfiguration.GetPageAction();

            return mvcData;
        }
        protected virtual string ProcessPageMetadata(IPage page, IDictionary<string, string> meta, Localization localization)
        {
            //First grab metadata from the page
            if (page.MetadataFields != null)
            {
                foreach (IField field in page.MetadataFields.Values)
                {
                    ProcessMetadataField(field, meta);
                }
            }
            string description = meta.ContainsKey("description") ? meta["description"] : null;
            string title = meta.ContainsKey("title") ? meta["title"] : null;
            string image = meta.ContainsKey("image") ? meta["image"] : null;

            //If we don't have a title or description - go hunting for a title and/or description from the first component in the main region on the page
            if (title == null || description == null)
            {
                bool first = true;
                foreach (IComponentPresentation cp in page.ComponentPresentations)
                {
                    MvcData regionMvcData = GetRegionMvcData(cp);
                    // determine title and description from first component in 'main' region
                    if (first && regionMvcData.ViewName.Equals(RegionForPageTitleComponent))
                    {
                        first = false;
                        IFieldSet metadata = cp.Component.MetadataFields;
                        IFieldSet fields = cp.Component.Fields;
                        if (metadata.ContainsKey(StandardMetadataXmlFieldName) && metadata[StandardMetadataXmlFieldName].EmbeddedValues.Count > 0)
                        {
                            IFieldSet standardMeta = metadata[StandardMetadataXmlFieldName].EmbeddedValues[0];
                            if (title == null && standardMeta.ContainsKey(StandardMetadataTitleXmlFieldName))
                            {
                                title = standardMeta[StandardMetadataTitleXmlFieldName].Value;
                            }
                            if (description == null && standardMeta.ContainsKey(StandardMetadataDescriptionXmlFieldName))
                            {
                                description = standardMeta[StandardMetadataDescriptionXmlFieldName].Value;
                            }
                        }
                        if (title == null && fields.ContainsKey(ComponentXmlFieldNameForPageTitle))
                        {
                            title = fields[ComponentXmlFieldNameForPageTitle].Value;
                        }
                        //Try to find an image
                        if (image == null && fields.ContainsKey("image"))
                        {
                            image = fields["image"].LinkedComponentValues[0].Multimedia.Url;
                        }
                    }
                }
            }
            string titlePostfix = GetResource("core.pageTitleSeparator") + GetResource("core.pageTitlePostfix");
            //if we still dont have a title, use the page title
            if (title == null)
            {
                title = Regex.Replace(page.Title, @"^\d{3}\s", String.Empty);
                // Index and Default are not a proper titles for an HTML page
                if (title.ToLowerInvariant().Equals("index") || title.ToLowerInvariant().Equals("default"))
                {
                    title = GetResource("core.defaultPageTitle");
                }
            }
            meta.Add("twitter:card", "summary");
            meta.Add("og:title", title);
            // TODO: if the URL is really needed, it should be added higher up (e.g. in the View code):  meta.Add("og:url", WebRequestContext.RequestUrl);
            // TODO: is this always article?
            meta.Add("og:type", "article");
            meta.Add("og:locale", localization.Culture);
            if (description != null)
            {
                meta.Add("og:description", description);
            }
            if (image != null)
            {
                image = localization.GetBaseUrl() + image;
                meta.Add("og:image", image);
            }
            if (!meta.ContainsKey("description"))
            {
                meta.Add("description", description ?? title);
            }
            // TODO: meta.Add("fb:admins", Configuration.GetConfig("core.fbadmins");
            return title + titlePostfix;
        }
 protected virtual IDictionary<string, string> GetXpmMetadata(IPage page)
 {
     IDictionary<string, string> result = new Dictionary<string, string>();
     if (page != null)
     {
         result.Add("PageID", page.Id);
         result.Add("PageModified", page.RevisionDate.ToString("yyyy-MM-ddTHH:mm:ss"));
         result.Add("PageTemplateID", page.PageTemplate.Id);
         result.Add("PageTemplateModified", page.PageTemplate.RevisionDate.ToString("yyyy-MM-ddTHH:mm:ss"));
     }
     return result;
 }
Beispiel #20
0
        /// <summary>
        /// Gets a Page Model for a given URL.
        /// </summary>
        /// <param name="urlPath">The URL path (unescaped).</param>
        /// <param name="localization">The context Localization.</param>
        /// <param name="addIncludes">Indicates whether include Pages should be expanded.</param>
        /// <returns>The Page Model.</returns>
        /// <exception cref="DxaItemNotFoundException">If no Page Model exists for the given URL.</exception>
        public virtual PageModel GetPageModel(string urlPath, Localization localization, bool addIncludes)
        {
            using (new Tracer(urlPath, localization, addIncludes))
            {
                if (urlPath == null)
                {
                    urlPath = "/";
                }
                else if (!urlPath.StartsWith("/"))
                {
                    urlPath = "/" + urlPath;
                }

                IPage page = GetPage(urlPath, localization);
                if (page == null && !urlPath.EndsWith("/"))
                {
                    // This may be a SG URL path; try if the index page exists.
                    urlPath += Constants.IndexPageUrlSuffix;
                    page     = GetPage(urlPath, localization);
                }
                else if (urlPath.EndsWith("/"))
                {
                    urlPath += Constants.DefaultExtensionLessPageName;
                }

                if (page == null)
                {
                    throw new DxaItemNotFoundException(urlPath, localization.Id);
                }

                IPage[] includes = addIncludes ? GetIncludesFromModel(page, localization).ToArray() : new IPage[0];

                List <string> dependencies = new List <string>()
                {
                    page.Id
                };
                dependencies.AddRange(includes.Select(p => p.Id));

                PageModel result = null;
                if (CacheRegions.IsViewModelCachingEnabled)
                {
                    PageModel cachedPageModel = SiteConfiguration.CacheProvider.GetOrAdd(
                        string.Format("{0}:{1}", page.Id, addIncludes), // Cache Page Models with and without includes separately
                        CacheRegions.PageModel,
                        () =>
                    {
                        PageModel pageModel = ModelBuilderPipeline.CreatePageModel(page, includes, localization);
                        pageModel.Url       = urlPath;
                        if (pageModel.NoCache)
                        {
                            result = pageModel;
                            return(null);
                        }
                        return(pageModel);
                    },
                        dependencies
                        );

                    if (cachedPageModel != null)
                    {
                        // Don't return the cached Page Model itself, because we don't want dynamic logic to modify the cached state.
                        result = (PageModel)cachedPageModel.DeepCopy();
                    }
                }
                else
                {
                    result     = ModelBuilderPipeline.CreatePageModel(page, includes, localization);
                    result.Url = urlPath;
                }

                if (SiteConfiguration.ConditionalEntityEvaluator != null)
                {
                    result.FilterConditionalEntities(localization);
                }

                return(result);
            }
        }
 protected virtual IEnumerable<IPage> GetIncludesFromModel(IPage page, Localization localization)
 {
     using (new Tracer(page.Id, localization))
     {
         List<IPage> result = new List<IPage>();
         string[] pageTemplateTcmUriParts = page.PageTemplate.Id.Split('-');
         IEnumerable<string> includePageUrls = localization.GetIncludePageUrls(pageTemplateTcmUriParts[1]);
         foreach (string includePageUrl in includePageUrls)
         {
             IPage includePage = GetPage(SiteConfiguration.LocalizeUrl(includePageUrl, localization), localization);
             if (includePage == null)
             {
                 Log.Error("Include Page '{0}' not found.", includePageUrl);
                 continue;
             }
             result.Add(includePage);
         }
         return result;
     }
 }