Try your search with a different keyword or use * as a wildcard.
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Domain.Configuration;
using Nop.Data;
namespace Nop.Services.Configuration;
///
/// Setting manager
///
public partial class SettingService : ISettingService
{
#region Fields
protected readonly IRepository _settingRepository;
protected readonly IStaticCacheManager _staticCacheManager;
#endregion
#region Ctor
public SettingService(IRepository settingRepository,
IStaticCacheManager staticCacheManager)
{
_settingRepository = settingRepository;
_staticCacheManager = staticCacheManager;
}
#endregion
#region Utilities
///
/// Gets all settings
///
///
/// A task that represents the asynchronous operation
/// The task result contains the settings
///
protected virtual async Task>> GetAllSettingsDictionaryAsync()
{
return await _staticCacheManager.GetAsync(NopSettingsDefaults.SettingsAllAsDictionaryCacheKey, async () =>
{
var settings = await GetAllSettingsAsync();
var dictionary = new Dictionary>();
foreach (var s in settings)
{
var resourceName = s.Name.ToLowerInvariant();
var settingForCaching = new Setting
{
Id = s.Id,
Name = s.Name,
Value = s.Value,
StoreId = s.StoreId
};
if (!dictionary.TryGetValue(resourceName, out var value))
//first setting
dictionary.Add(resourceName, new List
{
settingForCaching
});
else
//already added
//most probably it's the setting with the same name but for some certain store (storeId > 0)
value.Add(settingForCaching);
}
return dictionary;
});
}
///
/// Gets all settings
///
///
/// Settings
///
protected virtual IDictionary> GetAllSettingsDictionary()
{
return _staticCacheManager.Get(NopSettingsDefaults.SettingsAllAsDictionaryCacheKey, () =>
{
var settings = GetAllSettings();
var dictionary = new Dictionary>();
foreach (var s in settings)
{
var resourceName = s.Name.ToLowerInvariant();
var settingForCaching = new Setting
{
Id = s.Id,
Name = s.Name,
Value = s.Value,
StoreId = s.StoreId
};
if (!dictionary.TryGetValue(resourceName, out var value))
//first setting
dictionary.Add(resourceName, new List
{
settingForCaching
});
else
//already added
//most probably it's the setting with the same name but for some certain store (storeId > 0)
value.Add(settingForCaching);
}
return dictionary;
});
}
///
/// Set setting value
///
/// Type
/// Key
/// Value
/// Store identifier
/// A value indicating whether to clear cache after setting update
/// A task that represents the asynchronous operation
protected virtual async Task SetSettingAsync(Type type, string key, object value, int storeId = 0, bool clearCache = true)
{
ArgumentNullException.ThrowIfNull(key);
key = key.Trim().ToLowerInvariant();
var valueStr = TypeDescriptor.GetConverter(type).ConvertToInvariantString(value);
var allSettings = await GetAllSettingsDictionaryAsync();
var settingForCaching = allSettings.TryGetValue(key, out var settings) ?
settings.FirstOrDefault(x => x.StoreId == storeId) : null;
if (settingForCaching != null)
{
//update
var setting = await GetSettingByIdAsync(settingForCaching.Id);
setting.Value = valueStr;
await UpdateSettingAsync(setting, clearCache);
}
else
{
//insert
var setting = new Setting
{
Name = key,
Value = valueStr,
StoreId = storeId
};
await InsertSettingAsync(setting, clearCache);
}
}
///
/// Set setting value
///
/// Type
/// Key
/// Value
/// Store identifier
/// A value indicating whether to clear cache after setting update
protected virtual void SetSetting(Type type, string key, object value, int storeId = 0, bool clearCache = true)
{
ArgumentNullException.ThrowIfNull(key);
key = key.Trim().ToLowerInvariant();
var valueStr = TypeDescriptor.GetConverter(type).ConvertToInvariantString(value);
var allSettings = GetAllSettingsDictionary();
var settingForCaching = allSettings.TryGetValue(key, out var settings) ?
settings.FirstOrDefault(x => x.StoreId == storeId) : null;
if (settingForCaching != null)
{
//update
var setting = GetSettingById(settingForCaching.Id);
setting.Value = valueStr;
UpdateSetting(setting, clearCache);
}
else
{
//insert
var setting = new Setting
{
Name = key,
Value = valueStr,
StoreId = storeId
};
InsertSetting(setting, clearCache);
}
}
#endregion
#region Methods
///
/// Adds a setting
///
/// Setting
/// A value indicating whether to clear cache after setting update
/// A task that represents the asynchronous operation
public virtual async Task InsertSettingAsync(Setting setting, bool clearCache = true)
{
await _settingRepository.InsertAsync(setting);
//cache
if (clearCache)
await ClearCacheAsync();
}
///
/// Adds a setting
///
/// Setting
/// A value indicating whether to clear cache after setting update
public virtual void InsertSetting(Setting setting, bool clearCache = true)
{
_settingRepository.Insert(setting);
//cache
if (clearCache)
ClearCache();
}
///
/// Updates a setting
///
/// Setting
/// A value indicating whether to clear cache after setting update
/// A task that represents the asynchronous operation
public virtual async Task UpdateSettingAsync(Setting setting, bool clearCache = true)
{
ArgumentNullException.ThrowIfNull(setting);
await _settingRepository.UpdateAsync(setting);
//cache
if (clearCache)
await ClearCacheAsync();
}
///
/// Updates a setting
///
/// Setting
/// A value indicating whether to clear cache after setting update
public virtual void UpdateSetting(Setting setting, bool clearCache = true)
{
ArgumentNullException.ThrowIfNull(setting);
_settingRepository.Update(setting);
//cache
if (clearCache)
ClearCache();
}
///
/// Deletes a setting
///
/// Setting
/// A task that represents the asynchronous operation
public virtual async Task DeleteSettingAsync(Setting setting)
{
await _settingRepository.DeleteAsync(setting);
//cache
await ClearCacheAsync();
}
///
/// Deletes a setting
///
/// Setting
public virtual void DeleteSetting(Setting setting)
{
_settingRepository.Delete(setting);
//cache
ClearCache();
}
///
/// Deletes settings
///
/// Settings
/// A task that represents the asynchronous operation
public virtual async Task DeleteSettingsAsync(IList settings)
{
await _settingRepository.DeleteAsync(settings);
//cache
await ClearCacheAsync();
}
///
/// Gets a setting by identifier
///
/// Setting identifier
///
/// A task that represents the asynchronous operation
/// The task result contains the setting
///
public virtual async Task GetSettingByIdAsync(int settingId)
{
return await _settingRepository.GetByIdAsync(settingId, cache => default);
}
///
/// Gets a setting by identifier
///
/// Setting identifier
///
/// The setting
///
public virtual Setting GetSettingById(int settingId)
{
return _settingRepository.GetById(settingId, cache => default);
}
///
/// Get setting by key
///
/// Key
/// Store identifier
/// A value indicating whether a shared (for all stores) value should be loaded if a value specific for a certain is not found
///
/// A task that represents the asynchronous operation
/// The task result contains the setting
///
public virtual async Task GetSettingAsync(string key, int storeId = 0, bool loadSharedValueIfNotFound = false)
{
if (string.IsNullOrEmpty(key))
return null;
var settings = await GetAllSettingsDictionaryAsync();
key = key.Trim().ToLowerInvariant();
if (!settings.TryGetValue(key, out var value))
return null;
var settingsByKey = value;
var setting = settingsByKey.FirstOrDefault(x => x.StoreId == storeId);
//load shared value?
if (setting == null && storeId > 0 && loadSharedValueIfNotFound)
setting = settingsByKey.FirstOrDefault(x => x.StoreId == 0);
return setting != null ? await GetSettingByIdAsync(setting.Id) : null;
}
///
/// Get setting by key
///
/// Key
/// Store identifier
/// A value indicating whether a shared (for all stores) value should be loaded if a value specific for a certain is not found
///
/// The setting
///
public virtual Setting GetSetting(string key, int storeId = 0, bool loadSharedValueIfNotFound = false)
{
if (string.IsNullOrEmpty(key))
return null;
var settings = GetAllSettingsDictionary();
key = key.Trim().ToLowerInvariant();
if (!settings.TryGetValue(key, out var value))
return null;
var settingsByKey = value;
var setting = settingsByKey.FirstOrDefault(x => x.StoreId == storeId);
//load shared value?
if (setting == null && storeId > 0 && loadSharedValueIfNotFound)
setting = settingsByKey.FirstOrDefault(x => x.StoreId == 0);
return setting != null ? GetSettingById(setting.Id) : null;
}
///
/// Get setting value by key
///
/// Type
/// Key
/// Default value
/// Store identifier
/// A value indicating whether a shared (for all stores) value should be loaded if a value specific for a certain is not found
///
/// A task that represents the asynchronous operation
/// The task result contains the setting value
///
public virtual async Task GetSettingByKeyAsync(string key, T defaultValue = default,
int storeId = 0, bool loadSharedValueIfNotFound = false)
{
if (string.IsNullOrEmpty(key))
return defaultValue;
var settings = await GetAllSettingsDictionaryAsync();
key = key.Trim().ToLowerInvariant();
if (!settings.TryGetValue(key, out var value))
return defaultValue;
var settingsByKey = value;
var setting = settingsByKey.FirstOrDefault(x => x.StoreId == storeId);
//load shared value?
if (setting == null && storeId > 0 && loadSharedValueIfNotFound)
setting = settingsByKey.FirstOrDefault(x => x.StoreId == 0);
return setting != null ? CommonHelper.To(setting.Value) : defaultValue;
}
///
/// Get setting value by key
///
/// Type
/// Key
/// Default value
/// Store identifier
/// A value indicating whether a shared (for all stores) value should be loaded if a value specific for a certain is not found
///
/// Setting value
///
public virtual T GetSettingByKey(string key, T defaultValue = default,
int storeId = 0, bool loadSharedValueIfNotFound = false)
{
if (string.IsNullOrEmpty(key))
return defaultValue;
var settings = GetAllSettingsDictionary();
key = key.Trim().ToLowerInvariant();
if (!settings.TryGetValue(key, out var value))
return defaultValue;
var settingsByKey = value;
var setting = settingsByKey.FirstOrDefault(x => x.StoreId == storeId);
//load shared value?
if (setting == null && storeId > 0 && loadSharedValueIfNotFound)
setting = settingsByKey.FirstOrDefault(x => x.StoreId == 0);
return setting != null ? CommonHelper.To(setting.Value) : defaultValue;
}
///
/// Set setting value
///
/// Type
/// Key
/// Value
/// Store identifier
/// A value indicating whether to clear cache after setting update
/// A task that represents the asynchronous operation
public virtual async Task SetSettingAsync(string key, T value, int storeId = 0, bool clearCache = true)
{
await SetSettingAsync(typeof(T), key, value, storeId, clearCache);
}
///
/// Set setting value
///
/// Type
/// Key
/// Value
/// Store identifier
/// A value indicating whether to clear cache after setting update
public virtual void SetSetting(string key, T value, int storeId = 0, bool clearCache = true)
{
SetSetting(typeof(T), key, value, storeId, clearCache);
}
///
/// Gets all settings
///
///
/// A task that represents the asynchronous operation
/// The task result contains the settings
///
public virtual async Task> GetAllSettingsAsync()
{
var settings = await _settingRepository.GetAllAsync(query =>
{
return from s in query
orderby s.Name, s.StoreId
select s;
}, cache => default);
return settings;
}
///
/// Gets all settings
///
///
/// Settings
///
public virtual IList GetAllSettings()
{
var settings = _settingRepository.GetAll(query => from s in query
orderby s.Name, s.StoreId
select s, cache => default);
return settings;
}
///
/// Determines whether a setting exists
///
/// Entity type
/// Property type
/// Entity
/// Key selector
/// Store identifier
///
/// A task that represents the asynchronous operation
/// The task result contains the true -setting exists; false - does not exist
///
public virtual async Task SettingExistsAsync(T settings,
Expression> keySelector, int storeId = 0)
where T : ISettings, new()
{
var key = GetSettingKey(settings, keySelector);
var setting = await GetSettingByKeyAsync(key, storeId: storeId);
return setting != null;
}
///
/// Determines whether a setting exists
///
/// Entity type
/// Property type
/// Entity
/// Key selector
/// Store identifier
///
/// The true -setting exists; false - does not exist
///
public virtual bool SettingExists(T settings,
Expression> keySelector, int storeId = 0)
where T : ISettings, new()
{
var key = GetSettingKey(settings, keySelector);
var setting = GetSettingByKey(key, storeId: storeId);
return setting != null;
}
///
/// Load settings
///
/// Type
/// Store identifier for which settings should be loaded
/// A task that represents the asynchronous operation
public virtual async Task LoadSettingAsync(int storeId = 0) where T : ISettings, new()
{
return (T)await LoadSettingAsync(typeof(T), storeId);
}
///
/// Load settings
///
/// Type
/// Store identifier for which settings should be loaded
public virtual T LoadSetting(int storeId = 0) where T : ISettings, new()
{
return (T)LoadSetting(typeof(T), storeId);
}
///
/// Load settings
///
/// Type
/// Store identifier for which settings should be loaded
/// A task that represents the asynchronous operation
public virtual async Task LoadSettingAsync(Type type, int storeId = 0)
{
var settings = Activator.CreateInstance(type);
if (!DataSettingsManager.IsDatabaseInstalled())
return settings as ISettings;
foreach (var prop in type.GetProperties())
{
// get properties we can read and write to
if (!prop.CanRead || !prop.CanWrite)
continue;
var key = type.Name + "." + prop.Name;
//load by store
var setting = await GetSettingByKeyAsync(key, storeId: storeId, loadSharedValueIfNotFound: true);
if (setting == null)
continue;
if (!TypeDescriptor.GetConverter(prop.PropertyType).CanConvertFrom(typeof(string)))
continue;
if (!TypeDescriptor.GetConverter(prop.PropertyType).IsValid(setting))
continue;
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(setting);
//set property
prop.SetValue(settings, value, null);
}
return settings as ISettings;
}
///
/// Load settings
///
/// Type
/// Store identifier for which settings should be loaded
/// Settings
public virtual ISettings LoadSetting(Type type, int storeId = 0)
{
var settings = Activator.CreateInstance(type);
if (!DataSettingsManager.IsDatabaseInstalled())
return settings as ISettings;
foreach (var prop in type.GetProperties())
{
// get properties we can read and write to
if (!prop.CanRead || !prop.CanWrite)
continue;
var key = type.Name + "." + prop.Name;
//load by store
var setting = GetSettingByKey(key, storeId: storeId, loadSharedValueIfNotFound: true);
if (setting == null)
continue;
if (!TypeDescriptor.GetConverter(prop.PropertyType).CanConvertFrom(typeof(string)))
continue;
if (!TypeDescriptor.GetConverter(prop.PropertyType).IsValid(setting))
continue;
var value = TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromInvariantString(setting);
//set property
prop.SetValue(settings, value, null);
}
return settings as ISettings;
}
///
/// Save settings object
///
/// Type
/// Store identifier
/// Setting instance
/// A task that represents the asynchronous operation
public virtual async Task SaveSettingAsync(T settings, int storeId = 0) where T : ISettings, new()
{
/* We do not clear cache after each setting update.
* This behavior can increase performance because cached settings will not be cleared
* and loaded from database after each update */
foreach (var prop in typeof(T).GetProperties())
{
// get properties we can read and write to
if (!prop.CanRead || !prop.CanWrite)
continue;
if (!TypeDescriptor.GetConverter(prop.PropertyType).CanConvertFrom(typeof(string)))
continue;
var key = typeof(T).Name + "." + prop.Name;
var value = prop.GetValue(settings, null);
if (value != null)
await SetSettingAsync(prop.PropertyType, key, value, storeId, false);
else
await SetSettingAsync(key, string.Empty, storeId, false);
}
//and now clear cache
await ClearCacheAsync();
}
///
/// Save settings object
///
/// Type
/// Store identifier
/// Setting instance
public virtual void SaveSetting(T settings, int storeId = 0) where T : ISettings, new()
{
/* We do not clear cache after each setting update.
* This behavior can increase performance because cached settings will not be cleared
* and loaded from database after each update */
foreach (var prop in typeof(T).GetProperties())
{
// get properties we can read and write to
if (!prop.CanRead || !prop.CanWrite)
continue;
if (!TypeDescriptor.GetConverter(prop.PropertyType).CanConvertFrom(typeof(string)))
continue;
var key = typeof(T).Name + "." + prop.Name;
var value = prop.GetValue(settings, null);
if (value != null)
SetSetting(prop.PropertyType, key, value, storeId, false);
else
SetSetting(key, string.Empty, storeId, false);
}
//and now clear cache
ClearCache();
}
///
/// Save settings object
///
/// Entity type
/// Property type
/// Settings
/// Key selector
/// Store ID
/// A value indicating whether to clear cache after setting update
/// A task that represents the asynchronous operation
public virtual async Task SaveSettingAsync(T settings,
Expression> keySelector,
int storeId = 0, bool clearCache = true) where T : ISettings, new()
{
if (keySelector.Body is not MemberExpression member)
throw new ArgumentException($"Expression '{keySelector}' refers to a method, not a property.");
var propInfo = member.Member as PropertyInfo
?? throw new ArgumentException($"Expression '{keySelector}' refers to a field, not a property.");
var key = GetSettingKey(settings, keySelector);
var value = (TPropType)propInfo.GetValue(settings, null);
if (value != null)
await SetSettingAsync(key, value, storeId, clearCache);
else
await SetSettingAsync(key, string.Empty, storeId, clearCache);
}
///
/// Save settings object
///
/// Entity type
/// Property type
/// Settings
/// Key selector
/// Store ID
/// A value indicating whether to clear cache after setting update
public virtual void SaveSetting(T settings,
Expression> keySelector,
int storeId = 0, bool clearCache = true) where T : ISettings, new()
{
if (keySelector.Body is not MemberExpression member)
throw new ArgumentException($"Expression '{keySelector}' refers to a method, not a property.");
var propInfo = member.Member as PropertyInfo
?? throw new ArgumentException($"Expression '{keySelector}' refers to a field, not a property.");
var key = GetSettingKey(settings, keySelector);
var value = (TPropType)propInfo.GetValue(settings, null);
if (value != null)
SetSetting(key, value, storeId, clearCache);
else
SetSetting(key, string.Empty, storeId, clearCache);
}
///
/// Save settings object (per store). If the setting is not overridden per store then it'll be delete
///
/// Entity type
/// Property type
/// Settings
/// Key selector
/// A value indicating whether to setting is overridden in some store
/// Store ID
/// A value indicating whether to clear cache after setting update
/// A task that represents the asynchronous operation
public virtual async Task SaveSettingOverridablePerStoreAsync(T settings,
Expression> keySelector,
bool overrideForStore, int storeId = 0, bool clearCache = true) where T : ISettings, new()
{
if (overrideForStore || storeId == 0)
await SaveSettingAsync(settings, keySelector, storeId, clearCache);
else if (storeId > 0)
await DeleteSettingAsync(settings, keySelector, storeId);
}
///
/// Delete all settings
///
/// Type
/// A task that represents the asynchronous operation
public virtual async Task DeleteSettingAsync() where T : ISettings, new()
{
var settingsToDelete = new List();
var allSettings = await GetAllSettingsAsync();
foreach (var prop in typeof(T).GetProperties())
{
var key = typeof(T).Name + "." + prop.Name;
settingsToDelete.AddRange(allSettings.Where(x => x.Name.Equals(key, StringComparison.InvariantCultureIgnoreCase)));
}
await DeleteSettingsAsync(settingsToDelete);
}
///
/// Delete settings object
///
/// Entity type
/// Property type
/// Settings
/// Key selector
/// Store ID
/// A task that represents the asynchronous operation
public virtual async Task DeleteSettingAsync(T settings,
Expression> keySelector, int storeId = 0) where T : ISettings, new()
{
var key = GetSettingKey(settings, keySelector);
key = key.Trim().ToLowerInvariant();
var allSettings = await GetAllSettingsDictionaryAsync();
var settingForCaching = allSettings.TryGetValue(key, out var settings_) ?
settings_.FirstOrDefault(x => x.StoreId == storeId) : null;
if (settingForCaching == null)
return;
//update
var setting = await GetSettingByIdAsync(settingForCaching.Id);
await DeleteSettingAsync(setting);
}
///
/// Clear cache
///
/// A task that represents the asynchronous operation
public virtual async Task ClearCacheAsync()
{
await _staticCacheManager.RemoveByPrefixAsync(NopEntityCacheDefaults.Prefix);
}
///
/// Clear cache
///
public virtual void ClearCache()
{
_staticCacheManager.RemoveByPrefix(NopEntityCacheDefaults.Prefix);
}
///
/// Get setting key (stored into database)
///
/// Type of settings
/// Property type
/// Settings
/// Key selector
/// Key
public virtual string GetSettingKey(TSettings settings, Expression> keySelector)
where TSettings : ISettings, new()
{
if (keySelector.Body is not MemberExpression member)
throw new ArgumentException($"Expression '{keySelector}' refers to a method, not a property.");
if (member.Member is not PropertyInfo propInfo)
throw new ArgumentException($"Expression '{keySelector}' refers to a field, not a property.");
var key = $"{typeof(TSettings).Name}.{propInfo.Name}";
return key;
}
#endregion
}