-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8c5a86f
commit a5e11d3
Showing
124 changed files
with
5,583 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
src/OrchardCore.Modules/OrchardCore.Autoroute/Sitemaps/AutorouteContentTypeProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore.Mvc; | ||
using OrchardCore.Autoroute.Models; | ||
using OrchardCore.ContentManagement; | ||
using OrchardCore.ContentManagement.Metadata; | ||
using OrchardCore.ContentManagement.Metadata.Models; | ||
using OrchardCore.Sitemaps.Builders; | ||
using OrchardCore.Sitemaps.Services; | ||
|
||
namespace OrchardCore.Autoroute.Sitemaps | ||
{ | ||
public class AutorouteContentTypeProvider : IRouteableContentTypeProvider | ||
{ | ||
private readonly IContentDefinitionManager _contentDefinitionManager; | ||
private readonly IContentManager _contentManager; | ||
|
||
public AutorouteContentTypeProvider( | ||
IContentDefinitionManager contentDefinitionManager, | ||
IContentManager contentManager | ||
) | ||
{ | ||
_contentDefinitionManager = contentDefinitionManager; | ||
_contentManager = contentManager; | ||
} | ||
|
||
public async Task<string> GetRouteAsync(SitemapBuilderContext context, ContentItem contentItem) | ||
{ | ||
var ctd = ListRoutableTypeDefinitions()? | ||
.FirstOrDefault(rctd => rctd.Name == contentItem.ContentType); | ||
|
||
if (ctd != null) | ||
{ | ||
var contentItemMetadata = await _contentManager.PopulateAspectAsync<ContentItemMetadata>(contentItem); | ||
var routes = contentItemMetadata.DisplayRouteValues; | ||
|
||
// UrlHelper.Action includes BasePath automatically if present. | ||
// If content item is assigned as home route, Urlhelper resolves as site root. | ||
return context.HostPrefix + context.UrlHelper.Action(routes["Action"].ToString(), routes); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
public IEnumerable<ContentTypeDefinition> ListRoutableTypeDefinitions() | ||
{ | ||
return _contentDefinitionManager.ListTypeDefinitions() | ||
.Where(ctd => ctd.Parts.Any(p => p.Name == nameof(AutoroutePart))); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
...re.Modules/OrchardCore.ContentLocalization/Sitemaps/LocalizedContentItemsQueryProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using OrchardCore.ContentLocalization.Models; | ||
using OrchardCore.ContentLocalization.Records; | ||
using OrchardCore.ContentManagement; | ||
using OrchardCore.ContentManagement.Records; | ||
using OrchardCore.Localization; | ||
using OrchardCore.Sitemaps.Builders; | ||
using OrchardCore.Sitemaps.Models; | ||
using OrchardCore.Sitemaps.Services; | ||
using YesSql; | ||
using YesSql.Services; | ||
|
||
namespace OrchardCore.ContentLocalization.Sitemaps | ||
{ | ||
public class LocalizedContentItemsQueryProvider : IContentItemsQueryProvider | ||
{ | ||
private readonly ISession _session; | ||
private readonly IRouteableContentTypeCoordinator _routeableContentTypeCoordinator; | ||
private readonly ILocalizationService _localizationService; | ||
|
||
public LocalizedContentItemsQueryProvider( | ||
ISession session, | ||
IRouteableContentTypeCoordinator routeableContentTypeCoordinator, | ||
ILocalizationService localizationService | ||
) | ||
{ | ||
_session = session; | ||
_routeableContentTypeCoordinator = routeableContentTypeCoordinator; | ||
_localizationService = localizationService; | ||
} | ||
|
||
public async Task GetContentItems(ContentTypesSitemapSource source, ContentItemsQueryContext queryContext) | ||
{ | ||
var routeableContentTypeDefinitions = _routeableContentTypeCoordinator.ListRoutableTypeDefinitions(); | ||
|
||
if (source.IndexAll) | ||
{ | ||
// Assumption here is that at least one content type will be localized. | ||
var rctdNames = routeableContentTypeDefinitions.Select(rctd => rctd.Name); | ||
|
||
var queryResults = await _session.Query<ContentItem>() | ||
.With<ContentItemIndex>(x => x.Published && x.ContentType.IsIn(rctdNames)) | ||
.OrderBy(x => x.CreatedUtc) | ||
.ListAsync(); | ||
|
||
queryContext.ContentItems = queryResults; | ||
|
||
// Provide all content items with localization as reference content items. | ||
queryContext.ReferenceContentItems = queryResults | ||
.Where(ci => ci.Has<LocalizationPart>()); | ||
} | ||
else if (source.LimitItems) | ||
{ | ||
// Test that content type is still valid to include in sitemap. | ||
var contentType = routeableContentTypeDefinitions | ||
.FirstOrDefault(ctd => String.Equals(source.LimitedContentType.ContentTypeName, ctd.Name)); | ||
|
||
if (contentType == null) | ||
{ | ||
return; | ||
} | ||
|
||
if (contentType.Parts.Any(ctd => String.Equals(ctd.Name, nameof(LocalizationPart)))) | ||
{ | ||
// Get all content items here for reference. Then reduce by default culture. | ||
// We know that the content item should be localized. | ||
// If it doesn't have a localization part, the content item should have been saved. | ||
var queryResults = await _session.Query<ContentItem>() | ||
.With<ContentItemIndex>(ci => ci.ContentType == source.LimitedContentType.ContentTypeName && ci.Published) | ||
.OrderBy(ci => ci.CreatedUtc) | ||
.With<LocalizedContentItemIndex>() | ||
.ListAsync(); | ||
|
||
// When limiting items Content item is valid if it is for the default culture. | ||
var defaultCulture = await _localizationService.GetDefaultCultureAsync(); | ||
|
||
// Reduce by default culture. | ||
var items = queryResults | ||
.Where(ci => String.Equals(ci.As<LocalizationPart>().Culture, defaultCulture)) | ||
.Skip(source.LimitedContentType.Skip) | ||
.Take(source.LimitedContentType.Take); | ||
|
||
queryContext.ContentItems = items; | ||
|
||
// Provide all content items with localization as reference content items. | ||
queryContext.ReferenceContentItems = queryResults | ||
.Where(ci => ci.Has<LocalizationPart>()); | ||
} | ||
else | ||
{ | ||
// Content type is not localized. Produce standard results. | ||
var queryResults = await _session.Query<ContentItem>() | ||
.With<ContentItemIndex>(x => x.ContentType == source.LimitedContentType.ContentTypeName && x.Published) | ||
.OrderBy(x => x.CreatedUtc) | ||
.Skip(source.LimitedContentType.Skip) | ||
.Take(source.LimitedContentType.Take) | ||
.ListAsync(); | ||
|
||
queryContext.ContentItems = queryResults; | ||
} | ||
} | ||
else | ||
{ | ||
// Test that content types are still valid to include in sitemap. | ||
var typesToIndex = routeableContentTypeDefinitions | ||
.Where(ctd => source.ContentTypes.Any(s => String.Equals(ctd.Name,s.ContentTypeName))) | ||
.Select(x => x.Name); | ||
|
||
// No advantage here in reducing with localized index. | ||
var queryResults = await _session.Query<ContentItem>() | ||
.With<ContentItemIndex>(x => x.ContentType.IsIn(typesToIndex) && x.Published) | ||
.OrderBy(x => x.CreatedUtc) | ||
.ListAsync(); | ||
|
||
queryContext.ContentItems = queryResults; | ||
|
||
// Provide all content items with localization as reference content items. | ||
queryContext.ReferenceContentItems = queryResults | ||
.Where(ci => ci.Has<LocalizationPart>()); | ||
} | ||
} | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
...OrchardCore.ContentLocalization/Sitemaps/SitemapLocalizedContentItemValidationProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using System.Threading.Tasks; | ||
using OrchardCore.ContentLocalization.Models; | ||
using OrchardCore.ContentManagement; | ||
using OrchardCore.Localization; | ||
using OrchardCore.Sitemaps.Builders; | ||
|
||
namespace OrchardCore.ContentLocalization.Sitemaps | ||
{ | ||
public class SitemapLocalizedContentItemValidationProvider : ISitemapContentItemValidationProvider | ||
{ | ||
private readonly ILocalizationService _localizationService; | ||
|
||
public SitemapLocalizedContentItemValidationProvider( | ||
ILocalizationService localizationService) | ||
{ | ||
_localizationService = localizationService; | ||
} | ||
|
||
public async Task<bool> ValidateContentItem(ContentItem contentItem) | ||
{ | ||
var part = contentItem.As<LocalizationPart>(); | ||
if (part == null) | ||
{ | ||
return true; | ||
} | ||
|
||
// Content item is valid if it is for the default culture. | ||
var defaultCulture = await _localizationService.GetDefaultCultureAsync(); | ||
if (part.Culture == defaultCulture) | ||
{ | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
...es/OrchardCore.ContentLocalization/Sitemaps/SitemapUrlHrefLangExtendedMetadataProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using System.Xml.Linq; | ||
using OrchardCore.ContentLocalization.Models; | ||
using OrchardCore.ContentManagement; | ||
using OrchardCore.Sitemaps.Builders; | ||
using OrchardCore.Sitemaps.Services; | ||
|
||
namespace OrchardCore.ContentLocalization.Sitemaps | ||
{ | ||
public class SitemapUrlHrefLangExtendedMetadataProvider : ISitemapContentItemExtendedMetadataProvider | ||
{ | ||
private static readonly XNamespace ExtendedNamespace = "http://www.w3.org/TR/xhtml11/xhtml11_schema.html"; | ||
private static readonly XAttribute ExtendedAttribute = new XAttribute(XNamespace.Xmlns + "xhtml", ExtendedNamespace); | ||
|
||
private readonly ISitemapPartContentItemValidationProvider _sitemapPartContentItemValidationProvider; | ||
private readonly IRouteableContentTypeCoordinator _routeableContentTypeCoordinator; | ||
|
||
public SitemapUrlHrefLangExtendedMetadataProvider( | ||
ISitemapPartContentItemValidationProvider sitemapPartContentItemValidationProvider, | ||
IRouteableContentTypeCoordinator routeableContentTypeCoordinator | ||
) | ||
{ | ||
_sitemapPartContentItemValidationProvider = sitemapPartContentItemValidationProvider; | ||
_routeableContentTypeCoordinator = routeableContentTypeCoordinator; | ||
} | ||
|
||
public XAttribute GetExtendedAttribute => ExtendedAttribute; | ||
|
||
public async Task<bool> ApplyExtendedMetadataAsync( | ||
SitemapBuilderContext context, | ||
ContentItemsQueryContext queryContext, | ||
ContentItem contentItem, | ||
XElement url) | ||
{ | ||
var part = contentItem.As<LocalizationPart>(); | ||
if (part == null) | ||
{ | ||
return true; | ||
} | ||
|
||
var localizedContentParts = queryContext.ReferenceContentItems | ||
.Select(ci => ci.As<LocalizationPart>()) | ||
.Where(cp => cp.LocalizationSet == part.LocalizationSet); | ||
|
||
foreach (var localizedPart in localizedContentParts) | ||
{ | ||
if (!await _sitemapPartContentItemValidationProvider.ValidateContentItem(localizedPart.ContentItem)) | ||
{ | ||
continue; | ||
} | ||
|
||
var hrefValue = await _routeableContentTypeCoordinator.GetRouteAsync(context, localizedPart.ContentItem); | ||
|
||
var linkNode = new XElement(ExtendedNamespace + "link", | ||
new XAttribute("rel", "alternate"), | ||
new XAttribute("hreflang", localizedPart.Culture), | ||
new XAttribute("href", hrefValue)); | ||
|
||
url.Add(linkNode); | ||
} | ||
|
||
return true; | ||
} | ||
} | ||
} |
Oops, something went wrong.