254 lines
5.8 KiB
Ruby
254 lines
5.8 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
|
|
|
|
# Sorts and groups pages by directory.
|
|
#
|
|
# pages - an array of WikiPage objects.
|
|
#
|
|
# Returns an array of WikiPage and WikiDirectory objects. The entries are
|
|
# sorted by alphabetical order (directories and pages inside each directory).
|
|
# Pages at the root level come before everything.
|
|
def self.group_by_directory(pages)
|
|
return [] if pages.blank?
|
|
|
|
pages.sort_by { |page| [page.directory, page.slug] }.
|
|
group_by(&:directory).
|
|
map do |dir, pages|
|
|
if dir.present?
|
|
WikiDirectory.new(dir, pages)
|
|
else
|
|
pages
|
|
end
|
|
end.
|
|
flatten
|
|
end
|
|
|
|
def self.unhyphenize(name)
|
|
name.gsub(/-+/, ' ')
|
|
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 hook_attrs
|
|
attributes
|
|
end
|
|
|
|
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
|
|
if @attributes[:slug].present?
|
|
@attributes[:slug]
|
|
else
|
|
wiki.wiki.preview_page(title, '', format).url_path
|
|
end
|
|
end
|
|
|
|
alias_method :to_param, :slug
|
|
|
|
# The formatted title of this page.
|
|
def title
|
|
if @attributes[:title]
|
|
self.class.unhyphenize(@attributes[:title])
|
|
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] ||= @page&.text_data
|
|
end
|
|
|
|
# The hierarchy of the directory this page is contained in.
|
|
def directory
|
|
wiki.page_title_and_dir(slug).last
|
|
end
|
|
|
|
# The processed/formatted content of this page.
|
|
def formatted_content
|
|
@attributes[:formatted_content] ||= @page&.formatted_data
|
|
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? && versions.first.sha != version.sha
|
|
end
|
|
|
|
# Returns boolean True or False if this instance
|
|
# is the latest commit version of the page.
|
|
def latest?
|
|
!historical?
|
|
end
|
|
|
|
# Returns boolean True or False if this instance
|
|
# has been fully created on 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
|
|
|
|
# Relative path to the partial to be used when rendering collections
|
|
# of this object.
|
|
def to_partial_path
|
|
'projects/wikis/wiki_page'
|
|
end
|
|
|
|
def id
|
|
page.version.to_s
|
|
end
|
|
|
|
private
|
|
|
|
def set_attributes
|
|
attributes[:slug] = @page.url_path
|
|
attributes[:title] = @page.title
|
|
attributes[:format] = @page.format
|
|
end
|
|
|
|
def save(method, *args)
|
|
saved = false
|
|
|
|
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
|
|
saved = true
|
|
else
|
|
errors.add(:base, project_wiki.error_message) if project_wiki.error_message
|
|
end
|
|
saved
|
|
end
|
|
end
|