card 1.16.3 → 1.16.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +1 -1
  4. data/db/migrate_core_cards/20150724123438_update_file_and_image_cards.rb +1 -1
  5. data/db/migrate_core_cards/20150824135418_update_file_history.rb +20 -0
  6. data/db/migrate_core_cards/20150903130006_attachment_upload_cards.rb +13 -0
  7. data/db/seed/new/card_actions.yml +16 -0
  8. data/db/seed/new/card_acts.yml +1 -1
  9. data/db/seed/new/card_changes.yml +56 -80
  10. data/db/seed/new/card_references.yml +282 -58
  11. data/db/seed/new/cards.yml +1348 -1312
  12. data/db/seed/test/fixtures/card_actions.yml +884 -868
  13. data/db/seed/test/fixtures/card_acts.yml +250 -250
  14. data/db/seed/test/fixtures/card_changes.yml +1935 -1959
  15. data/db/seed/test/fixtures/card_references.yml +1024 -800
  16. data/db/seed/test/fixtures/cards.yml +2402 -2366
  17. data/db/version_core_cards.txt +1 -1
  18. data/lib/card.rb +3 -1
  19. data/lib/card/cache.rb +5 -5
  20. data/lib/card/chunk.rb +2 -0
  21. data/lib/card/env.rb +1 -1
  22. data/lib/card/query/card_clause.rb +59 -58
  23. data/lib/card/set.rb +7 -0
  24. data/lib/card/success.rb +143 -0
  25. data/mod/01_core/chunk/query_reference.rb +16 -7
  26. data/mod/01_core/chunk/reference.rb +3 -3
  27. data/mod/01_core/set/all/collection.rb +1 -1
  28. data/mod/01_core/set/all/name.rb +2 -1
  29. data/mod/01_core/set/all/phases.rb +12 -2
  30. data/mod/01_core/set/all/type.rb +5 -5
  31. data/mod/01_history/set/all/actions.rb +6 -2
  32. data/mod/01_history/set/all/content_history.rb +17 -2
  33. data/mod/01_history/set/all/history.rb +1 -1
  34. data/mod/02_basic_types/set/all/file.rb +0 -31
  35. data/mod/03_machines/lib/javascript/jquery.fileupload.js +539 -182
  36. data/mod/03_machines/lib/javascript/wagn.js.coffee +3 -0
  37. data/mod/03_machines/lib/javascript/wagn_mod.js.coffee +20 -18
  38. data/mod/03_machines/lib/stylesheets/style_cards.scss +28 -1
  39. data/mod/05_email/set/all/notify.rb +1 -1
  40. data/mod/05_standard/file/favicon/image-icon.png +0 -0
  41. data/mod/05_standard/file/favicon/image-large.png +0 -0
  42. data/mod/05_standard/file/favicon/image-medium.png +0 -0
  43. data/mod/05_standard/file/favicon/image-original.png +0 -0
  44. data/mod/05_standard/file/favicon/image-small.png +0 -0
  45. data/mod/05_standard/lib/carrier_wave/cardmount.rb +25 -6
  46. data/mod/05_standard/lib/file_uploader.rb +27 -11
  47. data/mod/05_standard/lib/image_uploader.rb +7 -4
  48. data/mod/05_standard/set/abstract/attachment.rb +132 -14
  49. data/mod/05_standard/set/right/account.rb +2 -2
  50. data/mod/05_standard/set/self/signin.rb +0 -1
  51. data/mod/05_standard/set/type/file.rb +48 -19
  52. data/mod/05_standard/set/type/image.rb +9 -12
  53. data/mod/05_standard/spec/chunk/include_spec.rb +13 -12
  54. data/mod/05_standard/spec/chunk/query_reference_spec.rb +50 -0
  55. data/mod/05_standard/spec/set/right/account_spec.rb +24 -25
  56. data/mod/05_standard/spec/set/type/file_spec.rb +1 -1
  57. data/spec/lib/card/reference_spec.rb +14 -0
  58. data/spec/lib/card/success_spec.rb +142 -0
  59. data/tmpsets/set/mod001-01_core/all/collection.rb +1 -1
  60. data/tmpsets/set/mod001-01_core/all/name.rb +2 -1
  61. data/tmpsets/set/mod001-01_core/all/phases.rb +12 -2
  62. data/tmpsets/set/mod001-01_core/all/type.rb +5 -5
  63. data/tmpsets/set/mod002-01_history/all/actions.rb +6 -2
  64. data/tmpsets/set/mod002-01_history/all/content_history.rb +17 -2
  65. data/tmpsets/set/mod002-01_history/all/history.rb +1 -1
  66. data/tmpsets/set/mod003-02_basic_types/all/file.rb +0 -24
  67. data/tmpsets/set/mod003-02_basic_types/all/rss.rb +8 -5
  68. data/tmpsets/set/mod003-02_basic_types/type/pointer.rb +2 -2
  69. data/tmpsets/set/mod005-04_settings/right/structure.rb +7 -2
  70. data/tmpsets/set/mod006-05_email/all/notify.rb +1 -1
  71. data/tmpsets/set/mod007-05_standard/abstract/attachment.rb +132 -14
  72. data/tmpsets/set/mod007-05_standard/all/links.rb +8 -0
  73. data/tmpsets/set/mod007-05_standard/all/rich_html/header.rb +5 -7
  74. data/tmpsets/set/mod007-05_standard/right/account.rb +2 -2
  75. data/tmpsets/set/mod007-05_standard/self/signin.rb +0 -1
  76. data/tmpsets/set/mod007-05_standard/type/file.rb +49 -20
  77. data/tmpsets/set/mod007-05_standard/type/image.rb +9 -12
  78. data/tmpsets/set/mod007-05_standard/type/search_type.rb +40 -22
  79. data/tmpsets/set/mod008-06_bootstrap/self/bootswatch_shared.rb +1 -1
  80. metadata +10 -4
@@ -0,0 +1,142 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ describe Card::Success do
4
+ let(:context) { Card['A'].cardname }
5
+ let(:previous) { '/B' }
6
+ let(:home) { Card['Home'] }
7
+ def success_params params
8
+ @success = Card::Success.new(context, params)
9
+ @success.stub(:previous_location) { previous }
10
+ end
11
+ describe '#target' do
12
+ subject { @success.target }
13
+
14
+ context 'initialized with nil' do
15
+ before do
16
+ success_params nil
17
+ end
18
+ it { is_expected.to eq Card['A'] }
19
+ end
20
+
21
+ context 'initialized with hash' do
22
+ before do
23
+ success_params :id=>home.id, :view=>'closed'
24
+ end
25
+ it { is_expected.to eq home}
26
+ end
27
+
28
+ context 'initialized with REDIRECT string' do
29
+ before do
30
+ success_params 'REDIRECT: Home'
31
+ end
32
+ it { is_expected.to eq home}
33
+ end
34
+
35
+ context 'initialized with TEXT string' do
36
+ before do
37
+ success_params 'TEXT: Hi'
38
+ end
39
+ it { is_expected.to eq 'Hi'}
40
+ end
41
+
42
+ context 'initialized with card object' do
43
+ before do
44
+ success_params home
45
+ end
46
+ it { is_expected.to eq home}
47
+ end
48
+
49
+ context 'initialized with url' do
50
+ before do
51
+ success_params 'http://wagn.org'
52
+ end
53
+ it { is_expected.to eq 'http://wagn.org'}
54
+ end
55
+ end
56
+
57
+ describe '#to_url' do
58
+ subject { @success.to_url}
59
+ context 'with params' do
60
+ context 'using initilization' do
61
+ before do
62
+ success_params :id=>home.id, :view=>'closed', :layout=>'my_layout'
63
+ end
64
+ it { is_expected.to eq '/Home?layout=my_layout&view=closed' }
65
+ end
66
+ context 'using array assignment' do
67
+ before do
68
+ success_params nil
69
+ @success[:view] = 'closed'
70
+ end
71
+ it { is_expected.to eq '/A?view=closed' }
72
+ end
73
+ context 'using assignment' do
74
+ before do
75
+ success_params nil
76
+ @success.view = 'closed'
77
+ end
78
+ it { is_expected.to eq '/A?view=closed' }
79
+ end
80
+ context 'using <<' do
81
+ before do
82
+ success_params nil
83
+ @success << { :card=>home, :view=>'closed'}
84
+ end
85
+ it { is_expected.to eq '/Home?view=closed' }
86
+ end
87
+ end
88
+ context 'redirect string' do
89
+ before do
90
+ success_params 'REDIRECT: *previous'
91
+ end
92
+ it { is_expected.to eq previous}
93
+ end
94
+ end
95
+
96
+ describe '#soft_redirect?' do
97
+ it 'returns true if soft_redirect parameter is true' do
98
+ success_params :soft_redirect=>true
99
+ expect(@success.soft_redirect?).to be_truthy
100
+ end
101
+ end
102
+
103
+ describe '#hard_redirect?' do
104
+ it 'true for "REDIRECT: anywhere"' do
105
+ success_params "REDIRECT: anywhere"
106
+ expect(@success.hard_redirect?).to be_truthy
107
+ end
108
+ end
109
+
110
+ describe '#mark=' do
111
+ subject { @success.target }
112
+ before do
113
+ success_params nil
114
+ end
115
+ it 'works with id' do
116
+ @success.mark = home.id
117
+ is_expected.to eq home
118
+ end
119
+ it 'works with name' do
120
+ @success.mark = home.name
121
+ is_expected.to eq home
122
+ end
123
+ it 'works with card object' do
124
+ @success.mark = home
125
+ is_expected.to eq home
126
+ end
127
+ end
128
+
129
+ describe 'params' do
130
+ it 'returns params hash' do
131
+ success_params :name=>'Home', :view=>'View'
132
+ @success.layout = 'Layout'
133
+ @success.apply :script => 'Script'
134
+ @success << {:structure => 'Structure'}
135
+ expect(@success.params.keys.sort).to eq [:layout, :script, :structure, :view]
136
+ end
137
+ it 'ignores "id", "name", "mark", "card"", target", and "redirect"' do
138
+ success_params :id=>5, :name=>'Home', :card=>Card['Home'], :mark=>'Home', :target=>'Home', :redirect=>false, :view=>'View'
139
+ expect(@success.params.keys).to eq [:view]
140
+ end
141
+ end
142
+ end
@@ -315,7 +315,7 @@ format :html do
315
315
  args[:tab_type] ||= 'tabs'
316
316
  end
317
317
 
318
- view :pills_static, :view=>:tabs
318
+ view :pills_static, :view=>:tabs_static
319
319
  def default_tabs_static_args args
320
320
  args[:tab_type] ||= 'pills'
321
321
  end
@@ -235,7 +235,7 @@ end
235
235
 
236
236
 
237
237
  event :cascade_name_changes, :after=>:store, :on=>:update, :changed=>:name do
238
- Rails.logger.debug "-------------------#{name_was}- CASCADE #{self.name} -------------------------------------"
238
+ #Rails.logger.info "------------------- #{name_was} CASCADE #{self.name} -------------------------------------"
239
239
 
240
240
  self.update_referencers = false if self.update_referencers == 'false' #handle strings from cgi
241
241
  Card::Reference.update_on_rename self, name, self.update_referencers
@@ -247,6 +247,7 @@ event :cascade_name_changes, :after=>:store, :on=>:update, :changed=>:name do
247
247
 
248
248
  deps.each do |dep|
249
249
  # here we specifically want NOT to invoke recursive cascades on these cards, have to go this low level to avoid callbacks.
250
+ Rails.logger.info "cascading name: #{dep.name}"
250
251
  Card.expire dep.name #old name
251
252
  newname = dep.cardname.replace_part name_was, name
252
253
  Card.where( :id=> dep.id ).update_all :name => newname.to_s, :key => newname.key
@@ -13,7 +13,7 @@ def abort status, msg='action canceled'
13
13
  if status == :failure && errors.empty?
14
14
  errors.add :abort, msg
15
15
  elsif Hash === status and status[:success]
16
- Env.params[:success] = status[:success]
16
+ success << status[:success]
17
17
  status = :success
18
18
  end
19
19
  raise Card::Abort.new( status, msg)
@@ -51,11 +51,18 @@ end
51
51
  # perhaps above should be in separate module?
52
52
  #~~~~~~
53
53
 
54
- def approve
54
+ def prepare
55
55
  @action = identify_action
56
56
  # the following should really happen when type, name etc are changed
57
57
  reset_patterns
58
58
  include_set_modules
59
+ run_callbacks :prepare
60
+ rescue =>e
61
+ rescue_event e
62
+ end
63
+
64
+ def approve
65
+ @action ||= identify_action
59
66
  run_callbacks :approve
60
67
  expire_pieces if errors.any?
61
68
  errors.empty?
@@ -180,6 +187,9 @@ event :store_subcards, :after=>:store do
180
187
  end
181
188
  end
182
189
 
190
+ def success
191
+ Env[:success] ||= Card::Success.new(cardname)
192
+ end
183
193
 
184
194
 
185
195
 
@@ -30,7 +30,7 @@ end
30
30
 
31
31
  def get_type_id args={}
32
32
  return if args[:type_id] # type_id was set explicitly. no need to set again.
33
-
33
+
34
34
  type_id = case
35
35
  when args[:type_code]
36
36
  if code=args[:type_code]
@@ -62,11 +62,11 @@ event :validate_type_change, :before=>:approve, :on=>:update, :changed=>:type_id
62
62
  end
63
63
  end
64
64
 
65
- event :validate_type, :before=>:approve, :changed=>:type_id do
65
+ event :validate_type, :before=>:approve, :changed=>:type_id do
66
66
  if !type_name
67
67
  errors.add :type, "No such type"
68
68
  end
69
-
69
+
70
70
  if rt = structure and rt.assigns_type? and type_id!=rt.type_id
71
71
  errors.add :type, "can't be changed because #{name} is hard templated to #{rt.type_name}"
72
72
  end
@@ -74,7 +74,7 @@ end
74
74
 
75
75
  event :reset_type_specific_fields, :after=>:store do
76
76
  Auth.as_bot do
77
- Card.search :left=>{ :left=>type_name }, :right=>{:codename=>'type_plus_right'} do |set_card|
77
+ Card.search :left=>{ :left_id=>type_id }, :right=>{:codename=>'type_plus_right'} do |set_card|
78
78
  set_card.reset_set_patterns
79
79
  end
80
80
  end
@@ -84,7 +84,7 @@ end
84
84
  # Card["#{lef}"]
85
85
  # set_card.reset_set_patterns
86
86
  # end
87
-
87
+
88
88
 
89
89
 
90
90
  # ~~~~~~~~~~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/01_core/set/all/type.rb ~~~~~~~~~~~
@@ -3,13 +3,17 @@ class Card; module Set; module All; module Actions; extend Card::Set # ~~~~~~~~~
3
3
  # -*- encoding : utf-8 -*-
4
4
 
5
5
  def select_action_by_params params
6
- action = find_action_by_params(params) and self.selected_action_id = action.id
6
+ if (action = find_action_by_params(params))
7
+ run_callbacks :select_action do
8
+ self.selected_action_id = action.id
9
+ end
10
+ end
7
11
  end
8
12
 
9
13
  def find_action_by_params args
10
14
  if args[:rev]
11
15
  nth_action args[:rev]
12
- elsif args[:rev_id] =~ /^\d+$/
16
+ elsif Integer === args[:rev_id] || args[:rev_id] =~ /^\d+$/
13
17
  if action = Action.fetch(args[:rev_id]) and action.card_id == id
14
18
  action
15
19
  end
@@ -6,7 +6,7 @@ class Card; module Set; module All; module ContentHistory; extend Card::Set # ~~
6
6
  def content
7
7
  if @selected_action_id
8
8
  @selected_content ||= begin
9
- (change = last_change_on( :db_content, :not_after=> @selected_action_id ) and change.value) || db_content
9
+ (change = last_change_on( :db_content, :not_after=> @selected_action_id, :including_drafts=>true ) and change.value) || db_content
10
10
  end
11
11
  else
12
12
  super
@@ -26,7 +26,10 @@ def save_content_draft content
26
26
  end
27
27
 
28
28
  def last_change_on(field, opts={})
29
- where_sql = 'card_actions.card_id = :card_id AND field = :field AND (draft is not true) '
29
+ where_sql = 'card_actions.card_id = :card_id AND field = :field '
30
+ if !opts[:including_drafts]
31
+ where_sql += 'AND (draft is not true) '
32
+ end
30
33
  where_sql += if opts[:before]
31
34
  'AND card_action_id < :action_id'
32
35
  elsif opts[:not_after]
@@ -56,6 +59,18 @@ def selected_action
56
59
  selected_action_id and Action.fetch(selected_action_id)
57
60
  end
58
61
 
62
+ def with_selected_action_id action_id
63
+ current_action_id = @selected_action_id
64
+ run_callbacks :select_action do
65
+ self.selected_action_id = action_id
66
+ end
67
+ result = yield
68
+ run_callbacks :select_action do
69
+ self.selected_action_id = current_action_id
70
+ end
71
+ result
72
+ end
73
+
59
74
  def selected_content_action_id
60
75
  @selected_action_id ||
61
76
  (@current_action && (new_card? || @current_action.new_content? || db_content_changed?) && @current_action.id) ||
@@ -7,7 +7,7 @@ def history?
7
7
  end
8
8
 
9
9
  # must be called on all actions and before :set_name, :process_subcards and :validate_delete_children
10
- event :assign_act, :before=>:approve, :when=>proc {|c| c.history?} do
10
+ event :assign_act, :before=>:prepare, :when=>proc {|c| c.history?} do
11
11
  @current_act = (@supercard && @supercard.current_act) || Card::Act.create(:ip_address=>Env.ip)
12
12
  end
13
13
 
@@ -1,29 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  class Card; module Set; module All; module File; extend Card::Set # ~~~~~~~~~~~ above autogenerated; below pulled from /Users/ethan/dev/wagn/gem/card/mod/02_basic_types/set/all/file.rb ~~~~~~~~~~~
3
- # FIXME: these methods should move to type/file.rb but some machine stuff is failing if it's not in a "all" set
4
- def store_dir
5
- if (mod = mod_file?)
6
- "#{ Cardio.gem_root}/mod/#{mod}/file/#{codename}"
7
- elsif id
8
- "#{ Card.paths['files'].existent.first }/#{id}"
9
- else
10
- tmp_store_dir
11
- end
12
- end
13
-
14
- def tmp_store_dir
15
- "#{ Card.paths['files'].existent.first }/#{key}"
16
- end
17
-
18
- def mod_file?
19
- # when db_content was changed assume that it's no longer a mod file
20
- if !db_content_changed? && content.present? && content =~ /^:[^\/]+\/([^.]+)/
21
- $1
22
- end
23
- end
24
-
25
-
26
-
27
3
  format :file do
28
4
 
29
5
  view :core do |args|
@@ -8,11 +8,10 @@ format :rss do
8
8
 
9
9
  def initialize card, args
10
10
  super
11
- @xml = @parent.xml if @parent
11
+ @xml = @parent ? @parent.xml : ::Builder::XmlMarkup.new
12
12
  end
13
13
 
14
14
  def show view, args
15
- @xml = ::Builder::XmlMarkup.new
16
15
  view ||= :feed
17
16
  render view, args
18
17
  end
@@ -26,7 +25,7 @@ format :rss do
26
25
  @xml.title render_feed_title
27
26
  @xml.description render_feed_description
28
27
  @xml.link render_url
29
- render_feed_item_list
28
+ render_feed_body
30
29
  end
31
30
  end
32
31
  rescue =>e
@@ -34,12 +33,16 @@ format :rss do
34
33
  end
35
34
  end
36
35
 
37
- def raw_feed_items
36
+ def raw_feed_items args
38
37
  [card]
39
38
  end
40
39
 
40
+ view :feed_body do |args|
41
+ render_feed_item_list
42
+ end
43
+
41
44
  view :feed_item_list do |args|
42
- raw_feed_items.each do |item|
45
+ raw_feed_items(args).each do |item|
43
46
  @xml.item do
44
47
  subformat(item).render_feed_item :view_changes=>(card.id==RecentID) #FIXME! yuck.
45
48
  end
@@ -187,7 +187,7 @@ format :css do
187
187
 
188
188
  view :core do |args|
189
189
  card.item_cards.map do |item|
190
- nest item, :view=>(params[:item] || args[:item] || :content)
190
+ nest item, :view=>(args[:item] || :content)
191
191
  end.join "\n\n"
192
192
  end
193
193
 
@@ -199,7 +199,7 @@ end
199
199
  format :js do
200
200
  view :core do |args|
201
201
  card.item_cards.map do |item|
202
- nest item, :view=>(params[:item] || args[:item] || :core)
202
+ nest item, :view=>( args[:item] || :core)
203
203
  end.join "\n\n"
204
204
  end
205
205
  end
@@ -2,13 +2,18 @@
2
2
  class Card; module Set; module Right; module Structure; extend Card::Set # ~~~~~~~~~~~ above autogenerated; below pulled from /Users/ethan/dev/wagn/gem/card/mod/04_settings/set/right/structure.rb ~~~~~~~~~~~
3
3
 
4
4
  format :rss do
5
- def raw_feed_items
5
+ def raw_feed_items args
6
6
  [card]
7
- end
7
+ end
8
8
  end
9
9
 
10
10
  format :html do
11
11
  include AddHelp::HtmlFormat
12
+
13
+ view :core do |args|
14
+ render_raw args
15
+ end
16
+
12
17
  end
13
18
 
14
19
 
@@ -65,7 +65,7 @@ def followable?
65
65
  end
66
66
 
67
67
  def notable_change?
68
- !supercard && current_act && Card::Auth.current_id != WagnBotID && followable?
68
+ !silent_change && !supercard && current_act && Card::Auth.current_id != WagnBotID && followable?
69
69
  end
70
70
 
71
71
  event :notify_followers_after_save, :after=>:subsequent, :on=>:save, :when=>proc{ |ca| ca.notable_change? } do
@@ -1,34 +1,87 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  class Card; module Set; module Abstract; module Attachment; extend Card::Set # ~~~~~~~~~~~ above autogenerated; below pulled from /Users/ethan/dev/wagn/gem/card/mod/05_standard/set/abstract/attachment.rb ~~~~~~~~~~~
3
3
  require 'carrier_wave/cardmount'
4
+
4
5
  def self.included host_class
5
6
  host_class.extend CarrierWave::CardMount
6
7
  end
7
8
 
9
+ event :select_file_revision, :after=>:select_action do
10
+ attachment.retrieve_from_store!(attachment.identifier)
11
+ end
8
12
 
9
- event :write_identifier, :after=>:assign_action do
10
- self.content = attachment.db_content
13
+ event :determine_store_place, :before=>:prepare, :on=>:update do
14
+ @store_place = load_from_mod || :deck
11
15
  end
12
16
 
13
- event :save_original_filename, :before=>:finalize_action do
14
- if @current_action
15
- @current_action.update_attributes! :comment=>original_filename
17
+ event :upload_attachment, :before=>:validate_name, :on=>:save, :when=>proc { |c| c.preliminary_upload? } do
18
+ save_original_filename # save original filename as comment in action
19
+ write_identifier # set db_content (needs original filename to determine extension)
20
+ store_attachment!
21
+ finalize_action # create Card::Change entry for db_content
22
+ @current_action.update_attributes! :draft => true, :card_id => (new_card? ? upload_cache_card.id : id)
23
+
24
+ success << {
25
+ :target => (new_card? ? upload_cache_card : '_self'),
26
+ :type=> type_name,
27
+ :view => 'preview_editor',
28
+ :rev_id => current_action.id
29
+ }
30
+ abort :success
31
+ end
32
+
33
+ event :assign_attachment_on_create, :after=>:prepare, :on=>:create do
34
+ if save_preliminary_upload? && (action = Card::Action.fetch(Card::Env.params[:cached_upload]))
35
+ upload_cache_card.selected_action_id = action.id
36
+ upload_cache_card.select_file_revision
37
+ assign_attachment upload_cache_card.attachment.file, action.comment
38
+ action.delete # TODO: delete files too
16
39
  end
17
40
  end
18
41
 
19
- event :move_file_to_store_dir, :after=>:store, :on=>:create do
20
- if ::File.exist? tmp_store_dir
21
- if ::File.exist? store_dir
22
- FileUtils.rm_rf store_dir
23
- end
24
- FileUtils.mv tmp_store_dir, store_dir
42
+ event :assign_attachment_on_update, :after=>:prepare, :on=>:update do
43
+ if save_preliminary_upload? && (action = Card::Action.fetch(Card::Env.params[:cached_upload]))
44
+ uploaded_file =
45
+ with_selected_action_id(action.id) do
46
+ attachment.file
47
+ end
48
+ assign_attachment uploaded_file, action.comment
49
+ action.delete
25
50
  end
26
- if !(content =~ /^[:~]/)
27
- update_column(:db_content,attachment.db_content)
28
- expire
51
+ end
52
+
53
+ def assign_attachment file, original_filename
54
+ send "#{attachment_name}=", file
55
+ write_identifier
56
+ @current_action.update_attributes! :comment=>original_filename
57
+ end
58
+
59
+ # we need a card id for the path so we have to update db_content when we got an id
60
+ event :correct_identifier, :after=>:store, :on=>:create do
61
+ update_column(:db_content,attachment.db_content(:mod=>load_from_mod))
62
+ expire
63
+ end
64
+
65
+
66
+ event :save_original_filename, :after=>:validate_name, :when => proc {|c| !c.preliminary_upload? && !c.save_preliminary_upload? && c.attachment_changed?} do
67
+ if @current_action
68
+ @current_action.update_attributes! :comment=>original_filename
29
69
  end
30
70
  end
31
71
 
72
+ event :write_identifier, :after=>:save_original_filename do
73
+ self.content = attachment.db_content(:mod=>load_from_mod)
74
+ end
75
+
76
+
77
+ def upload_cache_card
78
+ @upload_cache_card ||= Card["new_#{attachment_name}".to_sym ]
79
+ end
80
+
81
+ def tmp_store_dir action_id=nil
82
+ "#{ Card.paths['files'].existent.first }/#{upload_cache_card.id}"
83
+ end
84
+
32
85
  def item_names(args={}) # needed for flexmail attachments. hacky.
33
86
  [self.cardname]
34
87
  end
@@ -37,6 +90,60 @@ def original_filename
37
90
  attachment.original_filename
38
91
  end
39
92
 
93
+ def preliminary_upload?
94
+ Card::Env && Card::Env.params[:attachment_upload]
95
+ end
96
+
97
+ def save_preliminary_upload?
98
+ Card::Env.params[:cached_upload].present?
99
+ end
100
+
101
+ def attachment_changed?
102
+ send "#{attachment_name}_changed?"
103
+ end
104
+
105
+ def create_versions?
106
+ true
107
+ end
108
+
109
+ def store_place
110
+ @store_place ||= mod_file? || :deck
111
+ end
112
+
113
+ def load_from_mod= value
114
+ @mod = value
115
+ end
116
+
117
+ def load_from_mod
118
+ @mod
119
+ end
120
+
121
+ def store_dir
122
+ if (store_place == :deck)
123
+ if id
124
+ "#{ Card.paths['files'].existent.first }/#{id}"
125
+ else
126
+ tmp_store_dir
127
+ end
128
+ else
129
+ "#{ Cardio.gem_root}/mod/#{store_place}/file/#{codename}"
130
+ end
131
+ end
132
+
133
+ def mod_file?
134
+ # when db_content was changed assume that it's no longer a mod file
135
+ if @store_place != :deck && !db_content_changed? && content.present?
136
+ case content
137
+ when /^:[^\/]+\/([^.]+)/ ; $1 # current mod_file format
138
+ when /^\~/ ; false # current id file format
139
+ else
140
+ if lines = content.split("\n") and lines.size == 4 # old format, still used in card_changes.
141
+ lines.last
142
+ end
143
+ end
144
+ end
145
+ end
146
+
40
147
 
41
148
  def assign_set_specific_attributes
42
149
  if @set_specific && @set_specific.present?
@@ -45,6 +152,17 @@ def assign_set_specific_attributes
45
152
  super
46
153
  end
47
154
 
155
+ def clear_upload_tmp_dir
156
+ Dir.entries(tmp_store_dir).each do |filename|
157
+ if filename =~/^\d+/
158
+ path = File.join(tmp_store_dir, filename )
159
+ older_than_five_days = ( DateTime.now - File.ctime(path) > 432000)
160
+ if older_than_five_days
161
+ FileUtils.rm path
162
+ end
163
+ end
164
+ end
165
+ end
48
166
 
49
167
  def symlink_to(prior_action_id) # create filesystem links to files from prior action
50
168
  if prior_action_id != last_action_id