Merge pull request #6106 from sbwalker/dev

add property to Module class to indicate how the IPortable interface is being invoked (Export Module, Import Module, Copy Page, Global Replace, Site Template)
This commit is contained in:
Shaun Walker
2026-03-05 12:55:55 -05:00
committed by GitHub
5 changed files with 45 additions and 46 deletions

View File

@@ -558,11 +558,13 @@ namespace Oqtane.Controllers
module = _modules.AddModule(module);
// copy module content (includes settings)
string content = _modules.ExportModule(pm.ModuleId);
// deep copy module content (includes settings)
pm.Module.IPortable = "Copy Page";
string content = _modules.ExportModule(pm.Module);
if (content != "")
{
_modules.ImportModule(module.ModuleId, content);
module.IPortable = "Copy Page";
_modules.ImportModule(module, content);
}
}
else

View File

@@ -4,7 +4,6 @@ using System.Net;
using System.Text.Json;
using Microsoft.Extensions.DependencyInjection;
using Oqtane.Models;
using Oqtane.Modules;
using Oqtane.Repository;
using Oqtane.Shared;
@@ -20,6 +19,7 @@ namespace Oqtane.Infrastructure
var siteRepository = provider.GetRequiredService<ISiteRepository>();
var pageRepository = provider.GetRequiredService<IPageRepository>();
var pageModuleRepository = provider.GetRequiredService<IPageModuleRepository>();
var moduleRepository = provider.GetRequiredService<IModuleRepository>();
var settingRepository = provider.GetRequiredService<ISettingRepository>();
var tenantManager = provider.GetRequiredService<ITenantManager>();
var syncManager = provider.GetRequiredService<ISyncManager>();
@@ -147,26 +147,15 @@ namespace Oqtane.Infrastructure
}
// module content
if (pageModule.Module.ModuleDefinition != null && pageModule.Module.ModuleDefinition.ServerManagerType != "")
if (globalReplace.Content)
{
Type moduleType = Type.GetType(pageModule.Module.ModuleDefinition.ServerManagerType);
if (moduleType != null && moduleType.GetInterface(nameof(IPortable)) != null)
pageModule.Module.IPortable = "Global Replace";
var content = moduleRepository.ExportModule(pageModule.Module);
if (!string.IsNullOrEmpty(content) && content.Contains(WebUtility.HtmlEncode(find), comparisonType))
{
try
{
var moduleObject = ActivatorUtilities.CreateInstance(provider, moduleType);
var moduleContent = ((IPortable)moduleObject).ExportModule(pageModule.Module);
if (!string.IsNullOrEmpty(moduleContent) && moduleContent.Contains(WebUtility.HtmlEncode(find), comparisonType) && globalReplace.Content)
{
moduleContent = moduleContent.Replace(WebUtility.HtmlEncode(find), WebUtility.HtmlEncode(replace), comparisonType);
((IPortable)moduleObject).ImportModule(pageModule.Module, moduleContent, pageModule.Module.ModuleDefinition.Version);
log += $"Module Content Updated: {pageModule.Title} Page: /{page.Path}<br />";
}
}
catch (Exception ex)
{
log += $"Error Processing Module {pageModule.Module.ModuleDefinition.Name} - {ex.Message}<br />";
}
content = content.Replace(WebUtility.HtmlEncode(find), WebUtility.HtmlEncode(replace), comparisonType);
moduleRepository.ImportModule(pageModule.Module, content);
log += $"Module Content Updated: {pageModule.Title} Page: /{page.Path}<br />";
}
}
}

View File

@@ -20,7 +20,9 @@ namespace Oqtane.Repository
Module GetModule(int moduleId, bool tracking);
void DeleteModule(int moduleId);
string ExportModule(int moduleId);
string ExportModule(Module module);
bool ImportModule(int moduleId, string content);
bool ImportModule(Module module, string content);
}
public class ModuleRepository : IModuleRepository
@@ -99,18 +101,23 @@ namespace Oqtane.Repository
}
public string ExportModule(int moduleId)
{
Module module = GetModule(moduleId);
return ExportModule(module);
}
public string ExportModule(Module module)
{
string content = "";
try
{
Module module = GetModule(moduleId);
if (module != null)
{
List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(module.SiteId).ToList();
ModuleDefinition moduledefinition = moduledefinitions.FirstOrDefault(item => item.ModuleDefinitionName == module.ModuleDefinitionName);
if (moduledefinition != null)
{
var settings = _settings.GetSettings(EntityNames.Module, moduleId);
var settings = _settings.GetSettings(EntityNames.Module, module.ModuleId);
ModuleContent modulecontent = new ModuleContent();
modulecontent.ModuleDefinitionName = moduledefinition.ModuleDefinitionName;
@@ -125,6 +132,7 @@ namespace Oqtane.Repository
{
try
{
module.IPortable = "Export Module";
module.Settings = settings.ToDictionary(x => x.SettingName, x => x.SettingValue);
var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype);
modulecontent.Content = ((IPortable)moduleobject).ExportModule(module);
@@ -149,11 +157,16 @@ namespace Oqtane.Repository
}
public bool ImportModule(int moduleId, string content)
{
Module module = GetModule(moduleId);
return ImportModule(module, content);
}
public bool ImportModule(Module module, string content)
{
bool success = false;
try
{
Module module = GetModule(moduleId);
if (module != null)
{
List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(module.SiteId).ToList();
@@ -163,7 +176,7 @@ namespace Oqtane.Repository
ModuleContent modulecontent = JsonSerializer.Deserialize<ModuleContent>(content.Replace("\n", ""));
if (modulecontent.ModuleDefinitionName == moduledefinition.ModuleDefinitionName)
{
var settings = _settings.GetSettings(EntityNames.Module, moduleId);
var settings = _settings.GetSettings(EntityNames.Module, module.ModuleId);
if (modulecontent.Settings != null)
{
@@ -172,7 +185,7 @@ namespace Oqtane.Repository
var setting = settings.FirstOrDefault(item => item.SettingName == kvp.Key);
if (setting == null)
{
setting = new Setting { EntityName = EntityNames.Module, EntityId = moduleId, SettingName = kvp.Key, SettingValue = kvp.Value, IsPrivate = false };
setting = new Setting { EntityName = EntityNames.Module, EntityId = module.ModuleId, SettingName = kvp.Key, SettingValue = kvp.Value, IsPrivate = false };
_settings.AddSetting(setting);
}
else
@@ -193,7 +206,8 @@ namespace Oqtane.Repository
{
try
{
module.Settings = _settings.GetSettings(EntityNames.Module, moduleId).ToDictionary(x => x.SettingName, x => x.SettingValue);
module.IPortable = "Import Module";
module.Settings = _settings.GetSettings(EntityNames.Module, module.ModuleId).ToDictionary(x => x.SettingName, x => x.SettingValue);
var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype);
((IPortable)moduleobject).ImportModule(module, modulecontent.Content, modulecontent.Version);
success = true;

View File

@@ -532,27 +532,15 @@ namespace Oqtane.Repository
_logger.Log(LogLevel.Error, "Site Template", LogFunction.Other, ex, "Error Processing Page Module {PageModule}", pageModule);
}
}
if (pageTemplateModule.Content != "" && moduleDefinition.ServerManagerType != "")
if (!string.IsNullOrEmpty(pageTemplateModule.Content))
{
Type moduletype = Type.GetType(moduleDefinition.ServerManagerType);
if (moduletype != null && moduletype.GetInterface(nameof(IPortable)) != null)
var module = _moduleRepository.GetModule(pageModule.ModuleId);
module.IPortable = "Site Template";
if (!_moduleRepository.ImportModule(module, pageTemplateModule.Content))
{
try
if (alias != null)
{
var module = _moduleRepository.GetModule(pageModule.ModuleId);
if (module != null)
{
var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype);
((IPortable)moduleobject).ImportModule(module, pageTemplateModule.Content, moduleDefinition.Version);
}
}
catch (Exception ex)
{
if (alias != null)
{
_logger.Log(LogLevel.Error, "Site Template", LogFunction.Other, ex, "Error Importing Content For {ModuleDefinitionName}", pageTemplateModule.ModuleDefinitionName);
}
_logger.Log(LogLevel.Error, "Site Template", LogFunction.Other, "Error Importing Content For {ModuleDefinitionName}", pageTemplateModule.ModuleDefinitionName);
}
}
}

View File

@@ -39,6 +39,12 @@ namespace Oqtane.Models
[NotMapped]
public bool IsShared { get; set; }
/// <summary>
/// Specifies the scenario where the IPortable interface is being invoked
/// </summary>
[NotMapped]
public string IPortable { get; set; }
/// <summary>
/// Reference to the <see cref="ModuleDefinition"/> used for this module.
/// </summary>