1
0
mirror of https://github.com/meineerde/redmine.git synced 2026-02-01 03:57:15 +00:00

Fixes error executing the include macro (Page not found) in projects list (#43526).

Patch by Mizuki ISHIKAWA (user:ishikawa999). 



git-svn-id: https://svn.redmine.org/redmine/trunk@24234 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Marius Balteanu 2025-12-28 02:55:01 +00:00
parent c2cab7da79
commit 11612e5174
5 changed files with 102 additions and 10 deletions

View File

@ -459,10 +459,7 @@ module ApplicationHelper
s = +''
if projects.any?
ancestors = []
original_project = @project
projects.sort_by(&:lft).each do |project|
# set the project environment to please macros.
@project = project
if ancestors.empty? || project.is_descendant_of?(ancestors.last)
s << "<ul class='projects #{ancestors.empty? ? 'root' : nil}'>\n"
else
@ -481,7 +478,6 @@ module ApplicationHelper
ancestors << project
end
s << ("</li></ul>\n" * ancestors.size)
@project = original_project
end
s.html_safe
end

View File

@ -83,7 +83,7 @@ module ProjectsHelper
s << tag.span(sprite_icon('user', l(:label_my_projects), icon_only: true), class: 'icon-only icon-user my-project') if User.current.member_of?(project)
s << tag.span(sprite_icon('bookmarked', l(:label_my_bookmarks), icon_only: true), class: 'icon-only icon-bookmarked-project') if bookmarked_project_ids.include?(project.id)
if project.description.present?
s << content_tag('div', textilizable(project.short_description, :project => project), :class => 'wiki description')
s << content_tag('div', textilizable(project, :short_description, :project => project), :class => 'wiki description')
end
s
end

View File

@ -65,6 +65,10 @@ module Redmine
end
return [args, options]
end
def current_project(obj)
@project || (obj.is_a?(Project) && obj) || (obj.respond_to?(:project) && obj.project)
end
end
@@available_macros = {}
@ -223,8 +227,9 @@ module Redmine
"{{recent_pages(time=true)}} -- displays pages updated within the last 7 days with updated time"
macro :recent_pages do |obj, args|
return '' if @project.nil?
return '' unless User.current.allowed_to?(:view_wiki_pages, @project)
project = current_project(obj)
return '' if project.nil?
return '' unless User.current.allowed_to?(:view_wiki_pages, project)
args, options = extract_macro_options(args, :days, :limit, :time)
days_to_list = (options[:days].presence || 7).to_i
@ -233,7 +238,7 @@ module Redmine
pages = WikiPage.
joins(:content, :wiki).
where(["#{Wiki.table_name}.project_id = ? AND #{WikiContent.table_name}.updated_on >= ?", @project.id, days_to_list.days.ago]).
where(["#{Wiki.table_name}.project_id = ? AND #{WikiContent.table_name}.updated_on >= ?", project.id, days_to_list.days.ago]).
order("#{WikiContent.table_name}.updated_on desc, id").
limit(limit)
@ -241,7 +246,7 @@ module Redmine
pages.each do |page|
concat(
tag.li do
html = link_to(h(page.pretty_title), project_wiki_page_path(@project, page.title))
html = link_to(h(page.pretty_title), project_wiki_page_path(project, page.title))
html << " (#{time_ago_in_words(page.content.updated_on)})" if is_show_time
html
end
@ -254,7 +259,8 @@ module Redmine
"{{include(Foo)}}\n" +
"{{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)
project = current_project(obj)
page = Wiki.find_page(args.first.to_s, :project => project)
raise t(:error_page_not_found) if page.nil? || !User.current.allowed_to?(:view_wiki_pages, page.wiki.project)
@included_wiki_pages ||= []

View File

@ -68,4 +68,43 @@ class ProjectsTest < Redmine::IntegrationTest
assert_select 'td.buttons', text: ''
end
end
def test_index_should_render_include_macro_in_short_description
project = Project.find(1)
project.update!(:description => '{{include(Another page)}}')
log_user('admin', 'admin')
get '/projects', :params => {:display_type => 'list'}
assert_response :success
assert_select 'td.short_description div.wiki', :text => /This is a link to a ticket/
get '/projects', :params => {:display_type => ''}
assert_response :success
assert_select 'div.wiki.description', :text => /This is a link to a ticket/
end
def test_index_should_render_recent_pages_macro_in_short_description
freeze_time do
project = Project.find(1)
project.update!(:description => '{{recent_pages}}')
WikiContent.update_all(updated_on: Time.current)
project.wiki.pages.each_with_index do |page, i|
page.content.update_attribute(:updated_on, (i + 1).days.ago)
end
log_user('admin', 'admin')
get '/projects', :params => {:display_type => 'list'}
assert_response :success
assert_select 'td.short_description div.wiki ul li a', :count => 7
assert_select 'td.short_description div.wiki ul li:first a', :text => 'Another page'
get '/projects', :params => {:display_type => ''}
assert_response :success
assert_select 'div.wiki.description ul li a', :count => 7
assert_select 'div.wiki.description ul li:first a', :text => 'Another page'
end
end
end

View File

@ -232,6 +232,23 @@ class Redmine::WikiFormatting::MacrosTest < Redmine::HelperTest
assert_include 'Page not found', textilizable(text)
end
def test_include_macro_accepts_project_from_multiple_sources
project = Project.find(1)
# Resolve using the @project
@project = project
assert_include 'This is a link to a ticket', textilizable('{{include(Another page)}}')
@project = nil
# Resolve using object: project
assert_include 'This is a link to a ticket', textilizable('{{include(Another page)}}', {object: project})
# Resolve using issue.project
issue = Issue.first
issue.update(description: '{{include(Another page)}}')
assert_include 'This is a link to a ticket', textilizable(issue, :description)
end
def test_macro_collapse
text = "{{collapse\n*Collapsed* block of text\n}}"
with_locale 'en' do
@ -517,6 +534,40 @@ class Redmine::WikiFormatting::MacrosTest < Redmine::HelperTest
end
end
def test_recent_pages_macro_accepts_project_from_multiple_sources
project = Project.find(1)
freeze_time do
WikiContent.update_all(updated_on: Time.current)
project.wiki.pages.each_with_index do |page, i|
page.content.update_attribute(:updated_on, (i + 1).days.ago)
end
with_settings :text_formatting => 'textile' do
results = {}
# Resolve using the @project
@project = project
results[:project_instance_variable] = textilizable('{{recent_pages}}')
@project = nil
# Resolve using object: project
results[:object_project] = textilizable('{{recent_pages}}', {object: project})
# Resolve using issue.project
issue = Issue.first
issue.update(description: '{{recent_pages}}')
results[:issue_argument] = textilizable(issue, :description)
# Assertions
results.each do |key, result|
assert_select_in result, 'ul>li', {:count => 7}, "[#{key}] unexpected number of list items"
assert_select_in result, 'ul>li:first-of-type', {:text => 'Another page'}, "[#{key}] first list item text mismatch"
assert_select_in result, 'ul>li:last-of-type', {:text => 'Page with sections'}, "[#{key}] last list item text mismatch"
end
end
end
end
def test_recent_pages_macro_with_limit_option
@project = Project.find(1)
freeze_time do