refactor synchronization job
This commit is contained in:
@@ -18,6 +18,7 @@ namespace Oqtane.Infrastructure
|
|||||||
// synchronization only supports sites in the same tenant (database)
|
// synchronization only supports sites in the same tenant (database)
|
||||||
// module title is used as a key to identify module instances on a page
|
// module title is used as a key to identify module instances on a page
|
||||||
// modules must implement ISynchronizable interface
|
// modules must implement ISynchronizable interface
|
||||||
|
// change detection does not support deleted items as key values will usually be different due to localization
|
||||||
|
|
||||||
// define settings that should not be synchronized (should be extensible in the future)
|
// define settings that should not be synchronized (should be extensible in the future)
|
||||||
List<Setting> excludedSettings = new List<Setting>() {
|
List<Setting> excludedSettings = new List<Setting>() {
|
||||||
@@ -98,7 +99,7 @@ namespace Oqtane.Infrastructure
|
|||||||
siteLog = (siteGroupMember.SynchronizedOn != DateTime.MinValue) ? "No Changes Identified<br />" : "Initialization Complete<br />";
|
siteLog = (siteGroupMember.SynchronizedOn != DateTime.MinValue) ? "No Changes Identified<br />" : "Initialization Complete<br />";
|
||||||
}
|
}
|
||||||
|
|
||||||
// set synchronized on date/time
|
// set synchronized date/time
|
||||||
siteGroupMember.SynchronizedOn = DateTime.UtcNow;
|
siteGroupMember.SynchronizedOn = DateTime.UtcNow;
|
||||||
siteGroupMemberRepository.UpdateSiteGroupMember(siteGroupMember);
|
siteGroupMemberRepository.UpdateSiteGroupMember(siteGroupMember);
|
||||||
|
|
||||||
@@ -128,7 +129,7 @@ namespace Oqtane.Infrastructure
|
|||||||
{
|
{
|
||||||
var log = "";
|
var log = "";
|
||||||
|
|
||||||
// synchronize roles/users
|
// synchronize roles
|
||||||
log += SynchronizeRoles(provider, settingRepository, siteGroupMember, primarySite.SiteId, secondarySite.SiteId);
|
log += SynchronizeRoles(provider, settingRepository, siteGroupMember, primarySite.SiteId, secondarySite.SiteId);
|
||||||
|
|
||||||
// synchronize folders/files
|
// synchronize folders/files
|
||||||
@@ -139,6 +140,8 @@ namespace Oqtane.Infrastructure
|
|||||||
|
|
||||||
// synchronize site
|
// synchronize site
|
||||||
if (primarySite.ModifiedOn > siteGroupMember.SynchronizedOn)
|
if (primarySite.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||||
|
{
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
{
|
{
|
||||||
secondarySite.TimeZoneId = primarySite.TimeZoneId;
|
secondarySite.TimeZoneId = primarySite.TimeZoneId;
|
||||||
secondarySite.CultureCode = primarySite.CultureCode;
|
secondarySite.CultureCode = primarySite.CultureCode;
|
||||||
@@ -182,18 +185,20 @@ namespace Oqtane.Infrastructure
|
|||||||
secondarySite.DeletedBy = primarySite.DeletedBy;
|
secondarySite.DeletedBy = primarySite.DeletedBy;
|
||||||
secondarySite.DeletedOn = primarySite.DeletedOn;
|
secondarySite.DeletedOn = primarySite.DeletedOn;
|
||||||
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
|
||||||
var siteRepository = provider.GetRequiredService<ISiteRepository>();
|
var siteRepository = provider.GetRequiredService<ISiteRepository>();
|
||||||
siteRepository.UpdateSite(secondarySite);
|
siteRepository.UpdateSite(secondarySite);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Site Updated: {secondarySite.Name} - {CreateLink(siteGroupMember.AliasName)}");
|
log += Log(siteGroupMember, $"Site Updated: {secondarySite.Name} - {CreateLink(siteGroupMember.AliasName)}");
|
||||||
}
|
}
|
||||||
|
else // change detection
|
||||||
|
{
|
||||||
|
log += Log(siteGroupMember, $"Site Updated: {primarySite.Name} - {CreateLink(siteGroupMember.AliasName)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// site settings
|
// site settings
|
||||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Site, primarySite.SiteId, secondarySite.SiteId);
|
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Site, primarySite.SiteId, secondarySite.SiteId);
|
||||||
|
|
||||||
if (siteGroupMember.SynchronizedOn == DateTime.MinValue || !string.IsNullOrEmpty(log))
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization && (siteGroupMember.SynchronizedOn == DateTime.MinValue || !string.IsNullOrEmpty(log)))
|
||||||
{
|
{
|
||||||
// clear cache for secondary site if any content was Synchronized
|
// clear cache for secondary site if any content was Synchronized
|
||||||
var syncManager = provider.GetRequiredService<ISyncManager>();
|
var syncManager = provider.GetRequiredService<ISyncManager>();
|
||||||
@@ -201,11 +206,11 @@ namespace Oqtane.Infrastructure
|
|||||||
syncManager.AddSyncEvent(alias, EntityNames.Site, secondarySite.SiteId, SyncEventActions.Refresh);
|
syncManager.AddSyncEvent(alias, EntityNames.Site, secondarySite.SiteId, SyncEventActions.Refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(log) && siteGroupMember.SiteGroup.Type == SiteGroupTypes.ChangeDetection)
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.ChangeDetection && !string.IsNullOrEmpty(log))
|
||||||
{
|
{
|
||||||
// send change log to administrators
|
// send change log to administrators
|
||||||
SendNotifications(provider, secondarySite.SiteId, secondarySite.Name, log);
|
SendNotifications(provider, secondarySite.SiteId, secondarySite.Name, log);
|
||||||
log += Log(siteGroupMember, $"Change Log Sent To Administrators");
|
log += Log(siteGroupMember, $"Change Log Sent To Administrators For Secondary Site: {secondarySite.Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return log;
|
return log;
|
||||||
@@ -231,6 +236,8 @@ namespace Oqtane.Infrastructure
|
|||||||
var log = "";
|
var log = "";
|
||||||
|
|
||||||
foreach (var primaryRole in primaryRoles)
|
foreach (var primaryRole in primaryRoles)
|
||||||
|
{
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
{
|
{
|
||||||
var role = secondaryRoles.FirstOrDefault(item => item.Name == primaryRole.Name);
|
var role = secondaryRoles.FirstOrDefault(item => item.Name == primaryRole.Name);
|
||||||
|
|
||||||
@@ -250,19 +257,13 @@ namespace Oqtane.Infrastructure
|
|||||||
secondaryRole.IsSystem = primaryRole.IsSystem;
|
secondaryRole.IsSystem = primaryRole.IsSystem;
|
||||||
|
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
roleRepository.AddRole(secondaryRole);
|
roleRepository.AddRole(secondaryRole);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Role Added: {secondaryRole.Name}");
|
log += Log(siteGroupMember, $"Role Added: {secondaryRole.Name}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
roleRepository.UpdateRole(secondaryRole);
|
roleRepository.UpdateRole(secondaryRole);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Role Updated: {secondaryRole.Name}");
|
log += Log(siteGroupMember, $"Role Updated: {secondaryRole.Name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,16 +273,25 @@ namespace Oqtane.Infrastructure
|
|||||||
secondaryRoles.Remove(role);
|
secondaryRoles.Remove(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else // change detection
|
||||||
|
{
|
||||||
|
if (primaryRole.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||||
|
{
|
||||||
|
log += Log(siteGroupMember, $"Role Updated: {primaryRole.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
|
{
|
||||||
// remove roles in the secondary site which do not exist in the primary site
|
// remove roles in the secondary site which do not exist in the primary site
|
||||||
foreach (var secondaryRole in secondaryRoles)
|
foreach (var secondaryRole in secondaryRoles)
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
roleRepository.DeleteRole(secondaryRole.RoleId);
|
roleRepository.DeleteRole(secondaryRole.RoleId);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Role Deleted: {secondaryRole.Name}");
|
log += Log(siteGroupMember, $"Role Deleted: {secondaryRole.Name}");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Role, primarySiteId, secondarySiteId);
|
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Role, primarySiteId, secondarySiteId);
|
||||||
@@ -301,6 +311,8 @@ namespace Oqtane.Infrastructure
|
|||||||
|
|
||||||
// iterate through folders
|
// iterate through folders
|
||||||
foreach (var primaryFolder in primaryFolders)
|
foreach (var primaryFolder in primaryFolders)
|
||||||
|
{
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
{
|
{
|
||||||
var folder = secondaryFolders.FirstOrDefault(item => item.Path == primaryFolder.Path);
|
var folder = secondaryFolders.FirstOrDefault(item => item.Path == primaryFolder.Path);
|
||||||
|
|
||||||
@@ -333,19 +345,13 @@ namespace Oqtane.Infrastructure
|
|||||||
secondaryFolder.PermissionList = SynchronizePermissions(primaryFolder.PermissionList, secondarySiteId);
|
secondaryFolder.PermissionList = SynchronizePermissions(primaryFolder.PermissionList, secondarySiteId);
|
||||||
|
|
||||||
if (folder == null)
|
if (folder == null)
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
folderRepository.AddFolder(secondaryFolder);
|
folderRepository.AddFolder(secondaryFolder);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Folder Added: {secondaryFolder.Path}");
|
log += Log(siteGroupMember, $"Folder Added: {secondaryFolder.Path}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
folderRepository.UpdateFolder(secondaryFolder);
|
folderRepository.UpdateFolder(secondaryFolder);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Folder Updated: {secondaryFolder.Path}");
|
log += Log(siteGroupMember, $"Folder Updated: {secondaryFolder.Path}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -358,11 +364,52 @@ namespace Oqtane.Infrastructure
|
|||||||
// folder settings
|
// folder settings
|
||||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Folder, primaryFolder.FolderId, secondaryFolder.FolderId);
|
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Folder, primaryFolder.FolderId, secondaryFolder.FolderId);
|
||||||
|
|
||||||
|
// files
|
||||||
|
log += SynchronizeFiles(provider, folderRepository, fileRepository, siteGroupMember, primaryFolder, secondaryFolder);
|
||||||
|
}
|
||||||
|
else // change detection
|
||||||
|
{
|
||||||
|
if (primaryFolder.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||||
|
{
|
||||||
|
log += Log(siteGroupMember, $"Folder Updated: {primaryFolder.Path}");
|
||||||
|
|
||||||
|
// folder settings
|
||||||
|
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Folder, primaryFolder.FolderId, -1);
|
||||||
|
|
||||||
|
// files
|
||||||
|
log += SynchronizeFiles(provider, folderRepository, fileRepository, siteGroupMember, primaryFolder, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
|
{
|
||||||
|
// remove folders in the secondary site which do not exist in the primary site
|
||||||
|
foreach (var secondaryFolder in secondaryFolders)
|
||||||
|
{
|
||||||
|
folderRepository.DeleteFolder(secondaryFolder.FolderId);
|
||||||
|
log += Log(siteGroupMember, $"Folder Deleted: {secondaryFolder.Path}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SynchronizeFiles(IServiceProvider provider, IFolderRepository folderRepository, IFileRepository fileRepository, SiteGroupMember siteGroupMember, Folder primaryFolder, Folder secondaryFolder)
|
||||||
|
{
|
||||||
|
var log = "";
|
||||||
|
|
||||||
// get files for folder
|
// get files for folder
|
||||||
var primaryFiles = fileRepository.GetFiles(primaryFolder.FolderId);
|
var primaryFiles = fileRepository.GetFiles(primaryFolder.FolderId);
|
||||||
var secondaryFiles = fileRepository.GetFiles(secondaryFolder.FolderId).ToList();
|
var secondaryFiles = new List<Models.File>();
|
||||||
|
if (secondaryFolder != null)
|
||||||
|
{
|
||||||
|
secondaryFiles = fileRepository.GetFiles(secondaryFolder.FolderId).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var primaryFile in primaryFiles)
|
foreach (var primaryFile in primaryFiles)
|
||||||
|
{
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
{
|
{
|
||||||
var file = secondaryFiles.FirstOrDefault(item => item.Name == primaryFile.Name);
|
var file = secondaryFiles.FirstOrDefault(item => item.Name == primaryFile.Name);
|
||||||
|
|
||||||
@@ -384,21 +431,15 @@ namespace Oqtane.Infrastructure
|
|||||||
secondaryFile.Description = primaryFile.Description;
|
secondaryFile.Description = primaryFile.Description;
|
||||||
|
|
||||||
if (file == null)
|
if (file == null)
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
fileRepository.AddFile(secondaryFile);
|
fileRepository.AddFile(secondaryFile);
|
||||||
SynchronizeFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile);
|
SynchronizeFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"File Added: {CreateLink(siteGroupMember.AliasName + "/" + secondaryFolder.Path + secondaryFile.Name)}");
|
log += Log(siteGroupMember, $"File Added: {CreateLink(siteGroupMember.AliasName + "/" + secondaryFolder.Path + secondaryFile.Name)}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
fileRepository.UpdateFile(secondaryFile);
|
fileRepository.UpdateFile(secondaryFile);
|
||||||
SynchronizeFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile);
|
SynchronizeFile(folderRepository, primaryFolder, primaryFile, secondaryFolder, secondaryFile);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"File Updated: {CreateLink(siteGroupMember.AliasName + "/" + secondaryFolder.Path + secondaryFile.Name)}");
|
log += Log(siteGroupMember, $"File Updated: {CreateLink(siteGroupMember.AliasName + "/" + secondaryFolder.Path + secondaryFile.Name)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -408,30 +449,27 @@ namespace Oqtane.Infrastructure
|
|||||||
secondaryFiles.Remove(file);
|
secondaryFiles.Remove(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else // change detection
|
||||||
|
{
|
||||||
|
if (primaryFile.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||||
|
{
|
||||||
|
log += Log(siteGroupMember, $"File Updated: {CreateLink(siteGroupMember.AliasName + "/" + primaryFolder.Path + primaryFile.Name)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
|
{
|
||||||
// remove files in the secondary site which do not exist in the primary site
|
// remove files in the secondary site which do not exist in the primary site
|
||||||
foreach (var secondaryFile in secondaryFiles)
|
foreach (var secondaryFile in secondaryFiles)
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
fileRepository.DeleteFile(secondaryFile.FileId);
|
fileRepository.DeleteFile(secondaryFile.FileId);
|
||||||
var secondaryPath = Path.Combine(folderRepository.GetFolderPath(secondaryFolder), secondaryFile.Name);
|
var secondaryPath = Path.Combine(folderRepository.GetFolderPath(secondaryFolder), secondaryFile.Name);
|
||||||
System.IO.File.Delete(secondaryPath);
|
System.IO.File.Delete(secondaryPath);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"File Deleted: {CreateLink(siteGroupMember.AliasName + "/" + secondaryFolder.Path + secondaryFile.Name)}");
|
log += Log(siteGroupMember, $"File Deleted: {CreateLink(siteGroupMember.AliasName + "/" + secondaryFolder.Path + secondaryFile.Name)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove folders in the secondary site which do not exist in the primary site
|
|
||||||
foreach (var secondaryFolder in secondaryFolders)
|
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
|
||||||
folderRepository.DeleteFolder(secondaryFolder.FolderId);
|
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Folder Deleted: {secondaryFolder.Path}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,10 +494,11 @@ namespace Oqtane.Infrastructure
|
|||||||
var moduleRepository = provider.GetRequiredService<IModuleRepository>();
|
var moduleRepository = provider.GetRequiredService<IModuleRepository>();
|
||||||
var log = "";
|
var log = "";
|
||||||
|
|
||||||
List<PageModule> primaryPageModules = null;
|
|
||||||
List<PageModule> secondaryPageModules = null;
|
|
||||||
|
|
||||||
int tenantId = tenantManager.GetTenant().TenantId;
|
int tenantId = tenantManager.GetTenant().TenantId;
|
||||||
|
tenantManager.SetAlias(tenantId, primarySiteId); // required by ModuleDefinitionRepository.LoadModuleDefinitions()
|
||||||
|
var primaryPageModules = pageModuleRepository.GetPageModules(primarySiteId).ToList();
|
||||||
|
tenantManager.SetAlias(tenantId, secondarySiteId); // required by ModuleDefinitionRepository.LoadModuleDefinitions()
|
||||||
|
var secondaryPageModules = pageModuleRepository.GetPageModules(secondarySiteId).ToList();
|
||||||
|
|
||||||
// get pages (ignore personalized)
|
// get pages (ignore personalized)
|
||||||
var primaryPages = pageRepository.GetPages(primarySiteId).Where(item => item.UserId == null);
|
var primaryPages = pageRepository.GetPages(primarySiteId).Where(item => item.UserId == null);
|
||||||
@@ -467,6 +506,8 @@ namespace Oqtane.Infrastructure
|
|||||||
|
|
||||||
// iterate through primary pages
|
// iterate through primary pages
|
||||||
foreach (var primaryPage in primaryPages)
|
foreach (var primaryPage in primaryPages)
|
||||||
|
{
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
{
|
{
|
||||||
var page = secondaryPages.FirstOrDefault(item => item.Path == primaryPage.Path);
|
var page = secondaryPages.FirstOrDefault(item => item.Path == primaryPage.Path);
|
||||||
|
|
||||||
@@ -515,19 +556,13 @@ namespace Oqtane.Infrastructure
|
|||||||
secondaryPage.PermissionList = SynchronizePermissions(primaryPage.PermissionList, secondarySiteId);
|
secondaryPage.PermissionList = SynchronizePermissions(primaryPage.PermissionList, secondarySiteId);
|
||||||
|
|
||||||
if (page == null)
|
if (page == null)
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
secondaryPage = pageRepository.AddPage(secondaryPage);
|
secondaryPage = pageRepository.AddPage(secondaryPage);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Page Added: {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
log += Log(siteGroupMember, $"Page Added: {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
secondaryPage = pageRepository.UpdatePage(secondaryPage);
|
secondaryPage = pageRepository.UpdatePage(secondaryPage);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Page Updated: {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
log += Log(siteGroupMember, $"Page Updated: {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -541,17 +576,53 @@ namespace Oqtane.Infrastructure
|
|||||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Page, primaryPage.PageId, secondaryPage.PageId);
|
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Page, primaryPage.PageId, secondaryPage.PageId);
|
||||||
|
|
||||||
// modules
|
// modules
|
||||||
if (primaryPageModules == null)
|
log += SynchronizeModules(provider, settingRepository, pageModuleRepository, moduleRepository, siteGroupMember, primaryPageModules, secondaryPageModules, primaryPage, secondaryPage, secondarySiteId);
|
||||||
{
|
|
||||||
tenantManager.SetAlias(tenantId, primarySiteId); // required by ModuleDefinitionRepository.LoadModuleDefinitions()
|
|
||||||
primaryPageModules = pageModuleRepository.GetPageModules(primarySiteId).ToList();
|
|
||||||
}
|
}
|
||||||
if (secondaryPageModules == null)
|
else // change detection
|
||||||
{
|
{
|
||||||
tenantManager.SetAlias(tenantId, secondarySiteId); // required by ModuleDefinitionRepository.LoadModuleDefinitions()
|
if (primaryPage.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||||
secondaryPageModules = pageModuleRepository.GetPageModules(secondarySiteId).ToList();
|
{
|
||||||
|
log += Log(siteGroupMember, $"Page Updated: {CreateLink(siteGroupMember.AliasName + "/" + primaryPage.Path)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// page settings
|
||||||
|
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Page, primaryPage.PageId, -1);
|
||||||
|
|
||||||
|
// modules
|
||||||
|
log += SynchronizeModules(provider, settingRepository, pageModuleRepository, moduleRepository, siteGroupMember, primaryPageModules, secondaryPageModules, primaryPage, null, secondarySiteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
|
{
|
||||||
|
// remove pages in the secondary site which do not exist in the primary site
|
||||||
|
foreach (var secondaryPage in secondaryPages)
|
||||||
|
{
|
||||||
|
pageRepository.DeletePage(secondaryPage.PageId);
|
||||||
|
log += Log(siteGroupMember, $"Page Deleted: {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization && (siteGroupMember.SynchronizedOn == DateTime.MinValue || !string.IsNullOrEmpty(log)))
|
||||||
|
{
|
||||||
|
// clear cache for secondary site if any content was Synchronized
|
||||||
|
var syncManager = provider.GetRequiredService<ISyncManager>();
|
||||||
|
var alias = new Alias { TenantId = tenantManager.GetTenant().TenantId, SiteId = secondarySiteId };
|
||||||
|
syncManager.AddSyncEvent(alias, EntityNames.Site, secondarySiteId, SyncEventActions.Refresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SynchronizeModules(IServiceProvider provider, ISettingRepository settingRepository, IPageModuleRepository pageModuleRepository, IModuleRepository moduleRepository, SiteGroupMember siteGroupMember, List<PageModule> primaryPageModules, List<PageModule> secondaryPageModules, Page primaryPage, Page secondaryPage, int secondarySiteId)
|
||||||
|
{
|
||||||
|
var log = "";
|
||||||
|
|
||||||
|
// iterate through primary modules on primary page
|
||||||
foreach (var primaryPageModule in primaryPageModules.Where(item => item.PageId == primaryPage.PageId))
|
foreach (var primaryPageModule in primaryPageModules.Where(item => item.PageId == primaryPage.PageId))
|
||||||
|
{
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
{
|
{
|
||||||
var pageModule = secondaryPageModules.FirstOrDefault(item => item.PageId == secondaryPage.PageId && item.Module.ModuleDefinitionName == primaryPageModule.Module.ModuleDefinitionName && item.Title.ToLower() == primaryPageModule.Title.ToLower());
|
var pageModule = secondaryPageModules.FirstOrDefault(item => item.PageId == secondaryPage.PageId && item.Module.ModuleDefinitionName == primaryPageModule.Module.ModuleDefinitionName && item.Title.ToLower() == primaryPageModule.Title.ToLower());
|
||||||
|
|
||||||
@@ -584,22 +655,15 @@ namespace Oqtane.Infrastructure
|
|||||||
// check if module exists
|
// check if module exists
|
||||||
var module = secondaryPageModules.FirstOrDefault(item => item.Module.ModuleDefinitionName == primaryPageModule.Module.ModuleDefinitionName && item.Title.ToLower() == primaryPageModule.Title.ToLower())?.Module;
|
var module = secondaryPageModules.FirstOrDefault(item => item.Module.ModuleDefinitionName == primaryPageModule.Module.ModuleDefinitionName && item.Title.ToLower() == primaryPageModule.Title.ToLower())?.Module;
|
||||||
if (module == null)
|
if (module == null)
|
||||||
{
|
|
||||||
// add new module
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
module = moduleRepository.AddModule(secondaryPageModule.Module);
|
module = moduleRepository.AddModule(secondaryPageModule.Module);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Module Added: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
log += Log(siteGroupMember, $"Module Added: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||||
}
|
}
|
||||||
if (module != null)
|
if (module != null)
|
||||||
{
|
{
|
||||||
secondaryPageModule.ModuleId = module.ModuleId;
|
secondaryPageModule.ModuleId = module.ModuleId;
|
||||||
secondaryPageModule.Module = null; // remove tracking
|
secondaryPageModule.Module = null; // remove tracking
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
|
||||||
secondaryPageModule = pageModuleRepository.AddPageModule(secondaryPageModule);
|
secondaryPageModule = pageModuleRepository.AddPageModule(secondaryPageModule);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Module Instance Added: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
log += Log(siteGroupMember, $"Module Instance Added: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||||
secondaryPageModule.Module = module;
|
secondaryPageModule.Module = module;
|
||||||
}
|
}
|
||||||
@@ -608,25 +672,65 @@ namespace Oqtane.Infrastructure
|
|||||||
{
|
{
|
||||||
// update existing module
|
// update existing module
|
||||||
if (primaryPageModule.Module.ModifiedOn > siteGroupMember.SynchronizedOn)
|
if (primaryPageModule.Module.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
moduleRepository.UpdateModule(secondaryPageModule.Module);
|
moduleRepository.UpdateModule(secondaryPageModule.Module);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Module Updated: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
log += Log(siteGroupMember, $"Module Updated: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||||
}
|
}
|
||||||
if (primaryPageModule.ModifiedOn > siteGroupMember.SynchronizedOn)
|
if (primaryPageModule.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
{
|
||||||
secondaryPageModule = pageModuleRepository.UpdatePageModule(secondaryPageModule);
|
secondaryPageModule = pageModuleRepository.UpdatePageModule(secondaryPageModule);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Module Instance Updated: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
log += Log(siteGroupMember, $"Module Instance Updated: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pageModule != null)
|
||||||
|
{
|
||||||
|
secondaryPageModules.Remove(pageModule);
|
||||||
|
}
|
||||||
|
|
||||||
|
// module settings
|
||||||
|
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Module, primaryPageModule.ModuleId, secondaryPageModule.ModuleId);
|
||||||
|
|
||||||
// module content
|
// module content
|
||||||
|
log += SynchronizeModuleContent(provider, siteGroupMember, primaryPageModule, secondaryPageModule, primaryPage, secondaryPage);
|
||||||
|
}
|
||||||
|
else // change detection
|
||||||
|
{
|
||||||
|
if (primaryPageModule.Module.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||||
|
{
|
||||||
|
log += Log(siteGroupMember, $"Module Updated: {primaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + primaryPage.Path)}");
|
||||||
|
}
|
||||||
|
if (primaryPageModule.ModifiedOn > siteGroupMember.SynchronizedOn)
|
||||||
|
{
|
||||||
|
log += Log(siteGroupMember, $"Module Instance Updated: {primaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + primaryPage.Path)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// module settings
|
||||||
|
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Module, primaryPageModule.ModuleId, -1);
|
||||||
|
|
||||||
|
// module content
|
||||||
|
log += SynchronizeModuleContent(provider, siteGroupMember, primaryPageModule, null, primaryPage, secondaryPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
|
{
|
||||||
|
// remove modules on the secondary page which do not exist on the primary page
|
||||||
|
foreach (var secondaryPageModule in secondaryPageModules.Where(item => item.PageId == secondaryPage.PageId))
|
||||||
|
{
|
||||||
|
pageModuleRepository.DeletePageModule(secondaryPageModule.PageModuleId);
|
||||||
|
log += Log(siteGroupMember, $"Module Instance Deleted: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPageModule.Page.Path)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string SynchronizeModuleContent(IServiceProvider provider, SiteGroupMember siteGroupMember, PageModule primaryPageModule, PageModule secondaryPageModule, Page primaryPage, Page secondaryPage)
|
||||||
|
{
|
||||||
|
var log = "";
|
||||||
|
|
||||||
if (primaryPageModule.Module.ModuleDefinition.ServerManagerType != "")
|
if (primaryPageModule.Module.ModuleDefinition.ServerManagerType != "")
|
||||||
{
|
{
|
||||||
Type moduleType = Type.GetType(primaryPageModule.Module.ModuleDefinition.ServerManagerType);
|
Type moduleType = Type.GetType(primaryPageModule.Module.ModuleDefinition.ServerManagerType);
|
||||||
@@ -641,9 +745,13 @@ namespace Oqtane.Infrastructure
|
|||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
{
|
{
|
||||||
((ISynchronizable)moduleObject).LoadModule(secondaryPageModule.Module, moduleContent);
|
((ISynchronizable)moduleObject).LoadModule(secondaryPageModule.Module, moduleContent);
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Module Content Updated: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
log += Log(siteGroupMember, $"Module Content Updated: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
||||||
}
|
}
|
||||||
|
else // change detection
|
||||||
|
{
|
||||||
|
log += Log(siteGroupMember, $"Module Content Updated: {primaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + primaryPage.Path)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -652,57 +760,6 @@ namespace Oqtane.Infrastructure
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageModule != null)
|
|
||||||
{
|
|
||||||
secondaryPageModules.Remove(pageModule);
|
|
||||||
}
|
|
||||||
|
|
||||||
// module settings
|
|
||||||
log += SynchronizeSettings(settingRepository, siteGroupMember, EntityNames.Module, primaryPageModule.ModuleId, secondaryPageModule.ModuleId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove modules in the secondary site which do not exist in the primary site
|
|
||||||
foreach (var secondaryPageModule in secondaryPageModules)
|
|
||||||
{
|
|
||||||
var primaryPageId = -1;
|
|
||||||
var secondaryPage = secondaryPages.FirstOrDefault(item => item.PageId == secondaryPageModule.PageId);
|
|
||||||
if (secondaryPage != null)
|
|
||||||
{
|
|
||||||
var primaryPage = primaryPages.FirstOrDefault(item => item.Path == secondaryPage.Path);
|
|
||||||
if (primaryPage != null)
|
|
||||||
{
|
|
||||||
primaryPageId = primaryPage.PageId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!primaryPageModules.Any(item => item.PageId == primaryPageId && item.Module.ModuleDefinitionName == secondaryPageModule.Module.ModuleDefinitionName && item.Title.ToLower() == secondaryPageModule.Title.ToLower()))
|
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
|
||||||
pageModuleRepository.DeletePageModule(secondaryPageModule.PageModuleId);
|
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Module Instance Deleted: {secondaryPageModule.Title} - {CreateLink(siteGroupMember.AliasName + "/" + secondaryPageModule.Page.Path)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove pages in the secondary site which do not exist in the primary site
|
|
||||||
foreach (var secondaryPage in secondaryPages)
|
|
||||||
{
|
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
|
||||||
{
|
|
||||||
pageRepository.DeletePage(secondaryPage.PageId);
|
|
||||||
}
|
|
||||||
log += Log(siteGroupMember, $"Page Deleted: {CreateLink(siteGroupMember.AliasName + "/" + secondaryPage.Path)}");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (siteGroupMember.SynchronizedOn == DateTime.MinValue || !string.IsNullOrEmpty(log))
|
|
||||||
{
|
|
||||||
// clear cache for secondary site if any content was Synchronized
|
|
||||||
var syncManager = provider.GetRequiredService<ISyncManager>();
|
|
||||||
var alias = new Alias { TenantId = tenantManager.GetTenant().TenantId, SiteId = secondarySiteId };
|
|
||||||
syncManager.AddSyncEvent(alias, EntityNames.Site, secondarySiteId, SyncEventActions.Refresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,6 +786,8 @@ namespace Oqtane.Infrastructure
|
|||||||
|
|
||||||
var secondarySettings = settingRepository.GetSettings(entityName, secondaryEntityId).ToList();
|
var secondarySettings = settingRepository.GetSettings(entityName, secondaryEntityId).ToList();
|
||||||
foreach (var primarySetting in settingRepository.GetSettings(entityName, primaryEntityId))
|
foreach (var primarySetting in settingRepository.GetSettings(entityName, primaryEntityId))
|
||||||
|
{
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
{
|
{
|
||||||
var secondarySetting = secondarySettings.FirstOrDefault(item => item.SettingName == primarySetting.SettingName);
|
var secondarySetting = secondarySettings.FirstOrDefault(item => item.SettingName == primarySetting.SettingName);
|
||||||
if (secondarySetting == null)
|
if (secondarySetting == null)
|
||||||
@@ -739,7 +798,7 @@ namespace Oqtane.Infrastructure
|
|||||||
secondarySetting.SettingName = primarySetting.SettingName;
|
secondarySetting.SettingName = primarySetting.SettingName;
|
||||||
secondarySetting.SettingValue = primarySetting.SettingValue;
|
secondarySetting.SettingValue = primarySetting.SettingValue;
|
||||||
secondarySetting.IsPrivate = primarySetting.IsPrivate;
|
secondarySetting.IsPrivate = primarySetting.IsPrivate;
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
if (!excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
||||||
{
|
{
|
||||||
settingRepository.AddSetting(secondarySetting);
|
settingRepository.AddSetting(secondarySetting);
|
||||||
updated = true;
|
updated = true;
|
||||||
@@ -751,7 +810,7 @@ namespace Oqtane.Infrastructure
|
|||||||
{
|
{
|
||||||
secondarySetting.SettingValue = primarySetting.SettingValue;
|
secondarySetting.SettingValue = primarySetting.SettingValue;
|
||||||
secondarySetting.IsPrivate = primarySetting.IsPrivate;
|
secondarySetting.IsPrivate = primarySetting.IsPrivate;
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
if (!excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
||||||
{
|
{
|
||||||
settingRepository.UpdateSetting(secondarySetting);
|
settingRepository.UpdateSetting(secondarySetting);
|
||||||
updated = true;
|
updated = true;
|
||||||
@@ -760,16 +819,27 @@ namespace Oqtane.Infrastructure
|
|||||||
secondarySettings.Remove(secondarySetting);
|
secondarySettings.Remove(secondarySetting);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else // change detection
|
||||||
|
{
|
||||||
|
if (primarySetting.ModifiedOn > siteGroupMember.SynchronizedOn && !excludedSettings.Any(item => item.EntityName == primarySetting.EntityName && item.SettingName == primarySetting.SettingName))
|
||||||
|
{
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization)
|
||||||
|
{
|
||||||
// any remaining secondary settings need to be deleted
|
// any remaining secondary settings need to be deleted
|
||||||
foreach (var secondarySetting in secondarySettings)
|
foreach (var secondarySetting in secondarySettings)
|
||||||
{
|
{
|
||||||
if (siteGroupMember.SiteGroup.Type == SiteGroupTypes.Synchronization && !excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
if (!excludedSettings.Any(item => item.EntityName == secondarySetting.EntityName && item.SettingName == secondarySetting.SettingName))
|
||||||
{
|
{
|
||||||
settingRepository.DeleteSetting(secondarySetting.EntityName, secondarySetting.SettingId);
|
settingRepository.DeleteSetting(secondarySetting.EntityName, secondarySetting.SettingId);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (updated)
|
if (updated)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user