in src/OrchardCore.Modules/OrchardCore.Taxonomies/TermShapes.cs [17:249]
public void Discover(ShapeTableBuilder builder)
{
// Add standard alternates to a TermPart because it is rendered by a content display driver not a part display driver
builder.Describe("TermPart")
.OnDisplaying(context =>
{
dynamic shape = context.Shape;
var contentType = shape.ContentItem.ContentType;
var displayTypes = new[] { "", "_" + context.Shape.Metadata.DisplayType };
// [ShapeType]_[DisplayType], e.g. TermPart.Summary, TermPart.Detail
context.Shape.Metadata.Alternates.Add($"TermPart_{context.Shape.Metadata.DisplayType}");
foreach (var displayType in displayTypes)
{
// [ContentType]_[DisplayType]__[PartType], e.g. Category-TermPart, Category-TermPart.Detail
context.Shape.Metadata.Alternates.Add($"{contentType}{displayType}__TermPart");
}
});
builder.Describe("Term")
.OnProcessing(async context =>
{
dynamic termShape = context.Shape;
string identifier = termShape.TaxonomyContentItemId ?? termShape.Alias;
if (String.IsNullOrEmpty(identifier))
{
return;
}
termShape.Classes.Add("term");
// Term population is executed when processing the shape so that its value
// can be cached. IShapeDisplayEvents is called before the ShapeDescriptor
// events and thus this code can be cached.
var shapeFactory = context.ServiceProvider.GetRequiredService<IShapeFactory>();
var contentManager = context.ServiceProvider.GetRequiredService<IContentManager>();
var aliasManager = context.ServiceProvider.GetRequiredService<IContentAliasManager>();
var orchardHelper = context.ServiceProvider.GetRequiredService<IOrchardHelper>();
var contentDefinitionManager = context.ServiceProvider.GetRequiredService<IContentDefinitionManager>();
string taxonomyContentItemId = termShape.Alias != null
? await aliasManager.GetContentItemIdAsync(termShape.Alias)
: termShape.TaxonomyContentItemId;
if (taxonomyContentItemId == null)
{
return;
}
var taxonomyContentItem = await contentManager.GetAsync(taxonomyContentItemId);
if (taxonomyContentItem == null)
{
return;
}
termShape.TaxonomyContentItem = taxonomyContentItem;
termShape.TaxonomyName = taxonomyContentItem.DisplayText;
var taxonomyPart = taxonomyContentItem.As<TaxonomyPart>();
if (taxonomyPart == null)
{
return;
}
// When a TermContentItemId is provided render the term and its child terms.
var level = 0;
List<ContentItem> termItems = null;
string termContentItemId = termShape.TermContentItemId;
if (!String.IsNullOrEmpty(termContentItemId))
{
level = FindTerm(taxonomyContentItem.Content.TaxonomyPart.Terms as JArray, termContentItemId, level, out var termContentItem);
if (termContentItem == null)
{
return;
}
termItems = new List<ContentItem>
{
termContentItem
};
}
else
{
termItems = taxonomyPart.Terms;
}
if (termItems == null)
{
return;
}
var differentiator = FormatName((string)termShape.TaxonomyName);
if (!String.IsNullOrEmpty(differentiator))
{
// Term__[Differentiator] e.g. Term-Categories, Term-Tags
termShape.Metadata.Alternates.Add("Term__" + differentiator);
termShape.Metadata.Differentiator = differentiator;
termShape.Classes.Add(("term-" + differentiator).HtmlClassify());
}
termShape.Classes.Add(("term-" + taxonomyPart.TermContentType).HtmlClassify());
var encodedContentType = EncodeAlternateElement(taxonomyPart.TermContentType);
// Term__[ContentType] e.g. Term-Category, Term-Tag
termShape.Metadata.Alternates.Add("Term__" + encodedContentType);
// The first level of term item shapes is created.
// Each other level is created when the term item is displayed.
foreach (var termContentItem in termItems)
{
ContentItem[] childTerms = null;
if (termContentItem.Content.Terms is JArray termsArray)
{
childTerms = termsArray.ToObject<ContentItem[]>();
}
var shape = await shapeFactory.CreateAsync("TermItem", Arguments.From(new
{
Level = level,
Term = termShape,
TermContentItem = termContentItem,
Terms = childTerms ?? Array.Empty<ContentItem>(),
TaxonomyContentItem = taxonomyContentItem
}));
shape.Metadata.Differentiator = differentiator;
// Don't use Items.Add() or the collection won't be sorted
termShape.Add(shape);
}
});
builder.Describe("TermItem")
.OnDisplaying(async context =>
{
dynamic termItem = context.Shape;
var termShape = termItem.Term;
int level = termItem.Level;
ContentItem taxonomyContentItem = termItem.TaxonomyContentItem;
var taxonomyPart = taxonomyContentItem.As<TaxonomyPart>();
string differentiator = termItem.Metadata.Differentiator;
var shapeFactory = context.ServiceProvider.GetRequiredService<IShapeFactory>();
if (termItem.Terms != null)
{
foreach (var termContentItem in termItem.Terms)
{
ContentItem[] childTerms = null;
if (termContentItem.Content.Terms is JArray termsArray)
{
childTerms = termsArray.ToObject<ContentItem[]>();
}
var shape = await shapeFactory.CreateAsync("TermItem", Arguments.From(new
{
Level = level + 1,
TaxonomyContentItem = taxonomyContentItem,
TermContentItem = termContentItem,
Term = termShape,
Terms = childTerms ?? Array.Empty<ContentItem>()
}));
shape.Metadata.Differentiator = differentiator;
// Don't use Items.Add() or the collection won't be sorted
termItem.Add(shape);
}
}
var encodedContentType = EncodeAlternateElement(taxonomyPart.TermContentType);
// TermItem__level__[level] e.g. TermItem-level-2
termItem.Metadata.Alternates.Add("TermItem__level__" + level);
// TermItem__[ContentType] e.g. TermItem-Category
// TermItem__[ContentType]__level__[level] e.g. TermItem-Category-level-2
termItem.Metadata.Alternates.Add("TermItem__" + encodedContentType);
termItem.Metadata.Alternates.Add("TermItem__" + encodedContentType + "__level__" + level);
if (!String.IsNullOrEmpty(differentiator))
{
// TermItem__[Differentiator] e.g. TermItem-Categories, TermItem-Travel
// TermItem__[Differentiator]__level__[level] e.g. TermItem-Categories-level-2
termItem.Metadata.Alternates.Add("TermItem__" + differentiator);
termItem.Metadata.Alternates.Add("TermItem__" + differentiator + "__level__" + level);
// TermItem__[Differentiator]__[ContentType] e.g. TermItem-Categories-Category
// TermItem__[Differentiator]__[ContentType]__level__[level] e.g. TermItem-Categories-Category-level-2
termItem.Metadata.Alternates.Add("TermItem__" + differentiator + "__" + encodedContentType);
termItem.Metadata.Alternates.Add("TermItem__" + differentiator + "__" + encodedContentType + "__level__" + level);
}
});
builder.Describe("TermContentItem")
.OnDisplaying(displaying =>
{
dynamic termItem = displaying.Shape;
int level = termItem.Level;
string differentiator = termItem.Metadata.Differentiator;
ContentItem termContentItem = termItem.TermContentItem;
var encodedContentType = EncodeAlternateElement(termContentItem.ContentItem.ContentType);
termItem.Metadata.Alternates.Add("TermContentItem__level__" + level);
// TermContentItem__[ContentType] e.g. TermContentItem-Category
// TermContentItem__[ContentType]__level__[level] e.g. TermContentItem-Category-level-2
termItem.Metadata.Alternates.Add("TermContentItem__" + encodedContentType);
termItem.Metadata.Alternates.Add("TermContentItem__" + encodedContentType + "__level__" + level);
if (!String.IsNullOrEmpty(differentiator))
{
// TermContentItem__[Differentiator] e.g. TermContentItem-Categories
termItem.Metadata.Alternates.Add("TermContentItem__" + differentiator);
// TermContentItem__[Differentiator]__level__[level] e.g. TermContentItem-Categories-level-2
termItem.Metadata.Alternates.Add("TermContentItem__" + differentiator + "__level__" + level);
// TermContentItem__[Differentiator]__[ContentType] e.g. TermContentItem-Categories-Category
// TermContentItem__[Differentiator]__[ContentType] e.g. TermContentItem-Categories-Category-level-2
termItem.Metadata.Alternates.Add("TermContentItem__" + differentiator + "__" + encodedContentType);
termItem.Metadata.Alternates.Add("TermContentItem__" + differentiator + "__" + encodedContentType + "__level__" + level);
}
});
}