gitlab-org--gitlab-foss/app/models/wiki_page.rb
Douglas Barbosa Alexandre aac6598482 Relax constraints for wiki slug
Since GitHub doesn’t apply these constraints to theirs wiki slug
allowing characters like `,`, `:`, `*`, etc, we need to relax our
constraints or some wiki pages will not be available after they were
imported.

For an example the Devise project have a wiki page with the following
slug: “How To: Add sign_in, sign_out, and sign_up links to your layout
template”
2016-01-14 12:09:31 -02:00

201 lines
4.7 KiB
Ruby

class WikiPage
include ActiveModel::Validations
include ActiveModel::Conversion
include StaticModel
extend ActiveModel::Naming
def self.primary_key
'slug'
end
def self.model_name
ActiveModel::Name.new(self, nil, 'wiki')
end
def to_key
[:slug]
end
validates :title, presence: true
validates :content, presence: true
# The Gitlab ProjectWiki instance.
attr_reader :wiki
# The raw Gollum::Page instance.
attr_reader :page
# The attributes Hash used for storing and validating
# new Page values before writing to the Gollum repository.
attr_accessor :attributes
def initialize(wiki, page = nil, persisted = false)
@wiki = wiki
@page = page
@persisted = persisted
@attributes = {}.with_indifferent_access
set_attributes if persisted?
end
# The escaped URL path of this page.
def slug
@attributes[:slug]
end
alias_method :to_param, :slug
# The formatted title of this page.
def title
if @attributes[:title]
@attributes[:title].gsub(/-+/, ' ')
else
""
end
end
# Sets the title of this page.
def title=(new_title)
@attributes[:title] = new_title
end
# The raw content of this page.
def content
@attributes[:content] ||= if @page
@page.raw_data
end
end
# The processed/formatted content of this page.
def formatted_content
@attributes[:formatted_content] ||= if @page
@page.formatted_data
end
end
# The markup format for the page.
def format
@attributes[:format] || :markdown
end
# The commit message for this page version.
def message
version.try(:message)
end
# The Gitlab Commit instance for this page.
def version
return nil unless persisted?
@version ||= @page.version
end
# Returns an array of Gitlab Commit instances.
def versions
return [] unless persisted?
@page.versions
end
def commit
versions.first
end
# Returns the Date that this latest version was
# created on.
def created_at
@page.version.date
end
# Returns boolean True or False if this instance
# is an old version of the page.
def historical?
@page.historical?
end
# Returns boolean True or False if this instance
# has been fully saved to disk or not.
def persisted?
@persisted == true
end
# Creates a new Wiki Page.
#
# attr - Hash of attributes to set on the new page.
# :title - The title for the new page.
# :content - The raw markup content.
# :format - Optional symbol representing the
# content format. Can be any type
# listed in the ProjectWiki::MARKUPS
# Hash.
# :message - Optional commit message to set on
# the new page.
#
# Returns the String SHA1 of the newly created page
# or False if the save was unsuccessful.
def create(attr = {})
@attributes.merge!(attr)
save :create_page, title, content, format, message
end
# Updates an existing Wiki Page, creating a new version.
#
# new_content - The raw markup content to replace the existing.
# format - Optional symbol representing the content format.
# See ProjectWiki::MARKUPS Hash for available formats.
# message - Optional commit message to set on the new version.
#
# Returns the String SHA1 of the newly created page
# or False if the save was unsuccessful.
def update(new_content = "", format = :markdown, message = nil)
@attributes[:content] = new_content
@attributes[:format] = format
save :update_page, @page, content, format, message
end
# Destroys the Wiki Page.
#
# Returns boolean True or False.
def delete
if wiki.delete_page(@page)
true
else
false
end
end
private
def set_attributes
attributes[:slug] = @page.url_path
attributes[:title] = @page.title
attributes[:format] = @page.format
end
def save(method, *args)
project_wiki = wiki
if valid? && project_wiki.send(method, *args)
page_details = if method == :update_page
# Use url_path instead of path to omit format extension
@page.url_path
else
title
end
page_title, page_dir = project_wiki.page_title_and_dir(page_details)
gollum_wiki = project_wiki.wiki
@page = gollum_wiki.paged(page_title, page_dir)
set_attributes
@persisted = true
else
errors.add(:base, project_wiki.error_message) if project_wiki.error_message
@persisted = false
end
@persisted
end
end