Try your search with a different keyword or use * as a wildcard.
using System.Reflection;
using Microsoft.AspNetCore.Http;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Media;
using Nop.Core.Infrastructure;
using Nop.Data.Migrations;
using Nop.Services.Customers;
using Nop.Services.Localization;
using Nop.Services.Logging;
namespace Nop.Services.Plugins;
///
/// Represents the plugin service implementation
///
public partial class PluginService : IPluginService
{
#region Fields
protected readonly CatalogSettings _catalogSettings;
protected readonly ICustomerService _customerService;
protected readonly IHttpContextAccessor _httpContextAccessor;
protected readonly IMigrationManager _migrationManager;
protected readonly ILogger _logger;
protected readonly INopFileProvider _fileProvider;
protected readonly IPluginsInfo _pluginsInfo;
protected readonly IWebHelper _webHelper;
protected readonly MediaSettings _mediaSettings;
#endregion
#region Ctor
public PluginService(CatalogSettings catalogSettings,
ICustomerService customerService,
IHttpContextAccessor httpContextAccessor,
IMigrationManager migrationManager,
ILogger logger,
INopFileProvider fileProvider,
IWebHelper webHelper,
MediaSettings mediaSettings)
{
_catalogSettings = catalogSettings;
_customerService = customerService;
_httpContextAccessor = httpContextAccessor;
_migrationManager = migrationManager;
_logger = logger;
_fileProvider = fileProvider;
_pluginsInfo = Singleton.Instance;
_webHelper = webHelper;
_mediaSettings = mediaSettings;
}
#endregion
#region Utilities
///
/// Check whether to load the plugin based on the load mode passed
///
/// Plugin descriptor to check
/// Load plugins mode
/// Result of check
protected virtual bool FilterByLoadMode(PluginDescriptor pluginDescriptor, LoadPluginsMode loadMode)
{
ArgumentNullException.ThrowIfNull(pluginDescriptor);
return loadMode switch
{
LoadPluginsMode.All => true,
LoadPluginsMode.InstalledOnly => pluginDescriptor.Installed,
LoadPluginsMode.NotInstalledOnly => !pluginDescriptor.Installed,
_ => throw new NotSupportedException(nameof(loadMode)),
};
}
///
/// Check whether to load the plugin based on the plugin group passed
///
/// Plugin descriptor to check
/// Group name
/// Result of check
protected virtual bool FilterByPluginGroup(PluginDescriptor pluginDescriptor, string group)
{
ArgumentNullException.ThrowIfNull(pluginDescriptor);
if (string.IsNullOrEmpty(group))
return true;
return group.Equals(pluginDescriptor.Group, StringComparison.InvariantCultureIgnoreCase);
}
///
/// Check whether to load the plugin based on the customer passed
///
/// Plugin descriptor to check
/// Customer
///
/// A task that represents the asynchronous operation
/// The task result contains the result of check
///
protected virtual async Task FilterByCustomerAsync(PluginDescriptor pluginDescriptor, Customer customer)
{
ArgumentNullException.ThrowIfNull(pluginDescriptor);
if (customer == null || !pluginDescriptor.LimitedToCustomerRoles.Any())
return true;
if (_catalogSettings.IgnoreAcl)
return true;
return pluginDescriptor.LimitedToCustomerRoles.Intersect(await _customerService.GetCustomerRoleIdsAsync(customer)).Any();
}
///
/// Check whether to load the plugin based on the store identifier passed
///
/// Plugin descriptor to check
/// Store identifier
/// Result of check
protected virtual bool FilterByStore(PluginDescriptor pluginDescriptor, int storeId)
{
ArgumentNullException.ThrowIfNull(pluginDescriptor);
//no validation required
if (storeId == 0)
return true;
if (!pluginDescriptor.LimitedToStores.Any())
return true;
return pluginDescriptor.LimitedToStores.Contains(storeId);
}
///
/// Check whether to load the plugin based on dependency from other plugin
///
/// Plugin descriptor to check
/// Other plugin system name
/// Result of check
protected virtual bool FilterByDependsOn(PluginDescriptor pluginDescriptor, string dependsOnSystemName)
{
ArgumentNullException.ThrowIfNull(pluginDescriptor);
if (string.IsNullOrEmpty(dependsOnSystemName))
return true;
return pluginDescriptor.DependsOn?.Contains(dependsOnSystemName) ?? false;
}
///
/// Check whether to load the plugin based on the plugin friendly name passed
///
/// Plugin descriptor to check
/// Plugin friendly name
/// Result of check
protected virtual bool FilterByPluginFriendlyName(PluginDescriptor pluginDescriptor, string friendlyName)
{
ArgumentNullException.ThrowIfNull(pluginDescriptor);
if (string.IsNullOrEmpty(friendlyName))
return true;
return pluginDescriptor.FriendlyName.Contains(friendlyName, StringComparison.InvariantCultureIgnoreCase);
}
///
/// Check whether to load the plugin based on the plugin author passed
///
/// Plugin descriptor to check
/// Plugin author
/// Result of check
protected virtual bool FilterByPluginAuthor(PluginDescriptor pluginDescriptor, string author)
{
ArgumentNullException.ThrowIfNull(pluginDescriptor);
if (string.IsNullOrEmpty(author))
return true;
return pluginDescriptor.Author.Contains(author, StringComparison.InvariantCultureIgnoreCase);
}
///
/// Insert plugin data
///
/// Plugin type
/// Migration process type
protected virtual void InsertPluginData(Type pluginType, MigrationProcessType migrationProcessType = MigrationProcessType.NoMatter)
{
var assembly = Assembly.GetAssembly(pluginType);
_migrationManager.ApplyUpMigrations(assembly, migrationProcessType);
//mark update migrations as applied
if (migrationProcessType == MigrationProcessType.Installation)
{
_migrationManager.ApplyUpMigrations(assembly, MigrationProcessType.Update, true);
}
}
#endregion
#region Methods
///
/// Get plugin descriptors
///
/// The type of plugins to get
/// Filter by load plugins mode
/// Filter by customer; pass null to load all records
/// Filter by store; pass 0 to load all records
/// Filter by plugin group; pass null to load all records
/// Filter by plugin friendly name; pass null to load all records
/// Filter by plugin author; pass null to load all records
/// System name of the plugin to define dependencies
///
/// A task that represents the asynchronous operation
/// The task result contains the plugin descriptors
///
public virtual async Task> GetPluginDescriptorsAsync(LoadPluginsMode loadMode = LoadPluginsMode.InstalledOnly,
Customer customer = null, int storeId = 0, string group = null, string dependsOnSystemName = "", string friendlyName = null, string author = null) where TPlugin : class, IPlugin
{
var pluginDescriptors = _pluginsInfo.PluginDescriptors.Select(p => p.pluginDescriptor).ToList();
//filter plugins
pluginDescriptors = await pluginDescriptors.WhereAwait(async descriptor =>
FilterByLoadMode(descriptor, loadMode) &&
await FilterByCustomerAsync(descriptor, customer) &&
FilterByStore(descriptor, storeId) &&
FilterByPluginGroup(descriptor, group) &&
FilterByDependsOn(descriptor, dependsOnSystemName) &&
FilterByPluginFriendlyName(descriptor, friendlyName) &&
FilterByPluginAuthor(descriptor, author)).ToListAsync();
//filter by the passed type
if (typeof(TPlugin) != typeof(IPlugin))
pluginDescriptors = pluginDescriptors.Where(descriptor => typeof(TPlugin).IsAssignableFrom(descriptor.PluginType)).ToList();
//order by group name
pluginDescriptors = pluginDescriptors.OrderBy(descriptor => descriptor.Group)
.ThenBy(descriptor => descriptor.DisplayOrder).ToList();
return pluginDescriptors;
}
///
/// Get a plugin descriptor by the system name
///
/// The type of plugin to get
/// Plugin system name
/// Load plugins mode
/// Filter by customer; pass null to load all records
/// Filter by store; pass 0 to load all records
/// Filter by plugin group; pass null to load all records
///
/// A task that represents the asynchronous operation
/// The task result contains the >Plugin descriptor
///
public virtual async Task GetPluginDescriptorBySystemNameAsync(string systemName,
LoadPluginsMode loadMode = LoadPluginsMode.InstalledOnly,
Customer customer = null, int storeId = 0, string @group = null) where TPlugin : class, IPlugin
{
return (await GetPluginDescriptorsAsync(loadMode, customer, storeId, group))
.FirstOrDefault(descriptor => descriptor.SystemName.Equals(systemName));
}
///
/// Get plugins
///
/// The type of plugins to get
/// Filter by load plugins mode
/// Filter by customer; pass null to load all records
/// Filter by store; pass 0 to load all records
/// Filter by plugin group; pass null to load all records
///
/// A task that represents the asynchronous operation
/// The task result contains the plugins
///
public virtual async Task> GetPluginsAsync(
LoadPluginsMode loadMode = LoadPluginsMode.InstalledOnly,
Customer customer = null, int storeId = 0, string @group = null) where TPlugin : class, IPlugin
{
return (await GetPluginDescriptorsAsync(loadMode, customer, storeId, group))
.Select(descriptor => descriptor.Instance()).ToList();
}
///
/// Find a plugin by the type which is located into the same assembly as a plugin
///
/// Type
/// Plugin
public virtual IPlugin FindPluginByTypeInAssembly(Type typeInAssembly)
{
ArgumentNullException.ThrowIfNull(typeInAssembly);
//try to do magic
var pluginDescriptor = _pluginsInfo.PluginDescriptors.FirstOrDefault(descriptor =>
descriptor.pluginDescriptor?.ReferencedAssembly?.FullName?.Equals(typeInAssembly.Assembly.FullName,
StringComparison.InvariantCultureIgnoreCase) ?? false);
return pluginDescriptor.pluginDescriptor?.Instance();
}
///
/// Get plugin logo URL
///
/// Plugin descriptor
///
/// A task that represents the asynchronous operation
/// The task result contains the logo URL
///
public virtual Task GetPluginLogoUrlAsync(PluginDescriptor pluginDescriptor)
{
var pluginDirectory = _fileProvider.GetDirectoryName(pluginDescriptor.OriginalAssemblyFile);
if (string.IsNullOrEmpty(pluginDirectory))
return Task.FromResult(null);
//check for supported extensions
var logoExtension = NopPluginDefaults.SupportedLogoImageExtensions
.FirstOrDefault(ext => _fileProvider.FileExists(_fileProvider.Combine(pluginDirectory, $"{NopPluginDefaults.LogoFileName}.{ext}")));
if (string.IsNullOrWhiteSpace(logoExtension))
return Task.FromResult(null);
var pathBase = _httpContextAccessor.HttpContext.Request.PathBase.Value ?? string.Empty;
var logoPathUrl = _mediaSettings.UseAbsoluteImagePath ? _webHelper.GetStoreLocation() : $"{pathBase}/";
var logoUrl = $"{logoPathUrl}{NopPluginDefaults.PathName}/" +
$"{_fileProvider.GetDirectoryNameOnly(pluginDirectory)}/{NopPluginDefaults.LogoFileName}.{logoExtension}";
return Task.FromResult(logoUrl);
}
///
/// Prepare plugin to the installation
///
/// Plugin system name
/// Customer
/// Specifies whether to check plugin dependencies
/// A task that represents the asynchronous operation
public virtual async Task PreparePluginToInstallAsync(string systemName, Customer customer = null, bool checkDependencies = true)
{
//add plugin name to the appropriate list (if not yet contained) and save changes
if (_pluginsInfo.PluginNamesToInstall.Any(item => item.SystemName == systemName))
return;
var pluginsAfterRestart = _pluginsInfo.InstalledPlugins.Select(pd => pd.SystemName).Where(installedSystemName => !_pluginsInfo.PluginNamesToUninstall.Contains(installedSystemName)).ToList();
pluginsAfterRestart.AddRange(_pluginsInfo.PluginNamesToInstall.Select(item => item.SystemName));
if (checkDependencies)
{
var descriptor = await GetPluginDescriptorBySystemNameAsync(systemName, LoadPluginsMode.NotInstalledOnly);
if (descriptor.DependsOn?.Any() ?? false)
{
var dependsOn = descriptor.DependsOn
.Where(dependsOnSystemName => !pluginsAfterRestart.Contains(dependsOnSystemName)).ToList();
if (dependsOn.Any())
{
var dependsOnSystemNames = dependsOn.Aggregate((all, current) => $"{all}, {current}");
//do not inject services via constructor because it'll cause circular references
var localizationService = EngineContext.Current.Resolve();
var errorMessage = string.Format(await localizationService.GetResourceAsync("Admin.Plugins.Errors.InstallDependsOn"), string.IsNullOrEmpty(descriptor.FriendlyName) ? descriptor.SystemName : descriptor.FriendlyName, dependsOnSystemNames);
throw new NopException(errorMessage);
}
}
}
_pluginsInfo.PluginNamesToInstall.Add((systemName, customer?.CustomerGuid));
await _pluginsInfo.SaveAsync();
}
///
/// Prepare plugin to the uninstallation
///
/// Plugin system name
/// A task that represents the asynchronous operation
public virtual async Task PreparePluginToUninstallAsync(string systemName)
{
//add plugin name to the appropriate list (if not yet contained) and save changes
if (_pluginsInfo.PluginNamesToUninstall.Contains(systemName))
return;
var dependentPlugins = await GetPluginDescriptorsAsync(dependsOnSystemName: systemName);
var descriptor = await GetPluginDescriptorBySystemNameAsync(systemName);
if (dependentPlugins.Any())
{
var dependsOn = new List();
foreach (var dependentPlugin in dependentPlugins)
{
if (!_pluginsInfo.InstalledPlugins.Select(pd => pd.SystemName).Contains(dependentPlugin.SystemName))
continue;
if (_pluginsInfo.PluginNamesToUninstall.Contains(dependentPlugin.SystemName))
continue;
dependsOn.Add(string.IsNullOrEmpty(dependentPlugin.FriendlyName)
? dependentPlugin.SystemName
: dependentPlugin.FriendlyName);
}
if (dependsOn.Any())
{
var dependsOnSystemNames = dependsOn.Aggregate((all, current) => $"{all}, {current}");
//do not inject services via constructor because it'll cause circular references
var localizationService = EngineContext.Current.Resolve();
var errorMessage = string.Format(await localizationService.GetResourceAsync("Admin.Plugins.Errors.UninstallDependsOn"),
string.IsNullOrEmpty(descriptor.FriendlyName) ? descriptor.SystemName : descriptor.FriendlyName,
dependsOnSystemNames);
throw new NopException(errorMessage);
}
}
var plugin = descriptor?.Instance();
if (plugin != null)
await plugin.PreparePluginToUninstallAsync();
_pluginsInfo.PluginNamesToUninstall.Add(systemName);
await _pluginsInfo.SaveAsync();
}
///
/// Prepare plugin to the removing
///
/// Plugin system name
/// A task that represents the asynchronous operation
public virtual async Task PreparePluginToDeleteAsync(string systemName)
{
//add plugin name to the appropriate list (if not yet contained) and save changes
if (_pluginsInfo.PluginNamesToDelete.Contains(systemName))
return;
_pluginsInfo.PluginNamesToDelete.Add(systemName);
await _pluginsInfo.SaveAsync();
}
///
/// Reset changes
///
public virtual void ResetChanges()
{
//clear lists and save changes
_pluginsInfo.PluginNamesToDelete.Clear();
_pluginsInfo.PluginNamesToInstall.Clear();
_pluginsInfo.PluginNamesToUninstall.Clear();
_pluginsInfo.Save();
//display all plugins on the plugin list page
var pluginDescriptors = _pluginsInfo.PluginDescriptors.ToList();
foreach (var pluginDescriptor in pluginDescriptors)
pluginDescriptor.pluginDescriptor.ShowInPluginsList = true;
//clear the uploaded directory
foreach (var directory in _fileProvider.GetDirectories(_fileProvider.MapPath(NopPluginDefaults.UploadedPath)))
_fileProvider.DeleteDirectory(directory);
}
///
/// Clear installed plugins list
///
public virtual void ClearInstalledPluginsList()
{
_pluginsInfo.InstalledPlugins.Clear();
}
///
/// Install plugins
///
/// A task that represents the asynchronous operation
public virtual async Task InstallPluginsAsync()
{
//get all uninstalled plugins
var pluginDescriptors = _pluginsInfo.PluginDescriptors.Where(descriptor => !descriptor.pluginDescriptor.Installed).ToList();
//filter plugins need to install
pluginDescriptors = pluginDescriptors.Where(descriptor => _pluginsInfo.PluginNamesToInstall
.Any(item => item.SystemName.Equals(descriptor.pluginDescriptor.SystemName))).ToList();
if (!pluginDescriptors.Any())
return;
//do not inject services via constructor because it'll cause circular references
var localizationService = EngineContext.Current.Resolve();
var customerActivityService = EngineContext.Current.Resolve();
//install plugins
foreach (var descriptor in pluginDescriptors.OrderBy(pluginDescriptor => pluginDescriptor.pluginDescriptor.DisplayOrder))
{
try
{
InsertPluginData(descriptor.pluginDescriptor.PluginType, MigrationProcessType.Installation);
//try to install an instance
await descriptor.pluginDescriptor.Instance().InstallAsync();
//remove and add plugin system name to appropriate lists
var pluginToInstall = _pluginsInfo.PluginNamesToInstall
.FirstOrDefault(plugin => plugin.SystemName.Equals(descriptor.pluginDescriptor.SystemName));
_pluginsInfo.InstalledPlugins.Add(descriptor.pluginDescriptor.GetBaseInfoCopy);
_pluginsInfo.PluginNamesToInstall.Remove(pluginToInstall);
//activity log
var customer = await _customerService.GetCustomerByGuidAsync(pluginToInstall.CustomerGuid ?? Guid.Empty);
await customerActivityService.InsertActivityAsync(customer, "InstallNewPlugin",
string.Format(await localizationService.GetResourceAsync("ActivityLog.InstallNewPlugin"), descriptor.pluginDescriptor.SystemName, descriptor.pluginDescriptor.Version));
//mark the plugin as installed
descriptor.pluginDescriptor.Installed = true;
descriptor.pluginDescriptor.ShowInPluginsList = true;
}
catch (Exception exception)
{
//log error
var message = string.Format(await localizationService.GetResourceAsync("Admin.Plugins.Errors.NotInstalled"), descriptor.pluginDescriptor.SystemName);
await _logger.ErrorAsync(message, exception);
}
}
//save changes
await _pluginsInfo.SaveAsync();
}
///
/// Uninstall plugins
///
/// A task that represents the asynchronous operation
public virtual async Task UninstallPluginsAsync()
{
//get all installed plugins
var pluginDescriptors = _pluginsInfo.PluginDescriptors.Where(descriptor => descriptor.pluginDescriptor.Installed).ToList();
//filter plugins need to uninstall
pluginDescriptors = pluginDescriptors
.Where(descriptor => _pluginsInfo.PluginNamesToUninstall.Contains(descriptor.pluginDescriptor.SystemName)).ToList();
if (!pluginDescriptors.Any())
return;
//do not inject services via constructor because it'll cause circular references
var localizationService = EngineContext.Current.Resolve();
var customerActivityService = EngineContext.Current.Resolve();
//uninstall plugins
foreach (var descriptor in pluginDescriptors.OrderByDescending(pluginDescriptor => pluginDescriptor.pluginDescriptor.DisplayOrder))
{
try
{
var plugin = descriptor.pluginDescriptor.Instance();
//try to uninstall an instance
await plugin.UninstallAsync();
//clear plugin data on the database
var assembly = Assembly.GetAssembly(descriptor.pluginDescriptor.PluginType);
_migrationManager.ApplyDownMigrations(assembly);
//remove plugin system name from appropriate lists
_pluginsInfo.InstalledPlugins.Remove(descriptor.pluginDescriptor);
_pluginsInfo.PluginNamesToUninstall.Remove(descriptor.pluginDescriptor.SystemName);
//activity log
await customerActivityService.InsertActivityAsync("UninstallPlugin",
string.Format(await localizationService.GetResourceAsync("ActivityLog.UninstallPlugin"), descriptor.pluginDescriptor.SystemName, descriptor.pluginDescriptor.Version));
//mark the plugin as uninstalled
descriptor.pluginDescriptor.Installed = false;
descriptor.pluginDescriptor.ShowInPluginsList = true;
}
catch (Exception exception)
{
//log error
var message = string.Format(await localizationService.GetResourceAsync("Admin.Plugins.Errors.NotUninstalled"), descriptor.pluginDescriptor.SystemName);
await _logger.ErrorAsync(message, exception);
}
}
//save changes
await _pluginsInfo.SaveAsync();
}
///
/// Delete plugins
///
/// A task that represents the asynchronous operation
public virtual async Task DeletePluginsAsync()
{
//get all uninstalled plugins (delete plugin only previously uninstalled)
var pluginDescriptors = _pluginsInfo.PluginDescriptors.Where(descriptor => !descriptor.pluginDescriptor.Installed).ToList();
//filter plugins need to delete
pluginDescriptors = pluginDescriptors
.Where(descriptor => _pluginsInfo.PluginNamesToDelete.Contains(descriptor.pluginDescriptor.SystemName)).ToList();
if (!pluginDescriptors.Any())
return;
//do not inject services via constructor because it'll cause circular references
var localizationService = EngineContext.Current.Resolve();
var customerActivityService = EngineContext.Current.Resolve();
//delete plugins
foreach (var descriptor in pluginDescriptors)
{
try
{
//try to delete a plugin directory from disk storage
var pluginDirectory = _fileProvider.GetDirectoryName(descriptor.pluginDescriptor.OriginalAssemblyFile);
if (_fileProvider.DirectoryExists(pluginDirectory))
_fileProvider.DeleteDirectory(pluginDirectory);
//remove plugin system name from the appropriate list
_pluginsInfo.PluginNamesToDelete.Remove(descriptor.pluginDescriptor.SystemName);
//activity log
await customerActivityService.InsertActivityAsync("DeletePlugin",
string.Format(await localizationService.GetResourceAsync("ActivityLog.DeletePlugin"), descriptor.pluginDescriptor.SystemName, descriptor.pluginDescriptor.Version));
}
catch (Exception exception)
{
//log error
var message = string.Format(await localizationService.GetResourceAsync("Admin.Plugins.Errors.NotDeleted"), descriptor.pluginDescriptor.SystemName);
await _logger.ErrorAsync(message, exception);
}
}
//save changes
await _pluginsInfo.SaveAsync();
}
///
/// Check whether application restart is required to apply changes to plugins
///
/// Result of check
public virtual bool IsRestartRequired()
{
//return true if any of lists contains items or some plugins were uploaded
return _pluginsInfo.PluginNamesToInstall.Any()
|| _pluginsInfo.PluginNamesToUninstall.Any()
|| _pluginsInfo.PluginNamesToDelete.Any()
|| IsPluginsUploaded;
}
///
/// Update plugins
///
/// A task that represents the asynchronous operation
public virtual async Task UpdatePluginsAsync()
{
//do not inject services via constructor because it'll cause circular references
var localizationService = EngineContext.Current.Resolve();
var customerActivityService = EngineContext.Current.Resolve();
foreach (var installedPlugin in _pluginsInfo.InstalledPlugins)
{
var newVersion = _pluginsInfo.PluginDescriptors.FirstOrDefault(pd =>
pd.pluginDescriptor.SystemName.Equals(installedPlugin.SystemName, StringComparison.InvariantCultureIgnoreCase));
if (newVersion.pluginDescriptor == null)
continue;
if (installedPlugin.Version == newVersion.pluginDescriptor.Version)
continue;
//run new migrations from the plugin if there are exists
InsertPluginData(newVersion.pluginDescriptor.PluginType, MigrationProcessType.Update);
//run the plugin update logic
await newVersion.pluginDescriptor.Instance().UpdateAsync(installedPlugin.Version, newVersion.pluginDescriptor.Version);
//activity log
await customerActivityService.InsertActivityAsync("UpdatePlugin",
string.Format(await localizationService.GetResourceAsync("ActivityLog.UpdatePlugin"), newVersion.pluginDescriptor.SystemName, installedPlugin.Version, newVersion.pluginDescriptor.Version));
//update installed plugin info
installedPlugin.Version = newVersion.pluginDescriptor.Version;
}
await _pluginsInfo.SaveAsync();
}
///
/// Get names of incompatible plugins
///
/// List of plugin names
public virtual IDictionary GetIncompatiblePlugins()
{
return _pluginsInfo.IncompatiblePlugins;
}
///
/// Get all assembly loaded collisions
///
/// List of plugin loaded assembly info
public virtual IList GetAssemblyCollisions()
{
return _pluginsInfo.AssemblyLoadedCollision;
}
#endregion
#region Properties
///
/// Indicates whether new or updated plugins have been uploaded.
/// True - if the plugins were loaded, false otherwise
///
protected virtual bool IsPluginsUploaded
{
get
{
var pluginsDirectories =
_fileProvider.GetDirectories(_fileProvider.MapPath(NopPluginDefaults.UploadedPath));
if (!pluginsDirectories.Any())
return false;
return pluginsDirectories.Any(d =>
_fileProvider.GetFiles(d, "*.dll").Any() || _fileProvider.GetFiles(d, "plugin.json").Any());
}
}
#endregion
}