Search

Well, I'm not doing much more than copying the result to the .htaccess file. I'm using the Ninja Domains set up.

I'm adding the rewrite rules just below the GLOBAL REWRITE rules for the first domain.

### Symphony 2.2.x ###
Options +FollowSymlinks -Indexes

<IfModule mod_rewrite.c>

    RewriteEngine on
    RewriteBase /

    ### GLOBAL REWRITE

    RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]
    RewriteRule ^(.*)$ http://example.com/$1 [R,L]

    ################################################
    ### LEGACY SITE - 301 Redirect Rules ###
    ################################################

    RewriteRule ^Team/ShawnNeumann.html /team/shawn-neumann/ [R=301,L]
    RewriteRule ^Team/StephenBau.html /team/stephen-bau/ [R=301,L]

If there is a query string to deal with, I found that if the ? character is included at the end of redirect string, it's possible to avoid the query string being appended to the end of the new URL string.

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&Join_ID=351625&template=blog_view_category.htm7
RewriteRule .* /blog/category/seo/? [R=301,L]

And the simpler matches should be left to the end, such as an index.html file:

RewriteRule ^index.html / [R=301,L]

To deal with the query strings, I fired up TextXSLT and grabbed a list of URLs from the existing site:

<?xml version='1.0' encoding='utf-8'?>
<div>
    <a href="/?action=d7_article_view_folder&amp;Join_ID=355025&amp;template=blog_view_category.htm7">Community Projects</a>
    <a href="/?action=d7_article_view_folder&amp;Join_ID=444767&amp;template=blog_view_category.htm7">Content Rules Workshop</a>
    <a href="/?action=d7_article_view_folder&amp;Join_ID=365883&amp;template=blog_view_category.htm7">D7 News</a>
    <a href="/?action=d7_article_view_folder&amp;Join_ID=420261&amp;template=blog_view_category.htm7">Events</a>
    <a href="/?action=d7_article_view_folder&amp;Join_ID=357057&amp;template=blog_view_category.htm7">Interviews</a>
    <a href="/?action=d7_article_view_folder&amp;Join_ID=358037&amp;template=blog_view_category.htm7">Marketing</a>
    <a href="/?action=d7_article_view_folder&amp;Join_ID=351625&amp;template=blog_view_category.htm7">SEO</a>
    <a href="/?action=d7_article_view_folder&amp;Join_ID=357005&amp;template=blog_view_category.htm7">Technology</a>
    <a href="/?action=d7_article_view_folder&amp;Join_ID=399785&amp;template=blog_view_category.htm7">The Weekly Edit</a>
</div>

Then, transformed those links with this template:

<?xml version='1.0' encoding='utf-8'?>
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:output method='html' version='1.0' encoding='utf-8' indent='no'/>

<xsl:template match="/">
<xsl:for-each select="div/a">
    <xsl:sort select="member" />
    <xsl:text>  RewriteCond %{QUERY_STRING} </xsl:text><xsl:value-of select="substring-after(@href, '?')" /><xsl:text>
    RewriteRule .* </xsl:text>
    <xsl:text>/blog/category/</xsl:text><xsl:value-of select="translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ', 'abcdefghijklmnopqrstuvwxyz-')" />/? [R=301,L]
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

And I can process the following result output to paste into my .htaccess file:

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&amp;Join_ID=355025&amp;template=blog_view_category.htm7
RewriteRule .* /blog/category/community-projects/? [R=301,L]

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&amp;Join_ID=444767&amp;template=blog_view_category.htm7
RewriteRule .* /blog/category/content-rules-workshop/? [R=301,L]

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&amp;Join_ID=365883&amp;template=blog_view_category.htm7
RewriteRule .* /blog/category/d7-news/? [R=301,L]

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&amp;Join_ID=420261&amp;template=blog_view_category.htm7
RewriteRule .* /blog/category/events/? [R=301,L]

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&amp;Join_ID=357057&amp;template=blog_view_category.htm7
RewriteRule .* /blog/category/interviews/? [R=301,L]

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&amp;Join_ID=358037&amp;template=blog_view_category.htm7
RewriteRule .* /blog/category/marketing/? [R=301,L]

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&amp;Join_ID=351625&amp;template=blog_view_category.htm7
RewriteRule .* /blog/category/seo/? [R=301,L]

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&amp;Join_ID=357005&amp;template=blog_view_category.htm7
RewriteRule .* /blog/category/technology/? [R=301,L]

RewriteCond %{QUERY_STRING} action=d7_article_view_folder&amp;Join_ID=399785&amp;template=blog_view_category.htm7
RewriteRule .* /blog/category/the-weekly-edit/? [R=301,L]

Ah, I see... I thought you'd found some magical system to auto generate a .htaccess file with xslt...

One can dream...

I was dreaming about the possibility of doing this dynamically. But I was wondering how that might work, if Symphony relies very heavily on the .htaccess file to run both front end and back end. Because this is the case, I don't know if it would be possible to dynamically rewrite the file from within Symphony.

I also don't know whether XSLT is the best choice for handling the rewrites. I realized that I hadn't properly accounted for punctuation and the truncation of multiple consecutive hyphen characters. Plus, if an entry title contains apostrophe or quote characters, XSLT runs into issues with handling these characters without a means to escape them. I modified the template a little to account for some of these issues:

<?xml version='1.0' encoding='utf-8'?>

<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>

<xsl:output method='html' version='1.0' encoding='utf-8' indent='no'/>

<xsl:template match="/">
    <xsl:for-each select="div/a">
        <xsl:call-template name="rewrite-rule" />
    </xsl:for-each>
</xsl:template>

<xsl:template name="rewrite-rule">
    <xsl:param name="handle">
        <xsl:call-template name="string-to-handle">
            <xsl:with-param name="string" select="." />
        </xsl:call-template>
    </xsl:param>
    <xsl:text>  RewriteCond %{QUERY_STRING} </xsl:text><xsl:value-of select="substring-after(@href, '?')" /><xsl:text>
    RewriteRule .* </xsl:text>
    <xsl:text>/blog/</xsl:text><xsl:value-of select="$handle" />/? [R=301,L]
<xsl:text>
</xsl:text>
</xsl:template>

<xsl:template name="string-to-handle">
   <xsl:param name="string" />
    <xsl:param name="replaced-string">
        <xsl:call-template name="replace-apos">
            <xsl:with-param name="string" select="$string" />
        </xsl:call-template>
    </xsl:param>
    <xsl:param name="translated-string" select="translate($replaced-string, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ :,!?.’&amp;', 'abcdefghijklmnopqrstuvwxyz-')" />
    <xsl:call-template name="recursive-string-replace">
        <xsl:with-param name="string" select="$translated-string" />
        <xsl:with-param name="search" select="'--'" />
        <xsl:with-param name="replace" select="'-'" />
    </xsl:call-template>
</xsl:template>

<xsl:template name="replace-apos">
   <xsl:param name="string" />
   <xsl:variable name="apos" select='"&apos;"' />
   <xsl:choose>
      <xsl:when test="contains($string, $apos)">
         <xsl:value-of select="substring-before($string, $apos)" />
         <xsl:text></xsl:text>
         <xsl:call-template name="replace-apos">
            <xsl:with-param name="string" select="substring-after($string, $apos)" />
         </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
         <xsl:value-of select="$string" />
      </xsl:otherwise>
   </xsl:choose>
</xsl:template>

<xsl:template name="recursive-string-replace">
    <xsl:param name="string" />
    <xsl:param name="search" />
    <xsl:param name="replace" select="''" />
    <xsl:param name="result">
        <xsl:choose>
            <xsl:when test="contains($string, $search)">
                <xsl:value-of select="substring-before($string, $search)" />
                <xsl:value-of select="$replace" />
                <xsl:call-template name="recursive-string-replace">
                    <xsl:with-param name="string" select="substring-after($string, $search)" />
                    <xsl:with-param name="search" select="$search" />
                    <xsl:with-param name="replace" select="$replace" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$string" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:param>
    <xsl:choose>
        <xsl:when test="contains($result, $search)">
            <xsl:call-template name="recursive-string-replace">
                <xsl:with-param name="string" select="$result" />
                <xsl:with-param name="search" select="$search" />
                <xsl:with-param name="replace" select="$replace" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$result" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

Maybe regex would be better suited to handle this sort of string manipulation.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details