| 61 | 
  61 | 
  
       
   | 
  | 62 | 
  62 | 
  
      # edit an existing page or a new one 
   | 
  | 63 | 
  63 | 
  
      def edit 
   | 
  | 64 | 
   | 
  
        @page = @wiki.find_or_new_page(params[:page])     
   | 
  | 65 | 
   | 
  
        return render_403 unless editable? 
   | 
  | 66 | 
   | 
  
        @page.content = WikiContent.new(:page => @page) if @page.new_record? 
   | 
  | 67 | 
   | 
  
         
   | 
  | 68 | 
   | 
  
        @content = @page.content_for_version(params[:version]) 
   | 
  | 69 | 
   | 
  
        @content.text = initial_page_content(@page) if @content.text.blank? 
   | 
  | 70 | 
   | 
  
        # don't keep previous comment 
   | 
  | 71 | 
   | 
  
        @content.comments = nil 
   | 
  | 72 | 
   | 
  
        if request.get? 
   | 
   | 
  64 | 
  
        # Manuel Studer: check if it contains a section number as parameter 
   | 
   | 
  65 | 
  
        if params[:section] 
   | 
   | 
  66 | 
  
          # do special treatment to edit section 
   | 
   | 
  67 | 
  
          @page = @wiki.find_or_new_page(params[:page]) 
   | 
   | 
  68 | 
  
          return render_403 unless editable? 
   | 
   | 
  69 | 
  
          @page.content = WikiContent.new(:page => @page) if @page.new_record? 
   | 
   | 
  70 | 
  
    
   | 
   | 
  71 | 
  
          @content = @page.content_for_version(params[:version]) 
   | 
   | 
  72 | 
  
          @content.text = initial_page_content(@page) if @content.text.blank? 
   | 
   | 
  73 | 
  
          # don't keep previous comment 
   | 
   | 
  74 | 
  
          @content.comments = nil 
   | 
   | 
  75 | 
  
          @section_id = params[:section] 
   | 
   | 
  76 | 
  
          # change text here according to section 
   | 
   | 
  77 | 
  
          @content.text = get_textsection(@content.text,@section_id.to_i) 
   | 
  | 73 | 
  78 | 
  
          # To prevent StaleObjectError exception when reverting to a previous version 
   | 
  | 74 | 
  79 | 
  
          @content.version = @page.content.version 
   | 
  | 75 | 
   | 
  
        else 
   | 
  | 76 | 
   | 
  
          if !@page.new_record? && @content.text == params[:content][:text] 
   | 
   | 
  80 | 
  
          # Manuel Studer: this is for saving a section which has been edited 
   | 
   | 
  81 | 
  
        elsif request.post? && params[:content][:section_edit].to_i != 0 
   | 
   | 
  82 | 
  
          section_id = params[:content][:section_edit].to_i 
   | 
   | 
  83 | 
  
          new_section_text = params[:content][:text] 
   | 
   | 
  84 | 
  
    
   | 
   | 
  85 | 
  
          # get the original content from the db 
   | 
   | 
  86 | 
  
          @page = @wiki.find_or_new_page(params[:page]) 
   | 
   | 
  87 | 
  
          return render_403 unless editable? 
   | 
   | 
  88 | 
  
          @content = @page.content_for_version(params[:version]) 
   | 
   | 
  89 | 
  
    
   | 
   | 
  90 | 
  
          # don't keep previous comment 
   | 
   | 
  91 | 
  
          @content.comments = nil 
   | 
   | 
  92 | 
  
    
   | 
   | 
  93 | 
  
          text_original = @content.text 
   | 
   | 
  94 | 
  
          modify_text_endchars(new_section_text) 
   | 
   | 
  95 | 
  
    
   | 
   | 
  96 | 
  
          # replace the section 
   | 
   | 
  97 | 
  
          rebuilded_text = text_original.sub(get_textsection(text_original, section_id), new_section_text) 
   | 
   | 
  98 | 
  
    
   | 
   | 
  99 | 
  
          # create anchor so that after saving a page the browser jumps to the 
   | 
   | 
  100 | 
  
          # edited section 
   | 
   | 
  101 | 
  
          anchor = generate_anchor(rebuilded_text, section_id) 
   | 
   | 
  102 | 
  
    
   | 
   | 
  103 | 
  
          if !@page.new_record? && @content.text == rebuilded_text 
   | 
  | 77 | 
  104 | 
  
            # don't save if text wasn't changed 
   | 
  | 78 | 
   | 
  
            redirect_to :action => 'index', :id => @project, :page => @page.title 
   | 
   | 
  105 | 
  
            redirect_to :action => 'index', :id => @project, :page => @page.title, :anchor => anchor 
   | 
  | 79 | 
  106 | 
  
            return 
   | 
  | 80 | 
  107 | 
  
          end 
   | 
  | 81 | 
  108 | 
  
          #@content.text = params[:content][:text] 
   | 
  | 82 | 
  109 | 
  
          #@content.comments = params[:content][:comments] 
   | 
  | 83 | 
   | 
  
          @content.attributes = params[:content] 
   | 
   | 
  110 | 
  
          #@content.attributes = params[:content] 
   | 
   | 
  111 | 
  
    
   | 
   | 
  112 | 
  
          # manually set the content 
   | 
   | 
  113 | 
  
    
   | 
   | 
  114 | 
  
          @content.text = rebuilded_text 
   | 
   | 
  115 | 
  
          @content.comments = params[:content][:comments] 
   | 
   | 
  116 | 
  
          @content.version = params[:content][:version] 
   | 
  | 84 | 
  117 | 
  
          @content.author = User.current 
   | 
  | 85 | 
  118 | 
  
          # if page is new @page.save will also save content, but not if page isn't a new record 
   | 
  | 86 | 
  119 | 
  
          if (@page.new_record? ? @page.save : @content.save) 
   | 
  | 87 | 
  120 | 
  
            call_hook(:controller_wiki_edit_after_save, { :params => params, :page => @page})
   | 
  | 88 | 
   | 
  
            redirect_to :action => 'index', :id => @project, :page => @page.title 
   | 
   | 
  121 | 
  
            #redirect_to :action => 'index', :id => @project, :page => @page.title 
   | 
   | 
  122 | 
  
            redirect_to :action => 'index', :id => @project, :page => @page.title, :anchor => anchor 
   | 
  | 89 | 
  123 | 
  
          end 
   | 
   | 
  124 | 
  
    
   | 
   | 
  125 | 
  
          # this is invoked if no section has been chosen 
   | 
   | 
  126 | 
  
        else 
   | 
   | 
  127 | 
  
          # Manuel Studer: section id 0 means no section has been chosen, this means the whole 
   | 
   | 
  128 | 
  
          # page is selected 
   | 
   | 
  129 | 
  
          @section_id = 0 
   | 
   | 
  130 | 
  
    
   | 
   | 
  131 | 
  
          @page = @wiki.find_or_new_page(params[:page]) 
   | 
   | 
  132 | 
  
          return render_403 unless editable? 
   | 
   | 
  133 | 
  
          @page.content = WikiContent.new(:page => @page) if @page.new_record? 
   | 
   | 
  134 | 
  
    
   | 
   | 
  135 | 
  
          @content = @page.content_for_version(params[:version]) 
   | 
   | 
  136 | 
  
          @content.text = initial_page_content(@page) if @content.text.blank? 
   | 
   | 
  137 | 
  
          # don't keep previous comment 
   | 
   | 
  138 | 
  
          @content.comments = nil 
   | 
   | 
  139 | 
  
          if request.get? 
   | 
   | 
  140 | 
  
            # To prevent StaleObjectError exception when reverting to a previous version 
   | 
   | 
  141 | 
  
            @content.version = @page.content.version 
   | 
   | 
  142 | 
  
          else 
   | 
   | 
  143 | 
  
            if !@page.new_record? && @content.text == params[:content][:text] 
   | 
   | 
  144 | 
  
              # don't save if text wasn't changed 
   | 
   | 
  145 | 
  
              redirect_to :action => 'index', :id => @project, :page => @page.title 
   | 
   | 
  146 | 
  
              return 
   | 
   | 
  147 | 
  
            end 
   | 
   | 
  148 | 
  
            # Manuel Studer: manually set the content 
   | 
   | 
  149 | 
  
            #@content.attributes = params[:content] 
   | 
   | 
  150 | 
  
            @content.text = params[:content][:text] 
   | 
   | 
  151 | 
  
            @content.comments = params[:content][:comments] 
   | 
   | 
  152 | 
  
            @content.version = params[:content][:version] 
   | 
   | 
  153 | 
  
    
   | 
   | 
  154 | 
  
            @content.author = User.current 
   | 
   | 
  155 | 
  
            # if page is new @page.save will also save content, but not if page isn't a new record 
   | 
   | 
  156 | 
  
            if (@page.new_record? ? @page.save : @content.save) 
   | 
   | 
  157 | 
  
              redirect_to :action => 'index', :id => @project, :page => @page.title 
   | 
   | 
  158 | 
  
            end 
   | 
   | 
  159 | 
  
          end 
   | 
  | 90 | 
  160 | 
  
        end 
   | 
  | 91 | 
  161 | 
  
      rescue ActiveRecord::StaleObjectError 
   | 
  | 92 | 
  162 | 
  
        # Optimistic locking exception 
   | 
  | ... | ... |  | 
  | 234 | 
  304 | 
  
        extend helper unless self.instance_of?(helper) 
   | 
  | 235 | 
  305 | 
  
        helper.instance_method(:initial_page_content).bind(self).call(page) 
   | 
  | 236 | 
  306 | 
  
      end 
   | 
   | 
  307 | 
  
    
   | 
   | 
  308 | 
  
       
   | 
   | 
  309 | 
  
      # Manuel Studer: get the text of a given section 
   | 
   | 
  310 | 
  
      def get_textsection(textile_text, section_number) 
   | 
   | 
  311 | 
  
        current_section_number = 1 
   | 
   | 
  312 | 
  
        offset = 0 
   | 
   | 
  313 | 
  
        current_index = 0 
   | 
   | 
  314 | 
  
    
   | 
   | 
  315 | 
  
        # the index where the found section starts 
   | 
   | 
  316 | 
  
        start_section_index = 0 
   | 
   | 
  317 | 
  
        # the level of the found section 
   | 
   | 
  318 | 
  
        section_level = 0 
   | 
   | 
  319 | 
  
    
   | 
   | 
  320 | 
  
        while !current_index.nil? do 
   | 
   | 
  321 | 
  
          current_index =  textile_text.index(/h[1|2|3|4|5|6]\. ./i,offset) 
   | 
   | 
  322 | 
  
          if !current_index.nil? then 
   | 
   | 
  323 | 
  
    
   | 
   | 
  324 | 
  
            # we have found our start section 
   | 
   | 
  325 | 
  
            if current_section_number == section_number 
   | 
   | 
  326 | 
  
              start_section_index = current_index 
   | 
   | 
  327 | 
  
              section_level = textile_text[current_index+1..current_index+1].to_i 
   | 
   | 
  328 | 
  
            end 
   | 
   | 
  329 | 
  
    
   | 
   | 
  330 | 
  
            # now find the next section which has a smaller OR equal level than 
   | 
   | 
  331 | 
  
            # the found section 
   | 
   | 
  332 | 
  
            if current_section_number > section_number 
   | 
   | 
  333 | 
  
              current_section_level = textile_text[current_index+1..current_index+1].to_i 
   | 
   | 
  334 | 
  
              if current_section_level <= section_level 
   | 
   | 
  335 | 
  
                return textile_text[start_section_index..current_index-1] 
   | 
   | 
  336 | 
  
              end 
   | 
   | 
  337 | 
  
            end 
   | 
   | 
  338 | 
  
            offset = current_index + 3 
   | 
   | 
  339 | 
  
            current_section_number += 1 
   | 
   | 
  340 | 
  
          end 
   | 
   | 
  341 | 
  
        end 
   | 
   | 
  342 | 
  
        # return all up to the final char if it was the last h tag 
   | 
   | 
  343 | 
  
        return textile_text[start_section_index..textile_text.size-1] 
   | 
   | 
  344 | 
  
      end 
   | 
   | 
  345 | 
  
    
   | 
   | 
  346 | 
  
    
   | 
   | 
  347 | 
  
      # Manuel Studer: check if there is whole empty line at the end: which means 
   | 
   | 
  348 | 
  
      # 2x enter key: one enter key is 13 (\r) + 10 (\n) 
   | 
   | 
  349 | 
  
      def modify_text_endchars(text) 
   | 
   | 
  350 | 
  
        nst_last_char = text[text.size-1] 
   | 
   | 
  351 | 
  
        nst_2last_char = text[text.size-2] 
   | 
   | 
  352 | 
  
        nst_3last_char = text[text.size-3] 
   | 
   | 
  353 | 
  
        nst_4last_char = text[text.size-4] 
   | 
   | 
  354 | 
  
    
   | 
   | 
  355 | 
  
        if (nst_last_char == 10 && nst_2last_char == 13) && 
   | 
   | 
  356 | 
  
            (nst_3last_char == 10 && nst_4last_char == 13) 
   | 
   | 
  357 | 
  
          # all ok do nothing 
   | 
   | 
  358 | 
  
        elsif nst_last_char == 10 && nst_2last_char == 13 
   | 
   | 
  359 | 
  
          # add another one 
   | 
   | 
  360 | 
  
          text << "\r\n" 
   | 
   | 
  361 | 
  
        else 
   | 
   | 
  362 | 
  
          text << "\r\n\r\n" 
   | 
   | 
  363 | 
  
        end 
   | 
   | 
  364 | 
  
        return text 
   | 
   | 
  365 | 
  
      end 
   | 
   | 
  366 | 
  
    
   | 
   | 
  367 | 
  
    
   | 
   | 
  368 | 
  
      # generate the anchor from a given section 
   | 
   | 
  369 | 
  
      def generate_anchor(textile_text, section_number) 
   | 
   | 
  370 | 
  
        current_section_number = 1 
   | 
   | 
  371 | 
  
        offset = 0 
   | 
   | 
  372 | 
  
        current_index = 0 
   | 
   | 
  373 | 
  
    
   | 
   | 
  374 | 
  
        anchor = '' 
   | 
   | 
  375 | 
  
    
   | 
   | 
  376 | 
  
        while !current_index.nil? do 
   | 
   | 
  377 | 
  
          current_index =  textile_text.index(/h[1|2|3|4|5|6]\. ./i,offset) 
   | 
   | 
  378 | 
  
          if !current_index.nil? then 
   | 
   | 
  379 | 
  
    
   | 
   | 
  380 | 
  
            # we have found our start section 
   | 
   | 
  381 | 
  
            if current_section_number == section_number 
   | 
   | 
  382 | 
  
              # find index of next newline 
   | 
   | 
  383 | 
  
              index_next_newline = textile_text.index("\n",current_index)
   | 
   | 
  384 | 
  
    
   | 
   | 
  385 | 
  
              if !index_next_newline.nil? then 
   | 
   | 
  386 | 
  
                anchor = textile_text[current_index+3..index_next_newline].strip 
   | 
   | 
  387 | 
  
                # replaces non word caracters by dashes 
   | 
   | 
  388 | 
  
                anchor = anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
   | 
   | 
  389 | 
  
                return anchor 
   | 
   | 
  390 | 
  
              else 
   | 
   | 
  391 | 
  
                anchor = textile_text[current_index+3..textile_text.size-1].strip 
   | 
   | 
  392 | 
  
                # replaces non word caracters by dashes 
   | 
   | 
  393 | 
  
                anchor = anchor.gsub(%r{[^\w\s\-]}, '').gsub(%r{\s+(\-+\s*)?}, '-')
   | 
   | 
  394 | 
  
                return anchor 
   | 
   | 
  395 | 
  
              end 
   | 
   | 
  396 | 
  
    
   | 
   | 
  397 | 
  
            end 
   | 
   | 
  398 | 
  
            offset = current_index + 3 
   | 
   | 
  399 | 
  
            current_section_number += 1 
   | 
   | 
  400 | 
  
    
   | 
   | 
  401 | 
  
          else return anchor 
   | 
   | 
  402 | 
  
          end 
   | 
   | 
  403 | 
  
        end 
   | 
   | 
  404 | 
  
      end 
   | 
  | 237 | 
  405 | 
  
    end 
   | 
   | 
  406 | 
  
    
   |