Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable regions with the same name to be repeated multiple times on a page #27

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
24 changes: 21 additions & 3 deletions Sdl.Web.Common/Models/RegionModel.cs
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using Sdl.Web.Common.Configuration;

using System.Text.RegularExpressions;
using System;

namespace Sdl.Web.Common.Models
{
/// <summary>
Expand Down Expand Up @@ -54,7 +56,18 @@ public RegionModelSet Regions
}
}


public String NameWithoutPostfix
{
get
{
var match = Regex.Match(Name, @"(.*)___\d+");
if (match.Success)
{
return match.Groups[1].Value;
}
return Name;
}
}
#region Constructors
/// <summary>
/// Initializes a new <see cref="RegionModel"/> instance.
Expand All @@ -80,6 +93,11 @@ public RegionModel(string name, string qualifiedViewName)
}
#endregion

public String GetNameWithPostfix(int counter)
{
return String.Format("{0}___{1}", this.Name, counter);
}

#region Overrides

/// <summary>
Expand All @@ -89,7 +107,7 @@ public RegionModel(string name, string qualifiedViewName)
/// <returns>The XPM markup.</returns>
public override string GetXpmMarkup(Localization localization)
{
XpmRegion xpmRegion = localization.GetXpmRegionConfiguration(Name);
XpmRegion xpmRegion = localization.GetXpmRegionConfiguration(this.NameWithoutPostfix);
if (xpmRegion == null)
{
return string.Empty;
Expand Down
76 changes: 55 additions & 21 deletions Sdl.Web.Tridion/Mapping/DefaultModelBuilder.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -51,40 +51,24 @@ public virtual void BuildPageModel(ref PageModel pageModel, IPage page, IEnumera

// Create Regions/Entities from Component Presentations
IConditionalEntityEvaluator conditionalEntityEvaluator = SiteConfiguration.ConditionalEntityEvaluator;
RegionModel currentRegion = null;
Dictionary<String, int> duplicateRegionCounter = new Dictionary<string, int>();
foreach (IComponentPresentation cp in page.ComponentPresentations)
{
MvcData cpRegionMvcData = GetRegionMvcData(cp);
string regionName = cpRegionMvcData.RegionName ?? cpRegionMvcData.ViewName;
RegionModel region;
if (regions.TryGetValue(regionName, 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);
}

currentRegion = GetRegionForEntity(regions, cp, currentRegion, duplicateRegionCounter);
try
{
EntityModel entity = ModelBuilderPipeline.CreateEntityModel(cp, localization);

if (conditionalEntityEvaluator == null || conditionalEntityEvaluator.IncludeEntity(entity))
{
region.Entities.Add(entity);
currentRegion.Entities.Add(entity);
}
}
catch (Exception ex)
{
// If there is a problem mapping an Entity, we replace it with an ExceptionEntity which holds the error details and carry on.
Log.Error(ex);
region.Entities.Add(new ExceptionEntity(ex));
currentRegion.Entities.Add(new ExceptionEntity(ex));
}
}

Expand Down Expand Up @@ -133,6 +117,56 @@ public virtual void BuildPageModel(ref PageModel pageModel, IPage page, IEnumera
}
}

private RegionModel GetRegionForEntity(RegionModelSet regions, IComponentPresentation cp, RegionModel currentRegion, Dictionary<String,int> duplicateRegionCounter)
{
MvcData cpRegionMvcData = GetRegionMvcData(cp);
string regionName = cpRegionMvcData.RegionName ?? cpRegionMvcData.ViewName;
string currentRegionName = currentRegion!=null ? currentRegion.NameWithoutPostfix : null;
string duplicateRegionName = null;
RegionModel region = null;
//If we are still in the same region, reuse it, unless the mvc data is different,
//in which case we start a new region of the same name
if (regionName==currentRegionName)
{
if (currentRegion.MvcData.Equals(cpRegionMvcData))
{
return currentRegion;
}
else
{
Log.Debug("Region '{0}' is defined with different MVC data: [{1}] and [{2}]. Starting a new region.", regionName, currentRegion.MvcData, cpRegionMvcData);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that now we can have duplicate regions, a change in MVC data can simply trigger a new region of the same name. This ties in nicely with PR #29 which allows regions to be configurable via CT metadata. In this case we would want to start a new region if the region route values were different

}
}
//We already had this region, but there has been something else inbetween, so we need to create a new (postfixed) one
if (regions.ContainsKey(regionName))
{
int counter = 1;
if (duplicateRegionCounter.ContainsKey(regionName))
{
counter = duplicateRegionCounter[regionName] + 1;
duplicateRegionCounter[regionName] = counter;
}
else
{
duplicateRegionCounter.Add(regionName, counter);
}
duplicateRegionName = regions[regionName].GetNameWithPostfix(counter);
}
//New region required
if (region == null)
{
// Region does not exist in Page Model yet; create Region Model and add it.
if (!String.IsNullOrEmpty(duplicateRegionName))
{
cpRegionMvcData.RegionName = duplicateRegionName;
}
region = CreateRegionModel(cpRegionMvcData);
regions.Add(region);
currentRegion = region;
}
return region;
}

public virtual void BuildEntityModel(ref EntityModel entityModel, IComponentPresentation cp, Localization localization)
{
using (new Tracer(entityModel, cp, localization))
Expand Down