Skip to content

Instantly share code, notes, and snippets.

@keineahnung2345
Last active June 1, 2023 09:03
Show Gist options
  • Save keineahnung2345/4f5eee59079128645cad8aa88016fa77 to your computer and use it in GitHub Desktop.
Save keineahnung2345/4f5eee59079128645cad8aa88016fa77 to your computer and use it in GitHub Desktop.
Global wiki feature for Redmine 4.1.1 and 4.1.2, adapted from draft-feature-1040-r20825.patch by Mizuki ISHIKAWA on https://www.redmine.org/issues/1040#note-66
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index 4a88079..e7496fb 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -158,8 +158,10 @@ class AttachmentsController < ApplicationController
@attachment.destroy
end
+ container = @attachment.try(:container) || @container
respond_to do |format|
- format.html { redirect_to_referer_or project_path(@project) }
+ # redirect to project or global wiki page
+ format.html { redirect_to_referer_or @project ? project_path(@project) : wiki_index_path(container)}
format.js
format.api { render_api_ok }
end
diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb
index 423f94f..49c372f 100644
--- a/app/controllers/wiki_controller.rb
+++ b/app/controllers/wiki_controller.rb
@@ -33,7 +33,7 @@
# TODO: still being worked on
class WikiController < ApplicationController
default_search_scope :wiki_pages
- before_action :find_wiki, :authorize
+ before_action :find_wiki, :authorize_global
before_action :find_existing_or_new_page, :only => [:show, :edit]
before_action :find_existing_page, :only => [:rename, :protect, :history, :diff, :annotate, :add_attachment, :destroy, :destroy_version]
before_action :find_attachments, :only => [:preview]
@@ -41,11 +41,13 @@ class WikiController < ApplicationController
helper :attachments
include AttachmentsHelper
+ include WikiHelper
helper :watchers
include Redmine::Export::PDF
# List of pages, sorted alphabetically and by parent (hierarchy)
def index
+ authorize if params[:project_id]
load_pages_for_index
respond_to do |format|
@@ -64,7 +66,7 @@ class WikiController < ApplicationController
def new
@page = WikiPage.new(:wiki => @wiki, :title => params[:title])
- unless User.current.allowed_to?(:edit_wiki_pages, @project)
+ unless @wiki.allowed_to_permission?(:view_wiki_edits)
render_403
return
end
@@ -72,7 +74,7 @@ class WikiController < ApplicationController
@page.title = '' unless editable?
@page.validate
if @page.errors[:title].blank?
- path = project_wiki_page_path(@project, @page.title, :parent => params[:parent])
+ path = wiki_page_action_path('show', @page, {:parent => params[:parent]})
respond_to do |format|
format.html { redirect_to path }
format.js { render :js => "window.location = #{path.to_json}" }
@@ -83,13 +85,13 @@ class WikiController < ApplicationController
# display a page (in editing mode if it doesn't exist)
def show
- if params[:version] && !User.current.allowed_to?(:view_wiki_edits, @project)
+ if params[:version] && !@wiki.allowed_to_permission?(:view_wiki_edits)
deny_access
return
end
@content = @page.content_for_version(params[:version])
if @content.nil?
- if User.current.allowed_to?(:edit_wiki_pages, @project) && editable? && !api_request?
+ if @wiki.allowed_to_permission?(:view_wiki_edits) && editable? && !api_request?
edit
render :action => 'edit'
else
@@ -185,11 +187,11 @@ class WikiController < ApplicationController
respond_to do |format|
format.html {
anchor = @section ? "section-#{@section}" : nil
- redirect_to project_wiki_page_path(@project, @page.title, :anchor => anchor)
+ redirect_to wiki_page_action_path('show', @page, {:anchor => anchor})
}
format.api {
if was_new_page
- render :action => 'show', :status => :created, :location => project_wiki_page_path(@project, @page.title)
+ render :action => 'show', :status => :created, :location => wiki_page_action_path('show', @page)
else
render_api_ok
end
@@ -222,13 +224,13 @@ class WikiController < ApplicationController
@page.safe_attributes = params[:wiki_page]
if request.post? && @page.save
flash[:notice] = l(:notice_successful_update)
- redirect_to project_wiki_page_path(@page.project, @page.title)
+ redirect_to wiki_page_action_path('show', @page)
end
end
def protect
@page.update_attribute :protected, params[:protected]
- redirect_to project_wiki_page_path(@project, @page.title)
+ redirect_to wiki_page_action_path('show', @page)
end
# show page history
@@ -284,7 +286,13 @@ class WikiController < ApplicationController
end
@page.destroy
respond_to do |format|
- format.html { redirect_to project_wiki_index_path(@project) }
+ format.html {
+ if @project
+ redirect_to project_wiki_index_path(@project)
+ else
+ redirect_to wiki_index_path
+ end
+ }
format.api { render_api_ok }
end
end
@@ -294,7 +302,7 @@ class WikiController < ApplicationController
if content = @page.content.versions.find_by_version(params[:version])
content.destroy
- redirect_to_referer_or history_project_wiki_page_path(@project, @page.title)
+ redirect_to_referer_or wiki_page_action_path('history', @page)
else
render_404
end
@@ -339,13 +347,22 @@ class WikiController < ApplicationController
private
def find_wiki
- @project = Project.find(params[:project_id])
- @wiki = @project.wiki
+ if params[:project_id]
+ @project = Project.find(params[:project_id])
+ @wiki = @project.wiki
+ else
+ @wiki = Wiki.find_by(:project_id => nil)
+ Wiki.create(:project => nil, :start_page => 'Wiki') if @wiki.nil?
+ end
render_404 unless @wiki
rescue ActiveRecord::RecordNotFound
render_404
end
+ def global_wiki?
+ @wiki.project.nil?
+ end
+
# Finds the requested page or a new page if it doesn't exist
def find_existing_or_new_page
@page = @wiki.find_or_new_page(params[:id])
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index e8284a0..c1f97a6 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -200,7 +200,7 @@ module ApplicationHelper
'Project' => -> (project) { link_to_project(project) },
'User' => -> (user) { link_to_user(user) },
'Version' => -> (version) { link_to_version(version) },
- 'WikiPage' => -> (wiki_page) { link_to(wiki_page.pretty_title, project_wiki_page_path(wiki_page.project, wiki_page.title)) }
+ 'WikiPage' => -> (wiki_page) { link_to(wiki_page.pretty_title, url_for({:controller => 'wiki', :action => 'show', project_id: wiki_page.project, id: wiki_page.title})) }
}
def link_to_record(record)
@@ -270,10 +270,6 @@ module ApplicationHelper
end
end
- def wiki_page_path(page, options={})
- url_for({:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title}.merge(options))
- end
-
def thumbnail_tag(attachment)
thumbnail_size = Setting.thumbnails_size.to_i
link_to(
@@ -889,13 +885,14 @@ module ApplicationHelper
next link_to(title.present? ? title.html_safe : h(page), url, :class => 'wiki-page')
end
- if page =~ /^([^\:]+)\:(.*)$/
+ if page =~ /^(.*)\:(.*)$/
identifier, page = $1, $2
link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier)
title ||= identifier if page.blank?
end
-
- if link_project && link_project.wiki && User.current.allowed_to?(:view_wiki_pages, link_project)
+ wiki = Wiki.find_by(:project => link_project)
+ if wiki && wiki.allowed_to_permission?(:view_wiki_pages) &&
+ (link_project || (wiki.global? && link_project.nil?))
# extract anchor
anchor = nil
if page =~ /^(.+?)\#(.+)$/
@@ -903,7 +900,7 @@ module ApplicationHelper
end
anchor = sanitize_anchor_name(anchor) if anchor.present?
# check if page exists
- wiki_page = link_project.wiki.find_page(page)
+ wiki_page = wiki.find_page(page)
url =
if anchor.present? && wiki_page.present? &&
(obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) &&
diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb
index 0a94073..1d777c0 100644
--- a/app/helpers/wiki_helper.rb
+++ b/app/helpers/wiki_helper.rb
@@ -56,15 +56,23 @@ module WikiHelper
def wiki_page_edit_cancel_path(page)
if page.new_record?
if parent = page.parent
- project_wiki_page_path(parent.project, parent.title)
+ wiki_page_action_path('show', parent)
else
- project_wiki_index_path(page.project)
+ if page.project
+ project_wiki_index_path(page.project)
+ else
+ wiki_index_path
+ end
end
else
- project_wiki_page_path(page.project, page.title)
+ wiki_page_action_path('show', page)
end
end
+ def wiki_page_action_path(action_name, page=nil, options={})
+ url_for({:controller => 'wiki', :action => action_name, :project_id => (page.wiki.project if page), :id => (page.title if page)}.merge(options))
+ end
+
def wiki_content_update_info(content)
l(:label_updated_time_by, :author => link_to_user(content.author), :age => time_tag(content.updated_on)).html_safe
end
diff --git a/app/models/wiki.rb b/app/models/wiki.rb
index ed4331f..f18b01b 100644
--- a/app/models/wiki.rb
+++ b/app/models/wiki.rb
@@ -34,7 +34,7 @@ class Wiki < ActiveRecord::Base
safe_attributes 'start_page'
def visible?(user=User.current)
- !user.nil? && user.allowed_to?(:view_wiki_pages, project)
+ !user.nil? && user.allowed_to?(:view_wiki_pages, project, global: self.global?)
end
# Returns the wiki page that acts as the sidebar content
@@ -85,12 +85,13 @@ class Wiki < ActiveRecord::Base
# Wiki.find_page("foo:bar")
def self.find_page(title, options = {})
project = options[:project]
- if title.to_s =~ %r{^([^\:]+)\:(.*)$}
+ if title.to_s =~ %r{^(.*):(.*)$}
project_identifier, title = $1, $2
project = Project.find_by_identifier(project_identifier) || Project.find_by_name(project_identifier)
end
- if project && project.wiki
- page = project.wiki.find_page(title)
+ wiki = project_identifier.present? ? (project && project.wiki) : Wiki.find_by(project: nil)
+ if wiki
+ page = wiki.find_page(title)
if page && page.content
page
end
@@ -105,4 +106,16 @@ class Wiki < ActiveRecord::Base
title = (title.slice(0..0).upcase + (title.slice(1..-1) || '')) if title
title
end
+
+ def global?
+ self.project.nil?
+ end
+
+ def allowed_to_permission?(permission, user=User.current)
+ user.allowed_to?(permission, self.project, :global => self.global?)
+ end
+
+ def allowed_to_action?(action)
+ User.current.allowed_to?({:controller => 'wiki', :action => action}, self.project, :global => self.global?)
+ end
end
diff --git a/app/models/wiki_content.rb b/app/models/wiki_content.rb
index d38c5ca..82dc458 100644
--- a/app/models/wiki_content.rb
+++ b/app/models/wiki_content.rb
@@ -53,7 +53,7 @@ class WikiContent < ActiveRecord::Base
end
def notified_users
- project.notified_users.reject {|user| !visible?(user)}
+ self.global? ? [] : project.notified_users.reject {|user| !visible?(user)}
end
# Returns the mail addresses of users that should be notified
@@ -79,6 +79,10 @@ class WikiContent < ActiveRecord::Base
end
end
+ def global?
+ self.project.nil?
+ end
+
private
def create_version
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index c4da80f..6a139f0 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -62,10 +62,10 @@ class WikiPage < ActiveRecord::Base
DEFAULT_PROTECTED_PAGES = %w(sidebar)
safe_attributes 'parent_id', 'parent_title', 'title', 'redirect_existing_links', 'wiki_id',
- :if => lambda {|page, user| page.new_record? || user.allowed_to?(:rename_wiki_pages, page.project)}
+ :if => lambda {|page, user| page.new_record? || user.allowed_to?(:rename_wiki_pages, page.project, global: page.wiki.global?)}
safe_attributes 'is_start_page',
- :if => lambda {|page, user| user.allowed_to?(:manage_wiki, page.project)}
+ :if => lambda {|page, user| user.allowed_to?(:manage_wiki, page.project, global: page.wiki.global?)}
safe_attributes 'deleted_attachment_ids',
:if => lambda {|page, user| page.attachments_deletable?(user)}
@@ -78,7 +78,13 @@ class WikiPage < ActiveRecord::Base
end
def visible?(user=User.current)
- !user.nil? && user.allowed_to?(:view_wiki_pages, project)
+ !user.nil? &&
+ user.allowed_to?(:view_wiki_pages, self.project, global: self.wiki.global?)
+ end
+
+ def attachments_visible?(user=User.current)
+ (respond_to?(:visible?) ? visible?(user) : true) &&
+ user.allowed_to?(self.class.attachable_options[:view_permission], self.project, global: self.wiki.global?)
end
def title=(value)
@@ -203,7 +209,7 @@ class WikiPage < ActiveRecord::Base
# Returns true if usr is allowed to edit the page, otherwise false
def editable_by?(usr)
- !protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project)
+ !protected? || self.wiki.allowed_to_permission?(:protect_wiki_pages, usr)
end
def attachments_deletable?(usr=User.current)
diff --git a/app/views/wiki/_new_modal.html.erb b/app/views/wiki/_new_modal.html.erb
index 108c6ad..02f014b 100644
--- a/app/views/wiki/_new_modal.html.erb
+++ b/app/views/wiki/_new_modal.html.erb
@@ -1,7 +1,7 @@
<h3 class="title"><%=l(:label_wiki_page_new)%></h3>
<%= labelled_form_for :page, @page,
- :url => new_project_wiki_page_path(@project),
+ :url => wiki_page_action_path('new', @page),
:method => 'post',
:remote => true do |f| %>
diff --git a/app/views/wiki/annotate.html.erb b/app/views/wiki/annotate.html.erb
index 1b48f5d..7738c80 100644
--- a/app/views/wiki/annotate.html.erb
+++ b/app/views/wiki/annotate.html.erb
@@ -6,8 +6,8 @@
<%= wiki_page_breadcrumb(@page) %>
-<%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)],
- [l(:label_history), history_project_wiki_page_path(@page.project, @page.title)],
+<%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})],
+ [l(:label_history), wiki_page_action_path('history', @page)],
"#{l(:label_version)} #{@annotate.content.version}" %>
<p>
diff --git a/app/views/wiki/date_index.html.erb b/app/views/wiki/date_index.html.erb
index 274f19a..f4975f6 100644
--- a/app/views/wiki/date_index.html.erb
+++ b/app/views/wiki/date_index.html.erb
@@ -1,6 +1,6 @@
<div class="contextual">
<% if User.current.allowed_to?(:edit_wiki_pages, @project) %>
-<%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project), :remote => true, :class => 'icon icon-add' %>
+<%= link_to l(:label_wiki_page_new), wiki_page_action_path('new', @page), :remote => true, :class => 'icon icon-add' %>
<% end %>
<%= watcher_link(@wiki, User.current) %>
<% if User.current.allowed_to?(:manage_wiki, @project) %>
diff --git a/app/views/wiki/diff.html.erb b/app/views/wiki/diff.html.erb
index 765e51a..153af89 100644
--- a/app/views/wiki/diff.html.erb
+++ b/app/views/wiki/diff.html.erb
@@ -5,8 +5,8 @@
<%= wiki_page_breadcrumb(@page) %>
-<%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)],
- [l(:label_history), history_project_wiki_page_path(@page.project, @page.title)],
+<%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})],
+ [l(:label_history), wiki_page_action_path('history', @page)],
"#{l(:label_revision)} #{@diff.content_to.version}" %>
<p>
diff --git a/app/views/wiki/edit.html.erb b/app/views/wiki/edit.html.erb
index 0e1c23c..a86a1e9 100644
--- a/app/views/wiki/edit.html.erb
+++ b/app/views/wiki/edit.html.erb
@@ -64,7 +64,7 @@
<%= submit_tag l(:button_save) %>
<%= link_to l(:button_cancel), wiki_page_edit_cancel_path(@page) %>
</p>
-<%= wikitoolbar_for 'content_text', preview_project_wiki_page_path(:project_id => @project, :id => @page.title) %>
+<%= wikitoolbar_for 'content_text', wiki_page_action_path('preview', @page) %>
<% end %>
<% content_for :header_tags do %>
diff --git a/app/views/wiki/history.html.erb b/app/views/wiki/history.html.erb
index 3e638a8..dea9c58 100644
--- a/app/views/wiki/history.html.erb
+++ b/app/views/wiki/history.html.erb
@@ -1,6 +1,6 @@
<%= wiki_page_breadcrumb(@page) %>
-<%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)], l(:label_history) %>
+<%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})], l(:label_history) %>
<%= form_tag({:controller => 'wiki', :action => 'diff',
:project_id => @page.project, :id => @page.title},
@@ -31,7 +31,7 @@
<td class="comments"><%= ver.comments %></td>
<td class="buttons">
<%= link_to l(:button_annotate), :action => 'annotate', :id => @page.title, :version => ver.version %>
- <%= delete_link wiki_page_path(@page, :version => ver.version) if User.current.allowed_to?(:delete_wiki_pages, @page.project) && @version_count > 1 %>
+ <%= delete_link wiki_page_action_path('show', @page, {:version => ver.version}) if @page.wiki.allowed_to_permission?(:delete_wiki_pages) && @version_count > 1 %>
</td>
</tr>
<% line_num += 1 %>
diff --git a/app/views/wiki/index.html.erb b/app/views/wiki/index.html.erb
index bb60868..df8234f 100644
--- a/app/views/wiki/index.html.erb
+++ b/app/views/wiki/index.html.erb
@@ -1,6 +1,6 @@
<div class="contextual">
<% if User.current.allowed_to?(:edit_wiki_pages, @project) %>
-<%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project), :remote => true, :class => 'icon icon-add' %>
+<%= link_to l(:label_wiki_page_new), wiki_page_action_path('new'), :remote => true, :class => 'icon icon-add' %>
<% end %>
<%= watcher_link(@wiki, User.current) %>
<% if User.current.allowed_to?(:manage_wiki, @project) %>
diff --git a/app/views/wiki/new.html.erb b/app/views/wiki/new.html.erb
index d067420..1ad2f78 100644
--- a/app/views/wiki/new.html.erb
+++ b/app/views/wiki/new.html.erb
@@ -1,7 +1,7 @@
<%= title l(:label_wiki_page_new) %>
<%= labelled_form_for :page, @page,
- :url => new_project_wiki_page_path(@project) do |f| %>
+ :url => wiki_page_action_path('new', @page) do |f| %>
<%= render_error_messages @page.errors.full_messages_for(:title) %>
diff --git a/app/views/wiki/rename.html.erb b/app/views/wiki/rename.html.erb
index 13fb41a..46e9295 100644
--- a/app/views/wiki/rename.html.erb
+++ b/app/views/wiki/rename.html.erb
@@ -13,7 +13,7 @@
<p><%= f.check_box :is_start_page, :label => :field_start_page, :disabled => @page.is_start_page %></p>
<% end %>
<p><%= f.check_box :redirect_existing_links %></p>
-<% if @page.safe_attribute? 'wiki_id' %>
+<% if @page.safe_attribute? 'wiki_id' && !@page.wiki.global? %>
<p><%= f.select :wiki_id, wiki_page_wiki_options_for_select(@page), :label => :label_project %></p>
<% end %>
<p><%= f.select :parent_id,
@@ -30,7 +30,7 @@
<%= javascript_tag do %>
$('#wiki_page_wiki_id').change(function() {
$.ajax({
- url: '<%= rename_project_wiki_page_path(@wiki, :format => 'js') %>',
+ url: '<%= wiki_page_action_path('rename', @page, {:format => 'js'}) %>',
type: 'get',
data: { 'wiki_page[wiki_id]': $('#wiki_page_wiki_id').val() }
});
diff --git a/app/views/wiki/show.html.erb b/app/views/wiki/show.html.erb
index a710496..856793f 100644
--- a/app/views/wiki/show.html.erb
+++ b/app/views/wiki/show.html.erb
@@ -2,27 +2,27 @@
<% if @editable %>
<% if @content.current_version? %>
- <%= link_to_if_authorized(l(:button_edit), {:action => 'edit', :id => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
+ <%= link_to(l(:button_edit), {:action => 'edit', :id => @page.title}, :class => 'icon icon-edit', :accesskey => accesskey(:edit)) if @page.wiki.allowed_to_action?('edit') %>
<%= watcher_link(@page, User.current) %>
<% end %>
<% end %>
<%= actions_dropdown do %>
- <%= link_to_if_authorized(l(:label_history), {:action => 'history', :id => @page.title}, :class => 'icon icon-history') %>
+ <%= link_to(l(:label_history), {:action => 'history', :id => @page.title}, :class => 'icon icon-history') if @page.wiki.allowed_to_action?('history') %>
<% if @editable %>
<% if @content.current_version? %>
- <%= link_to_if_authorized(l(:button_lock), {:action => 'protect', :id => @page.title, :protected => 1}, :method => :post, :class => 'icon icon-lock') if !@page.protected? %>
- <%= link_to_if_authorized(l(:button_unlock), {:action => 'protect', :id => @page.title, :protected => 0}, :method => :post, :class => 'icon icon-unlock') if @page.protected? %>
- <%= link_to_if_authorized(l(:button_rename), {:action => 'rename', :id => @page.title}, :class => 'icon icon-move') %>
- <%= link_to_if_authorized(l(:button_delete), {:action => 'destroy', :id => @page.title}, :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'icon icon-del') %>
+ <%= link_to(l(:button_lock), {:action => 'protect', :id => @page.title, :protected => 1}, :method => :post, :class => 'icon icon-lock') if !@page.protected? && @page.wiki.allowed_to_action?('protect') %>
+ <%= link_to(l(:button_unlock), {:action => 'protect', :id => @page.title, :protected => 0}, :method => :post, :class => 'icon icon-unlock') if @page.protected? && @page.wiki.allowed_to_action?('protect') %>
+ <%= link_to(l(:button_rename), {:action => 'rename', :id => @page.title}, :class => 'icon icon-move') if @page.wiki.allowed_to_action?('rename') %>
+ <%= link_to(l(:button_delete), {:action => 'destroy', :id => @page.title}, :method => :delete, :data => {:confirm => l(:text_are_you_sure)}, :class => 'icon icon-del') if @page.wiki.allowed_to_action?('destroy') %>
<% else %>
- <%= link_to_if_authorized(l(:button_rollback), {:action => 'edit', :id => @page.title, :version => @content.version }, :class => 'icon icon-cancel') %>
+ <%= link_to(l(:button_rollback), {:action => 'edit', :id => @page.title, :version => @content.version }, :class => 'icon icon-cancel') if @page.wiki.allowed_to_action?('edit') %>
<% end %>
<% end %>
- <% if User.current.allowed_to?(:edit_wiki_pages, @project) %>
- <%= link_to l(:label_wiki_page_new), new_project_wiki_page_path(@project, :parent => @page.title), :remote => true, :class => 'icon icon-add' %>
+ <% if @page.wiki.allowed_to_permission?(:edit_wiki_pages) %>
+ <%= link_to l(:label_wiki_page_new), wiki_page_action_path('new', @page, {:parent => @page.title}), :remote => true, :class => 'icon icon-add' %>
<% end %>
<% end %>
</div>
@@ -30,8 +30,8 @@
<%= wiki_page_breadcrumb(@page) %>
<% unless @content.current_version? %>
- <%= title [@page.pretty_title, project_wiki_page_path(@page.project, @page.title, :version => nil)],
- [l(:label_history), history_project_wiki_page_path(@page.project, @page.title)],
+ <%= title [@page.pretty_title, wiki_page_action_path('show', @page, {:version => nil})],
+ [l(:label_history), wiki_page_action_path('history', @page)],
"#{l(:label_revision)} #{@content.version}" %>
<p>
diff --git a/config/routes.rb b/config/routes.rb
index d8e5fd7..68f316f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -183,6 +183,30 @@ Rails.application.routes.draw do
get 'wiki/:id/:version/annotate', :to => 'wiki#annotate'
get 'wiki/:id/:version/diff', :to => 'wiki#diff'
end
+ match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get
+ resources :wiki, :except => [:index, :create, :show], :as => 'wiki_page' do
+ member do
+ get 'wiki', :as => 'show_wiki_page'
+ get 'rename'
+ post 'rename'
+ get 'history'
+ get 'diff'
+ match 'preview', :via => [:post, :put, :patch]
+ post 'protect'
+ post 'add_attachment'
+ end
+ collection do
+ get 'export'
+ get 'date_index'
+ post 'new'
+ end
+ end
+ match 'wiki', :controller => 'wiki', :action => 'show', :via => :get
+ get 'wiki/:id/:version', :to => 'wiki#show', :constraints => {:version => /\d+/}
+ delete 'wiki/:id/:version', :to => 'wiki#destroy_version'
+ get 'wiki/:id/:version/annotate', :to => 'wiki#annotate'
+ get 'wiki/:id/:version/diff', :to => 'wiki#diff'
+ match 'wiki/:id/destroy', :to => 'wikis#destroy', :via => [:get, :post]
resources :issues do
member do
diff --git a/db/migrate/20200729083854_allow_wiki_project_id_to_be_nil.rb b/db/migrate/20200729083854_allow_wiki_project_id_to_be_nil.rb
new file mode 100644
index 0000000..7312d08
--- /dev/null
+++ b/db/migrate/20200729083854_allow_wiki_project_id_to_be_nil.rb
@@ -0,0 +1,8 @@
+class AllowWikiProjectIdToBeNil < ActiveRecord::Migration[5.2]
+ def up
+ change_column_null :wikis, :project_id, true
+ end
+ def down
+ change_column_null :wikis, :project_id, false
+ end
+end
diff --git a/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb b/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb
index 4df4b6a..3ca03a3 100644
--- a/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb
+++ b/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb
@@ -58,7 +58,7 @@ module Redmine
def attachments_deletable?(user=User.current)
(respond_to?(:visible?) ? visible?(user) : true) &&
- user.allowed_to?(self.class.attachable_options[:delete_permission], self.project)
+ user.allowed_to?(self.class.attachable_options[:delete_permission], self.project, :global => ((self.is_a? WikiPage) ? self.wiki.global?: false))
end
def saved_attachments
diff --git a/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb b/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb
index 83fa394..6ff8347 100644
--- a/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb
+++ b/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb
@@ -196,6 +196,22 @@ module Redmine
if projects
scope = scope.where("#{searchable_options[:project_key]} IN (?)", projects.map(&:id))
+ elsif scope.table_name == "wiki_pages" && options[:params][:wiki_pages] == "1"
+ # including global wiki
+ scope_global_wikis = WikiPage.joins(:wiki).where("wikis.project_id is null")
+ # Method 1:
+ # ArgumentError (Relation passed to #or must be structurally compatible. Incompatible values: [:joins])
+ #scope = scope.or(scope_global_wikis)
+ # Method 2:
+ # TypeError (Cannot visit WikiPage::ActiveRecord_Relation)
+ #wiki_page_table = WikiPage.arel_table
+ #combined = Arel::Nodes::UnionAll.new(scope, scope_global_wikis)
+ #scope = WikiPage.from(Arel::Nodes::As.new(combined, wiki_page_table))
+ # Method 3:
+ # https://stackoverflow.com/questions/57491185/obtain-union-all-result-in-activerecord
+ # https://stackoverflow.com/questions/17331862/converting-an-array-of-objects-to-activerecordrelation
+ scope_array = WikiPage.find_by_sql("#{scope.to_sql} UNION #{scope_global_wikis.to_sql}")
+ scope = WikiPage.where(id: scope_array.map(&:id)).joins(:content) #.joins({:wiki => :project})
end
scope
end
diff --git a/lib/redmine.rb b/lib/redmine.rb
index 9ecca63..58da75b 100644
--- a/lib/redmine.rb
+++ b/lib/redmine.rb
@@ -242,6 +242,15 @@ Redmine::MenuManager.map :application_menu do |menu|
EnabledModule.exists?(:project => Project.visible, :name => :news)
},
:caption => :label_news_plural
+ menu.push(
+ :wiki,
+ {:controller => 'wiki', :action => 'show'},
+ :if =>
+ Proc.new do
+ User.current.allowed_to?(:view_wiki_pages, nil, :global => true)
+ end,
+ :caption => :label_wiki
+ )
end
Redmine::MenuManager.map :admin_menu do |menu|
diff --git a/lib/redmine/wiki_formatting/macros.rb b/lib/redmine/wiki_formatting/macros.rb
index 99eac68..c2d03b7 100644
--- a/lib/redmine/wiki_formatting/macros.rb
+++ b/lib/redmine/wiki_formatting/macros.rb
@@ -205,7 +205,7 @@ module Redmine
else
raise 'With no argument, this macro can be called from wiki pages only.'
end
- raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
+ raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project, global: page.wiki.global?)
pages = page.self_and_descendants(options[:depth]).group_by(&:parent_id)
render_page_hierarchy(pages, options[:parent] ? page.parent_id : page.id)
end
@@ -215,7 +215,7 @@ module Redmine
"{{include(projectname:Foo)}} -- to include a page of a specific project wiki"
macro :include do |obj, args|
page = Wiki.find_page(args.first.to_s, :project => @project)
- raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
+ raise 'Page not found' if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project, global: page.wiki.global?)
@included_wiki_pages ||= []
raise 'Circular inclusion detected' if @included_wiki_pages.include?(page.id)
@included_wiki_pages << page.id
@keineahnung2345
Copy link
Author

revision 5: attachments_deletable? Fix for non-WikiPage class

@keineahnung2345
Copy link
Author

Usage: download it as global_wiki_redmine-4.1.1.patch4, and then git apply --reject global_wiki_redmine-4.1.1.patch, then RAILS_ENV=production bundle exec rake db:migrate.

@keineahnung2345
Copy link
Author

revision 6: make global wiki searchable

@keineahnung2345
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment