Try your search with a different keyword or use * as a wildcard.
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Stores;
using Nop.Data;
namespace Nop.Services.Stores;
/// <summary>
/// Store mapping service
/// </summary>
public partial class StoreMappingService : IStoreMappingService
{
#region Fields
protected readonly CatalogSettings _catalogSettings;
protected readonly INopDataProvider _dataProvider;
protected readonly IRepository<StoreMapping> _storeMappingRepository;
protected readonly IStaticCacheManager _staticCacheManager;
protected readonly IStoreContext _storeContext;
protected readonly IStoreService _storeService;
#endregion
#region Ctor
public StoreMappingService(CatalogSettings catalogSettings,
INopDataProvider dataProvider,
IRepository<StoreMapping> storeMappingRepository,
IStaticCacheManager staticCacheManager,
IStoreContext storeContext,
IStoreService storeService)
{
_catalogSettings = catalogSettings;
_dataProvider = dataProvider;
_storeMappingRepository = storeMappingRepository;
_staticCacheManager = staticCacheManager;
_storeContext = storeContext;
_storeService = storeService;
}
#endregion
#region Utilities
/// <summary>
/// Inserts a store mapping record
/// </summary>
/// <param name="storeMapping">Store mapping</param>
/// <returns>A task that represents the asynchronous operation</returns>
protected virtual async Task InsertStoreMappingAsync(StoreMapping storeMapping)
{
await _storeMappingRepository.InsertAsync(storeMapping);
}
/// <summary>
/// Get a value indicating whether a store mapping exists for an entity type
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains true if exists; otherwise false
/// </returns>
protected virtual async Task<bool> IsEntityMappingExistsAsync<TEntity>() where TEntity : BaseEntity, IStoreMappingSupported
{
var entityName = typeof(TEntity).Name;
var key = _staticCacheManager.PrepareKeyForDefaultCache(NopStoreDefaults.StoreMappingExistsCacheKey, entityName);
var query = from sm in _storeMappingRepository.Table
where sm.EntityName == entityName
select sm.StoreId;
return await _staticCacheManager.GetAsync(key, async () => await query.AnyAsync());
}
#endregion
#region Methods
/// <summary>
/// Apply store mapping to the passed query
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <param name="query">Query to filter</param>
/// <param name="storeId">Store identifier</param>
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains the filtered query
/// </returns>
public virtual async Task<IQueryable<TEntity>> ApplyStoreMapping<TEntity>(IQueryable<TEntity> query, int storeId)
where TEntity : BaseEntity, IStoreMappingSupported
{
ArgumentNullException.ThrowIfNull(query);
if (storeId == 0 || _catalogSettings.IgnoreStoreLimitations || !await IsEntityMappingExistsAsync<TEntity>())
return query;
return from entity in query
where !entity.LimitedToStores || _storeMappingRepository.Table.Any(sm =>
sm.EntityName == typeof(TEntity).Name && sm.EntityId == entity.Id && sm.StoreId == storeId)
select entity;
}
/// <summary>
/// Deletes a store mapping record
/// </summary>
/// <param name="storeMapping">Store mapping record</param>
/// <returns>A task that represents the asynchronous operation</returns>
public virtual async Task DeleteStoreMappingAsync(StoreMapping storeMapping)
{
await _storeMappingRepository.DeleteAsync(storeMapping);
}
/// <summary>
/// Gets store mapping records
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <param name="entity">Entity</param>
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains the store mapping records
/// </returns>
public virtual async Task<IList<StoreMapping>> GetStoreMappingsAsync<TEntity>(TEntity entity) where TEntity : BaseEntity, IStoreMappingSupported
{
ArgumentNullException.ThrowIfNull(entity);
var entityId = entity.Id;
var entityName = entity.GetType().Name;
var key = _staticCacheManager.PrepareKeyForDefaultCache(NopStoreDefaults.StoreMappingsCacheKey, entityId, entityName);
var query = from sm in _storeMappingRepository.Table
where sm.EntityId == entityId &&
sm.EntityName == entityName
select sm;
var storeMappings = await _staticCacheManager.GetAsync(key, async () => await query.ToListAsync());
return storeMappings;
}
/// <summary>
/// Inserts a store mapping record
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <param name="entity">Entity</param>
/// <param name="storeId">Store id</param>
/// <returns>A task that represents the asynchronous operation</returns>
public virtual async Task InsertStoreMappingAsync<TEntity>(TEntity entity, int storeId) where TEntity : BaseEntity, IStoreMappingSupported
{
ArgumentNullException.ThrowIfNull(entity);
if (storeId == 0)
throw new ArgumentOutOfRangeException(nameof(storeId));
var entityId = entity.Id;
var entityName = entity.GetType().Name;
var storeMapping = new StoreMapping
{
EntityId = entityId,
EntityName = entityName,
StoreId = storeId
};
await InsertStoreMappingAsync(storeMapping);
}
/// <summary>
/// Find store identifiers with granted access (mapped to the entity)
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <param name="entity">Entity</param>
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains the store identifiers
/// </returns>
public virtual async Task<int[]> GetStoresIdsWithAccessAsync<TEntity>(TEntity entity) where TEntity : BaseEntity, IStoreMappingSupported
{
ArgumentNullException.ThrowIfNull(entity);
var entityId = entity.Id;
var entityName = entity.GetType().Name;
var key = _staticCacheManager.PrepareKeyForDefaultCache(NopStoreDefaults.StoreMappingIdsCacheKey, entityId, entityName);
var query = from sm in _storeMappingRepository.Table
where sm.EntityId == entityId &&
sm.EntityName == entityName
select sm.StoreId;
return await _staticCacheManager.GetAsync(key, () => query.ToArrayAsync());
}
/// <summary>
/// Find store identifiers with granted access (mapped to the entity)
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <param name="entity">Entity</param>
/// <returns>
/// The store identifiers
/// </returns>
public virtual int[] GetStoresIdsWithAccess<TEntity>(TEntity entity) where TEntity : BaseEntity, IStoreMappingSupported
{
ArgumentNullException.ThrowIfNull(entity);
var entityId = entity.Id;
var entityName = entity.GetType().Name;
var key = _staticCacheManager.PrepareKeyForDefaultCache(NopStoreDefaults.StoreMappingIdsCacheKey, entityId, entityName);
var query = from sm in _storeMappingRepository.Table
where sm.EntityId == entityId &&
sm.EntityName == entityName
select sm.StoreId;
return _staticCacheManager.Get(key, () => query.ToArray());
}
/// <summary>
/// Authorize whether entity could be accessed in the current store (mapped to this store)
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <param name="entity">Entity</param>
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains true - authorized; otherwise, false
/// </returns>
public virtual async Task<bool> AuthorizeAsync<TEntity>(TEntity entity) where TEntity : BaseEntity, IStoreMappingSupported
{
var store = await _storeContext.GetCurrentStoreAsync();
return await AuthorizeAsync(entity, store.Id);
}
/// <summary>
/// Authorize whether entity could be accessed in a store (mapped to this store)
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <param name="entity">Entity</param>
/// <param name="storeId">Store identifier</param>
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains true - authorized; otherwise, false
/// </returns>
public virtual async Task<bool> AuthorizeAsync<TEntity>(TEntity entity, int storeId) where TEntity : BaseEntity, IStoreMappingSupported
{
if (entity == null)
return false;
if (storeId == 0)
//return true if no store specified/found
return true;
if (_catalogSettings.IgnoreStoreLimitations)
return true;
if (!entity.LimitedToStores)
return true;
foreach (var storeIdWithAccess in await GetStoresIdsWithAccessAsync(entity))
if (storeId == storeIdWithAccess)
//yes, we have such permission
return true;
//no permission found
return false;
}
/// <summary>
/// Authorize whether entity could be accessed in a store (mapped to this store)
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <param name="entity">Entity</param>
/// <param name="storeId">Store identifier</param>
/// <returns>
/// True - authorized; otherwise, false
/// </returns>
public virtual bool Authorize<TEntity>(TEntity entity, int storeId) where TEntity : BaseEntity, IStoreMappingSupported
{
if (entity == null)
return false;
if (storeId == 0)
//return true if no store specified/found
return true;
if (_catalogSettings.IgnoreStoreLimitations)
return true;
if (!entity.LimitedToStores)
return true;
foreach (var storeIdWithAccess in GetStoresIdsWithAccess(entity))
if (storeId == storeIdWithAccess)
//yes, we have such permission
return true;
//no permission found
return false;
}
/// <summary>
/// Save store mappings for the passed entity
/// </summary>
/// <typeparam name="TEntity">Type of entity that supports store mapping</typeparam>
/// <param name="entity">Entity</param>
/// <param name="storeIds">Store identifiers</param>
/// <returns>
/// A task that represents the asynchronous operation
/// </returns>
public virtual async Task SaveStoreMappingsAsync<TEntity>(TEntity entity, IEnumerable<int> storeIds) where TEntity : BaseEntity, IStoreMappingSupported
{
ArgumentNullException.ThrowIfNull(entity);
ArgumentNullException.ThrowIfNull(storeIds);
ArgumentOutOfRangeException.ThrowIfZero(entity.Id);
var allStores = await _storeService.GetAllStoresAsync();
var existingStoreMappings = await GetStoreMappingsAsync(entity);
if (entity.LimitedToStores != storeIds.Any())
{
entity.LimitedToStores = storeIds.Any();
await _dataProvider.UpdateEntityAsync(entity);
}
foreach (var store in allStores)
{
if (storeIds.Contains(store.Id))
{
//new store
if (!existingStoreMappings.Any(sm => sm.StoreId == store.Id))
await InsertStoreMappingAsync(entity, store.Id);
}
else
{
//remove store
var storeMappingToDelete = existingStoreMappings.FirstOrDefault(sm => sm.StoreId == store.Id);
if (storeMappingToDelete != null)
await DeleteStoreMappingAsync(storeMappingToDelete);
}
}
}
#endregion
}