Posted in: Comments

Rewrites tags, dates and pages. Supports the format /Templates/Blog.aspx?id=3&epslanguage=en&year=2012&month=5&page=2&tag=episerver

namespace DV.UrlRewriters
{
    using System;
    using System.Collections.Specialized;
    using System.Globalization;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Web;
    using EPiServer;
    using EPiServer.Core;
    using EPiServer.DataAbstraction;
    using EPiServer.Globalization;
    using EPiServer.Web;

    public class CustomUrlRewriter : FriendlyUrlRewriteProvider
    {
        /// <summary>
        /// Check if the url needs to be rewritten with our provider to an internal url
        /// </summary>
        private static bool RewriteToInternal(UrlBuilder url)
        {
            return Regex.Match(url.Path, "/tag/|/((?:19|20)\\d\\d)/(0[1-9]|1[012])/|/((?:19|20)\\d\\d)/|/page/\\d*/", RegexOptions.Compiled | RegexOptions.IgnoreCase).Success;
        }

        /// <summary>
        /// Check if the url needs to be rewritten with our provider to an external url
        /// </summary>
        private static bool RewriteToExternal(UrlBuilder url)
        {
            return url.QueryCollection["tag"] != null
                || url.QueryCollection["year"] != null
                || url.QueryCollection["month"] != null
                || url.QueryCollection["page"] != null;
        }

        public override bool TryConvertToInternal(UrlBuilder url, out CultureInfo preferredCulture, out object internalObject)
        {
            preferredCulture = null;
            internalObject = null;

            if (url == null)
            {
                return false;
            }

            if (RewriteToInternal(url))
            {
                bool isModified;

                if (base.IsVppPath(url, out isModified))
                {
                    return isModified;
                }

                if (!url.Path.EndsWith("/"))
                {
                    HttpContext.Current.Response.Redirect(url.Path + "/" + url.Query + url.Fragment);
                }

                // Get the address to the blog (remove all rewritten query parameters)
                string path = Regex.Replace(url.Path, "tag/[^/]*/|(?:19|20)\\d\\d/0[1-9]|1[012]/|(?:19|20)\\d\\d/|page/\\d*/", string.Empty, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                string pathWithOutLanguage = string.Empty;

                LanguageBranch languageBranch = GetLanguageBranchAndPath(path, out pathWithOutLanguage);

                if (languageBranch == null)
                {
                    languageBranch = LanguageBranch.Load(ContentLanguage.PreferredCulture);
                }
                else
                {
                    ContentLanguage.PreferredCulture = languageBranch.Culture;
                }

                preferredCulture = languageBranch.Culture;

                // Get the blog page
                NameValueCollection queryCollection = url.QueryCollection;
                PageData blogPage = null;
                PageReference blogPageReference = null;

                if (PageReference.TryParse(queryCollection["id"], out blogPageReference))
                {
                    if ((blogPageReference.WorkID > 0) || !string.IsNullOrEmpty(blogPageReference.RemoteSite))
                    {
                        blogPage = DataFactory.Instance.GetPage(blogPageReference);
                    }

                    queryCollection.Remove("id");
                }

                if (blogPage == null)
                {
                    blogPage = GetPageFromStartByPath(pathWithOutLanguage, languageBranch);
                }

                // Add query parameters
                queryCollection.Add("id", blogPage.PageLink.ToString());
                queryCollection.Add("epslanguage", ContentLanguage.PreferredCulture.Name);

                Match tag = Regex.Match(url.Path, "/tag/([^/]*)/", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                Match dates = Regex.Match(url.Path, "/((?:19|20)\\d\\d)/(0[1-9]|1[012])/|/((?:19|20)\\d\\d)/", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                Match page = Regex.Match(url.Path, "/page/(\\d*)/", RegexOptions.Compiled | RegexOptions.IgnoreCase);

                if (tag.Success)
                {
                    queryCollection.Add("tag", tag.Groups[1].Value);
                }

                if (dates.Success)
                {
                    if (!string.IsNullOrEmpty(dates.Groups[1].Value) && !string.IsNullOrEmpty(dates.Groups[2].Value))
                    {
                        queryCollection.Add("year", dates.Groups[1].Value);
                        queryCollection.Add("month", dates.Groups[2].Value);
                    }
                    else if (!string.IsNullOrEmpty(dates.Groups[3].Value))
                    {
                        queryCollection.Add("year", dates.Groups[3].Value);
                    }
                }

                if (page.Success)
                {
                    queryCollection.Add("page", page.Groups[1].Value);
                }


                // Set the address to the internal address
                url.Path = new Url(blogPage.StaticLinkURL).Path;
                internalObject = blogPage.PageLink;

                return true;
            }
            else
            {
                return base.TryConvertToInternal(url, out preferredCulture, out internalObject);
            }
        }

        protected override bool ConvertToExternalInternal(UrlBuilder url, object internalObject, Encoding toEncoding)
        {
            try
            {
                if (RewriteToExternal(url))
                {
                    PageData blogPage = DataFactory.Instance.GetPage(internalObject as PageReference);
                    UrlBuilder urlToBlog = new UrlBuilder(blogPage.LinkURL);

                    Global.UrlRewriteProvider.ConvertToExternal(urlToBlog, blogPage.PageLink, UTF8Encoding.UTF8);

                    string friendlyUrl = urlToBlog.Path;

                    if (url.QueryCollection["tag"] != null)
                    {
                        friendlyUrl = string.Concat(friendlyUrl, "tag/", url.QueryCollection["tag"].ToLower(), "/");
                    }

                    if (url.QueryCollection["year"] != null)
                    {
                        friendlyUrl = string.Concat(friendlyUrl, url.QueryCollection["year"], "/");
                    }

                    if (url.QueryCollection["month"] != null)
                    {
                        friendlyUrl = string.Concat(friendlyUrl, url.QueryCollection["month"], "/");
                    }

                    // Allways check for paging
                    if (url.QueryCollection["page"] != null)
                    {
                        friendlyUrl = string.Concat(friendlyUrl, "page/", url.QueryCollection["page"], "/");
                    }

                    url.Path = friendlyUrl;
                    url.QueryCollection.Clear();

                    return true;
                }
                else
                {
                    return base.ConvertToExternalInternal(url, internalObject, toEncoding);
                }
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}