add id to wiki page urls. fixes #2635.

prepend all wiki page urls with the object id to ensure that,
even if the title/url change, the record can still be retrieved
with the id.

test plan:
1. create a new wiki page;
2. in the body of another wiki page, link to the newly created
   wiki page;
3. change the title of the newly created wiki page;
4. verify that the link to the new wiki page still works (even
   though the title has changed).

Change-Id: I4a6ab2dea3e156abe88d022ae5f17cd7a0fb3924
Reviewed-on: https://gerrit.instructure.com/6792
Tested-by: Hudson <hudson@instructure.com>
Reviewed-by: Zach Pendleton <zachp@instructure.com>
This commit is contained in:
Zach Pendleton 2011-11-08 13:12:12 -07:00
parent b4b27c496a
commit d9d5715b2b
6 changed files with 67 additions and 25 deletions

View File

@ -31,17 +31,18 @@ class WikiPage < ActiveRecord::Base
belongs_to :user
has_many :context_module_tags, :as => :content, :class_name => 'ContentTag', :conditions => ['content_tags.tag_type = ? AND workflow_state != ?', 'context_module', 'deleted'], :include => {:context_module => [:content_tags, :context_module_progressions]}
has_many :wiki_page_comments, :order => "created_at DESC"
acts_as_url :title, :scope => [:wiki_id, :not_deleted], :sync_url => true
acts_as_url :title_with_id, :scope => [:wiki_id, :not_deleted], :sync_url => true
before_save :set_revised_at
before_save :set_revised_at
before_validation :ensure_unique_title
after_create :resave_url_with_id
after_validation :resave_url_with_id, :if => lambda { |page| page.title_changed? }, :unless => lambda { |page| page.new_record? }
TITLE_LENGTH = WikiPage.columns_hash['title'].limit rescue 255
def ensure_unique_title
return if deleted?
return if deleted? || !self.wiki
self.title ||= (self.url || "page").to_cased_title
return unless self.wiki
# TODO i18n (see wiki.rb)
if self.title == "Front Page" && self.new_record?
baddies = self.wiki.wiki_pages.not_deleted.find_all_by_title("Front Page").select{|p| p.url != "front-page" }
@ -56,8 +57,9 @@ class WikiPage < ActiveRecord::Base
new_title = real_title[0...(TITLE_LENGTH - mod.length)] + mod
n = n.succ
end while self.wiki.wiki_pages.not_deleted.find_by_title(new_title)
self.title = new_title
title
end
end
@ -66,6 +68,12 @@ class WikiPage < ActiveRecord::Base
base_url = self.send(url_attribute)
base_url = self.send(self.class.attribute_to_urlify).to_s.to_url if base_url.blank? || !self.only_when_blank
conditions = [wildcard("#{url_attribute}", base_url, :type => :right)]
# This check only needs to happen for pages named "Front Page;" everything
# else will be unique because it includes the object ID.
unless title.strip.match /^Front Page$/i
write_attribute url_attribute, base_url
return
end
unless new_record?
conditions.first << " and id != ?"
conditions << id
@ -102,6 +110,13 @@ class WikiPage < ActiveRecord::Base
end
end
# When a record is first created, the ID isn't properly appended to the
# URL because the ID doesn't exist. So once a record is created, re-save
# it to make sure that the ID is prepended to the URL.
def resave_url_with_id
id_changed? ? self.update_attribute(:url, title_with_id.to_url) : self.url = title_with_id.to_url
end
sanitize_field :body, Instructure::SanitizeField::SANITIZE
copy_authorized_links(:body) { [self.current_namespace(self.user).context, self.user] }
@ -343,6 +358,12 @@ class WikiPage < ActiveRecord::Base
def to_param
url
end
def title_with_id
# don't make any changes to front page URL b/c app matches against
# that name for deleting logic.
title == "Front Page" ? title : "#{id} #{title}"
end
def last_revision_at
res = self.revised_at || self.updated_at

View File

@ -47,7 +47,7 @@ class ImportedHtmlConverter
type_for_url = type
type = 'context_modules' if type == 'modules'
if type == 'wiki'
if page = context.wiki.wiki_pages.find_by_url(migration_id)
if page = context.wiki.wiki_pages.select { |s| s.url.match(/#{migration_id}$/) }[0]
node[attr] = URI::escape("#{course_path}/wiki/#{page.url}")
end
elsif type == 'attachments'

View File

@ -95,6 +95,16 @@ describe WikiPagesController do
assigns[:page].title.should eql("Some Page")
end
it "should still have old urls work when a page is renamed" do
course_with_teacher_logged_in(:active_all => true)
wiki = WikiNamespace.default_for_context(@course).wiki
page = wiki.wiki_pages.create(:title => 'old page name', :body => 'test content')
old_page_url = page.url
page.update_attribute(:title, 'new page name')
get 'show', :course_id => @course.id, :id => old_page_url
assigns[:page].title.should eql 'new page name'
end
it "should allow students when allowed" do
course_with_teacher_logged_in(:active_all => true)
post 'create', :course_id => @course.id, :wiki_page => {:title => "Some Secret Page"}

View File

@ -493,7 +493,7 @@ describe "Canvas Cartridge importing" do
page_2 = @copy_to.wiki.wiki_pages.find_by_migration_id(migration_id)
page_2.title.should == page.title
page_2.url.should == page.url
page_2.url.should match /\d{1,3}-#{page.title.to_url}/
page_2.body.should == body_with_link % ([ @copy_to.id, attachment_import.id ] * 4)
end
@ -517,7 +517,6 @@ describe "Canvas Cartridge importing" do
to_att.save
path = to_att.full_display_path.gsub('course files/', '')
@copy_to.attachment_path_id_lookup = {path => to_att.migration_id}
body_with_link = %{<p>Watup? <strong>eh?</strong>
<a href=\"/courses/%s/assignments\">Assignments</a>
<a href=\"/courses/%s/file_contents/course%%20files/tbe_banner.jpg\">Some file</a>
@ -543,9 +542,10 @@ describe "Canvas Cartridge importing" do
WikiPage.import_from_migration(hash, @copy_to)
page_2 = @copy_to.wiki.wiki_pages.find_by_migration_id(migration_id)
wiki_assignments_segment = page_2.body.match(/wiki\/\d+-assignments/)
page_2.title.should == page.title
page_2.url.should == page.url
page_2.body.should == (body_with_link % [ @copy_to.id, @copy_to.id, @copy_to.id, @copy_to.id, @copy_to.id, mod2.id, @copy_to.id, to_att.id ]).gsub(/png">/, 'png" />')
page_2.url.should match /^\d+-#{page.title.to_url}$/
page_2.body.should == (body_with_link % [ @copy_to.id, @copy_to.id, @copy_to.id, @copy_to.id, @copy_to.id, mod2.id, @copy_to.id, to_att.id ]).gsub(/png">/, 'png" />').gsub(/wiki\/assignments/, wiki_assignments_segment[0])
end
it "should import migrate inline external tool URLs in wiki pages" do
@ -565,7 +565,7 @@ describe "Canvas Cartridge importing" do
page_2 = @copy_to.wiki.wiki_pages.find_by_migration_id(migration_id)
page_2.title.should == page.title
page_2.url.should == page.url
page_2.url.should match /^\d+-#{page.title.to_url}$/
page_2.body.should match(/\/courses\/#{@copy_to.id}\/external_tools\/retrieve/)
end

View File

@ -48,9 +48,9 @@ describe "Importing wikis" do
# The wiki references should resolve to course urls
WikiPage.count.should == 18
wiki = WikiPage.find_by_migration_id('res00146')
(wiki.body =~ /\/courses\/\d+\/wiki\/course-glossary-a-to-d/).should_not be_nil
(wiki.body =~ /\/courses\/\d+\/wiki\/course-glossary-e-f-g-h/).should_not be_nil
(wiki.body =~ /\/courses\/\d+\/wiki\/course-glossary-i-j-k-l-m/).should_not be_nil
(wiki.body =~ /\/courses\/\d+\/wiki\/course-glossary-n-o-p-q-r/).should_not be_nil
(wiki.body =~ /\/courses\/\d+\/wiki\/\d+-course-glossary-a-to-d/).should_not be_nil
(wiki.body =~ /\/courses\/\d+\/wiki\/\d+-course-glossary-e-f-g-h/).should_not be_nil
(wiki.body =~ /\/courses\/\d+\/wiki\/\d+-course-glossary-i-j-k-l-m/).should_not be_nil
(wiki.body =~ /\/courses\/\d+\/wiki\/\d+-course-glossary-n-o-p-q-r/).should_not be_nil
end
end

View File

@ -19,8 +19,11 @@
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
describe WikiPage do
it "should send page updated notifications" do
before(:each) do
course_with_teacher(:active_all => true)
end
it "should send page updated notifications" do
n = Notification.create(:name => "Updated Wiki Page", :category => "TestImmediately")
NotificationPolicy.create(:notification => n, :communication_channel => @user.communication_channel, :user => @user, :frequency => "immediately")
p = @course.wiki.wiki_pages.create(:title => "some page")
@ -37,7 +40,6 @@ describe WikiPage do
end
it "should validate the title" do
course_with_teacher(:active_all => true)
@course.wiki.wiki_pages.new(:title => "").valid?.should_not be_true
@course.wiki.wiki_pages.new(:title => "!!!").valid?.should_not be_true
@course.wiki.wiki_pages.new(:title => "a"*256).valid?.should_not be_true
@ -45,15 +47,13 @@ describe WikiPage do
end
it "should make the title/url unique" do
course_with_teacher(:active_all => true)
p1 = @course.wiki.wiki_pages.create(:title => "Asdf")
p2 = @course.wiki.wiki_pages.create(:title => "Asdf")
p2.title.should eql('Asdf-2')
p2.url.should eql('asdf-2')
p2.url.should eql("#{p2.id}-asdf-2")
end
it "should make the title unique and truncate to proper length" do
course_with_teacher(:active_all => true)
p1 = @course.wiki.wiki_pages.create!(:title => "a" * WikiPage::TITLE_LENGTH)
p2 = @course.wiki.wiki_pages.create!(:title => p1.title)
p3 = @course.wiki.wiki_pages.create!(:title => p1.title)
@ -67,7 +67,6 @@ describe WikiPage do
end
it "should let you reuse the title/url of a deleted page" do
course_with_teacher(:active_all => true)
p1 = @course.wiki.wiki_pages.create(:title => "Asdf")
p1.workflow_state = 'deleted'
p1.save
@ -75,17 +74,29 @@ describe WikiPage do
p2 = @course.wiki.wiki_pages.create(:title => "Asdf")
p2.reload
p2.title.should eql('Asdf')
p2.url.should eql('asdf')
p2.url.should eql("#{p2.id}-asdf")
# so long as it's deleted, we don't care about uniqueness of the title/url
p1.save.should be_true
p1.title.should eql('Asdf')
p1.url.should eql('asdf')
p1.url.should eql("#{p1.id}-asdf")
p1.workflow_state = 'active'
p1.save.should be_true
p1.title.should eql('Asdf-2')
p1.url.should eql('asdf-2')
p1.url.should eql("#{p1.id}-asdf-2")
end
it "should prepend the id to its url" do
page = @course.wiki.wiki_pages.create(:title => "The Unbearable Lightness of Being")
page.url.should eql "#{page.id}-the-unbearable-lightness-of-being"
end
it "should change its url when renamed" do
page = @course.wiki.wiki_pages.create(:title => "Blood Meridian")
page.title = "Blood Meridian, or the Evening Redness in the West"
page.save
page.url.should eql "#{page.id}-blood-meridian-or-the-evening-redness-in-the-west"
end
context "atom" do