|
- class WikiPagesController < ApplicationController
- rescue_from Wiki::Commit::Conflict, with: :render_wiki_conflict
-
- def index
- render json: WikiPage.all
- end
-
- def show
- render_wiki_page_or_404 WikiPage.find(params[:id])
- end
-
- def show_by_title
- render_wiki_page_or_404 WikiPage.find_by(title: params[:title])
- end
-
- def exists
- if WikiPage.exists?(params[:id])
- head :no_content
- else
- head :not_found
- end
- end
-
- def exists_by_title
- if WikiPage.exists?(title: params[:title])
- head :no_content
- else
- head :not_found
- end
- end
-
- def diff
- id = params[:id]
- return head :bad_request if id.blank?
-
- from = params[:from].presence
- to = params[:to].presence
-
- page = WikiPage.find(id)
-
- from_rev = from && page.wiki_revisions.find(from)
- to_rev = to ? page.wiki_revisions.find(to) : page.current_revision
- if ((from_rev && !(from_rev.content?)) || !(to_rev&.content?))
- return head :unprocessable_entity
- end
-
- diffs = Diff::LCS.sdiff(from_rev&.body&.lines || [], to_rev.body.lines)
- diff_json = diffs.map { |change|
- case change.action
- when ?=
- { type: 'context', content: change.old_element }
- when ?!
- [{ type: 'removed', content: change.old_element },
- { type: 'added', content: change.new_element }]
- when ?+
- { type: 'added', content: change.new_element }
- when ?-
- { type: 'removed', content: change.old_element }
- end
- }.flatten.compact
-
- render json: { wiki_page_id: page.id,
- title: page.title,
- older_revision_id: from_rev&.id,
- newer_revision_id: to_rev.id,
- diff: diff_json }
- end
-
- def create
- return head :unauthorized unless current_user
- return head :forbidden unless current_user.member?
-
- title = params[:title]&.strip
- body = params[:body].to_s
-
- return head :unprocessable_entity if title.blank? || body.blank?
-
- page = WikiPage.new(title:, created_user: current_user, updated_user: current_user)
-
- if page.save
- message = params[:message].presence
- Wiki::Commit.content!(page:, body:, created_user: current_user, message:)
-
- render json: page, status: :created
- else
- render json: { errors: page.errors.full_messages },
- status: :unprocessable_entity
- end
- end
-
- def update
- return head :unauthorized unless current_user
- return head :forbidden unless current_user.member?
-
- title = params[:title]&.strip
- body = params[:body].to_s
-
- return head :unprocessable_entity if title.blank? || body.blank?
-
- page = WikiPage.find(params[:id])
- base_revision_id = page.current_revision.id
-
- if params[:title].present? && params[:title].strip != page.title
- return head :unprocessable_entity
- end
-
- message = params[:message].presence
- Wiki::Commit.content!(page:,
- body:,
- created_user: current_user,
- message:,
- base_revision_id:)
-
- head :ok
- end
-
- def search
- title = params[:title]&.strip
-
- q = WikiPage.all
- if title.present?
- q = q.where('title LIKE ?', "%#{ WikiPage.sanitize_sql_like(title) }%")
- end
-
- render json: q.limit(20)
- end
-
- def changes
- id = params[:id].presence
- q = WikiRevision.includes(:wiki_page, :created_user).order(id: :desc)
- q = q.where(wiki_page_id: id) if id
-
- render json: q.limit(200).map { |rev|
- { revision_id: rev.id,
- pred: rev.base_revision_id,
- succ: nil,
- wiki_page: { id: rev.wiki_page_id, title: rev.wiki_page.title },
- user: { id: rev.created_user.id, name: rev.created_user.name },
- kind: rev.kind,
- message: rev.message,
- timestamp: rev.created_at }
- }.compact
- end
-
- private
-
- def render_wiki_page_or_404 page
- return head :not_found unless page
-
- if params[:version].present?
- rev = page.wiki_revisions.find_by(id: params[:version])
- return head :not_found unless rev
-
- if rev.redirect?
- return (
- redirect_to wiki_page_by_title_path(title: rev.redirect_page.title),
- status: :moved_permanently)
- end
-
- body = rev.body
- revision_id = rev.id
- pred = page.pred_revision_id(revision_id)
- succ = page.succ_revision_id(revision_id)
- updated_at = rev.created_at
-
- return render json: page.as_json.merge(body:, revision_id:, pred:, succ:, updated_at:)
- end
-
- rev = page.current_revision
- unless rev
- return render json: page.as_json.merge(body: nil, revision_id: nil, pred: nil, succ: nil)
- end
-
- if rev.redirect?
- return (
- redirect_to wiki_page_by_title_path(title: rev.redirect_page.title),
- status: :moved_permanently)
- end
-
- body = rev.body
- revision_id = rev.id
- pred = page.pred_revision_id(revision_id)
- succ = page.succ_revision_id(revision_id)
- updated_at = rev.created_at
-
- render json: page.as_json.merge(body:, revision_id:, pred:, succ:, updated_at:)
- end
-
- def render_wiki_conflict err
- render json: { error: 'conflict', message: err.message }, status: :conflict
- end
- end
|