From 0b1a80a852916a7250c05dd2ea4ac65c83fd704e Mon Sep 17 00:00:00 2001 From: Alexey Verkhovsky Date: Mon, 14 Nov 2005 08:38:37 +0000 Subject: [PATCH] [BUILD STILL BROKEN] File uploads roughly speaking work (to about same extent as in 0.10) --- app/controllers/application.rb | 2 - app/controllers/file_controller.rb | 22 ++- app/controllers/wiki_controller.rb | 9 +- app/models/web.rb | 42 ++-- app/models/wiki_file.rb | 13 +- app/views/admin/edit_web.rhtml | 4 - app/views/file/file.rhtml | 39 ++-- app/views/layouts/default.rhtml | 9 +- lib/url_generator.rb | 6 +- public/stylesheets/instiki.css | 245 +++++------------------- test/functional/file_controller_test.rb | 66 ++++--- test/test_helper.rb | 4 +- test/unit/page_renderer_test.rb | 8 +- 13 files changed, 172 insertions(+), 297 deletions(-) diff --git a/app/controllers/application.rb b/app/controllers/application.rb index 362558fe..e43b0d8e 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -38,8 +38,6 @@ class ApplicationController < ActionController::Base return false end end - @page_name = @file_name = @params['id'] - @page = @wiki.read_page(@web_name, @page_name) unless @page_name.nil? @author = cookies['author'] || 'AnonymousCoward' end diff --git a/app/controllers/file_controller.rb b/app/controllers/file_controller.rb index fdf3b8ae..724e6b4c 100644 --- a/app/controllers/file_controller.rb +++ b/app/controllers/file_controller.rb @@ -9,23 +9,26 @@ class FileController < ApplicationController def file if @params['file'] # form supplied - new_file = upload_file(@file_name, @params['file']) + new_file = @web.wiki_files.create(@params['file']) if new_file.valid? flash[:info] = "File '#{@file_name}' successfully uploaded" return_to_last_remembered else - # FIXME handle validation errors more gracefully - flash[:errors] = new_file.errors.to_s + # pass the file with errors back into the form + @file = new_file + render end - else + else + (render(:status => 404, :text => 'Unspecified file name') and return) unless @file_name # no form supplied, this is a request to download the file file = WikiFile.find_by_file_name(@file_name) if file send_data(file.content, :filename => @file_name, :type => content_type_header(@file_name)) + else + @file = WikiFile.new(:file_name => @file_name) + render end end - # if it's neither a supplied form for upload, nor a request for a known file, - # display the file/file.rhtml template (which happens to be an upload form) end def cancel_upload @@ -41,7 +44,7 @@ class FileController < ApplicationController if @problems.empty? flash[:info] = 'Import successfully finished' else - flash[:error] = "Import finished, but some pages were not imported:
  • " + + flash[:error] = 'Import finished, but some pages were not imported:
  • ' + @problems.join('
  • ') + '
  • ' end return_to_last_remembered @@ -60,6 +63,11 @@ class FileController < ApplicationController return false end end + + def connect_to_model + super + @file_name = @params['id'] + end private diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index 2e7eb3b7..dbed5666 100644 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -272,9 +272,16 @@ class WikiController < ApplicationController @tex_content = RedClothForTex.new(@page.content).to_tex end + protected + + def connect_to_model + super + @page_name = @params['id'] + @page = @wiki.read_page(@web_name, @page_name) if @page_name + end private - + def convert_tex_to_pdf(tex_path) # TODO remove earlier PDF files with the same prefix # TODO handle gracefully situation where pdflatex is not available diff --git a/app/models/web.rb b/app/models/web.rb index 1ca17a9e..b37811a6 100644 --- a/app/models/web.rb +++ b/app/models/web.rb @@ -6,10 +6,6 @@ class Web < ActiveRecord::Base Wiki.new end - def file_yard - @file_yard ||= FileYard.new("#{Wiki.storage_path}/#{address}", max_upload_size) - end - def settings_changed?(markup, safe_mode, brackets_only) self.markup != markup || self.safe_mode != safe_mode || @@ -84,6 +80,23 @@ class Web < ActiveRecord::Base address end + def create_files_directory + return unless allow_uploads == 1 + dummy_file = self.wiki_files.build(:file_name => '0', :description => '0', :content => '0') + dir = File.dirname(dummy_file.content_path) + begin + require 'fileutils' + FileUtils.mkdir_p dir + dummy_file.save + dummy_file.destroy + rescue => e + logger.error("Failed create files directory for #{self.address}: #{e}") + raise "Instiki could not create directory to store uploaded files. " + + "Please make sure that Instiki is allowed to create directory " + + "#{File.expand_path(dir)} and add files to it." + end + end + private # Returns an array of all the wiki words in any current revision @@ -114,32 +127,15 @@ class Web < ActiveRecord::Base end end - def create_files_directory - return unless allow_uploads == 1 - dummy_file = self.wiki_files.build(:file_name => '0', :description => '0', :content => '0') - dir = File.dirname(dummy_file.content_path) - begin - require 'fileutils' - FileUtils.mkdir_p dir - dummy_file.save - dummy_file.destroy - rescue => e - logger.error("Failed create files directory for #{self.address}: #{e}") - raise "Instiki could not create directory to store uploaded files. " + - "Please make sure that Instiki is allowed to create directory " + - "#{File.expand_path(dir)} and add files to it." - end - end - def default_web? defined? DEFAULT_WEB and self.address == DEFAULT_WEB end def files_path if default_web? - "#{RAILS_ROOT}/public/#{self.address}/files" - else "#{RAILS_ROOT}/public/files" + else + "#{RAILS_ROOT}/public/#{self.address}/files" end end end diff --git a/app/models/wiki_file.rb b/app/models/wiki_file.rb index 89b166c0..635025e5 100644 --- a/app/models/wiki_file.rb +++ b/app/models/wiki_file.rb @@ -4,9 +4,9 @@ class WikiFile < ActiveRecord::Base before_save :write_content_to_file before_destroy :delete_content_file - validates_presence_of %w( web file_name description ) + validates_presence_of %w( web file_name ) validates_length_of :file_name, :within=>1..50 - validates_length_of :description, :within=>1..255 + validates_length_of :description, :maximum=>255 def self.find_by_file_name(file_name) find(:first, :conditions => ['file_name = ?', file_name]) @@ -34,7 +34,11 @@ class WikiFile < ActiveRecord::Base end def content=(content) - @content = content + if content.respond_to? :read + @content = content.read + else + @content = content + end end def content @@ -46,6 +50,7 @@ class WikiFile < ActiveRecord::Base end def write_content_to_file + web.create_files_directory unless File.exists?(web.files_path) File.open(self.content_path, 'wb') { |f| f.write(@content) } end @@ -54,4 +59,6 @@ class WikiFile < ActiveRecord::Base FileUtils.rm_f(content_path) if File.exists?(content_path) end + + end diff --git a/app/views/admin/edit_web.rhtml b/app/views/admin/edit_web.rhtml index 558ef68a..58734136 100644 --- a/app/views/admin/edit_web.rhtml +++ b/app/views/admin/edit_web.rhtml @@ -48,9 +48,6 @@ /> Count pages
    -

    diff --git a/app/views/file/file.rhtml b/app/views/file/file.rhtml index 63c188eb..4216a9ed 100644 --- a/app/views/file/file.rhtml +++ b/app/views/file/file.rhtml @@ -1,19 +1,32 @@ <% - @title = "Upload #{@file_name}" + @title = "Upload #{h @file_name}" @hide_navigation = false %> -

    +<%= error_messages_for 'file' %> + <%= form_tag({:controller => 'file', :web => @web_name, :action => 'file'}, {:multipart => true}) %> -

    - File to upload: + <%= hidden_field 'file', 'file_name' %> +

    + Content of <%= h @file_name %> to upload (required):
    - -

    -

    - as - -

    -<%= end_form_tag %> -

    \ No newline at end of file + +
    + + Please note that the file you are uploadng will be named <%= h @file_name %> on the wiki - + regardless of how it is named on your computer. To change the wiki name of the file, please go + <%= link_to :back %> and edit the wiki page that refers to the file. + +
    +
    + Description (optional): +
    + <%= text_field "file", "description", "size" => 40 %> +
    +
    + as + <%= text_field_tag :author, @author, + :onfocus => "this.value == 'AnonymousCoward' ? this.value = '' : true;", + :onblur => "this.value == '' ? this.value = 'AnonymousCoward' : true" %> +
    +<%= end_form_tag %> \ No newline at end of file diff --git a/app/views/layouts/default.rhtml b/app/views/layouts/default.rhtml index fb5e550e..d43208fa 100644 --- a/app/views/layouts/default.rhtml +++ b/app/views/layouts/default.rhtml @@ -55,15 +55,16 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <% end %> -<% if @error or @flash[:error] %>
    -

    <%= escape_preserving_linefeeds(@error || @flash[:error]) %>


    -<% end %> - <% if @flash[:info] %>

    <%= escape_preserving_linefeeds @flash[:info] %>


    <% end %> <%= render 'navigation' unless @web.nil? || @hide_navigation %> + +<% if @error or @flash[:error] %> +
    <%= escape_preserving_linefeeds(@error || @flash[:error]) %>
    +<% end %> + <%= @content_for_layout %> <% if @show_footer %> diff --git a/lib/url_generator.rb b/lib/url_generator.rb index fcc08312..ed4da4c4 100644 --- a/lib/url_generator.rb +++ b/lib/url_generator.rb @@ -47,14 +47,14 @@ class UrlGenerator < AbstractUrlGenerator end when :publish if known_file - href = @controller.url_for :controller => 'wiki', :web => web_address, :action => 'published', + href = @controller.url_for :controller => 'file', :web => web_address, :action => 'file', :id => name %{#{text}} else %{#{text}} end else - href = @controller.url_for :controller => 'wiki', :web => web_address, :action => 'file', + href = @controller.url_for :controller => 'file', :web => web_address, :action => 'file', :id => name if known_file %{#{text}} @@ -108,7 +108,7 @@ class UrlGenerator < AbstractUrlGenerator %{#{text}} end else - href = @controller.url_for @controller => 'file', :web => web_address, :action => 'pic', + href = @controller.url_for :controller => 'file', :web => web_address, :action => 'file', :id => name if known_pic %{#{text}} diff --git a/public/stylesheets/instiki.css b/public/stylesheets/instiki.css index e1bcb19c..667fb8e9 100644 --- a/public/stylesheets/instiki.css +++ b/public/stylesheets/instiki.css @@ -1,31 +1,12 @@ -#Container { - float: none; - margin: 0 auto; - text-align: center; -} - -#Content { - margin: 0; - padding: 5px; - text-align: left; - border-top: none; - float: left; -} - body { background-color: #fff; color: #333; } +body, p, ol, ul, td { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 18px; } -body, p, ol, ul, td { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 13px; - line-height: 18px; -} +#Container { float: none; margin: 0 auto; text-align: center; } +#Content { margin: 0; padding: 5px; text-align: left; border-top: none; float: left; } a { color: #000; } a:visited { color: #666; } -a:hover { - color: #fff; - background-color:#000; -} +a:hover { color: #fff; background-color:#000; } .newWikiWord { background-color: #eee; } .newWikiWord a:hover { background-color: white; } @@ -35,208 +16,72 @@ h1 { font-size: 28px } h2 { font-size: 19px } h3 { font-size: 16px } -h1#pageName { - margin: 5px 0 0; - padding: 0; - line-height: 28px; -} - -h1#pageName small { - color: #444; - line-height: 10px; - font-size: 10px; - padding: 0; -} +h1#pageName { margin: 5px 0 0; padding: 0; line-height: 28px; } +h1#pageName small { color: #444; line-height: 10px; font-size: 10px; padding: 0; } a.nav, a.nav:link, a.nav:visited { color: #000; } a.nav:hover { color: #fff; background-color:#000; } li { margin-bottom: 7px } -.navigation { - margin-top: 5px; - font-size : 12px; - color: #999; -} - +.navigation { margin-top: 5px; font-size : 12px; color: #999; } .navigation a:hover { color: #fff; background-color:#000; } - -.navigation a { - font-size: 11px; - color: black; - font-weight: bold; -} - -.navigation small a { - font-weight: normal; - font-size: 11px; -} +.navigation a { font-size: 11px; color: black; font-weight: bold; } +.navigation small a { font-weight: normal; font-size: 11px; } -.navOn{ - font-size: 11px; - color: #444; - font-weight: bold; - text-decoration: none; -} +.navOn{ font-size: 11px; color: #444; font-weight: bold; text-decoration: none; } -.help { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 11px; -} +.help { font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; } -.inputBox { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 11px; - background-color: #eee; - padding: 5px; - margin-bottom: 20px; -} +.inputBox { font-family: verdana, arial, helvetica, sans-serif; font-size: 11px; background-color: #eee; padding: 5px; margin-bottom: 20px; } -blockquote { - display: block; - margin: 0px 0px 20px 0px; - padding: 0px 30px; - font-size:11px; - line-height:17px; - font-style: italic; -} +blockquote { display: block; margin: 0px 0px 20px 0px; padding: 0px 30px; font-size:11px; line-height:17px; font-style: italic; } -pre { - background-color: #eee; - padding: 10px; - font-size: 11px; - overflow: auto; -} +pre { background-color: #eee; padding: 10px; font-size: 11px; overflow: auto; } -ol.setup { - font-size: 19px; - font-family: georgia, verdana, sans-serif; - padding-left: 25px; -} +ol.setup { font-size: 19px; font-family: georgia, verdana, sans-serif; padding-left: 25px; } +ol.setup li { margin-bottom: 20px } -ol.setup li { - margin-bottom: 20px -} +.byline { font-size: 10px; font-style: italic; margin-bottom: 10px; color: #999; } -.byline { - font-size: 10px; - font-style: italic; - margin-bottom: 10px; - color: #999; -} +.references { font-size: 10px; } -.references { - font-size: 10px; -} +.diffdel, del.diffmod { background: pink; } +.diffins, ins.diffmod { background: lightgreen; } -.diffdel, del.diffmod { - background: pink; -} +#footer { height: 14px; padding: .25em 0; } +#footer p { font-size: 10px; color: gray; font-style: italic; margin: 0; float: right; text-align: right; } -.diffins, ins.diffmod { - background: lightgreen; -} +div.inputFieldWithPrompt { margin: 0.75em 0; } -#footer { - height: 14px; - padding: .25em 0; -} -#footer p { - font-size: 10px; - color: gray; - font-style: italic; - margin: 0; - float: right; - text-align: right; -} +div.errorExplanation { color: #900; font-style: italic; font-weight: bold; margin: 1.5em 0; padding: 1em; background: #FFA; } +div.errorExplanation h2 { display: none; } +div.errorExplanation p { padding: 0; margin: 0; border: none; } +div.errorExplanation ul { padding: 0; margin: 0.5em 0 0 2em; border: none; } +div.errorExplanation li { padding 0; margin: 0; border: none; } +div.fieldWithErrors input { border: 1px solid #900; } -#error { - color: #900; - font-style: italic; - font-weight: bold; - width: 600px; -} -#info { - color: #060; - font-style: italic; - width: 600px; -} -#TextileHelp table { - margin-bottom: 0; -} +#info { color: #060; font-style: italic; width: 600px; } +#TextileHelp table { margin-bottom: 0; } +#TextileHelp table+h3 { margin-top: 11px; } +#TextileHelp table td { font-size: 11px; padding: 3px; vertical-align: top; border-top: 1px dotted #ccc; } +#TextileHelp table td.arrow { padding-right: 5px; padding-left: 10px; color: #999; } +#TextileHelp table td.label { font-weight: bold; white-space: nowrap; font-size: 10px; padding-right: 15px; color: #000; } +#TextileHelp h3 { font-size: 11px; font-weight: bold; font-weight: normal; margin: 0 0 5px 0; padding: 5px 0 0 0; } +#TextileHelp p { font-size: 10px; } -#TextileHelp table+h3 { - margin-top: 11px; -} +.rightHandSide { float: right; width: 147px; margin-left: 10px; padding-left: 20px; border-left: 1px dotted #ccc; } +.rightHandSide p { font-size: 10px; } -#TextileHelp table td { - font-size: 11px; - padding: 3px; - vertical-align: top; - border-top: 1px dotted #ccc; -} +.newsList { margin-top: 20px; } +.newsList p { margin-bottom:30px; } -#TextileHelp table td.arrow { - padding-right: 5px; - padding-left: 10px; - color: #999; -} - -#TextileHelp table td.label { - font-weight: bold; - white-space: nowrap; - font-size: 10px; - padding-right: 15px; - color: #000; -} - -#TextileHelp h3 { - font-size: 11px; - font-weight: bold; - font-weight: normal; - margin: 0 0 5px 0; - padding: 5px 0 0 0; -} - -#TextileHelp p { - font-size: 10px; -} - -.rightHandSide { - float: right; - width: 147px; - margin-left: 10px; - padding-left: 20px; - border-left: 1px dotted #ccc; -} - -.rightHandSide p { - font-size: 10px; -} - -.newsList { - margin-top: 20px; -} - -.newsList p { - margin-bottom:30px -} - -td {border:thin solid grey;} -table { - border: double black; - border-collapse: collapse; -} - -.byline { - padding-top: 15px; -} +table { border: double black; border-collapse: collapse; } +td { border:thin solid grey; } +.byline { padding-top: 15px; } /* Affects the display of "category: ..." */ -.property { - color: grey; - font-size: 10px; -} +.property { color: grey; font-size: 10px; } diff --git a/test/functional/file_controller_test.rb b/test/functional/file_controller_test.rb index b18862c0..4c6f4909 100755 --- a/test/functional/file_controller_test.rb +++ b/test/functional/file_controller_test.rb @@ -16,6 +16,7 @@ class FileControllerTest < Test::Unit::TestCase @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new @web = webs(:test_wiki) + @wiki = Wiki.new WikiFile.delete_all require 'fileutils' FileUtils.rm_rf("#{RAILS_ROOT}/public/wiki1/files/*") @@ -61,37 +62,40 @@ class FileControllerTest < Test::Unit::TestCase assert_equal pic, r.body end -# def test_pic_unknown_pic -# r = process 'pic', 'web' => 'wiki1', 'id' => 'non-existant.gif' -# -# assert_success -# assert_rendered_file 'file/file' -# end -# -# def test_pic_upload_end_to_end -# # edit and re-render home page so that it has an "unknown file" link to 'rails-e2e.gif' -# @wiki.revise_page('wiki1', 'HomePage', '[[rails-e2e.gif:pic]]', Time.now, 'AnonymousBrave') -# assert_equal "

    rails-e2e.gif" + -# "?

    ", -# @home.display_content -# -# # rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form -# r = process 'pic', 'web' => 'wiki1', 'id' => 'rails-e2e.gif' -# assert_success -# assert_rendered_file 'file/file' -# -# # User uploads the picture -# picture = File.read("#{RAILS_ROOT}/test/fixtures/rails.gif") -# r = process 'pic', 'web' => 'wiki1', 'id' => 'rails-e2e.gif', 'file' => StringIO.new(picture) -# assert_redirect_url '/' -# assert @wiki.file_yard(@web).has_file?('rails-e2e.gif') -# assert_equal(picture, File.read("#{RAILS_ROOT}/storage/test/wiki1/rails-e2e.gif")) -# -# # this should refresh the page display content (cached) -# assert_equal "

    \"rails-e2e.gif\"

    ", -# @home.display_content -# end -# + def test_pic_unknown_pic + r = get :file, :web => 'wiki1', :id => 'non-existant.gif' + + assert_success + assert_rendered_file 'file/file' + end + + def test_pic_upload_end_to_end + # edit and re-render home page so that it has an "unknown file" link to 'rails-e2e.gif' + PageRenderer.setup_url_generator(StubUrlGenerator.new) + renderer = PageRenderer.new + @wiki.revise_page('wiki1', 'HomePage', '[[rails-e2e.gif:pic]]', + Time.now, 'AnonymousBrave', renderer) + assert_equal "

    rails-e2e.gif" + + "?

    ", + renderer.display_content + + # rails-e2e.gif is unknown to the system, so pic action goes to the file [upload] form + r = get :file, :web => 'wiki1', :id => 'rails-e2e.gif' + assert_success + assert_rendered_file 'file/file' + + # User uploads the picture + picture = File.read("#{RAILS_ROOT}/test/fixtures/rails.gif") + r = get :file, :web => 'wiki1', :id => 'rails-e2e.gif', :file => StringIO.new(picture) + assert_redirect_url '/' + assert @web.has_file?('rails-e2e.gif') + assert_equal(picture, File.read("#{RAILS_ROOT}/public/file/rails-e2e.gif")) + + # this should refresh the page display content (cached) + assert_equal "

    \"rails-e2e.gif\"

    ", + @home.display_content + end + # def test_pic_upload_end_to_end # # edit and re-render home page so that it has an "unknown file" link to 'rails-e2e.gif' # @wiki.revise_page('wiki1', 'HomePage', '[[instiki-e2e.txt:file]]', Time.now, 'AnonymousBrave', diff --git a/test/test_helper.rb b/test/test_helper.rb index fc2079f3..2dae41c9 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -150,8 +150,8 @@ class StubUrlGenerator < AbstractUrlGenerator if known_pic then %{#{text}} else %{#{text}} end else - if known_pic then %{#{text}} - else %{#{text}?} end + if known_pic then %{#{text}} + else %{#{text}?} end end end end diff --git a/test/unit/page_renderer_test.rb b/test/unit/page_renderer_test.rb index 00746bff..aabaccf3 100644 --- a/test/unit/page_renderer_test.rb +++ b/test/unit/page_renderer_test.rb @@ -282,20 +282,20 @@ class PageRendererTest < Test::Unit::TestCase FileUtils.rm_rf("#{RAILS_ROOT}/public/wiki1/files/*") @web.wiki_files.create(:file_name => 'square.jpg', :description => 'Square', :content => 'never mind') assert_markup_parsed_as( - '

    Square

    ', + '

    Square

    ', '[[square.jpg|Square:pic]]') assert_markup_parsed_as( - '

    square.jpg

    ', + '

    square.jpg

    ', '[[square.jpg:pic]]') end def test_link_to_non_existant_pic assert_markup_parsed_as( - '

    NonExistant?' + + '

    NonExistant?' + '

    ', '[[NonExistant.jpg|NonExistant:pic]]') assert_markup_parsed_as( - '

    NonExistant.jpg?' + + '

    NonExistant.jpg?' + '

    ', '[[NonExistant.jpg:pic]]') end