SaaS CMS has officially launched! Learn more now.

Le Giang
Apr 2, 2018
  3249
(2 votes)

Implement search provider for pages, blocks and media

Currently when I type to search in navigationtree, surprisingly there is no result returned even for pages, block or media. It seems that someone forgot to implement searching feature or it is being underplayed smile.

In this post, I would like show you how to implement a search provider for pages, blocks and media and you can customize to fit your need.

For pages:

[SearchProvider]
    public class DefaultPageSearchProvider : ContentSearchProviderBase<IContent, ContentType>
    {
        public DefaultPageSearchProvider(LocalizationService localizationService, ISiteDefinitionResolver siteDefinitionResolver, IContentTypeRepository<ContentType> contentTypeRepository, EditUrlResolver editUrlResolver, ServiceAccessor<SiteDefinition> currentSiteDefinition, LanguageResolver languageResolver, UrlResolver urlResolver, TemplateResolver templateResolver, UIDescriptorRegistry uiDescriptorRegistry) : base(localizationService, siteDefinitionResolver, contentTypeRepository, editUrlResolver, currentSiteDefinition, languageResolver, urlResolver, templateResolver, uiDescriptorRegistry)
        {

        }

        /// <summary>
        ///
        /// </summary>
        public override string Area
        {
            get
            {
                return "cms/pages";
            }
        }

        /// <summary>
        ///
        /// </summary>
        public override string Category
        {
            get
            {
                return "pages";
            }
        }

        protected override string IconCssClass
        {
            get
            {
                return "epi-iconObjectPage";
            }
        }

        public override IEnumerable<SearchResult> Search(Query query)
        {
            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var pageQueryService = ServiceLocator.Current.GetInstance<IPageCriteriaQueryable>();
            PropertyCriteriaCollection crits = new PropertyCriteriaCollection();

            PropertyCriteria nameCriteria = new PropertyCriteria();
            nameCriteria.Name = MetaDataProperties.PageName;
            nameCriteria.Value = query.SearchQuery;
            nameCriteria.Type = PropertyDataType.String;
            nameCriteria.Required = true;
            nameCriteria.Condition = CompareCondition.Contained;

            crits.Add(nameCriteria);
            //Add criteria so search is performed against all providers
            crits.Add(new PropertyCriteria
            {
                Name = "EPI:MultipleSearch",
                Value = "*"
            });

            PageDataCollection pages = null;
            try
            {
                pages = pageQueryService.FindAllPagesWithCriteria(ContentReference.RootPage, crits, null, LanguageSelector.MasterLanguage());
            }
            catch (NotImplementedException)
            {
                // If the provider hasn't implemented FindAllPagesWithCriteria, call old FindPagesWithCriteria instead.
                pages = pageQueryService.FindPagesWithCriteria(ContentReference.RootPage, crits, null, LanguageSelector.MasterLanguage());
            }
            return pages.Select(CreateSearchResult);
        }
    }

For blocks

 [SearchProvider]
    public class DefaultBlockSearchProvider : ContentSearchProviderBase<IContent, ContentType>
    {
        public DefaultBlockSearchProvider(LocalizationService localizationService, ISiteDefinitionResolver siteDefinitionResolver, IContentTypeRepository<ContentType> contentTypeRepository, EditUrlResolver editUrlResolver, ServiceAccessor<SiteDefinition> currentSiteDefinition, LanguageResolver languageResolver, UrlResolver urlResolver, TemplateResolver templateResolver, UIDescriptorRegistry uiDescriptorRegistry) : base(localizationService, siteDefinitionResolver, contentTypeRepository, editUrlResolver, currentSiteDefinition, languageResolver, urlResolver, templateResolver, uiDescriptorRegistry)
        {

        }

        /// <summary>
        ///
        /// </summary>
        public override string Area
        {
            get
            {
                return "cms/blocks";
            }
        }

        /// <summary>
        ///
        /// </summary>
        public override string Category
        {
            get
            {
                return "blocks";
            }
        }

        protected override string IconCssClass
        {
            get
            {
                return "epi-objectIcon";
            }
        }

        public override IEnumerable<SearchResult> Search(Query query)
        {
            ContentReference root = null;
            if (query.SearchRoots != null && query.SearchRoots.Count() > 0)
            {
                root = new ContentReference(query.SearchRoots.First());
            }
            else
            {
                root = new ContentReference();
            }

            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var contentTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
            var contentProviderManager = ServiceLocator.Current.GetInstance<IContentProviderManager>();
            var blockTypes = contentTypeRepository.List().Where(x => typeof(BlockData).IsAssignableFrom(x.ModelType));
            var provider = contentProviderManager.GetProvider(root);

            if (provider != null && provider.HasCapability(ContentProviderCapabilities.Search))
            {
                List<IContent> blocks = new List<IContent>();
                foreach(var blockType in blockTypes)
                {
                    blocks.AddRange(provider.ListContentOfContentType(blockType).Where(x => x.Name.IndexOf(query.SearchQuery, StringComparison.InvariantCultureIgnoreCase) >= 0).Select(x => contentRepository.Get<IContent>(x.ContentLink)));
                }

                return blocks.Select(CreateSearchResult);
            }

            return Enumerable.Empty<SearchResult>();
        }
    }

For media:

[SearchProvider]
    public class DefaultMediaSearchProvider : ContentSearchProviderBase<IContent, ContentType>
    {
        public DefaultMediaSearchProvider(LocalizationService localizationService,
            ISiteDefinitionResolver siteDefinitionResolver,
            IContentTypeRepository<ContentType> contentTypeRepository,
            EditUrlResolver editUrlResolver,
            ServiceAccessor<SiteDefinition> currentSiteDefinition,
            LanguageResolver languageResolver,
            UrlResolver urlResolver,
            TemplateResolver templateResolver,
            UIDescriptorRegistry uiDescriptorRegistry) : base(localizationService,
                siteDefinitionResolver,
                contentTypeRepository,
                editUrlResolver,
                currentSiteDefinition,
                languageResolver,
                urlResolver,
                templateResolver,
                uiDescriptorRegistry)
        {

        }

        /// <summary>
        ///
        /// </summary>
        public override string Area
        {
            get
            {
                return "CMS/files";
            }
        }

        /// <summary>
        ///
        /// </summary>
        public override string Category
        {
            get
            {
                return "media";
            }
        }

        protected override string IconCssClass
        {
            get
            {
                return "";
            }
        }

        public override IEnumerable<SearchResult> Search(Query query)
        {
            ContentReference root = null;
            if (query.SearchRoots != null && query.SearchRoots.Count() > 0)
            {
                root = new ContentReference(query.SearchRoots.First());
            }
            else
            {
                root = new ContentReference();
            }

            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();
            var contentTypeRepository = ServiceLocator.Current.GetInstance<IContentTypeRepository>();
            var contentProviderManager = ServiceLocator.Current.GetInstance<IContentProviderManager>();
            var mediaTypes = contentTypeRepository.List().Where(x => typeof(MediaData).IsAssignableFrom(x.ModelType));
            var provider = contentProviderManager.GetProvider(root);

            if (provider != null && provider.HasCapability(ContentProviderCapabilities.Search))
            {
                List<IContent> mediaList = new List<IContent>();
                foreach (var blockType in mediaTypes)
                {
                    mediaList.AddRange(provider.ListContentOfContentType(blockType).Where(x => x.Name.IndexOf(query.SearchQuery, StringComparison.InvariantCultureIgnoreCase) >= 0).Select(x => contentRepository.Get<IContent>(x.ContentLink)));
                }

                return mediaList.Select(CreateSearchResult);
            }

            return Enumerable.Empty<SearchResult>();
        }
    }

After adding these search providers, now I can enjoy the filtering feature. You can customize the code to fit your need and improve the performance (for example: implement caching mechanism).

Apr 02, 2018

Comments

Please login to comment.
Latest blogs
Creating Custom Actors for Optimizely Forms

Optimizely Forms is a powerful tool for creating web forms for various purposes such as registrations, job applications, surveys, etc. By default,...

Nahid | Jul 16, 2024

Optimizely SaaS CMS Concepts and Terminologies

Whether you're a new user of Optimizely CMS or a veteran who have been through the evolution of it, the SaaS CMS is bringing some new concepts and...

Patrick Lam | Jul 15, 2024

How to have a link plugin with extra link id attribute in TinyMce

Introduce Optimizely CMS Editing is using TinyMce for editing rich-text content. We need to use this control a lot in CMS site for kind of WYSWYG...

Binh Nguyen Thi | Jul 13, 2024

Create your first demo site with Optimizely SaaS/Visual Builder

Hello everyone, We are very excited about the launch of our SaaS CMS and the new Visual Builder that comes with it. Since it is the first time you'...

Patrick Lam | Jul 11, 2024