add sitemap generator which outputs all public pages and also includes an ISitemap interface for modules

This commit is contained in:
Shaun Walker 2023-02-20 08:35:46 -05:00
parent d1d00e6c98
commit 8c6c66fb11
7 changed files with 160 additions and 8 deletions

View File

@ -190,12 +190,7 @@ namespace Oqtane.Modules
public string AddUrlParameters(params object[] parameters) public string AddUrlParameters(params object[] parameters)
{ {
var url = ""; return Utilities.AddUrlParameters(parameters);
for (var i = 0; i < parameters.Length; i++)
{
url += "/" + parameters[i].ToString();
}
return url;
} }
// template is in the form of a standard route template ie. "/{id}/{name}" and produces dictionary of key/value pairs // template is in the form of a standard route template ie. "/{id}/{name}" and produces dictionary of key/value pairs

View File

@ -1,10 +1,10 @@
using Oqtane.Models; using Oqtane.Models;
namespace Oqtane.Modules namespace Oqtane.Modules
{ {
public interface IPortable public interface IPortable
{ {
// You Must Set The "ServerAssemblyName" In Your IModule Interface // You Must Set The "ServerManagerType" In Your IModule Interface
string ExportModule(Module module); string ExportModule(Module module);

View File

@ -0,0 +1,12 @@
using System.Collections.Generic;
using Oqtane.Models;
namespace Oqtane.Modules
{
public interface ISitemap
{
// You Must Set The "ServerManagerType" In Your IModule Interface
List<Sitemap> GetUrls(string alias, string path, Module module);
}
}

View File

@ -0,0 +1,3 @@
@page "/pages/sitemap.xml"
@namespace Oqtane.Pages
@model Oqtane.Pages.SitemapModel

View File

@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.DependencyInjection;
using Oqtane.Enums;
using Oqtane.Infrastructure;
using Oqtane.Models;
using Oqtane.Modules;
using Oqtane.Repository;
using Oqtane.Security;
using Oqtane.Shared;
namespace Oqtane.Pages
{
[AllowAnonymous]
public class SitemapModel : PageModel
{
private readonly IServiceProvider _serviceProvider;
private readonly IPageRepository _pages;
private readonly IPageModuleRepository _pageModules;
private readonly IModuleDefinitionRepository _moduleDefinitions;
private readonly IUserPermissions _userPermissions;
private readonly ILogManager _logger;
private readonly Alias _alias;
public SitemapModel(IServiceProvider serviceProvider, IPageRepository pages, IPageModuleRepository pageModules, IModuleDefinitionRepository moduleDefinitions, IUserPermissions userPermissions, IUrlMappingRepository urlMappings, ISyncManager syncManager, ILogManager logger, ITenantManager tenantManager)
{
_serviceProvider = serviceProvider;
_pages = pages;
_pageModules = pageModules;
_moduleDefinitions = moduleDefinitions;
_userPermissions = userPermissions;
_logger = logger;
_alias = tenantManager.GetAlias();
}
public IActionResult OnGet()
{
var sitemap = new List<Sitemap>();
// build site map
var moduleDefinitions = _moduleDefinitions.GetModuleDefinitions(_alias.SiteId).ToList();
var pageModules = _pageModules.GetPageModules(_alias.SiteId);
foreach (var page in _pages.GetPages(_alias.SiteId))
{
if (_userPermissions.IsAuthorized(null, PermissionNames.View, page.Permissions))
{
sitemap.Add(new Sitemap { Url = _alias.Protocol + _alias.Name + Utilities.NavigateUrl(_alias.Path, page.Path, ""), ModifiedOn = page.ModifiedOn });
foreach (var pageModule in pageModules.Where(item => item.PageId == page.PageId))
{
if (_userPermissions.IsAuthorized(null, PermissionNames.View, pageModule.Module.Permissions))
{
var moduleDefinition = moduleDefinitions.Where(item => item.ModuleDefinitionName == pageModule.Module.ModuleDefinitionName).FirstOrDefault();
if (moduleDefinition != null && moduleDefinition.ServerManagerType != "")
{
Type moduletype = Type.GetType(moduleDefinition.ServerManagerType);
if (moduletype != null && moduletype.GetInterface("ISitemap") != null)
{
try
{
var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype);
var urls = ((ISitemap)moduleobject).GetUrls(_alias.Path, page.Path, pageModule.Module);
foreach (var url in urls)
{
sitemap.Add(new Sitemap { Url = _alias.Protocol + _alias.Name + url.Url, ModifiedOn = url.ModifiedOn });
}
}
catch (Exception ex)
{
_logger.Log(LogLevel.Error, this, LogFunction.Other, ex, "Error Retrieving SiteMap For {Name} Module", moduleDefinition.Name);
}
}
}
}
}
}
}
// write XML
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = (" ");
settings.CloseOutput = true;
settings.OmitXmlDeclaration = true;
settings.WriteEndDocumentOnClose = true;
StringBuilder builder = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(builder, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("urlset", "http://www.sitemaps.org/schemas/sitemap/0.9");
foreach (var url in sitemap)
{
writer.WriteStartElement("url");
writer.WriteElementString("loc", url.Url);
writer.WriteElementString("lastmod", url.ModifiedOn.ToString("yyyy-MM-dd"));
writer.WriteEndElement();
}
writer.Close();
}
return Content(builder.ToString());
}
}
}

View File

@ -0,0 +1,20 @@
using System;
namespace Oqtane.Models
{
/// <summary>
/// Describes a Sitemap
/// </summary>
public class Sitemap
{
/// <summary>
/// Url
/// </summary>
public string Url { get; set; }
/// <summary>
/// Url
/// </summary>
public DateTime ModifiedOn { get; set; }
}
}

View File

@ -143,6 +143,16 @@ namespace Oqtane.Shared
return $"{alias?.BaseUrl}{url}"; return $"{alias?.BaseUrl}{url}";
} }
public static string AddUrlParameters(params object[] parameters)
{
var url = "";
for (var i = 0; i < parameters.Length; i++)
{
url += "/" + parameters[i].ToString();
}
return url;
}
public static string FormatContent(string content, Alias alias, string operation) public static string FormatContent(string content, Alias alias, string operation)
{ {
var aliasUrl = (alias != null && !string.IsNullOrEmpty(alias.Path)) ? "/" + alias.Path : ""; var aliasUrl = (alias != null && !string.IsNullOrEmpty(alias.Path)) ? "/" + alias.Path : "";