using Nop.Core; using Nop.Core.Caching; using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Media; using Nop.Data; namespace Nop.Services.Catalog; /// /// Product attribute service /// public partial class ProductAttributeService : IProductAttributeService { #region Fields protected readonly IRepository _pictureRepository; protected readonly IRepository _predefinedProductAttributeValueRepository; protected readonly IRepository _productRepository; protected readonly IRepository _productAttributeRepository; protected readonly IRepository _productAttributeCombinationRepository; protected readonly IRepository _productAttributeCombinationPictureRepository; protected readonly IRepository _productAttributeMappingRepository; protected readonly IRepository _productAttributeValueRepository; protected readonly IRepository _productAttributeValuePictureRepository; protected readonly IRepository _productPictureRepository; protected readonly IStaticCacheManager _staticCacheManager; #endregion #region Ctor public ProductAttributeService(IRepository pictureRepository, IRepository predefinedProductAttributeValueRepository, IRepository productRepository, IRepository productAttributeRepository, IRepository productAttributeCombinationRepository, IRepository productAttributeCombinationPictureRepository, IRepository productAttributeMappingRepository, IRepository productAttributeValueRepository, IRepository productAttributeValuePictureRepository, IRepository productPictureRepository, IStaticCacheManager staticCacheManager) { _pictureRepository = pictureRepository; _predefinedProductAttributeValueRepository = predefinedProductAttributeValueRepository; _productRepository = productRepository; _productAttributeRepository = productAttributeRepository; _productAttributeCombinationRepository = productAttributeCombinationRepository; _productAttributeCombinationPictureRepository = productAttributeCombinationPictureRepository; _productAttributeMappingRepository = productAttributeMappingRepository; _productAttributeValueRepository = productAttributeValueRepository; _productAttributeValuePictureRepository = productAttributeValuePictureRepository; _productPictureRepository = productPictureRepository; _staticCacheManager = staticCacheManager; } #endregion #region Methods #region Product attributes /// /// Deletes a product attribute /// /// Product attribute /// A task that represents the asynchronous operation public virtual async Task DeleteProductAttributeAsync(ProductAttribute productAttribute) { await _productAttributeRepository.DeleteAsync(productAttribute); } /// /// Deletes product attributes /// /// Product attributes /// A task that represents the asynchronous operation public virtual async Task DeleteProductAttributesAsync(IList productAttributes) { ArgumentNullException.ThrowIfNull(productAttributes); foreach (var productAttribute in productAttributes) await DeleteProductAttributeAsync(productAttribute); } /// /// Gets all product attributes /// /// Page index /// Page size /// /// A task that represents the asynchronous operation /// The task result contains the product attributes /// public virtual async Task> GetAllProductAttributesAsync(int pageIndex = 0, int pageSize = int.MaxValue) { var productAttributes = await _productAttributeRepository.GetAllPagedAsync(query => { return from pa in query orderby pa.Name select pa; }, pageIndex, pageSize); return productAttributes; } /// /// Gets a product attribute /// /// Product attribute identifier /// /// A task that represents the asynchronous operation /// The task result contains the product attribute /// public virtual async Task GetProductAttributeByIdAsync(int productAttributeId) { return await _productAttributeRepository.GetByIdAsync(productAttributeId, cache => default); } /// /// Gets product attributes /// /// Product attribute identifiers /// /// A task that represents the asynchronous operation /// The task result contains the product attributes /// public virtual async Task> GetProductAttributeByIdsAsync(int[] productAttributeIds) { return await _productAttributeRepository.GetByIdsAsync(productAttributeIds); } /// /// Inserts a product attribute /// /// Product attribute /// A task that represents the asynchronous operation public virtual async Task InsertProductAttributeAsync(ProductAttribute productAttribute) { await _productAttributeRepository.InsertAsync(productAttribute); } /// /// Updates the product attribute /// /// Product attribute /// A task that represents the asynchronous operation public virtual async Task UpdateProductAttributeAsync(ProductAttribute productAttribute) { await _productAttributeRepository.UpdateAsync(productAttribute); } /// /// Returns a list of IDs of not existing attributes /// /// The IDs of the attributes to check /// /// A task that represents the asynchronous operation /// The task result contains the list of IDs not existing attributes /// public virtual async Task GetNotExistingAttributesAsync(int[] attributeId) { ArgumentNullException.ThrowIfNull(attributeId); var query = _productAttributeRepository.Table; var queryFilter = attributeId.Distinct().ToArray(); var filter = await query.Select(a => a.Id) .Where(m => queryFilter.Contains(m)) .ToListAsync(); return queryFilter.Except(filter).ToArray(); } #endregion #region Product attributes mappings /// /// Deletes a product attribute mapping /// /// Product attribute mapping /// A task that represents the asynchronous operation public virtual async Task DeleteProductAttributeMappingAsync(ProductAttributeMapping productAttributeMapping) { await _productAttributeMappingRepository.DeleteAsync(productAttributeMapping); } /// /// Gets product attribute mappings by product identifier /// /// The product identifier /// /// A task that represents the asynchronous operation /// The task result contains the product attribute mapping collection /// public virtual async Task> GetProductAttributeMappingsByProductIdAsync(int productId) { var allCacheKey = _staticCacheManager.PrepareKeyForDefaultCache(NopCatalogDefaults.ProductAttributeMappingsByProductCacheKey, productId); var query = from pam in _productAttributeMappingRepository.Table orderby pam.DisplayOrder, pam.Id where pam.ProductId == productId select pam; var attributes = await _staticCacheManager.GetAsync(allCacheKey, async () => await query.ToListAsync()) ?? new List(); return attributes; } /// /// Gets a product attribute mapping /// /// Product attribute mapping identifier /// /// A task that represents the asynchronous operation /// The task result contains the product attribute mapping /// public virtual async Task GetProductAttributeMappingByIdAsync(int productAttributeMappingId) { return await _productAttributeMappingRepository.GetByIdAsync(productAttributeMappingId, cache => default); } /// /// Inserts a product attribute mapping /// /// The product attribute mapping /// A task that represents the asynchronous operation public virtual async Task InsertProductAttributeMappingAsync(ProductAttributeMapping productAttributeMapping) { await _productAttributeMappingRepository.InsertAsync(productAttributeMapping); } /// /// Updates the product attribute mapping /// /// The product attribute mapping /// A task that represents the asynchronous operation public virtual async Task UpdateProductAttributeMappingAsync(ProductAttributeMapping productAttributeMapping) { await _productAttributeMappingRepository.UpdateAsync(productAttributeMapping); } #endregion #region Product attribute values /// /// Deletes a product attribute value /// /// Product attribute value /// A task that represents the asynchronous operation public virtual async Task DeleteProductAttributeValueAsync(ProductAttributeValue productAttributeValue) { await _productAttributeValueRepository.DeleteAsync(productAttributeValue); } /// /// Gets product attribute values by product attribute mapping identifier /// /// The product attribute mapping identifier /// /// A task that represents the asynchronous operation /// The task result contains the product attribute mapping collection /// public virtual async Task> GetProductAttributeValuesAsync(int productAttributeMappingId) { var key = _staticCacheManager.PrepareKeyForDefaultCache(NopCatalogDefaults.ProductAttributeValuesByAttributeCacheKey, productAttributeMappingId); var query = from pav in _productAttributeValueRepository.Table orderby pav.DisplayOrder, pav.Id where pav.ProductAttributeMappingId == productAttributeMappingId select pav; var productAttributeValues = await _staticCacheManager.GetAsync(key, async () => await query.ToListAsync()); return productAttributeValues; } /// /// Gets a product attribute value /// /// Product attribute value identifier /// /// A task that represents the asynchronous operation /// The task result contains the product attribute value /// public virtual async Task GetProductAttributeValueByIdAsync(int productAttributeValueId) { return await _productAttributeValueRepository.GetByIdAsync(productAttributeValueId, cache => default); } /// /// Inserts a product attribute value /// /// The product attribute value /// A task that represents the asynchronous operation public virtual async Task InsertProductAttributeValueAsync(ProductAttributeValue productAttributeValue) { await _productAttributeValueRepository.InsertAsync(productAttributeValue); } /// /// Updates the product attribute value /// /// The product attribute value /// A task that represents the asynchronous operation public virtual async Task UpdateProductAttributeValueAsync(ProductAttributeValue productAttributeValue) { await _productAttributeValueRepository.UpdateAsync(productAttributeValue); } #endregion #region Product attribute value pictures /// /// Deletes a product attribute value picture /// /// Product attribute value picture /// A task that represents the asynchronous operation public virtual async Task DeleteProductAttributeValuePictureAsync(ProductAttributeValuePicture valuePicture) { await _productAttributeValuePictureRepository.DeleteAsync(valuePicture); } /// /// Inserts a product attribute value picture /// /// Product attribute value picture /// A task that represents the asynchronous operation public virtual async Task InsertProductAttributeValuePictureAsync(ProductAttributeValuePicture valuePicture) { await _productAttributeValuePictureRepository.InsertAsync(valuePicture); } /// /// Updates a product attribute value picture /// /// Product attribute value picture /// A task that represents the asynchronous operation public virtual async Task UpdateProductAttributeValuePictureAsync(ProductAttributeValuePicture valuePicture) { await _productAttributeValuePictureRepository.UpdateAsync(valuePicture); } /// /// Get product attribute value pictures /// /// Value id /// /// A task that represents the asynchronous operation /// The task result contains the product attribute value pictures /// public virtual async Task> GetProductAttributeValuePicturesAsync(int valueId) { var allCacheKey = _staticCacheManager.PrepareKeyForDefaultCache(NopCatalogDefaults.ProductAttributeValuePicturesByValueCacheKey, valueId); var query = from pacp in _productAttributeValuePictureRepository.Table join p in _pictureRepository.Table on pacp.PictureId equals p.Id join pp in _productPictureRepository.Table on p.Id equals pp.PictureId where pacp.ProductAttributeValueId == valueId orderby pp.DisplayOrder, pacp.PictureId select pacp; var valuePictures = await _staticCacheManager.GetAsync(allCacheKey, async () => await query.ToListAsync()) ?? new List(); return valuePictures; } /// /// Returns a ProductAttributeValuePicture that has the specified values /// /// Source /// Product attribute value identifier /// Picture identifier /// A ProductAttributeValuePicture that has the specified values; otherwise null public virtual ProductAttributeValuePicture FindProductAttributeValuePicture(IList source, int valueId, int pictureId) { foreach (var valuePicture in source) if (valuePicture.ProductAttributeValueId == valueId && valuePicture.PictureId == pictureId) return valuePicture; return null; } #endregion #region Predefined product attribute values /// /// Deletes a predefined product attribute value /// /// Predefined product attribute value /// A task that represents the asynchronous operation public virtual async Task DeletePredefinedProductAttributeValueAsync(PredefinedProductAttributeValue ppav) { await _predefinedProductAttributeValueRepository.DeleteAsync(ppav); } /// /// Gets predefined product attribute values by product attribute identifier /// /// The product attribute identifier /// /// A task that represents the asynchronous operation /// The task result contains the product attribute mapping collection /// public virtual async Task> GetPredefinedProductAttributeValuesAsync(int productAttributeId) { var key = _staticCacheManager.PrepareKeyForDefaultCache(NopCatalogDefaults.PredefinedProductAttributeValuesByAttributeCacheKey, productAttributeId); var query = from ppav in _predefinedProductAttributeValueRepository.Table orderby ppav.DisplayOrder, ppav.Id where ppav.ProductAttributeId == productAttributeId select ppav; var values = await _staticCacheManager.GetAsync(key, async () => await query.ToListAsync()); return values; } /// /// Gets a predefined product attribute value /// /// Predefined product attribute value identifier /// /// A task that represents the asynchronous operation /// The task result contains the predefined product attribute value /// public virtual async Task GetPredefinedProductAttributeValueByIdAsync(int id) { return await _predefinedProductAttributeValueRepository.GetByIdAsync(id, cache => default); } /// /// Inserts a predefined product attribute value /// /// The predefined product attribute value /// A task that represents the asynchronous operation public virtual async Task InsertPredefinedProductAttributeValueAsync(PredefinedProductAttributeValue ppav) { await _predefinedProductAttributeValueRepository.InsertAsync(ppav); } /// /// Updates the predefined product attribute value /// /// The predefined product attribute value /// A task that represents the asynchronous operation public virtual async Task UpdatePredefinedProductAttributeValueAsync(PredefinedProductAttributeValue ppav) { await _predefinedProductAttributeValueRepository.UpdateAsync(ppav); } #endregion #region Product attribute combinations /// /// Deletes a product attribute combination /// /// Product attribute combination /// A task that represents the asynchronous operation public virtual async Task DeleteProductAttributeCombinationAsync(ProductAttributeCombination combination) { await _productAttributeCombinationRepository.DeleteAsync(combination); } /// /// Gets all product attribute combinations /// /// Product identifier /// /// A task that represents the asynchronous operation /// The task result contains the product attribute combinations /// public virtual async Task> GetAllProductAttributeCombinationsAsync(int productId) { if (productId == 0) return new List(); var combinations = await _productAttributeCombinationRepository.GetAllAsync(query => { return from c in query orderby c.Id where c.ProductId == productId select c; }, cache => cache.PrepareKeyForDefaultCache(NopCatalogDefaults.ProductAttributeCombinationsByProductCacheKey, productId)); return combinations; } /// /// Gets a product attribute combination /// /// Product attribute combination identifier /// /// A task that represents the asynchronous operation /// The task result contains the product attribute combination /// public virtual async Task GetProductAttributeCombinationByIdAsync(int productAttributeCombinationId) { return await _productAttributeCombinationRepository.GetByIdAsync(productAttributeCombinationId, cache => default); } /// /// Gets a product attribute combination by SKU /// /// SKU /// /// A task that represents the asynchronous operation /// The task result contains the product attribute combination /// public virtual async Task GetProductAttributeCombinationBySkuAsync(string sku) { if (string.IsNullOrEmpty(sku)) return null; sku = sku.Trim(); var query = from pac in _productAttributeCombinationRepository.Table join p in _productRepository.Table on pac.ProductId equals p.Id orderby pac.Id where !p.Deleted && pac.Sku == sku select pac; var combination = await query.FirstOrDefaultAsync(); return combination; } /// /// Inserts a product attribute combination /// /// Product attribute combination /// A task that represents the asynchronous operation public virtual async Task InsertProductAttributeCombinationAsync(ProductAttributeCombination combination) { await _productAttributeCombinationRepository.InsertAsync(combination); } /// /// Updates a product attribute combination /// /// Product attribute combination /// A task that represents the asynchronous operation public virtual async Task UpdateProductAttributeCombinationAsync(ProductAttributeCombination combination) { await _productAttributeCombinationRepository.UpdateAsync(combination); } #endregion #region Product attribute combination pictures /// /// Deletes a product attribute combination picture /// /// Product attribute combination picture /// A task that represents the asynchronous operation public virtual async Task DeleteProductAttributeCombinationPictureAsync(ProductAttributeCombinationPicture combinationPicture) { await _productAttributeCombinationPictureRepository.DeleteAsync(combinationPicture); } /// /// Inserts a product attribute combination picture /// /// Product attribute combination picture /// A task that represents the asynchronous operation public virtual async Task InsertProductAttributeCombinationPictureAsync(ProductAttributeCombinationPicture combinationPicture) { await _productAttributeCombinationPictureRepository.InsertAsync(combinationPicture); } /// /// Updates a product attribute combination picture /// /// Product attribute combination picture /// A task that represents the asynchronous operation public virtual async Task UpdateProductAttributeCombinationPictureAsync(ProductAttributeCombinationPicture combinationPicture) { await _productAttributeCombinationPictureRepository.UpdateAsync(combinationPicture); } /// /// Get product attribute combination pictures /// /// Combination id /// /// A task that represents the asynchronous operation /// The task result contains the product attribute combination pictures /// public virtual async Task> GetProductAttributeCombinationPicturesAsync(int combinationId) { var allCacheKey = _staticCacheManager.PrepareKeyForDefaultCache(NopCatalogDefaults.ProductAttributeCombinationPicturesByCombinationCacheKey, combinationId); var query = from pacp in _productAttributeCombinationPictureRepository.Table join p in _pictureRepository.Table on pacp.PictureId equals p.Id join pp in _productPictureRepository.Table on p.Id equals pp.PictureId where pacp.ProductAttributeCombinationId == combinationId orderby pp.DisplayOrder, pacp.PictureId select pacp; var combinationPictures = await _staticCacheManager.GetAsync(allCacheKey, async () => await query.ToListAsync()) ?? new List(); return combinationPictures; } /// /// Returns a ProductAttributeCombinationPicture that has the specified values /// /// Source /// Product attribute combination identifier /// Picture identifier /// A ProductAttributeCombinationPicture that has the specified values; otherwise null public virtual ProductAttributeCombinationPicture FindProductAttributeCombinationPicture(IList source, int combinationId, int pictureId) { foreach (var combinationPicture in source) if (combinationPicture.ProductAttributeCombinationId == combinationId && combinationPicture.PictureId == pictureId) return combinationPicture; return null; } #endregion #endregion }