Allow for unicode alphanumeric characters in page URL slugs with some validation changes and escaping #172

Merged
merged 2 commits into from Apr 7, 2012
Jump to file or symbol
Failed to load files and symbols.
+35 −2
Diff settings

Always

Just for now

View
@@ -1,3 +1,4 @@
+# encoding: utf-8
class Cms::Page < ActiveRecord::Base
ComfortableMexicanSofa.establish_connection(self)
@@ -24,10 +25,12 @@ class Cms::Page < ActiveRecord::Base
# -- Callbacks ------------------------------------------------------------
before_validation :assigns_label,
:assign_parent
+ after_validation :escape_slug
before_create :assign_position
before_save :assign_full_path,
:set_cached_content
after_save :sync_child_pages
+ after_find :unescape_slug_and_path
# -- Validations ----------------------------------------------------------
validates :site_id,
@@ -36,7 +39,7 @@ class Cms::Page < ActiveRecord::Base
:presence => true
validates :slug,
:presence => true,
- :format => /^\w[\.a-z0-9_-]*$/i,
+ :format => /^\p{Alnum}[\.\p{Alnum}_-]*$/i,
:uniqueness => { :scope => :parent_id },
:unless => lambda{ |p| p.site && (p.site.pages.count == 0 || p.site.pages.root == self) }
validates :layout,
@@ -139,7 +142,7 @@ def assign_parent
end
def assign_full_path
- self.full_path = self.parent ? "#{self.parent.full_path}/#{self.slug}".squeeze('/') : '/'
+ self.full_path = self.parent ? "#{CGI::escape(self.parent.full_path).gsub('%2F', '/')}/#{self.slug}".squeeze('/') : '/'
end
def assign_position
@@ -166,5 +169,16 @@ def set_cached_content
def sync_child_pages
children.each{ |p| p.save! } if full_path_changed?
end
+
+ # Escape slug unless it's nonexistent (root)
+ def escape_slug
+ self.slug = CGI::escape(self.slug) unless self.slug.nil?
+ end
+
+ # Unescape the slug and full path back into their original forms unless they're nonexistent
+ def unescape_slug_and_path
+ self.slug = CGI::unescape(self.slug) unless self.slug.nil?
+ self.full_path = CGI::unescape(self.full_path) unless self.full_path.nil?
+ end
end
@@ -1,3 +1,4 @@
+# encoding: utf-8
require File.expand_path('../../test_helper', File.dirname(__FILE__))
class CmsPageTest < ActiveSupport::TestCase
@@ -51,6 +52,9 @@ def test_validation_of_slug
page.slug = 'inva lid'
assert page.invalid?
+
+ page.slug = 'acción'
+ assert page.valid?
end
def test_label_assignment
@@ -204,6 +208,21 @@ def test_url
assert_equal 'http://test.host/', cms_pages(:default).url
assert_equal 'http://test.host/child-page', cms_pages(:child).url
end
+
+ def test_unicode_slug_escaping
+ page = cms_pages(:child)
+ page_1 = cms_sites(:default).pages.create!(new_params(:parent => page, :slug => 'tést-ünicode-slug'))
+ assert_equal CGI::escape('tést-ünicode-slug'), page_1.slug
+ assert_equal CGI::escape('/child-page/tést-ünicode-slug').gsub('%2F', '/'), page_1.full_path
+ end
+
+ def test_unicode_slug_unescaping
+ page = cms_pages(:child)
+ page_1 = cms_sites(:default).pages.create!(new_params(:parent => page, :slug => 'tést-ünicode-slug'))
+ found_page = cms_sites(:default).pages.where(:slug => CGI::escape('tést-ünicode-slug')).first
+ assert_equal 'tést-ünicode-slug', found_page.slug
+ assert_equal '/child-page/tést-ünicode-slug', found_page.full_path
+ end
protected