card 1.20.0 → 1.20.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/card.gemspec +1 -1
- data/lib/card.rb +7 -3
- data/lib/card/act_manager/stage_director.rb +22 -10
- data/lib/card/cache/persistent.rb +15 -9
- data/lib/card/format/nest.rb +12 -5
- data/lib/card/format/nest/fetch.rb +2 -1
- data/lib/card/format/render.rb +5 -2
- data/lib/card/set/event.rb +7 -1
- data/lib/card/subcards.rb +3 -3
- data/lib/card/view/cache.rb +1 -1
- data/lib/card/view/fetch.rb +17 -5
- data/lib/card/view/options.rb +52 -26
- data/lib/cardio.rb +2 -1
- data/mod/account/spec/set/right/account_spec.rb +17 -3
- data/mod/admin/set/self/admin.rb +0 -2
- data/mod/admin/spec/set/self/admin_spec.rb +14 -11
- data/mod/bootstrap/set/all/bootstrap/helper.rb +27 -29
- data/mod/carrierwave/set/type/file.rb +1 -1
- data/mod/carrierwave/set/type/image.rb +18 -6
- data/mod/core/set/all/collection.rb +33 -7
- data/mod/core/set/all/fetch.rb +16 -3
- data/mod/core/set/all/permissions.rb +6 -12
- data/mod/core/set/all/trash.rb +3 -1
- data/mod/core/spec/set/all/collection_spec.rb +9 -8
- data/mod/email/set/all/notify.rb +27 -17
- data/mod/email/set/right/follow.rb +49 -36
- data/mod/email/set/type/email_template.rb +25 -69
- data/mod/email/set/type/email_template/email_config.rb +63 -0
- data/mod/email/set/type_plus_right/user/follow.rb +3 -3
- data/mod/machines/lib/stylesheets/style_cards.scss +292 -0
- data/mod/pointer/set/abstract/01_pointer.rb +8 -8
- data/mod/pointer/set/abstract/01_pointer/edit.rb +6 -2
- data/mod/prosemirror_editor/lib/javascript/script_prosemirror.js +12283 -11605
- data/mod/prosemirror_editor/lib/javascript/script_prosemirror_config.js.coffee +1 -1
- data/mod/standard/set/abstract/01_search_params.rb +1 -1
- data/mod/standard/set/abstract/search/paging.rb +4 -4
- data/mod/standard/set/all/comment.rb +67 -47
- data/mod/standard/set/all/links.rb +2 -2
- data/mod/standard/set/all/rich_html/content.rb +1 -1
- data/mod/standard/set/all/rich_html/editing.rb +3 -2
- data/mod/standard/set/all/rich_html/form.rb +21 -12
- data/mod/standard/set/all/rich_html/header.rb +9 -0
- data/mod/standard/set/all/rich_html/menu.rb +16 -12
- data/mod/standard/set/all/rich_html/toolbar.rb +140 -130
- data/mod/standard/set/all/rich_html/wrapper.rb +11 -1
- data/mod/standard/set/rstar/rules_editor.rb +2 -34
- data/mod/standard/set/self/search.rb +1 -1
- data/mod/standard/set/type/set.rb +4 -4
- data/mod/standard/spec/set/type/email_template/email_config_spec.rb +218 -0
- data/mod/standard/spec/set/type/email_template_spec.rb +3 -185
- data/spec/lib/card/cache_spec.rb +0 -1
- data/spec/lib/card/format/render_spec.rb +19 -0
- data/spec/lib/card/stage_director_spec.rb +1 -1
- data/tmpsets/set/mod001-core/all/actify.rb +5 -6
- data/tmpsets/set/mod001-core/all/fetch.rb +14 -12
- data/tmpsets/set/mod001-core/all/name.rb +1 -1
- data/tmpsets/set/mod001-core/all/permissions.rb +12 -22
- data/tmpsets/set/mod001-core/all/tracked_attributes.rb +76 -0
- data/tmpsets/set/mod001-core/all/utils.rb +40 -3
- data/tmpsets/set/mod002-history/all/history.rb +1 -2
- data/tmpsets/set/mod008-solid_cache/abstract/solid_cache.rb +1 -1
- data/tmpsets/set/mod013-carrierwave/abstract/attachment.rb +282 -0
- data/tmpsets/set/mod013-carrierwave/type/file.rb +155 -0
- data/tmpsets/set/mod013-carrierwave/type/image.rb +96 -0
- data/tmpsets/set/mod014-admin/self/admin.rb +113 -0
- data/tmpsets/set/mod014-admin/self/admin_info.rb +110 -0
- data/tmpsets/set/mod014-admin/self/version.rb +15 -0
- data/tmpsets/set/mod015-developer/all/event_viz.rb +59 -0
- data/tmpsets/set/mod015-developer/all/view_viz.rb +30 -0
- data/tmpsets/set/mod015-developer/right/debug.rb +96 -0
- metadata +15 -2
data/spec/lib/card/cache_spec.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
describe Card::Format::Render do
|
2
|
+
describe "view cache" do
|
3
|
+
before { Cardio.config.view_cache = true }
|
4
|
+
|
5
|
+
let(:cache_key) do
|
6
|
+
"a-Card::Format::HtmlFormat-normal-home_view:content;"\
|
7
|
+
"nest_name:A;nest_syntax:A|content;view:contentcontent:show"
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { Card::Cache[Card::View] }
|
11
|
+
|
12
|
+
it "can be changed with nest option" do
|
13
|
+
is_expected.to receive(:fetch).with cache_key
|
14
|
+
render_content "{{A|content}}"
|
15
|
+
is_expected.not_to receive(:fetch)
|
16
|
+
render_content "{{A|cache:never}}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -52,12 +52,12 @@ def valid?(*)
|
|
52
52
|
act { super }
|
53
53
|
end
|
54
54
|
|
55
|
-
def update_attributes
|
56
|
-
act
|
55
|
+
def update_attributes(*)
|
56
|
+
act { super }
|
57
57
|
end
|
58
58
|
|
59
|
-
def update_attributes!
|
60
|
-
act
|
59
|
+
def update_attributes!(*)
|
60
|
+
act { super }
|
61
61
|
end
|
62
62
|
|
63
63
|
def abortable
|
@@ -88,8 +88,7 @@ def with_transaction_returning_status
|
|
88
88
|
end
|
89
89
|
|
90
90
|
event :notable_exception_raised do
|
91
|
-
|
92
|
-
Rails.logger.debug "#{error.message}\n#{error.backtrace * "\n "}"
|
91
|
+
Rails.logger.debug "BT: #{Card::Error.current.backtrace * "\n "}"
|
93
92
|
end
|
94
93
|
|
95
94
|
def success
|
@@ -11,18 +11,20 @@ module ClassMethods
|
|
11
11
|
# * database
|
12
12
|
# * virtual cards
|
13
13
|
#
|
14
|
-
# @param
|
15
|
-
# one
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# If you pass more then one mark they get
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
14
|
+
# @param mark [Integer, String, Card::Name, Symbol, Array]
|
15
|
+
# one of three unique identifiers
|
16
|
+
# 1. a numeric id (Integer)
|
17
|
+
# 2. a name/key (String or Card::Name)
|
18
|
+
# 3. a codename (Symbol)
|
19
|
+
# or any combination of those. If you pass more then one mark they get
|
20
|
+
# joined with a '+'
|
21
|
+
# @param options [Hash]
|
22
|
+
# Options:
|
23
|
+
# :skip_virtual Real cards only
|
24
|
+
# :skip_modules Don't load Set modules
|
25
|
+
# :look_in_trash Return trashed card objects
|
26
|
+
# :local_only Use only local cache for lookup and storing
|
27
|
+
# new: { opts for Card#new } Return a new card when not found
|
26
28
|
#
|
27
29
|
# @return [Card]
|
28
30
|
def fetch *args
|
@@ -56,11 +56,11 @@ def update_subcard_names cardname
|
|
56
56
|
# and self is a subcard as well that changed from +B to A+B then
|
57
57
|
# +C should change to A+B+C. #replace_part doesn't work in this case
|
58
58
|
# because the old name +B is not a part of +C
|
59
|
+
# name_to_replace =
|
59
60
|
name_to_replace =
|
60
61
|
if subcard.cardname.junction? &&
|
61
62
|
subcard.cardname.parts.first.empty? &&
|
62
63
|
cardname.parts.first.present?
|
63
|
-
# replace the empty part
|
64
64
|
"".to_name
|
65
65
|
else
|
66
66
|
name
|
@@ -187,38 +187,28 @@ event :set_field_read_rules,
|
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
190
|
-
|
191
|
-
|
192
|
-
|
190
|
+
def update_read_rule
|
191
|
+
Card.record_timestamps = false
|
192
|
+
reset_patterns # why is this needed?
|
193
|
+
rcard_id, rclass = permission_rule_id_and_class :read
|
194
|
+
# these two are just to make sure vals are correct on current object
|
195
|
+
self.read_rule_id = rcard_id
|
196
|
+
self.read_rule_class = rclass
|
197
|
+
Card.where(id: id).update_all read_rule_id: rcard_id, read_rule_class: rclass
|
198
|
+
expire_hard
|
199
|
+
|
200
|
+
# currently doing a brute force search for every card that may be impacted.
|
201
|
+
# may want to optimize(?)
|
193
202
|
Auth.as_bot do
|
194
203
|
fields.each do |field|
|
195
204
|
field.update_read_rule if field.rule(:read) == "_left"
|
196
205
|
end
|
197
206
|
end
|
198
|
-
end
|
199
207
|
|
200
|
-
def without_timestamps
|
201
|
-
Card.record_timestamps = false
|
202
|
-
yield
|
203
208
|
ensure
|
204
209
|
Card.record_timestamps = true
|
205
210
|
end
|
206
211
|
|
207
|
-
event :update_read_rule do
|
208
|
-
without_timestamps do
|
209
|
-
reset_patterns # why is this needed?
|
210
|
-
rcard_id, rclass = permission_rule_id_and_class :read
|
211
|
-
# these two are just to make sure vals are correct on current object
|
212
|
-
self.read_rule_id = rcard_id
|
213
|
-
self.read_rule_class = rclass
|
214
|
-
Card.where(id: id).update_all read_rule_id: rcard_id,
|
215
|
-
read_rule_class: rclass
|
216
|
-
expire_hard
|
217
|
-
|
218
|
-
update_field_read_rules
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
212
|
def add_to_read_rule_update_queue updates
|
223
213
|
@read_rule_update_queue = Array.wrap(@read_rule_update_queue).concat updates
|
224
214
|
end
|
@@ -73,6 +73,82 @@ event :set_content, :store, on: :save do
|
|
73
73
|
reset_patterns_if_rule true
|
74
74
|
end
|
75
75
|
|
76
|
+
# FIXME: the following don't really belong here, but they have to come after
|
77
|
+
# the reference stuff. we need to organize a bit!
|
78
|
+
|
79
|
+
event :update_ruled_cards, :finalize do
|
80
|
+
if is_rule?
|
81
|
+
# warn "updating ruled cards for #{name}"
|
82
|
+
self.class.clear_rule_cache
|
83
|
+
set = rule_set
|
84
|
+
|
85
|
+
if right_id == Card::ReadID && (name_changed? || trash_changed?)
|
86
|
+
update_read_ruled_cards set
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def update_read_rules_of_set_members_not_governed_by_narrower_rules set
|
92
|
+
return {} if trash || !set || !(set_class = set.tag) ||
|
93
|
+
!(class_id = set_class.id)
|
94
|
+
in_set = {}
|
95
|
+
rule_class_ids = set_patterns.map(&:pattern_id)
|
96
|
+
Auth.as_bot do
|
97
|
+
cur_index = rule_class_ids.index Card[read_rule_class].id
|
98
|
+
if (rule_class_index = rule_class_ids.index(class_id))
|
99
|
+
set.item_cards(limit: 0).each do |item_card|
|
100
|
+
in_set[item_card.key] = true
|
101
|
+
next if cur_index < rule_class_index
|
102
|
+
item_card.update_read_rule if cur_index >= rule_class_index
|
103
|
+
end
|
104
|
+
else
|
105
|
+
warn "No current rule index #{class_id}, #{rule_class_ids.inspect}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
in_set
|
109
|
+
end
|
110
|
+
|
111
|
+
def update_read_ruled_cards set
|
112
|
+
self.class.clear_read_rule_cache
|
113
|
+
Card.cache.reset # maybe be more surgical, just Auth.user related
|
114
|
+
expire # probably shouldn't be necessary,
|
115
|
+
# but was sometimes getting cached version when card should be in the
|
116
|
+
# trash. could be related to other bugs?
|
117
|
+
|
118
|
+
updated = update_read_rules_of_set_members_not_governed_by_narrower_rules set
|
119
|
+
|
120
|
+
# then find all cards with me as read_rule_id that were not just updated
|
121
|
+
# and regenerate their read_rules
|
122
|
+
return if new_card?
|
123
|
+
Card.search(read_rule_id: id) do |card|
|
124
|
+
card.update_read_rule unless updated[card.key]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
event :process_read_rule_update_queue, :finalize do
|
129
|
+
Array.wrap(@read_rule_update_queue).each(&:update_read_rule)
|
130
|
+
@read_rule_update_queue = []
|
131
|
+
end
|
132
|
+
|
133
|
+
event :expire_related, :finalize do
|
134
|
+
subcards.keys.each do |key|
|
135
|
+
Card.cache.soft.delete key
|
136
|
+
end
|
137
|
+
expire # FIXME: where do we put this. Here it deletes @stage
|
138
|
+
reset_patterns
|
139
|
+
if is_structure?
|
140
|
+
structuree_names.each do |name|
|
141
|
+
Card.expire name
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
event :expire_related_names, before: :expire_related, changed: :name do
|
147
|
+
# FIXME: look for opportunities to avoid instantiating the following
|
148
|
+
descendants.each(&:expire)
|
149
|
+
name_referers.each(&:expire)
|
150
|
+
end
|
151
|
+
|
76
152
|
|
77
153
|
# ~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/core/set/all/tracked_attributes.rb ~~
|
78
154
|
end;end;end;end;
|
@@ -8,6 +8,7 @@ module ClassMethods
|
|
8
8
|
Card::Action.delete_cardless
|
9
9
|
Card::Reference.unmap_if_referee_missing
|
10
10
|
Card::Reference.delete_if_referer_missing
|
11
|
+
Card.delete_tmp_files_of_cached_uploads
|
11
12
|
end
|
12
13
|
|
13
14
|
# deletes any file not associated with a real card.
|
@@ -43,6 +44,20 @@ module ClassMethods
|
|
43
44
|
sql_results.map(&:values).flatten.map(&:to_i)
|
44
45
|
end
|
45
46
|
|
47
|
+
def delete_tmp_files_of_cached_uploads
|
48
|
+
actions = Card::Action.find_by_sql "SELECT * FROM card_actions
|
49
|
+
INNER JOIN cards ON card_actions.card_id = cards.id
|
50
|
+
WHERE cards.type_id IN (#{Card::FileID}, #{Card::ImageID})
|
51
|
+
AND card_actions.draft = true"
|
52
|
+
actions.each do |action|
|
53
|
+
# we don't want to delete uploads in progress
|
54
|
+
if older_than_five_days?(action.created_at) && (card = action.card)
|
55
|
+
# we don't want to delete uploads in progress
|
56
|
+
card.delete_files_for_action action
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
46
61
|
def merge_list attribs, opts={}
|
47
62
|
unmerged = []
|
48
63
|
attribs.each do |row|
|
@@ -72,7 +87,7 @@ module ClassMethods
|
|
72
87
|
end
|
73
88
|
|
74
89
|
def merge name, attribs={}, opts={}
|
75
|
-
puts "merging #{name}"
|
90
|
+
# puts "merging #{name}"
|
76
91
|
card = fetch name, new: {}
|
77
92
|
[:image, :file].each do |attach|
|
78
93
|
next unless attribs[attach] && attribs[attach].is_a?(String)
|
@@ -85,11 +100,33 @@ module ClassMethods
|
|
85
100
|
end
|
86
101
|
end
|
87
102
|
|
88
|
-
def
|
89
|
-
|
103
|
+
def older_than_five_days? time
|
104
|
+
Time.now - time > 432_000
|
90
105
|
end
|
91
106
|
end
|
92
107
|
|
108
|
+
def debug_type
|
109
|
+
"#{type_code || ''}:#{type_id}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_s
|
113
|
+
"#<#{self.class.name}[#{debug_type}]#{attributes['name']}>"
|
114
|
+
end
|
115
|
+
|
116
|
+
def inspect
|
117
|
+
tags = []
|
118
|
+
tags << "trash" if trash
|
119
|
+
tags << "new" if new_card?
|
120
|
+
tags << "frozen" if frozen?
|
121
|
+
tags << "readonly" if readonly?
|
122
|
+
tags << "virtual" if @virtual
|
123
|
+
tags << "set_mods_loaded" if @set_mods_loaded
|
124
|
+
|
125
|
+
error_messages = errors.any? ? "<E*#{errors.full_messages * ', '}*>" : ""
|
126
|
+
|
127
|
+
"#<Card##{id}[#{debug_type}](#{name})#{error_messages}{#{tags * ','}}"
|
128
|
+
end
|
129
|
+
|
93
130
|
|
94
131
|
# ~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/core/set/all/utils.rb ~~
|
95
132
|
end;end;end;end;
|
@@ -85,8 +85,7 @@ event :rollback_actions, :prepare_to_validate,
|
|
85
85
|
Env.params["action_ids"] = nil
|
86
86
|
update_attributes! revision
|
87
87
|
rollback_actions.each do |action|
|
88
|
-
|
89
|
-
action.card.try :rollback_to, action
|
88
|
+
action.card.try :symlink_to, action.id
|
90
89
|
end
|
91
90
|
clear_drafts
|
92
91
|
abort :success
|
@@ -31,7 +31,7 @@ module ClassMethods
|
|
31
31
|
# cards whose solid caches are expired because of the update.
|
32
32
|
# @param set_of_changed_card [set constant] a set of cards that triggers
|
33
33
|
# a cache update
|
34
|
-
# @
|
34
|
+
# @params args [Hash]
|
35
35
|
# @option args [Symbol, Array of symbols] :on the action(s)
|
36
36
|
# (:create, :update, or :delete) on which the cache update
|
37
37
|
# should be triggered. Default is all actions.
|
@@ -0,0 +1,282 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
class Card; module Set; class Abstract; module Attachment; extend Card::Set
|
3
|
+
# ~~ above autogenerated; below pulled from /Users/ethan/dev/wagn/gem/card/mod/carrierwave/set/abstract/attachment.rb ~~
|
4
|
+
require "carrier_wave/cardmount"
|
5
|
+
|
6
|
+
def self.included host_class
|
7
|
+
host_class.extend CarrierWave::CardMount
|
8
|
+
end
|
9
|
+
|
10
|
+
event :select_file_revision, after: :select_action do
|
11
|
+
attachment.retrieve_from_store!(attachment.identifier)
|
12
|
+
end
|
13
|
+
|
14
|
+
event :upload_attachment, :prepare_to_validate,
|
15
|
+
on: :save, when: proc { |c| c.preliminary_upload? } do
|
16
|
+
save_original_filename # save original filename as comment in action
|
17
|
+
write_identifier # set db_content
|
18
|
+
# (needs original filename to determine extension)
|
19
|
+
store_attachment!
|
20
|
+
finalize_action # create Card::Change entry for db_content
|
21
|
+
|
22
|
+
card_id = new_card? ? upload_cache_card.id : id
|
23
|
+
@current_action.update_attributes! draft: true, card_id: card_id
|
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, :initialize,
|
34
|
+
after: :assign_action, on: :create,
|
35
|
+
when: proc { |c| c.save_preliminary_upload? } do
|
36
|
+
if (action = Card::Action.fetch(@action_id_of_cached_upload))
|
37
|
+
upload_cache_card.selected_action_id = action.id
|
38
|
+
upload_cache_card.select_file_revision
|
39
|
+
assign_attachment upload_cache_card.attachment.file, action.comment
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
event :assign_attachment_on_update, :initialize,
|
44
|
+
after: :assign_action, on: :update,
|
45
|
+
when: proc { |c| c.save_preliminary_upload? } do
|
46
|
+
if (action = Card::Action.fetch(@action_id_of_cached_upload))
|
47
|
+
uploaded_file =
|
48
|
+
with_selected_action_id(action.id) do
|
49
|
+
attachment.file
|
50
|
+
end
|
51
|
+
assign_attachment uploaded_file, action.comment
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def assign_attachment file, original_filename
|
56
|
+
send "#{attachment_name}=", file
|
57
|
+
write_identifier
|
58
|
+
@current_action.update_attributes! comment: original_filename
|
59
|
+
end
|
60
|
+
|
61
|
+
# we need a card id for the path so we have to update db_content when we have
|
62
|
+
# an id
|
63
|
+
event :correct_identifier, :finalize, on: :create do
|
64
|
+
update_column(:db_content, attachment.db_content(mod: load_from_mod))
|
65
|
+
expire
|
66
|
+
end
|
67
|
+
|
68
|
+
def file_ready_to_save?
|
69
|
+
attachment.file.present? &&
|
70
|
+
!preliminary_upload? &&
|
71
|
+
!save_preliminary_upload? &&
|
72
|
+
attachment_changed?
|
73
|
+
end
|
74
|
+
|
75
|
+
event :save_original_filename, :prepare_to_store,
|
76
|
+
when: proc { |c| c.file_ready_to_save? } do
|
77
|
+
return unless @current_action
|
78
|
+
@current_action.update_attributes! comment: original_filename
|
79
|
+
end
|
80
|
+
|
81
|
+
event :delete_cached_upload_file_on_create, :integrate,
|
82
|
+
on: :create, when: proc { |c| c.save_preliminary_upload? } do
|
83
|
+
if (action = Card::Action.fetch(@action_id_of_cached_upload))
|
84
|
+
upload_cache_card.delete_files_for_action action
|
85
|
+
action.delete
|
86
|
+
end
|
87
|
+
clear_upload_cache_dir_for_new_cards
|
88
|
+
end
|
89
|
+
|
90
|
+
event :delete_cached_upload_file_on_update, :integrate,
|
91
|
+
on: :update, when: proc { |c| c.save_preliminary_upload? } do
|
92
|
+
if (action = Card::Action.fetch(@action_id_of_cached_upload))
|
93
|
+
delete_files_for_action action
|
94
|
+
action.delete
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
event :validate_file_exist, :validate, on: :create do
|
99
|
+
unless attachment.file.present? || empty_ok?
|
100
|
+
errors.add attachment_name, "is missing"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
event :write_identifier, after: :save_original_filename do
|
105
|
+
self.content = attachment.db_content(mod: load_from_mod)
|
106
|
+
end
|
107
|
+
|
108
|
+
def item_names _args={} # needed for flexmail attachments. hacky.
|
109
|
+
[cardname]
|
110
|
+
end
|
111
|
+
|
112
|
+
def original_filename
|
113
|
+
attachment.original_filename
|
114
|
+
end
|
115
|
+
|
116
|
+
def unfilled?
|
117
|
+
!attachment.present? && !save_preliminary_upload? && !subcards.present?
|
118
|
+
end
|
119
|
+
|
120
|
+
def preliminary_upload?
|
121
|
+
Card::Env && Card::Env.params[:attachment_upload]
|
122
|
+
end
|
123
|
+
|
124
|
+
def save_preliminary_upload?
|
125
|
+
@action_id_of_cached_upload.present?
|
126
|
+
end
|
127
|
+
|
128
|
+
def attachment_changed?
|
129
|
+
send "#{attachment_name}_changed?"
|
130
|
+
end
|
131
|
+
|
132
|
+
def create_versions?
|
133
|
+
true
|
134
|
+
end
|
135
|
+
|
136
|
+
# used for uploads for new cards until the new card is created
|
137
|
+
def upload_cache_card
|
138
|
+
@upload_cache_card ||= Card["new_#{attachment_name}".to_sym]
|
139
|
+
end
|
140
|
+
|
141
|
+
# action id of the cached upload
|
142
|
+
attr_writer :action_id_of_cached_upload
|
143
|
+
|
144
|
+
attr_reader :action_id_of_cached_upload
|
145
|
+
|
146
|
+
attr_writer :empty_ok
|
147
|
+
|
148
|
+
def empty_ok?
|
149
|
+
@empty_ok
|
150
|
+
end
|
151
|
+
|
152
|
+
def load_from_mod= value
|
153
|
+
@mod = value
|
154
|
+
write_identifier
|
155
|
+
@store_in_mod = true if value
|
156
|
+
end
|
157
|
+
|
158
|
+
def load_from_mod
|
159
|
+
@mod
|
160
|
+
end
|
161
|
+
|
162
|
+
def store_dir
|
163
|
+
if @store_in_mod
|
164
|
+
mod_dir
|
165
|
+
else
|
166
|
+
upload_dir
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def retrieve_dir
|
171
|
+
if mod_file?
|
172
|
+
mod_dir
|
173
|
+
else
|
174
|
+
upload_dir
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# place for files of regular file cards
|
179
|
+
def upload_dir
|
180
|
+
if id
|
181
|
+
"#{Card.paths['files'].existent.first}/#{id}"
|
182
|
+
else
|
183
|
+
tmp_upload_dir
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# place for files if card doesn't have an id yet
|
188
|
+
def tmp_upload_dir _action_id=nil
|
189
|
+
"#{Card.paths['files'].existent.first}/#{upload_cache_card.id}"
|
190
|
+
end
|
191
|
+
|
192
|
+
# place for files of mod file cards
|
193
|
+
def mod_dir
|
194
|
+
mod = @mod || mod_file?
|
195
|
+
Card.paths["mod"].to_a.each do |mod_path|
|
196
|
+
dir = File.join(mod_path, mod, "file", codename)
|
197
|
+
return dir if Dir.exist? dir
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def mod_file?
|
202
|
+
return @mod if @store_in_mod
|
203
|
+
# when db_content was changed assume that it's no longer a mod file
|
204
|
+
return if db_content_changed? || !content.present?
|
205
|
+
case content
|
206
|
+
when %r{^:[^/]+/([^.]+)} then Regexp.last_match(1) # current mod_file format
|
207
|
+
when /^\~/ then false # current id file format
|
208
|
+
else
|
209
|
+
if (lines = content.split("\n")) && (lines.size == 4)
|
210
|
+
# old format, still used in card_changes.
|
211
|
+
lines.last
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def assign_set_specific_attributes
|
217
|
+
# reset content if we really have something to upload
|
218
|
+
if @set_specific.present? && @set_specific[attachment_name.to_s].present?
|
219
|
+
self.content = nil
|
220
|
+
end
|
221
|
+
super
|
222
|
+
end
|
223
|
+
|
224
|
+
def clear_upload_cache_dir_for_new_cards
|
225
|
+
Dir.entries(tmp_upload_dir).each do |filename|
|
226
|
+
if filename =~ /^\d+/
|
227
|
+
path = File.join(tmp_upload_dir, filename)
|
228
|
+
FileUtils.rm path if Card.older_than_five_days? File.ctime(path)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def delete_files_for_action action
|
234
|
+
with_selected_action_id(action.id) do
|
235
|
+
FileUtils.rm attachment.file.path
|
236
|
+
attachment.versions.each_value do |version|
|
237
|
+
FileUtils.rm version.path
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# create filesystem links to files from prior action
|
243
|
+
def symlink_to prior_action_id
|
244
|
+
return unless prior_action_id != last_action_id
|
245
|
+
save_action_id = selected_action_id
|
246
|
+
links = {}
|
247
|
+
|
248
|
+
self.selected_action_id = prior_action_id
|
249
|
+
attachment.versions.each do |name, version|
|
250
|
+
links[name] = version.store_path
|
251
|
+
end
|
252
|
+
original = attachment.store_path
|
253
|
+
|
254
|
+
self.selected_action_id = last_action_id
|
255
|
+
attachment.versions.each do |name, version|
|
256
|
+
::File.symlink links[name], version.store_path
|
257
|
+
end
|
258
|
+
::File.symlink original, attachment.store_path
|
259
|
+
|
260
|
+
self.selected_action_id = save_action_id
|
261
|
+
end
|
262
|
+
|
263
|
+
def attachment_format ext
|
264
|
+
if ext.present? && attachment && (original_ext = attachment.extension)
|
265
|
+
if ["file", original_ext].member? ext
|
266
|
+
original_ext
|
267
|
+
elsif (exts = MIME::Types[attachment.content_type])
|
268
|
+
if exts.find { |mt| mt.extensions.member? ext }
|
269
|
+
ext
|
270
|
+
else
|
271
|
+
exts[0].extensions[0]
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
rescue => e
|
276
|
+
Rails.logger.info "attachment_format issue: #{e.message}"
|
277
|
+
nil
|
278
|
+
end
|
279
|
+
|
280
|
+
|
281
|
+
# ~~ below autogenerated; above pulled from /Users/ethan/dev/wagn/gem/card/mod/carrierwave/set/abstract/attachment.rb ~~
|
282
|
+
end;end;end;end;
|