public ActionResult InstantSearch(CatalogSearchQuery query)
        {
            if (string.IsNullOrWhiteSpace(query.Term) || query.Term.Length < _searchSettings.InstantSearchTermMinLength)
            {
                return(Content(string.Empty));
            }

            query
            .BuildFacetMap(false)
            .Slice(0, Math.Min(16, _searchSettings.InstantSearchNumberOfProducts))
            .SortBy(ProductSortingEnum.Relevance);

            var result = _catalogSearchService.Search(query);

            var model = new SearchResultModel(query)
            {
                SearchResult       = result,
                Term               = query.Term,
                TotalProductsCount = result.TotalHitsCount
            };

            var mappingSettings = _catalogHelper.GetBestFitProductSummaryMappingSettings(ProductSummaryViewMode.Mini, x =>
            {
                x.MapPrices            = false;
                x.MapShortDescription  = true;
                x.MapPictures          = _searchSettings.ShowProductImagesInInstantSearch;
                x.ThumbnailSize        = _mediaSettings.ProductThumbPictureSizeOnProductDetailsPage;
                x.PrefetchTranslations = true;
                x.PrefetchUrlSlugs     = true;
            });

            using (_urlRecordService.BeginScope(false))
                using (_localizedEntityService.BeginScope(false))
                {
                    // InstantSearch should be REALLY very fast! No time for smart caching stuff.
                    if (result.Hits.Count > 0)
                    {
                        _localizedEntityService.PrefetchLocalizedProperties(
                            nameof(Product),
                            Services.WorkContext.WorkingLanguage.Id,
                            result.Hits.Select(x => x.Id).ToArray());
                    }

                    // Add product hits.
                    model.TopProducts = _catalogHelper.MapProductSummaryModel(result.Hits, mappingSettings);

                    // Add spell checker suggestions (if any).
                    model.AddSpellCheckerSuggestions(result.SpellCheckerSuggestions, T, x => Url.RouteUrl("Search", new { q = x }));
                }

            return(PartialView(model));
        }
        public virtual int CopyAttributeOptions(ProductVariantAttribute productVariantAttribute, int productAttributeOptionsSetId, bool deleteExistingValues)
        {
            Guard.NotNull(productVariantAttribute, nameof(productVariantAttribute));
            Guard.NotZero(productVariantAttribute.Id, nameof(productVariantAttribute.Id));
            Guard.NotZero(productAttributeOptionsSetId, nameof(productAttributeOptionsSetId));

            if (deleteExistingValues)
            {
                var existingValues = productVariantAttribute.ProductVariantAttributeValues.ToList();
                if (!existingValues.Any())
                {
                    existingValues = GetProductVariantAttributeValues(productVariantAttribute.Id).ToList();
                }

                existingValues.Each(x => DeleteProductVariantAttributeValue(x));
            }

            var result           = 0;
            var attributeOptions = _productAttributeOptionRepository.TableUntracked
                                   .Where(x => x.ProductAttributeOptionsSetId == productAttributeOptionsSetId)
                                   .ToList();

            if (!attributeOptions.Any())
            {
                return(result);
            }

            // Do not insert already existing values (identified by name field).
            var existingValueNames = new HashSet <string>(_productVariantAttributeValueRepository.TableUntracked
                                                          .Where(x => x.ProductVariantAttributeId == productVariantAttribute.Id)
                                                          .Select(x => x.Name)
                                                          .ToList());

            Picture picture = null;
            ProductVariantAttributeValue productVariantAttributeValue = null;
            var pictureIds = attributeOptions.Where(x => x.PictureId != 0).Select(x => x.PictureId).Distinct().ToArray();
            var pictures   = _pictureService.GetPicturesByIds(pictureIds, true).ToDictionarySafe(x => x.Id);

            using (_localizedEntityService.BeginScope())
            {
                foreach (var option in attributeOptions)
                {
                    if (existingValueNames.Contains(option.Name))
                    {
                        continue;
                    }

                    productVariantAttributeValue           = option.Clone();
                    productVariantAttributeValue.PictureId = 0;
                    productVariantAttributeValue.ProductVariantAttributeId = productVariantAttribute.Id;

                    // Copy picture.
                    if (option.PictureId != 0 && pictures.TryGetValue(option.PictureId, out picture))
                    {
                        var pictureBinary = _pictureService.LoadPictureBinary(picture);

                        var newPicture = _pictureService.InsertPicture(
                            pictureBinary,
                            picture.MimeType,
                            picture.SeoFilename,
                            picture.IsNew,
                            picture.Width ?? 0,
                            picture.Height ?? 0,
                            picture.IsTransient
                            );

                        productVariantAttributeValue.PictureId = newPicture.Id;
                    }

                    // No scope commit, we need new entity id.
                    _productVariantAttributeValueRepository.Insert(productVariantAttributeValue);
                    ++result;

                    // Copy localized properties too.
                    var optionProperties = _localizedEntityService.GetLocalizedProperties(option.Id, "ProductAttributeOption");

                    foreach (var property in optionProperties)
                    {
                        _localizedEntityService.InsertLocalizedProperty(new LocalizedProperty
                        {
                            EntityId       = productVariantAttributeValue.Id,
                            LocaleKeyGroup = "ProductVariantAttributeValue",
                            LocaleKey      = property.LocaleKey,
                            LocaleValue    = property.LocaleValue,
                            LanguageId     = property.LanguageId
                        });
                    }
                }
            }

            return(result);
        }
Example #3
0
        private void ImportCoreOuter(DataImporterContext ctx)
        {
            if (ctx.Request.Profile == null || !ctx.Request.Profile.Enabled)
            {
                return;
            }

            var logPath = ctx.Request.Profile.GetImportLogPath();

            FileSystemHelper.Delete(logPath);

            using (var logger = new TraceLogger(logPath))
            {
                var scopes = new List <IDisposable>();

                try
                {
                    _dbCache.Enabled = false;
                    scopes.Add(_localizedEntityService.BeginScope());
                    scopes.Add(_urlRecordService.BeginScope());

                    ctx.Log = logger;

                    ctx.ExecuteContext.Request = ctx.Request;
                    ctx.ExecuteContext.DataExchangeSettings = _dataExchangeSettings.Value;
                    ctx.ExecuteContext.Services             = _services;
                    ctx.ExecuteContext.Log           = logger;
                    ctx.ExecuteContext.Languages     = _languageService.GetAllLanguages(true);
                    ctx.ExecuteContext.UpdateOnly    = ctx.Request.Profile.UpdateOnly;
                    ctx.ExecuteContext.KeyFieldNames = ctx.Request.Profile.KeyFieldNames.SplitSafe(",");
                    ctx.ExecuteContext.ImportFolder  = ctx.Request.Profile.GetImportFolder();
                    ctx.ExecuteContext.ExtraData     = XmlHelper.Deserialize <ImportExtraData>(ctx.Request.Profile.ExtraData);

                    {
                        var mapConverter = new ColumnMapConverter();
                        ctx.ExecuteContext.ColumnMap = mapConverter.ConvertFrom <ColumnMap>(ctx.Request.Profile.ColumnMapping) ?? new ColumnMap();
                    }

                    var files = ctx.Request.Profile.GetImportFiles();

                    if (files.Count == 0)
                    {
                        throw new SmartException("No files to import.");
                    }

                    if (!HasPermission(ctx))
                    {
                        throw new SmartException("You do not have permission to perform the selected import.");
                    }

                    ctx.Importer = _importerFactory(ctx.Request.Profile.EntityType);

                    _services.EventPublisher.Publish(new ImportExecutingEvent(ctx.ExecuteContext));

                    files.ForEach(x => ImportCoreInner(ctx, x));
                }
                catch (Exception exception)
                {
                    ctx.ExecuteContext.Result.AddError(exception);
                }
                finally
                {
                    try
                    {
                        _dbCache.Enabled = true;
                        scopes.Each(x => x.Dispose());

                        _services.EventPublisher.Publish(new ImportExecutedEvent(ctx.ExecuteContext));
                    }
                    catch (Exception exception)
                    {
                        ctx.ExecuteContext.Result.AddError(exception);
                    }

                    try
                    {
                        // database context sharing problem: if there are entities in modified state left by the provider due to SaveChanges failure,
                        // then all subsequent SaveChanges would fail too (e.g. IImportProfileService.UpdateImportProfile, IScheduledTaskService.UpdateTask...).
                        // so whatever it is, detach\dispose all what the tracker still has tracked.

                        _services.DbContext.DetachAll(false);
                    }
                    catch (Exception exception)
                    {
                        ctx.ExecuteContext.Result.AddError(exception);
                    }

                    try
                    {
                        //SendCompletionEmail(ctx);
                    }
                    catch (Exception exception)
                    {
                        ctx.ExecuteContext.Result.AddError(exception);
                    }

                    try
                    {
                        ctx.ExecuteContext.Result.EndDateUtc = DateTime.UtcNow;
                        LogResult(ctx);
                    }
                    catch (Exception exception)
                    {
                        logger.ErrorsAll(exception);
                    }

                    try
                    {
                        ctx.Request.Profile.ResultInfo = XmlHelper.Serialize(ctx.ExecuteContext.Result.Clone());
                        _importProfileService.UpdateImportProfile(ctx.Request.Profile);
                    }
                    catch (Exception exception)
                    {
                        logger.ErrorsAll(exception);
                    }

                    try
                    {
                        ctx.Request.CustomData.Clear();
                        ctx.Log = null;
                    }
                    catch (Exception exception)
                    {
                        logger.ErrorsAll(exception);
                    }
                }
            }
        }
Example #4
0
        private void ImportCoreOuter(DataImporterContext ctx)
        {
            var customer = _services.WorkContext.CurrentCustomer;
            var profile  = ctx.Request.Profile;
            var logPath  = profile.GetImportLogPath();

            FileSystemHelper.DeleteFile(logPath);

            using (var logger = new TraceLogger(logPath))
            {
                var scopes = new List <IDisposable>();

                try
                {
                    var files        = profile.GetImportFiles(profile.ImportRelatedData);
                    var groupedFiles = files.GroupBy(x => x.RelatedType);

                    if (!files.Any())
                    {
                        throw new SmartException("No files to import.");
                    }

                    if (!HasPermission(ctx))
                    {
                        throw new SmartException("You do not have permission to perform the selected import.");
                    }

                    _dbCache.Enabled = false;
                    _services.MediaService.ImagePostProcessingEnabled = false;
                    scopes.Add(_localizedEntityService.BeginScope());
                    scopes.Add(_urlRecordService.BeginScope());

                    ctx.Log      = logger;
                    ctx.Importer = _importerFactory(profile.EntityType);

                    ctx.ExecuteContext.Request = ctx.Request;
                    ctx.ExecuteContext.DataExchangeSettings = _dataExchangeSettings.Value;
                    ctx.ExecuteContext.Services             = _services;
                    ctx.ExecuteContext.Log           = logger;
                    ctx.ExecuteContext.Languages     = _languageService.GetAllLanguages(true);
                    ctx.ExecuteContext.UpdateOnly    = profile.UpdateOnly;
                    ctx.ExecuteContext.KeyFieldNames = profile.KeyFieldNames.SplitSafe(",");
                    ctx.ExecuteContext.ImportFolder  = profile.GetImportFolder();
                    ctx.ExecuteContext.ExtraData     = XmlHelper.Deserialize <ImportExtraData>(profile.ExtraData);

                    var sb = new StringBuilder();
                    sb.AppendLine();
                    sb.AppendLine(new string('-', 40));
                    sb.AppendLine("Smartstore: v." + SmartStoreVersion.CurrentFullVersion);
                    sb.AppendLine("Import profile: {0} {1}".FormatInvariant(profile.Name, profile.Id == 0 ? " (volatile)" : $" (Id {profile.Id})"));
                    foreach (var fileGroup in groupedFiles)
                    {
                        var entityName = fileGroup.Key.HasValue ? fileGroup.Key.Value.ToString() : profile.EntityType.ToString();
                        var fileNames  = string.Join(", ", fileGroup.Select(x => x.Name));
                        sb.AppendLine("{0} files: {1}".FormatInvariant(entityName, fileNames));
                    }
                    sb.Append("Executed by: " + customer.Email.NullEmpty() ?? customer.SystemName.NaIfEmpty());
                    ctx.Log.Info(sb.ToString());

                    _services.EventPublisher.Publish(new ImportExecutingEvent(ctx.ExecuteContext));

                    foreach (var fileGroup in groupedFiles)
                    {
                        ctx.ExecuteContext.Result = ctx.Results[fileGroup.Key.HasValue ? fileGroup.Key.Value.ToString() : string.Empty] = new ImportResult();

                        fileGroup.Each(x => ImportCoreInner(ctx, x));
                    }
                }
                catch (Exception ex)
                {
                    logger.ErrorsAll(ex);
                }
                finally
                {
                    try
                    {
                        _dbCache.Enabled = true;
                        _services.MediaService.ImagePostProcessingEnabled = true;
                        scopes.Each(x => x.Dispose());

                        _services.EventPublisher.Publish(new ImportExecutedEvent(ctx.ExecuteContext));
                    }
                    catch (Exception ex)
                    {
                        logger.ErrorsAll(ex);
                    }

                    try
                    {
                        // Database context sharing problem: if there are entities in modified state left by the provider due to SaveChanges failure,
                        // then all subsequent SaveChanges would fail too (e.g. IImportProfileService.UpdateImportProfile, IScheduledTaskService.UpdateTask...).
                        // so whatever it is, detach\dispose all what the tracker still has tracked.

                        _services.DbContext.DetachAll(false);
                    }
                    catch (Exception ex)
                    {
                        logger.ErrorsAll(ex);
                    }

                    try
                    {
                        SendCompletionEmail(ctx);
                    }
                    catch (Exception ex)
                    {
                        logger.ErrorsAll(ex);
                    }

                    try
                    {
                        LogResults(ctx);
                    }
                    catch (Exception ex)
                    {
                        logger.ErrorsAll(ex);
                    }

                    try
                    {
                        if (ctx.Results.TryGetValue(string.Empty, out var result))
                        {
                            profile.ResultInfo = XmlHelper.Serialize(result.Clone());
                            _importProfileService.UpdateImportProfile(profile);
                        }
                    }
                    catch (Exception ex)
                    {
                        logger.ErrorsAll(ex);
                    }

                    try
                    {
                        ctx.Request.CustomData.Clear();
                        ctx.Results.Clear();
                        ctx.Log = null;
                    }
                    catch (Exception ex)
                    {
                        logger.ErrorsAll(ex);
                    }
                }
            }
        }
        public virtual int CopyAttributeOptions(ProductVariantAttribute productVariantAttribute, int productAttributeOptionsSetId, bool deleteExistingValues)
        {
            Guard.NotNull(productVariantAttribute, nameof(productVariantAttribute));
            Guard.NotZero(productVariantAttribute.Id, nameof(productVariantAttribute.Id));
            Guard.NotZero(productAttributeOptionsSetId, nameof(productAttributeOptionsSetId));

            if (deleteExistingValues)
            {
                var existingValues = productVariantAttribute.ProductVariantAttributeValues.ToList();
                if (!existingValues.Any())
                {
                    existingValues = GetProductVariantAttributeValues(productVariantAttribute.Id).ToList();
                }

                existingValues.Each(x => DeleteProductVariantAttributeValue(x));
            }

            var result           = 0;
            var attributeOptions = _productAttributeOptionRepository.TableUntracked
                                   .Where(x => x.ProductAttributeOptionsSetId == productAttributeOptionsSetId)
                                   .ToList();

            if (!attributeOptions.Any())
            {
                return(result);
            }

            // Do not insert already existing values (identified by name field).
            var existingValueNames = new HashSet <string>(_productVariantAttributeValueRepository.TableUntracked
                                                          .Where(x => x.ProductVariantAttributeId == productVariantAttribute.Id)
                                                          .Select(x => x.Name)
                                                          .ToList());

            using (_localizedEntityService.BeginScope())
            {
                foreach (var option in attributeOptions)
                {
                    if (existingValueNames.Contains(option.Name))
                    {
                        continue;
                    }

                    var pvav = option.Clone();
                    pvav.ProductVariantAttributeId = productVariantAttribute.Id;

                    // No scope commit, we need new entity id.
                    _productVariantAttributeValueRepository.Insert(pvav);
                    ++result;

                    // Copy localized properties too.
                    var optionProperties = _localizedEntityService.GetLocalizedProperties(option.Id, "ProductAttributeOption");

                    foreach (var property in optionProperties)
                    {
                        _localizedEntityService.InsertLocalizedProperty(new LocalizedProperty
                        {
                            EntityId       = pvav.Id,
                            LocaleKeyGroup = "ProductVariantAttributeValue",
                            LocaleKey      = property.LocaleKey,
                            LocaleValue    = property.LocaleValue,
                            LanguageId     = property.LanguageId
                        });
                    }
                }
            }

            return(result);
        }