コード例 #1
0
 public void Should_remove_illegal_chars()
 {
     SeoExtensions.GetSeName("test!@#$%^&*()+<>?/", false, false).ShouldEqual("test");
 }
コード例 #2
0
 public void Should_return_lowercase()
 {
     SeoExtensions.GetSeName("tEsT", false, false).ShouldEqual("test");
 }
コード例 #3
0
 public void Should_allow_all_latin_chars()
 {
     SeoExtensions.GetSeName("abcdefghijklmnopqrstuvwxyz1234567890", false, false).ShouldEqual("abcdefghijklmnopqrstuvwxyz1234567890");
 }
コード例 #4
0
        private async Task From430To440()
        {
            #region Install String resources
            await InstallStringResources("430_440.nopres.xml");

            #endregion

            #region Permisions
            IPermissionProvider provider = new StandardPermissionProvider();
            await _serviceProvider.GetRequiredService <IPermissionService>().InstallPermissions(provider);

            #endregion

            #region Update tags on the products

            var productTagService = _serviceProvider.GetRequiredService <IProductTagService>();
            var productRepository = _serviceProvider.GetRequiredService <IRepository <Product> >();

            foreach (var tag in await productTagService.GetAllProductTags())
            {
                var builder = Builders <Product> .Filter;
                var filter  = new BsonDocument {
                    new BsonElement("ProductTags", tag.Id)
                };
                var update = Builders <Product> .Update
                             .Set(x => x.ProductTags.ElementAt(-1), tag.Name);

                await productRepository.Collection.UpdateManyAsync(filter, update);

                tag.SeName = SeoExtensions.GetSeName(tag.Name, false, false);
                await productTagService.UpdateProductTag(tag);
            }

            #endregion

            #region User api

            _serviceProvider.GetRequiredService <IRepository <UserApi> >().Collection.Indexes.CreateOne(new CreateIndexModel <UserApi>((Builders <UserApi> .IndexKeys.Ascending(x => x.Email)), new CreateIndexOptions()
            {
                Name = "Email", Unique = true, Background = true
            }));

            #endregion

            #region Update message templates (tokens)

            string ReplaceValue(string value)
            {
                string Evaluator(Match match)
                {
                    return($"{{{{{match.Value.Replace("%", "")}}}}}");
                }

                var evaluator = new MatchEvaluator(Evaluator);

                return(Regex.Replace(value, @"%([A-Za-z0-9_.]*?)%", new MatchEvaluator(Evaluator)));
            }

            var orderProducts    = File.ReadAllText(CommonHelper.MapPath("~/App_Data/Upgrade/Order.Products.txt"));
            var shipmentProducts = File.ReadAllText(CommonHelper.MapPath("~/App_Data/Upgrade/Shipment.Products.txt"));

            var messagetemplateService = _serviceProvider.GetRequiredService <Grand.Services.Messages.IMessageTemplateService>();
            var messagetemplates       = await messagetemplateService.GetAllMessageTemplates(string.Empty);

            foreach (var messagetemplate in messagetemplates)
            {
                messagetemplate.Subject = ReplaceValue(messagetemplate.Subject);
                if (messagetemplate.Body.Contains("%Order.Product(s)%"))
                {
                    messagetemplate.Body = messagetemplate.Body.Replace("%Order.Product(s)%", orderProducts);
                }
                if (messagetemplate.Body.Contains("%Shipment.Product(s)%"))
                {
                    messagetemplate.Body = messagetemplate.Body.Replace("%Shipment.Product(s)%", shipmentProducts);
                }
                messagetemplate.Body = ReplaceValue(messagetemplate.Body);
                await messagetemplateService.UpdateMessageTemplate(messagetemplate);
            }
            #endregion

            #region Insert message template

            var eaGeneral = _serviceProvider.GetRequiredService <IRepository <EmailAccount> >().Table.FirstOrDefault();
            if (eaGeneral == null)
            {
                throw new Exception("Default email account cannot be loaded");
            }
            var messageTemplates = new List <MessageTemplate>
            {
                new MessageTemplate
                {
                    Name    = "AuctionExpired.StoreOwnerNotification",
                    Subject = "Your auction to product {{Product.Name}}  has expired.",
                    Body    = "Hello, <br> Your auction to product {{Product.Name}} has expired without bid.",
                    //this template is disabled by default
                    IsActive       = false,
                    EmailAccountId = eaGeneral.Id,
                }
            };
            await _serviceProvider.GetRequiredService <IRepository <MessageTemplate> >().InsertAsync(messageTemplates);

            #endregion
        }
コード例 #5
0
 /// <summary>
 /// Get picture SEO friendly name
 /// </summary>
 /// <param name="name">Name</param>
 /// <returns>Result</returns>
 public virtual string GetPictureSeName(string name)
 {
     return(SeoExtensions.GetSeName(name, true, false));
 }
コード例 #6
0
        /// <summary>
        /// Route request to the particular action
        /// </summary>
        /// <param name="context">A route context object</param>
        /// <returns>Task of the routing</returns>
        public override async Task RouteAsync(RouteContext context)
        {
            if (!DataSettingsHelper.DatabaseIsInstalled())
            {
                return;
            }

            //try to get slug from the route data
            var routeValues = await GetRouteValues(context);

            if (!routeValues.TryGetValue("GenericSeName", out object slugValue) || string.IsNullOrEmpty(slugValue as string))
            {
                return;
            }

            var slug = slugValue as string;

            //virtual directory path
            var pathBase = context.HttpContext.Request.PathBase;
            //performance optimization, we load a cached verion here. It reduces number of SQL requests for each page load
            var urlRecordService = context.HttpContext.RequestServices.GetRequiredService <IUrlRecordService>();
            var urlRecord        = await urlRecordService.GetBySlugCached(slug);

            //no URL record found
            if (urlRecord == null)
            {
                return;
            }

            //if URL record is not active let's find the latest one
            if (!urlRecord.IsActive)
            {
                var activeSlug = await urlRecordService.GetActiveSlug(urlRecord.EntityId, urlRecord.EntityName, urlRecord.LanguageId);

                if (string.IsNullOrEmpty(activeSlug))
                {
                    return;
                }

                //redirect to active slug if found
                var redirectionRouteData = new RouteData(context.RouteData);
                redirectionRouteData.Values["controller"]        = "Common";
                redirectionRouteData.Values["action"]            = "InternalRedirect";
                redirectionRouteData.Values["url"]               = $"{pathBase}/{activeSlug}{context.HttpContext.Request.QueryString}";
                redirectionRouteData.Values["permanentRedirect"] = true;
                context.HttpContext.Items["grand.RedirectFromGenericPathRoute"] = true;
                context.RouteData = redirectionRouteData;
                await _target.RouteAsync(context);

                return;
            }

            //ensure that the slug is the same for the current language,
            //otherwise it can cause some issues when customers choose a new language but a slug stays the same
            var workContext            = context.HttpContext.RequestServices.GetRequiredService <IWorkContext>();
            var slugForCurrentLanguage = await SeoExtensions.GetSeName(urlRecordService, context.HttpContext, urlRecord.EntityId, urlRecord.EntityName, workContext.WorkingLanguage.Id);

            if (!string.IsNullOrEmpty(slugForCurrentLanguage) && !slugForCurrentLanguage.Equals(slug, StringComparison.OrdinalIgnoreCase))
            {
                //we should make validation above because some entities does not have SeName for standard (Id = 0) language (e.g. news, blog posts)

                //redirect to the page for current language
                var redirectionRouteData = new RouteData(context.RouteData);
                redirectionRouteData.Values["controller"]        = "Common";
                redirectionRouteData.Values["action"]            = "InternalRedirect";
                redirectionRouteData.Values["url"]               = $"{pathBase}/{slugForCurrentLanguage}{context.HttpContext.Request.QueryString}";
                redirectionRouteData.Values["permanentRedirect"] = false;
                context.HttpContext.Items["grand.RedirectFromGenericPathRoute"] = true;
                context.RouteData = redirectionRouteData;
                await _target.RouteAsync(context);

                return;
            }

            //since we are here, all is ok with the slug, so process URL
            var currentRouteData = new RouteData(context.RouteData);

            switch (urlRecord.EntityName.ToLowerInvariant())
            {
            case "product":
                currentRouteData.Values["controller"] = "Product";
                currentRouteData.Values["action"]     = "ProductDetails";
                currentRouteData.Values["productid"]  = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "category":
                currentRouteData.Values["controller"] = "Catalog";
                currentRouteData.Values["action"]     = "Category";
                currentRouteData.Values["categoryid"] = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "manufacturer":
                currentRouteData.Values["controller"]     = "Catalog";
                currentRouteData.Values["action"]         = "Manufacturer";
                currentRouteData.Values["manufacturerid"] = urlRecord.EntityId;
                currentRouteData.Values["SeName"]         = urlRecord.Slug;
                break;

            case "vendor":
                currentRouteData.Values["controller"] = "Catalog";
                currentRouteData.Values["action"]     = "Vendor";
                currentRouteData.Values["vendorid"]   = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "newsitem":
                currentRouteData.Values["controller"] = "News";
                currentRouteData.Values["action"]     = "NewsItem";
                currentRouteData.Values["newsItemId"] = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "blogpost":
                currentRouteData.Values["controller"] = "Blog";
                currentRouteData.Values["action"]     = "BlogPost";
                currentRouteData.Values["blogPostId"] = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "topic":
                currentRouteData.Values["controller"] = "Topic";
                currentRouteData.Values["action"]     = "TopicDetails";
                currentRouteData.Values["topicId"]    = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "knowledgebasearticle":
                currentRouteData.Values["controller"] = "Knowledgebase";
                currentRouteData.Values["action"]     = "KnowledgebaseArticle";
                currentRouteData.Values["articleId"]  = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "knowledgebasecategory":
                currentRouteData.Values["controller"] = "Knowledgebase";
                currentRouteData.Values["action"]     = "ArticlesByCategory";
                currentRouteData.Values["categoryId"] = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "course":
                currentRouteData.Values["controller"] = "Course";
                currentRouteData.Values["action"]     = "Details";
                currentRouteData.Values["courseId"]   = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            default:
                //no record found, thus generate an event this way developers could insert their own types
                await context.HttpContext.RequestServices.GetRequiredService <IMediator>().Publish(new CustomUrlRecordEntityNameRequested(currentRouteData, urlRecord));

                break;
            }
            context.RouteData = currentRouteData;

            //route request
            await _target.RouteAsync(context);
        }
コード例 #7
0
        /// <summary>
        /// Returns information about the requested route.
        /// </summary>
        /// <param name="httpContext">An object that encapsulates information about the HTTP request.</param>
        /// <returns>
        /// An object that contains the values from the route definition.
        /// </returns>
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            RouteData data = base.GetRouteData(httpContext);

            if (data != null && DataSettingsHelper.DatabaseIsInstalled())
            {
                var urlRecordService = EngineContext.Current.Resolve <IUrlRecordService>();
                var slug             = data.Values["generic_se_name"] as string;
                //performance optimization.
                //we load a cached verion here. it reduces number of SQL requests for each page load
                var urlRecord = urlRecordService.GetBySlugCached(slug);
                //comment the line above and uncomment the line below in order to disable this performance "workaround"
                //var urlRecord = urlRecordService.GetBySlug(slug);
                if (urlRecord == null)
                {
                    //no URL record found

                    //var webHelper = EngineContext.Current.Resolve<IWebHelper>();
                    //var response = httpContext.Response;
                    //response.Status = "302 Found";
                    //response.RedirectLocation = webHelper.GetStoreLocation(false);
                    //response.End();
                    //return null;

                    data.Values["controller"] = "Common";
                    data.Values["action"]     = "PageNotFound";
                    return(data);
                }
                //ensre that URL record is active
                if (!urlRecord.IsActive)
                {
                    //URL record is not active. let's find the latest one
                    var activeSlug = urlRecordService.GetActiveSlug(urlRecord.EntityId, urlRecord.EntityName, urlRecord.LanguageId);
                    if (string.IsNullOrWhiteSpace(activeSlug))
                    {
                        //no active slug found

                        //var webHelper = EngineContext.Current.Resolve<IWebHelper>();
                        //var response = httpContext.Response;
                        //response.Status = "302 Found";
                        //response.RedirectLocation = webHelper.GetStoreLocation(false);
                        //response.End();
                        //return null;

                        data.Values["controller"] = "Common";
                        data.Values["action"]     = "PageNotFound";
                        return(data);
                    }

                    //the active one is found
                    var webHelper = EngineContext.Current.Resolve <IWebHelper>();
                    var response  = httpContext.Response;
                    response.Status           = "301 Moved Permanently";
                    response.RedirectLocation = string.Format("{0}{1}", webHelper.GetStoreLocation(false), activeSlug);
                    response.End();
                    return(null);
                }

                //ensure that the slug is the same for the current language
                //otherwise, it can cause some issues when customers choose a new language but a slug stays the same
                var workContext            = EngineContext.Current.Resolve <IWorkContext>();
                var slugForCurrentLanguage = SeoExtensions.GetSeName(urlRecord.EntityId, urlRecord.EntityName, workContext.WorkingLanguage.Id);
                if (!String.IsNullOrEmpty(slugForCurrentLanguage) &&
                    !slugForCurrentLanguage.Equals(slug, StringComparison.InvariantCultureIgnoreCase))
                {
                    //we should make not null or "" validation above because some entities does not have SeName for standard (ID=0) language (e.g. news, blog posts)
                    var webHelper = EngineContext.Current.Resolve <IWebHelper>();
                    var response  = httpContext.Response;
                    //response.Status = "302 Found";
                    response.Status           = "302 Moved Temporarily";
                    response.RedirectLocation = string.Format("{0}{1}", webHelper.GetStoreLocation(false), slugForCurrentLanguage);
                    response.End();
                    return(null);
                }

                //process URL
                switch (urlRecord.EntityName.ToLowerInvariant())
                {
                case "product":
                {
                    data.Values["controller"] = "Product";
                    data.Values["action"]     = "ProductDetails";
                    data.Values["productid"]  = urlRecord.EntityId;
                    data.Values["SeName"]     = urlRecord.Slug;
                }
                break;

                case "category":
                {
                    data.Values["controller"] = "Catalog";
                    data.Values["action"]     = "Category";
                    data.Values["categoryid"] = urlRecord.EntityId;
                    data.Values["SeName"]     = urlRecord.Slug;
                }
                break;

                case "manufacturer":
                {
                    data.Values["controller"]     = "Catalog";
                    data.Values["action"]         = "Manufacturer";
                    data.Values["manufacturerid"] = urlRecord.EntityId;
                    data.Values["SeName"]         = urlRecord.Slug;
                }
                break;

                case "vendor":
                {
                    data.Values["controller"] = "Catalog";
                    data.Values["action"]     = "Vendor";
                    data.Values["vendorid"]   = urlRecord.EntityId;
                    data.Values["SeName"]     = urlRecord.Slug;
                }
                break;

                case "newsitem":
                {
                    data.Values["controller"] = "News";
                    data.Values["action"]     = "NewsItem";
                    data.Values["newsItemId"] = urlRecord.EntityId;
                    data.Values["SeName"]     = urlRecord.Slug;
                }
                break;

                case "blogpost":
                {
                    data.Values["controller"] = "Blog";
                    data.Values["action"]     = "BlogPost";
                    data.Values["blogPostId"] = urlRecord.EntityId;
                    data.Values["SeName"]     = urlRecord.Slug;
                }
                break;

                case "topic":
                {
                    data.Values["controller"] = "Topic";
                    data.Values["action"]     = "TopicDetails";
                    data.Values["topicId"]    = urlRecord.EntityId;
                    data.Values["SeName"]     = urlRecord.Slug;
                }
                break;

                default:
                {
                    //no record found

                    //generate an event this way developers could insert their own types
                    EngineContext.Current.Resolve <IEventPublisher>()
                    .Publish(new CustomUrlRecordEntityNameRequested(data, urlRecord));
                }
                break;
                }
            }
            return(data);
        }
コード例 #8
0
 public void Can_convert_non_western_chars()
 {
     //german letters with diacritics
     SeoExtensions.GetSeName("testäöü", true, false).ShouldEqual("testaou");
     SeoExtensions.GetSeName("testäöü", false, false).ShouldEqual("test");
 }
コード例 #9
0
 public void Can_allow_unicode_chars()
 {
     //russian letters
     SeoExtensions.GetSeName("testтест", true, true).ShouldEqual("testтест");
     SeoExtensions.GetSeName("testтест", true, false).ShouldEqual("test");
 }
コード例 #10
0
        public IViewComponentResult Invoke(string widgetZone, object additionalData)
        {
            IViewComponentResult viewComponent;
            EmptyResult          emptyResult = new EmptyResult();

            VendorDetailsSettings VendorDetailsSetting = _settingService.LoadSetting <VendorDetailsSettings>(_storeContext.CurrentStore.Id);

            if (VendorDetailsSetting != null)
            {
                int productId = Convert.ToInt32(additionalData);

                if (productId != 0)
                {
                    var     P           = _customersInfo.GetCount(productId);
                    Product productById = _productService.GetProductById(productId);

                    if (productById == null ? false : productById.VendorId == 0)
                    {
                        PublicInfoModel yom = new PublicInfoModel();
                        yom.Name      = productById.Name;
                        yom.SoldCount = P.Count;
                        PublicInfoModel email1 = yom;
                        viewComponent = base.View("~/Plugins/Widgets.VendorDetails/Views/raw.cshtml", email1);
                    }
                    else if (productById == null ? false : productById.VendorId != 0)
                    {
                        var             VendorIds   = this._vendorService.GetVendorById(productById.VendorId).Id;
                        var             CustomerIds = _customersInfo.GetCustomerId(VendorIds);
                        Vendor          vendorById  = this._vendorService.GetVendorById(productById.VendorId);
                        PublicInfoModel Model       = new PublicInfoModel();
                        //Model.Id(vendorById.get_Id());
                        Model.Name        = vendorById.Name;
                        Model.Description = vendorById.Description;
                        //Model.Rating = productById.ApprovedRatingSum;
                        //Model.SoldCount = P.Count;
                        //Model.Phone = CustomerIds.GetAttribute<String>(SystemCustomerAttributeNames.Phone);
                        Model.SeName = SeoExtensions.GetSeName(vendorById);
                        PublicInfoModel email = Model;

                        if (VendorDetailsSetting.ShowVendorEmail)
                        {
                            email.Email = vendorById.Email;
                        }
                        if (VendorDetailsSetting.ShowProductRating)
                        {
                            email.Rating = productById.ApprovedRatingSum;
                        }
                        if (VendorDetailsSetting.ShowProductSoldCount)
                        {
                            email.SoldCount = P.Count;
                        }

                        if (VendorDetailsSetting.ShowVendorPhoneNumer)
                        {
                            email.Phone = CustomerIds.GetAttribute <String>(SystemCustomerAttributeNames.Phone);
                        }


                        viewComponent = base.View("~/Plugins/Widgets.VendorDetails/Views/PublicInfo.cshtml", email);
                    }

                    else
                    {
                        viewComponent = null;
                    }
                }
                else
                {
                    viewComponent = null;
                }
            }
            else
            {
                viewComponent = null;
            }

            return(viewComponent);
        }
コード例 #11
0
 public void Should_replace_space_with_dash()
 {
     SeoExtensions.GetSeName("test test", false, false).ShouldEqual("test-test");
     SeoExtensions.GetSeName("test     test", false, false).ShouldEqual("test-test");
 }
コード例 #12
0
        public ActionResult Edit(EventPageModel model, bool continueEditing)
        {
            //todo: add later
            //if (!_permissionService.Authorize(MobSocialPermissionProvider.ManageEventPages))
            //    return AccessDeniedView();

            var item = _eventPageService.GetById(model.Id);

            if (item == null)
            {
                //No product found with the specified id
                return(RedirectToAction("List"));
            }

            if (ModelState.IsValid)
            {
                item.Name                  = model.Name;
                item.LocationName          = model.LocationName;
                item.LocationAddress1      = model.Address1;
                item.LocationAddress2      = model.Address2;
                item.LocationCity          = model.City;
                item.LocationState         = model.LocationState;
                item.LocationZipPostalCode = model.ZipPostalCode;
                item.LocationCountry       = model.LocationCountry;
                item.LocationPhone         = model.Phone;
                item.LocationWebsite       = model.Website;
                item.LocationEmail         = model.Email;
                item.StartDate             = model.StartDate;
                item.EndDate               = model.EndDate;
                item.Description           = model.Description;
                item.MetaKeywords          = model.MetaKeywords;
                item.MetaDescription       = model.MetaDescription;

                item.DateUpdated = DateTime.Now;


                _eventPageService.Update(item);

                //search engine name
                model.SeName = SeoExtensions.GetSeName(item, _workContext.WorkingLanguage.Id);

                _urlRecordService.SaveSlug(item, model.SeName, _workContext.WorkingLanguage.Id);

                //picture seo names
                //UpdatePictureSeoNames(product);

                SuccessNotification(_localizationService.GetResource("Admin.MobSocial.EventPage.Updated"));

                if (continueEditing)
                {
                    //selected tab
                    SaveSelectedTabName();

                    return(RedirectToAction("Edit", new { id = item.Id }));
                }
                else
                {
                    return(RedirectToAction("List"));
                }
            }

            return(View("~/Plugins/Widgets.mobSocial/Views/mobSocial/Admin/ManageEventPage/Edit.cshtml", model));
        }
コード例 #13
0
        /// <summary>
        /// Route request to the particular action
        /// </summary>
        /// <param name="context">A route context object</param>
        /// <returns>Task of the routing</returns>
        public override Task RouteAsync(RouteContext context)
        {
            if (!DataSettingsHelper.DatabaseIsInstalled())
            {
                return(Task.CompletedTask);
            }

            //get current route data
            var urlRecordService = EngineContextExperimental.Current.Resolve <IUrlRecordService>();

            //get slug from path
            var currentRouteData = new RouteData(context.RouteData);

            //tbh
            string slug = string.Empty;

#if NET451
            slug = currentRouteData.Values["generic_se_name"] as string;
#endif
#if NETCOREAPP1_1
            //temporary solution until we can get currentRouteData.Values
            string path = context.HttpContext.Request.Path.Value;
            if (!string.IsNullOrEmpty(path) && path[0] == '/')
            {
                path = path.Substring(1);
            }
            var pathParts = path.Split('/');
            slug = pathParts.Length > 1 ? pathParts[0] : path;
#endif

            //performance optimization
            //we load a cached verion here. It reduces number of SQL requests for each page load
            var urlRecord = urlRecordService.GetBySlugCached(slug);

            //comment the line above and uncomment the line below in order to disable this performance "workaround"
            //var urlRecord = urlRecordService.GetBySlug(slug);

            //no URL record found
            if (urlRecord == null)
            {
                return(Task.CompletedTask);
            }

            if (!urlRecord.IsActive)
            {
                //URL record is not active. let's find the latest one
                var activeSlug = urlRecordService.GetActiveSlug(urlRecord.EntityId, urlRecord.EntityName, urlRecord.LanguageId);

                //no active slug found
                if (string.IsNullOrEmpty(activeSlug))
                {
                    return(Task.CompletedTask);
                }

                //the active one is found
                var webHelper = EngineContextExperimental.Current.Resolve <IWebHelper>();
                var location  = string.Format("{0}{1}", webHelper.GetStoreLocation(), activeSlug);
                context.HttpContext.Response.Redirect(location, true);
                return(Task.CompletedTask);
            }

            //ensure that the slug is the same for the current language
            //otherwise, it can cause some issues when customers choose a new language but a slug stays the same
            var workContext            = EngineContextExperimental.Current.Resolve <IWorkContext>();
            var slugForCurrentLanguage = SeoExtensions.GetSeName(urlRecord.EntityId, urlRecord.EntityName, workContext.WorkingLanguage.Id);
            if (!string.IsNullOrEmpty(slugForCurrentLanguage) && !slugForCurrentLanguage.Equals(slug, StringComparison.OrdinalIgnoreCase))
            {
                //we should make validation above because some entities does not have SeName for standard (Id = 0) language (e.g. news, blog posts)
                var webHelper = EngineContextExperimental.Current.Resolve <IWebHelper>();
                var location  = string.Format("{0}{1}", webHelper.GetStoreLocation(), slugForCurrentLanguage);
                context.HttpContext.Response.Redirect(location, false);
                return(Task.CompletedTask);
            }

            //process URL
            switch (urlRecord.EntityName.ToLowerInvariant())
            {
            case "product":
                currentRouteData.Values["controller"] = "Product";
                currentRouteData.Values["action"]     = "ProductDetails";
                currentRouteData.Values["productid"]  = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "category":
                currentRouteData.Values["controller"] = "Catalog";
                currentRouteData.Values["action"]     = "Category";
                currentRouteData.Values["categoryid"] = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "manufacturer":
                currentRouteData.Values["controller"]     = "Catalog";
                currentRouteData.Values["action"]         = "Manufacturer";
                currentRouteData.Values["manufacturerid"] = urlRecord.EntityId;
                currentRouteData.Values["SeName"]         = urlRecord.Slug;
                break;

            case "vendor":
                currentRouteData.Values["controller"] = "Catalog";
                currentRouteData.Values["action"]     = "Vendor";
                currentRouteData.Values["vendorid"]   = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "newsitem":
                currentRouteData.Values["controller"] = "News";
                currentRouteData.Values["action"]     = "NewsItem";
                currentRouteData.Values["newsItemId"] = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "blogpost":
                currentRouteData.Values["controller"] = "Blog";
                currentRouteData.Values["action"]     = "BlogPost";
                currentRouteData.Values["blogPostId"] = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            case "topic":
                currentRouteData.Values["controller"] = "Topic";
                currentRouteData.Values["action"]     = "TopicDetails";
                currentRouteData.Values["topicId"]    = urlRecord.EntityId;
                currentRouteData.Values["SeName"]     = urlRecord.Slug;
                break;

            default:
                //no record found
                //thus generate an event this way developers could insert their own types
                EngineContextExperimental.Current.Resolve <IEventPublisher>().Publish(new CustomUrlRecordEntityNameRequested(currentRouteData, urlRecord));
                break;
            }
            context.RouteData = currentRouteData;

            //route request
            return(_target.RouteAsync(context));
        }
コード例 #14
0
        private async Task From460To470()
        {
            #region Install String resources
            await InstallStringResources("EN_460_470.nopres.xml");

            #endregion

            #region MessageTemplates

            var emailAccount = _serviceProvider.GetRequiredService <IRepository <EmailAccount> >().Table.FirstOrDefault();
            if (emailAccount == null)
            {
                throw new Exception("Default email account cannot be loaded");
            }
            var messageTemplates = new List <MessageTemplate>
            {
                new MessageTemplate
                {
                    Name           = "Customer.EmailTokenValidationMessage",
                    Subject        = "{{Store.Name}} - Email Verification Code",
                    Body           = "Hello {{Customer.FullName}}, <br /><br />\r\n Enter this 6 digit code on the sign in page to confirm your identity:<br /><br /> \r\n <b>{{Customer.Token}}</b><br /><br />\r\n Yours securely, <br /> \r\n Team",
                    IsActive       = true,
                    EmailAccountId = emailAccount.Id,
                },
                new MessageTemplate
                {
                    Name           = "OrderCancelled.VendorNotification",
                    Subject        = "{{Store.Name}}. Order #{{Order.OrderNumber}} cancelled",
                    Body           = "<p><a href=\"{{Store.URL}}\">{{Store.Name}}</a> <br /><br />Order #{{Order.OrderNumber}} has been cancelled. <br /><br />Order Number: {{Order.OrderNumber}}<br />   Date Ordered: {{Order.CreatedOn}} <br /><br /> ",
                    IsActive       = false,
                    EmailAccountId = emailAccount.Id,
                },
            };

            await _serviceProvider.GetRequiredService <IRepository <MessageTemplate> >().InsertAsync(messageTemplates);

            #endregion

            #region Update store

            var storeService = _serviceProvider.GetRequiredService <IStoreService>();
            foreach (var store in await storeService.GetAllStores())
            {
                store.Shortcut = "Store";
                await storeService.UpdateStore(store);
            }

            #endregion

            #region Update specification - sename field

            var specification = _serviceProvider.GetRequiredService <IRepository <SpecificationAttribute> >();

            foreach (var specificationAttribute in specification.Table.ToList())
            {
                specificationAttribute.SeName = SeoExtensions.GetSeName(specificationAttribute.Name, false, false);
                specificationAttribute.SpecificationAttributeOptions.ToList().ForEach(x =>
                {
                    x.SeName = SeoExtensions.GetSeName(x.Name, false, false);
                });
                await specification.UpdateAsync(specificationAttribute);
            }

            #endregion

            #region Update product attributes - sename field

            var attributes = _serviceProvider.GetRequiredService <IRepository <ProductAttribute> >();
            foreach (var attribute in attributes.Table.ToList())
            {
                attribute.SeName = SeoExtensions.GetSeName(attribute.Name, false, false);
                await attributes.UpdateAsync(attribute);
            }

            #endregion

            #region Update blog category - sename field

            var blogcategories = _serviceProvider.GetRequiredService <IRepository <BlogCategory> >();

            foreach (var category in blogcategories.Table.ToList())
            {
                category.SeName = SeoExtensions.GetSeName(category.Name, false, false);
                await blogcategories.UpdateAsync(category);
            }

            #endregion

            #region Update media settings

            var settingsService = _serviceProvider.GetRequiredService <ISettingService>();
            var storeInDB       = settingsService.GetSettingByKey("Media.Images.StoreInDB", true);
            await settingsService.SetSetting("MediaSettings.StoreInDb", storeInDB);

            #endregion
        }
コード例 #15
0
        private void HookObject(BaseEntity baseEntity, IHookedEntity entry)
        {
            var type = entry.EntityType;

            if (!_candidateTypes.Contains(type))
            {
                throw new NotSupportedException();
            }

            if (type == typeof(SpecificationAttribute))
            {
                if (HasAliasDuplicate <ProductAttribute, SpecificationAttribute>(entry, baseEntity))
                {
                    return;
                }

                if (IsPropertyModified(entry, "Alias"))
                {
                    _catalogSearchQueryAliasMapper.Value.ClearAttributeCache();
                }
            }
            else if (type == typeof(SpecificationAttributeOption))
            {
                var entity = (SpecificationAttributeOption)baseEntity;

                if (HasEntityDuplicate <SpecificationAttributeOption>(entry, baseEntity, x => x.Name,
                                                                      x => x.SpecificationAttributeId == entity.SpecificationAttributeId && x.Name == entity.Name))
                {
                    return;
                }

                if (HasAliasDuplicate <SpecificationAttributeOption>(entry, baseEntity))
                {
                    return;
                }

                if (IsPropertyModified(entry, "Alias"))
                {
                    _catalogSearchQueryAliasMapper.Value.ClearAttributeCache();
                }
            }
            else if (type == typeof(ProductSpecificationAttribute))
            {
                var entity = (ProductSpecificationAttribute)baseEntity;

                if (HasEntityDuplicate <ProductSpecificationAttribute>(entry, baseEntity, x => x.SpecificationAttributeOption?.Name,
                                                                       x => x.ProductId == entity.ProductId && x.SpecificationAttributeOptionId == entity.SpecificationAttributeOptionId))
                {
                    return;
                }
            }
            else if (type == typeof(ProductAttribute))
            {
                if (HasAliasDuplicate <ProductAttribute, SpecificationAttribute>(entry, baseEntity))
                {
                    return;
                }

                if (IsPropertyModified(entry, "Alias"))
                {
                    _catalogSearchQueryAliasMapper.Value.ClearVariantCache();
                }
            }
            else if (type == typeof(ProductAttributeOption))
            {
                var entity = (ProductAttributeOption)baseEntity;

                if (HasEntityDuplicate <ProductAttributeOption>(entry, baseEntity, x => x.Name,
                                                                x => x.ProductAttributeOptionsSetId == entity.ProductAttributeOptionsSetId && x.Name == entity.Name))
                {
                    return;
                }

                // ClearVariantCache() not necessary
                if (HasAliasDuplicate <ProductAttributeOption>(entry, baseEntity))
                {
                    return;
                }
            }
            else if (type == typeof(ProductVariantAttribute))
            {
                var entity = (ProductVariantAttribute)baseEntity;

                if (HasEntityDuplicate <ProductVariantAttribute>(entry, baseEntity, x => x.ProductAttribute?.Name,
                                                                 x => x.ProductId == entity.ProductId && x.ProductAttributeId == entity.ProductAttributeId))
                {
                    return;
                }
            }
            else if (type == typeof(ProductVariantAttributeValue))
            {
                var entity = (ProductVariantAttributeValue)baseEntity;

                if (HasEntityDuplicate <ProductVariantAttributeValue>(entry, baseEntity, x => x.Name,
                                                                      x => x.ProductVariantAttributeId == entity.ProductVariantAttributeId && x.Name == entity.Name))
                {
                    return;
                }

                if (HasAliasDuplicate <ProductVariantAttributeValue>(entry, baseEntity,
                                                                     (all, e) => all.Any(x => x.Id != e.Id && x.ProductVariantAttributeId == e.ProductVariantAttributeId && x.Alias == e.Alias)))
                {
                    return;
                }

                if (IsPropertyModified(entry, "Alias"))
                {
                    _catalogSearchQueryAliasMapper.Value.ClearVariantCache();
                }
            }
            else if (type == typeof(LocalizedProperty))
            {
                // note: not fired when SpecificationAttribute or SpecificationAttributeOption deleted.
                // not necessary anyway because cache cleared by above code.
                var prop     = (LocalizedProperty)baseEntity;
                var keyGroup = prop.LocaleKeyGroup;

                if (!prop.LocaleKey.IsCaseInsensitiveEqual("Alias"))
                {
                    return;
                }

                // validating ProductVariantAttributeValue goes too far here.
                if (!keyGroup.IsCaseInsensitiveEqual("SpecificationAttribute") &&
                    !keyGroup.IsCaseInsensitiveEqual("SpecificationAttributeOption") &&
                    !keyGroup.IsCaseInsensitiveEqual("ProductAttribute") &&
                    !keyGroup.IsCaseInsensitiveEqual("ProductAttributeOption"))
                {
                    return;
                }

                // check alias duplicate
                if (entry.InitialState == EntityState.Added || entry.InitialState == EntityState.Modified)
                {
                    prop.LocaleValue = SeoExtensions.GetSeName(prop.LocaleValue);
                    if (prop.LocaleValue.HasValue() && HasAliasDuplicate(prop))
                    {
                        RevertChanges(entry, string.Concat(T("Common.Error.AliasAlreadyExists", prop.LocaleValue), " ", T("Common.Error.ChooseDifferentValue")));
                        return;
                    }
                }

                if (IsPropertyModified(entry, "LocaleValue"))
                {
                    if (keyGroup.IsCaseInsensitiveEqual("SpecificationAttribute") || keyGroup.IsCaseInsensitiveEqual("SpecificationAttributeOption"))
                    {
                        _catalogSearchQueryAliasMapper.Value.ClearAttributeCache();
                    }
                    else if (keyGroup.IsCaseInsensitiveEqual("ProductAttribute") || keyGroup.IsCaseInsensitiveEqual("ProductVariantAttributeValue"))
                    {
                        // not necessary for ProductAttributeOption
                        _catalogSearchQueryAliasMapper.Value.ClearVariantCache();
                    }
                }
            }
        }
コード例 #16
0
 public void Can_encode_for_url()
 {
     //russian letters т should be encoded as "%d1%82"
     SeoExtensions.GetSeName("testт", true, true, true).ShouldEqual("test%d1%82");
 }