403 lines
17 KiB
C#
403 lines
17 KiB
C#
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
using Nop.Core;
|
|
using Nop.Core.Caching;
|
|
using Nop.Services.Authentication.External;
|
|
using Nop.Services.Authentication.MultiFactor;
|
|
using Nop.Services.Catalog;
|
|
using Nop.Services.Cms;
|
|
using Nop.Services.Common;
|
|
using Nop.Services.Localization;
|
|
using Nop.Services.Payments;
|
|
using Nop.Services.Plugins;
|
|
using Nop.Services.Plugins.Marketplace;
|
|
using Nop.Services.Shipping;
|
|
using Nop.Services.Shipping.Pickup;
|
|
using Nop.Services.Tax;
|
|
using Nop.Web.Areas.Admin.Infrastructure.Mapper.Extensions;
|
|
using Nop.Web.Areas.Admin.Models.Plugins;
|
|
using Nop.Web.Areas.Admin.Models.Plugins.Marketplace;
|
|
using Nop.Web.Framework.Factories;
|
|
using Nop.Web.Framework.Models.Extensions;
|
|
|
|
namespace Nop.Web.Areas.Admin.Factories;
|
|
|
|
/// <summary>
|
|
/// Represents the plugin model factory implementation
|
|
/// </summary>
|
|
public partial class PluginModelFactory : IPluginModelFactory
|
|
{
|
|
#region Fields
|
|
|
|
protected readonly IAuthenticationPluginManager _authenticationPluginManager;
|
|
protected readonly IBaseAdminModelFactory _baseAdminModelFactory;
|
|
protected readonly ILocalizationService _localizationService;
|
|
protected readonly ILocalizedModelFactory _localizedModelFactory;
|
|
protected readonly IMultiFactorAuthenticationPluginManager _multiFactorAuthenticationPluginManager;
|
|
protected readonly IPaymentPluginManager _paymentPluginManager;
|
|
protected readonly IPickupPluginManager _pickupPluginManager;
|
|
protected readonly IPluginService _pluginService;
|
|
protected readonly ISearchPluginManager _searchPluginManager;
|
|
protected readonly IShippingPluginManager _shippingPluginManager;
|
|
protected readonly IStaticCacheManager _staticCacheManager;
|
|
protected readonly IStoreMappingSupportedModelFactory _storeMappingSupportedModelFactory;
|
|
protected readonly ITaxPluginManager _taxPluginManager;
|
|
protected readonly IWidgetPluginManager _widgetPluginManager;
|
|
protected readonly IWorkContext _workContext;
|
|
protected readonly OfficialFeedManager _officialFeedManager;
|
|
|
|
#endregion
|
|
|
|
#region Ctor
|
|
|
|
public PluginModelFactory(IAuthenticationPluginManager authenticationPluginManager,
|
|
IBaseAdminModelFactory baseAdminModelFactory,
|
|
ILocalizationService localizationService,
|
|
IMultiFactorAuthenticationPluginManager multiFactorAuthenticationPluginManager,
|
|
ILocalizedModelFactory localizedModelFactory,
|
|
IPaymentPluginManager paymentPluginManager,
|
|
IPickupPluginManager pickupPluginManager,
|
|
IPluginService pluginService,
|
|
ISearchPluginManager searchPluginManager,
|
|
IShippingPluginManager shippingPluginManager,
|
|
IStaticCacheManager staticCacheManager,
|
|
IStoreMappingSupportedModelFactory storeMappingSupportedModelFactory,
|
|
ITaxPluginManager taxPluginManager,
|
|
IWidgetPluginManager widgetPluginManager,
|
|
IWorkContext workContext,
|
|
OfficialFeedManager officialFeedManager)
|
|
{
|
|
_authenticationPluginManager = authenticationPluginManager;
|
|
_baseAdminModelFactory = baseAdminModelFactory;
|
|
_localizationService = localizationService;
|
|
_localizedModelFactory = localizedModelFactory;
|
|
_multiFactorAuthenticationPluginManager = multiFactorAuthenticationPluginManager;
|
|
_paymentPluginManager = paymentPluginManager;
|
|
_pickupPluginManager = pickupPluginManager;
|
|
_pluginService = pluginService;
|
|
_searchPluginManager = searchPluginManager;
|
|
_shippingPluginManager = shippingPluginManager;
|
|
_staticCacheManager = staticCacheManager;
|
|
_storeMappingSupportedModelFactory = storeMappingSupportedModelFactory;
|
|
_taxPluginManager = taxPluginManager;
|
|
_widgetPluginManager = widgetPluginManager;
|
|
_workContext = workContext;
|
|
_officialFeedManager = officialFeedManager;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Utilities
|
|
|
|
/// <summary>
|
|
/// Prepare plugin model properties of the installed plugin
|
|
/// </summary>
|
|
/// <param name="model">Plugin model</param>
|
|
/// <param name="plugin">Plugin</param>
|
|
protected virtual void PrepareInstalledPluginModel(PluginModel model, IPlugin plugin)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(model);
|
|
|
|
ArgumentNullException.ThrowIfNull(plugin);
|
|
|
|
//prepare configuration URL
|
|
model.ConfigurationUrl = plugin.GetConfigurationPageUrl();
|
|
|
|
//prepare enabled/disabled (only for some plugin types)
|
|
model.CanChangeEnabled = true;
|
|
switch (plugin)
|
|
{
|
|
case IMiscPlugin:
|
|
model.CanChangeEnabled = false;
|
|
break;
|
|
|
|
case IPaymentMethod paymentMethod:
|
|
model.IsEnabled = _paymentPluginManager.IsPluginActive(paymentMethod);
|
|
break;
|
|
|
|
case IShippingRateComputationMethod shippingRateComputationMethod:
|
|
model.IsEnabled = _shippingPluginManager.IsPluginActive(shippingRateComputationMethod);
|
|
break;
|
|
|
|
case IPickupPointProvider pickupPointProvider:
|
|
model.IsEnabled = _pickupPluginManager.IsPluginActive(pickupPointProvider);
|
|
break;
|
|
|
|
case ITaxProvider taxProvider:
|
|
model.IsEnabled = _taxPluginManager.IsPluginActive(taxProvider);
|
|
break;
|
|
|
|
case IExternalAuthenticationMethod externalAuthenticationMethod:
|
|
model.IsEnabled = _authenticationPluginManager.IsPluginActive(externalAuthenticationMethod);
|
|
break;
|
|
|
|
case IMultiFactorAuthenticationMethod multiFactorAuthenticationMethod:
|
|
model.IsEnabled = _multiFactorAuthenticationPluginManager.IsPluginActive(multiFactorAuthenticationMethod);
|
|
break;
|
|
|
|
case ISearchProvider searchProvider:
|
|
model.IsEnabled = _searchPluginManager.IsPluginActive(searchProvider);
|
|
break;
|
|
|
|
case IWidgetPlugin widgetPlugin:
|
|
model.IsEnabled = _widgetPluginManager.IsPluginActive(widgetPlugin);
|
|
break;
|
|
|
|
default:
|
|
model.CanChangeEnabled = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
/// Prepare plugin search model
|
|
/// </summary>
|
|
/// <param name="searchModel">Plugin search model</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the plugin search model
|
|
/// </returns>
|
|
public virtual async Task<PluginSearchModel> PreparePluginSearchModelAsync(PluginSearchModel searchModel)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(searchModel);
|
|
|
|
//prepare available load plugin modes
|
|
await _baseAdminModelFactory.PrepareLoadPluginModesAsync(searchModel.AvailableLoadModes, false);
|
|
|
|
//prepare available groups
|
|
await _baseAdminModelFactory.PreparePluginGroupsAsync(searchModel.AvailableGroups);
|
|
|
|
//prepare page parameters
|
|
searchModel.SetGridPageSize();
|
|
|
|
searchModel.NeedToRestart = _pluginService.IsRestartRequired();
|
|
|
|
return searchModel;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare paged plugin list model
|
|
/// </summary>
|
|
/// <param name="searchModel">Plugin search model</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the plugin list model
|
|
/// </returns>
|
|
public virtual async Task<PluginListModel> PreparePluginListModelAsync(PluginSearchModel searchModel)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(searchModel);
|
|
|
|
//get parameters to filter plugins
|
|
var group = string.IsNullOrEmpty(searchModel.SearchGroup) || searchModel.SearchGroup.Equals("0") ? null : searchModel.SearchGroup;
|
|
var loadMode = (LoadPluginsMode)searchModel.SearchLoadModeId;
|
|
var friendlyName = string.IsNullOrEmpty(searchModel.SearchFriendlyName) ? null : searchModel.SearchFriendlyName;
|
|
var author = string.IsNullOrEmpty(searchModel.SearchAuthor) ? null : searchModel.SearchAuthor;
|
|
|
|
//filter visible plugins
|
|
var plugins = (await _pluginService.GetPluginDescriptorsAsync<IPlugin>(group: group, loadMode: loadMode, friendlyName: friendlyName, author: author))
|
|
.Where(p => p.ShowInPluginsList)
|
|
.OrderBy(plugin => plugin.Group).ToList()
|
|
.ToPagedList(searchModel);
|
|
|
|
//prepare list model
|
|
var model = await new PluginListModel().PrepareToGridAsync(searchModel, plugins, () =>
|
|
{
|
|
return plugins.SelectAwait(async pluginDescriptor =>
|
|
{
|
|
//fill in model values from the entity
|
|
var pluginModel = pluginDescriptor.ToPluginModel<PluginModel>();
|
|
|
|
//fill in additional values (not existing in the entity)
|
|
pluginModel.LogoUrl = await _pluginService.GetPluginLogoUrlAsync(pluginDescriptor);
|
|
|
|
if (pluginDescriptor.Installed)
|
|
PrepareInstalledPluginModel(pluginModel, pluginDescriptor.Instance<IPlugin>());
|
|
|
|
return pluginModel;
|
|
});
|
|
});
|
|
|
|
return model;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare plugin model
|
|
/// </summary>
|
|
/// <param name="model">Plugin model</param>
|
|
/// <param name="pluginDescriptor">Plugin descriptor</param>
|
|
/// <param name="excludeProperties">Whether to exclude populating of some properties of model</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the plugin model
|
|
/// </returns>
|
|
public virtual async Task<PluginModel> PreparePluginModelAsync(PluginModel model, PluginDescriptor pluginDescriptor, bool excludeProperties = false)
|
|
{
|
|
Func<PluginLocalizedModel, int, Task> localizedModelConfiguration = null;
|
|
|
|
if (pluginDescriptor != null)
|
|
{
|
|
//fill in model values from the entity
|
|
model ??= pluginDescriptor.ToPluginModel(model);
|
|
|
|
model.LogoUrl = await _pluginService.GetPluginLogoUrlAsync(pluginDescriptor);
|
|
model.SelectedStoreIds = pluginDescriptor.LimitedToStores;
|
|
model.SelectedCustomerRoleIds = pluginDescriptor.LimitedToCustomerRoles;
|
|
var plugin = pluginDescriptor.Instance<IPlugin>();
|
|
if (pluginDescriptor.Installed)
|
|
PrepareInstalledPluginModel(model, plugin);
|
|
|
|
//define localized model configuration action
|
|
localizedModelConfiguration = async (locale, languageId) =>
|
|
{
|
|
locale.FriendlyName = await _localizationService.GetLocalizedFriendlyNameAsync(plugin, languageId, false);
|
|
};
|
|
}
|
|
|
|
//prepare localized models
|
|
if (!excludeProperties)
|
|
model.Locales = await _localizedModelFactory.PrepareLocalizedModelsAsync(localizedModelConfiguration);
|
|
|
|
//prepare available stores
|
|
await _storeMappingSupportedModelFactory.PrepareModelStoresAsync(model);
|
|
|
|
return model;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare search model of plugins of the official feed
|
|
/// </summary>
|
|
/// <param name="searchModel">Search model of plugins of the official feed</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the search model of plugins of the official feed
|
|
/// </returns>
|
|
public virtual async Task<OfficialFeedPluginSearchModel> PrepareOfficialFeedPluginSearchModelAsync(OfficialFeedPluginSearchModel searchModel)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(searchModel);
|
|
|
|
//prepare available versions
|
|
var pluginVersions = await _officialFeedManager.GetVersionsAsync();
|
|
searchModel.AvailableVersions.Add(new SelectListItem { Text = await _localizationService.GetResourceAsync("Admin.Common.All"), Value = "0" });
|
|
foreach (var version in pluginVersions)
|
|
searchModel.AvailableVersions.Add(new SelectListItem { Text = version.Name, Value = version.Id.ToString() });
|
|
|
|
//pre-select current version
|
|
//current version name and named on official site do not match. that's why we use "Contains"
|
|
var currentVersionItem = searchModel.AvailableVersions.FirstOrDefault(x => x.Text.Contains(NopVersion.CURRENT_VERSION));
|
|
if (currentVersionItem != null)
|
|
{
|
|
searchModel.SearchVersionId = int.Parse(currentVersionItem.Value);
|
|
currentVersionItem.Selected = true;
|
|
}
|
|
|
|
//prepare available plugin categories
|
|
var pluginCategories = await _officialFeedManager.GetCategoriesAsync();
|
|
searchModel.AvailableCategories.Add(new SelectListItem { Text = await _localizationService.GetResourceAsync("Admin.Common.All"), Value = "0" });
|
|
foreach (var pluginCategory in pluginCategories)
|
|
{
|
|
var pluginCategoryNames = new List<string>();
|
|
var tmpCategory = pluginCategory;
|
|
while (tmpCategory != null)
|
|
{
|
|
pluginCategoryNames.Add(tmpCategory.Name);
|
|
tmpCategory = pluginCategories.FirstOrDefault(category => category.Id == tmpCategory.ParentCategoryId);
|
|
}
|
|
|
|
pluginCategoryNames.Reverse();
|
|
|
|
searchModel.AvailableCategories.Add(new SelectListItem
|
|
{
|
|
Value = pluginCategory.Id.ToString(),
|
|
Text = string.Join(" >> ", pluginCategoryNames)
|
|
});
|
|
}
|
|
|
|
//prepare available prices
|
|
searchModel.AvailablePrices.Add(new SelectListItem
|
|
{
|
|
Value = "0",
|
|
Text = await _localizationService.GetResourceAsync("Admin.Common.All")
|
|
});
|
|
searchModel.AvailablePrices.Add(new SelectListItem
|
|
{
|
|
Value = "10",
|
|
Text = await _localizationService.GetResourceAsync("Admin.Configuration.Plugins.OfficialFeed.Price.Free")
|
|
});
|
|
searchModel.AvailablePrices.Add(new SelectListItem
|
|
{
|
|
Value = "20",
|
|
Text = await _localizationService.GetResourceAsync("Admin.Configuration.Plugins.OfficialFeed.Price.Commercial")
|
|
});
|
|
|
|
//prepare page parameters
|
|
searchModel.SetGridPageSize(15, "15");
|
|
|
|
return searchModel;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare paged list model of plugins of the official feed
|
|
/// </summary>
|
|
/// <param name="searchModel">Search model of plugins of the official feed</param>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the list model of plugins of the official feed
|
|
/// </returns>
|
|
public virtual async Task<OfficialFeedPluginListModel> PrepareOfficialFeedPluginListModelAsync(OfficialFeedPluginSearchModel searchModel)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(searchModel);
|
|
|
|
//get plugins
|
|
var plugins = await _officialFeedManager.GetAllPluginsAsync(categoryId: searchModel.SearchCategoryId,
|
|
versionId: searchModel.SearchVersionId,
|
|
price: searchModel.SearchPriceId,
|
|
searchTerm: searchModel.SearchName,
|
|
pageIndex: searchModel.Page - 1, pageSize: searchModel.PageSize);
|
|
|
|
//prepare list model
|
|
var model = new OfficialFeedPluginListModel().PrepareToGrid(searchModel, plugins, () =>
|
|
{
|
|
//fill in model values from the entity
|
|
return plugins?.Select(plugin => new OfficialFeedPluginModel
|
|
{
|
|
Url = plugin.Url,
|
|
Name = plugin.Name,
|
|
CategoryName = plugin.Category,
|
|
SupportedVersions = plugin.SupportedVersions,
|
|
PictureUrl = plugin.PictureUrl,
|
|
Price = plugin.Price
|
|
}) ?? new List<OfficialFeedPluginModel>();
|
|
});
|
|
|
|
return model;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prepare plugin models for admin navigation
|
|
/// </summary>
|
|
/// <returns>
|
|
/// A task that represents the asynchronous operation
|
|
/// The task result contains the list of models
|
|
/// </returns>
|
|
public virtual async Task<IList<AdminNavigationPluginModel>> PrepareAdminNavigationPluginModelsAsync()
|
|
{
|
|
var customer = await _workContext.GetCurrentCustomerAsync();
|
|
var cacheKey = _staticCacheManager.PrepareKeyForDefaultCache(NopPluginDefaults.AdminNavigationPluginsCacheKey, customer);
|
|
return await _staticCacheManager.GetAsync(cacheKey, async () =>
|
|
{
|
|
//get installed plugins
|
|
return (await _pluginService.GetPluginDescriptorsAsync<IPlugin>(LoadPluginsMode.InstalledOnly, customer))
|
|
.Where(plugin => plugin.ShowInPluginsList)
|
|
.Select(plugin => new AdminNavigationPluginModel
|
|
{
|
|
FriendlyName = plugin.FriendlyName,
|
|
ConfigurationUrl = plugin.Instance<IPlugin>().GetConfigurationPageUrl()
|
|
}).Where(model => !string.IsNullOrEmpty(model.ConfigurationUrl)).ToList();
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
} |