card 1.18.1 → 1.18.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0e96aef9fe8581d7e787b0ad6ed56db1b3ec7d1
4
- data.tar.gz: bbdd504c7800d1c372bd4199a293eeeb4e0ad501
3
+ metadata.gz: 040ce812a1f8d7900a5c5e742871133e90225ff0
4
+ data.tar.gz: e03884ae6c5850eeec5b6456cdaa202c4f6da9c2
5
5
  SHA512:
6
- metadata.gz: 2bb8bfa7d9df016796744af64b3361c5abbf5fefe1b10d17f4ae08af370e12600e1e1353da8ed00ae07bc281c484a0fbf458fe51d535e06ff0b49fd2987d58a1
7
- data.tar.gz: d0f7b44c9ec0b44118f29a0fab7721402fcdfb397df4396a914243aa5477e18eeefed973fcb1434eb56eb8af6c788104a59178f23fcf10c414b17b1394d4eb38
6
+ metadata.gz: d6de0ea37ead3e1e4de679e46e2d013e9707303550e43d3c44a111c83a857d1483e0ace41ea9c31cbf92f109713391ab5f8f49518353cbd429517aeabb5de277
7
+ data.tar.gz: 0b923c3dd12e2ef9df97c19d5fae2c0a198dddc8b032bc70fea8a82637aba4eacecb0765e177427828976f469847512fe36b7f148b669cb521afce246acc955f
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.18.1
1
+ 1.18.2
@@ -20,7 +20,7 @@ class SearchCardContext < Card::CoreMigration
20
20
  end
21
21
  card.update_column :db_content, content
22
22
  card.actions.each do |action|
23
- next unless (content_change = action.change_for(:db_content).first)
23
+ next unless (content_change = action.change :db_content)
24
24
  content = content_change.value
25
25
  replace.each do |key, val|
26
26
  content.gsub!(/(#{sep})_(#{key})(?=#{sep})/, "\\1_#{val}")
@@ -2,11 +2,17 @@
2
2
 
3
3
  class AddRecentSettingSessionCard < Card::CoreMigration
4
4
  def up
5
- Card.create! name: '*recent settings', codename: 'recent_settings', type_code: :pointer, subcards: {
6
- '+*self+*options' => { type_code: :search_type, content: '{"type":"setting"}' },
7
- '+*self+*update' => { content: '[[Anyone]]' },
8
- '+*self**create' => { content: '[[Anyone]]' },
9
- '+*self**read' => { content: '[[Anyone]]' }
10
- }
5
+ Card.create!(
6
+ name: '*recent settings',
7
+ codename: 'recent_settings',
8
+ type_code: :pointer,
9
+ subcards: {
10
+ '+*self+*options' => { type_code: :search_type,
11
+ content: '{"type":"setting"}' },
12
+ '+*self+*update' => { content: '[[Anyone]]' },
13
+ '+*self**create' => { content: '[[Anyone]]' },
14
+ '+*self**read' => { content: '[[Anyone]]' }
15
+ }
16
+ )
11
17
  end
12
18
  end
@@ -26,7 +26,7 @@ class UpdateFileAndImageCards < Card::CoreMigration
26
26
  Card::Cache.reset_all
27
27
  Card.search(type: [:in, 'file', 'image']).each do |card|
28
28
  card.actions.each do |action|
29
- if (content_change = action.change_for(:db_content).first)
29
+ if (content_change = action.change :db_content)
30
30
  original_filename = content_change.value.split("\n").first
31
31
  action.update_attributes! comment: original_filename
32
32
  end
@@ -4,7 +4,7 @@ class UpdateFileHistory < Card::CoreMigration
4
4
  def up
5
5
  Card.search(type: [:in, 'file', 'image']).each do |card|
6
6
  card.actions.each do |action|
7
- next unless (content_change = action.change_for(:db_content).first)
7
+ next unless (content_change = action.change :db_content)
8
8
  original_filename, file_type, action_id, mod = content_change.value.split("\n")
9
9
  next unless file_type.present? && action_id.present?
10
10
  value =
data/lib/card/cache.rb CHANGED
@@ -1,17 +1,6 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  class Card
4
- ActiveSupport::Cache::FileStore.class_eval do
5
- # escape special symbols \*"<>| additionaly to :?.
6
- # All of them not allowed to use in ms windows file system
7
- def real_file_path name
8
- name = name.gsub('%', '%25').gsub('?', '%3F').gsub(':', '%3A')
9
- name = name.gsub('\\', '%5C').gsub('*', '%2A').gsub('"', '%22')
10
- name = name.gsub('<', '%3C').gsub('>', '%3E').gsub('|', '%7C')
11
- '%s/%s.cache' % [@cache_path, name]
12
- end
13
- end
14
-
15
4
  class Cache
16
5
  TEST_ENVS = %w(test cucumber).freeze
17
6
  @@prepopulating = TEST_ENVS.include? Rails.env
@@ -28,22 +17,14 @@ class Card
28
17
  store: cache_type
29
18
  end
30
19
 
20
+ # establish clean context;
21
+ # clear the temporary caches and ensure we're using the latest stamp
22
+ # on the persistent caches.
31
23
  def renew
32
- cache_by_class.keys do |klass|
33
- raise "renewing nil cache: #{klass}" unless klass.cache
34
- cache_by_class[klass].system_prefix = system_prefix(klass)
24
+ cache_by_class.each do |_klass, cache|
25
+ cache.soft.reset
26
+ cache.hard.renew if cache.hard
35
27
  end
36
- reset_soft
37
- end
38
-
39
- def database_name
40
- @database_name ||= (cfg = Cardio.config) &&
41
- (dbcfg = cfg.database_configuration) &&
42
- dbcfg[Rails.env]['database']
43
- end
44
-
45
- def system_prefix klass
46
- "#{database_name}/#{klass}"
47
28
  end
48
29
 
49
30
  def restore
@@ -51,16 +32,18 @@ class Card
51
32
  prepopulate
52
33
  end
53
34
 
54
- def reset_global # deprecated
55
- reset_all
35
+ def reset_global
36
+ cache_by_class.each do |_klass, cache|
37
+ cache.soft.reset
38
+ cache.hard.annihilate if cache.hard
39
+ end
40
+ reset_other
56
41
  end
57
42
 
58
43
  def reset_all
59
44
  reset_hard
60
45
  reset_soft
61
-
62
- Card::Codename.reset_cache
63
- Cardio.delete_tmp_files
46
+ reset_other
64
47
  end
65
48
 
66
49
  def reset_hard
@@ -75,6 +58,11 @@ class Card
75
58
  end
76
59
  end
77
60
 
61
+ def reset_other
62
+ Card::Codename.reset_cache
63
+ Cardio.delete_tmp_files
64
+ end
65
+
78
66
  def obj_to_key obj
79
67
  case obj
80
68
  when Hash
@@ -161,3 +149,14 @@ class Card
161
149
  end
162
150
  end
163
151
  end
152
+
153
+ ActiveSupport::Cache::FileStore.class_eval do
154
+ # escape special symbols \*"<>| additionaly to :?.
155
+ # All of them not allowed to use in ms windows file system
156
+ def real_file_path name
157
+ name = name.gsub('%', '%25').gsub('?', '%3F').gsub(':', '%3A')
158
+ name = name.gsub('\\', '%5C').gsub('*', '%2A').gsub('"', '%22')
159
+ name = name.gsub('<', '%3C').gsub('>', '%3E').gsub('|', '%7C')
160
+ '%s/%s.cache' % [@cache_path, name]
161
+ end
162
+ end
@@ -1,33 +1,68 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  class Card::Cache::Persistent
4
- attr_reader :prefix
4
+ attr_accessor :prefix
5
+
6
+ class << self
7
+ def database_name
8
+ @database_name ||= (cfg = Cardio.config) &&
9
+ (dbcfg = cfg.database_configuration) &&
10
+ dbcfg[Rails.env]['database']
11
+ end
12
+ end
5
13
 
6
14
  def initialize opts
7
15
  @store = opts[:store]
8
- self.system_prefix =
9
- opts[:prefix] || Card::Cache.system_prefix(opts[:class])
16
+ @klass = opts[:class]
17
+ @class_key = @klass.to_s.to_name.key
18
+ @database = opts[:database] || self.class.database_name
10
19
  end
11
20
 
12
- def system_prefix= system_prefix
13
- @system_prefix = system_prefix
14
- @prefix = "#{system_prefix}/"
21
+ def renew
22
+ @stamp = nil
23
+ @prefix = nil
24
+ end
25
+
26
+ def reset
27
+ @stamp = new_stamp
28
+ @prefix = nil
29
+ Cardio.cache.write stamp_key, @stamp
30
+ end
31
+
32
+ def stamp
33
+ @stamp ||= Cardio.cache.fetch stamp_key { new_stamp }
34
+ end
35
+
36
+ def stamp_key
37
+ "#{@database}/#{@class_key}/stamp"
38
+ end
39
+
40
+ def new_stamp
41
+ Time.now.to_i.to_s 32
42
+ end
43
+
44
+ def prefix
45
+ @prefix ||= "#{@database}/#{@class_key}/#{stamp}"
46
+ end
47
+
48
+ def full_key key
49
+ "#{prefix}/#{key}"
15
50
  end
16
51
 
17
52
  def read key
18
- @store.read(full_key(key))
53
+ @store.read full_key(key)
19
54
  end
20
55
 
21
56
  def write_variable key, variable, value
22
- if @store && (object = @store.read key)
57
+ if @store && (object = read key)
23
58
  object.instance_variable_set "@#{variable}", value
24
- @store.write key, object
59
+ write key, object
25
60
  end
26
61
  value
27
62
  end
28
63
 
29
64
  def write key, value
30
- @store.write(full_key(key), value)
65
+ @store.write full_key(key), value
31
66
  end
32
67
 
33
68
  def fetch key, &block
@@ -38,17 +73,11 @@ class Card::Cache::Persistent
38
73
  @store.delete full_key(key)
39
74
  end
40
75
 
41
- def reset
76
+ def annihilate
42
77
  @store.clear
43
- rescue => e
44
- Rails.logger.debug "Problem clearing cache: #{e.message}"
45
78
  end
46
79
 
47
80
  def exist? key
48
81
  @store.exist? full_key(key)
49
82
  end
50
-
51
- def full_key key
52
- @prefix + key
53
- end
54
83
  end
@@ -1,9 +1,9 @@
1
1
  class Card
2
2
  class Query
3
3
  class SqlStatement
4
- def initialize query
4
+ def initialize query=nil
5
5
  @query = query
6
- @mods = query.mods
6
+ @mods = query && query.mods
7
7
  end
8
8
 
9
9
  def build
@@ -146,18 +146,19 @@ class Card
146
146
  end
147
147
 
148
148
  def standard_conditions query
149
- [trash_condition(query), permission_conditions(query)].compact * ' AND '
149
+ table = query.table_alias
150
+ [trash_condition(table), permission_conditions(table)].compact * ' AND '
150
151
  end
151
152
 
152
- def trash_condition query
153
- "#{query.table_alias}.trash is false"
153
+ def trash_condition table
154
+ "#{table}.trash is false"
154
155
  end
155
156
 
156
- def permission_conditions query
157
+ def permission_conditions table
157
158
  return if Auth.always_ok?
158
159
  read_rules = Auth.as_card.read_rules
159
160
  read_rule_list = read_rules.present? ? read_rules.join(',') : 1
160
- "#{query.table_alias}.read_rule_id IN (#{read_rule_list})"
161
+ "#{table}.read_rule_id IN (#{read_rule_list})"
161
162
  end
162
163
 
163
164
  def group
@@ -205,7 +206,7 @@ class Card
205
206
  when 'id' then "#{table}.id"
206
207
  when 'update' then "#{table}.updated_at"
207
208
  when 'create' then "#{table}.created_at"
208
- when /^(name|alpha)$/ then "LOWER( #{table}.key )"
209
+ when /^(name|alpha)$/ then "#{table}.key"
209
210
  when 'content' then "#{table}.db_content"
210
211
  when 'relevance' then "#{table}.updated_at" # deprecated
211
212
  else
data/lib/cardio.rb CHANGED
@@ -29,7 +29,6 @@ module Cardio
29
29
  recaptcha_private_key: nil,
30
30
  recaptcha_proxy: nil,
31
31
 
32
- cache_store: [:file_store, 'tmp/cache'],
33
32
  override_host: nil,
34
33
  override_protocol: nil,
35
34
 
@@ -41,7 +40,7 @@ module Cardio
41
40
  email_defaults: nil,
42
41
 
43
42
  token_expiry: 2.days,
44
- revisions_per_page: 10,
43
+ acts_per_page: 10,
45
44
  space_last_in_multispace: true,
46
45
  closed_search_limit: 50,
47
46
 
@@ -9,7 +9,7 @@ describe Card::Set::All::Content do
9
9
  @card.save_content_draft('booboo')
10
10
  @card.reload
11
11
  expect(@card.drafts.length).to eq 1
12
- expect(@card.drafts[0].new_values[:content]).to eq 'booboo'
12
+ expect(@card.drafts[0].value(:db_content)).to eq 'booboo'
13
13
  end
14
14
  end
15
15
  end
@@ -9,13 +9,20 @@ class Card
9
9
  class_name: 'Card::Action'
10
10
 
11
11
  belongs_to :actor, class_name: 'Card'
12
- belongs_to :card
12
+
13
+ def card
14
+ Card.fetch card_id, look_in_trash: true, skip_modules: true
15
+ end
13
16
 
14
17
  class << self
18
+ def delete_cardless
19
+ left_join = 'LEFT JOIN cards ON card_acts.card_id = cards.id'
20
+ joins(left_join).where('cards.id IS NULL').delete_all
21
+ end
22
+
15
23
  def delete_actionless
16
24
  joins(
17
- 'LEFT JOIN card_actions '\
18
- 'ON card_acts.id = card_actions.card_act_id'
25
+ 'LEFT JOIN card_actions ON card_acts.id = card_act_id'
19
26
  ).where(
20
27
  'card_actions.id is null'
21
28
  ).delete_all
@@ -27,6 +34,19 @@ class Card
27
34
  vars = { card_ids: card_ids, current_user_id: Card::Auth.current_id }
28
35
  joins(:actions).where(sql, vars).uniq.order(:id).reverse_order
29
36
  end
37
+
38
+ def all_viewable
39
+ joins = 'JOIN card_actions ON card_acts.id = card_act_id ' \
40
+ 'JOIN cards ON cards.id = card_actions.card_id'
41
+ where = [
42
+ 'card_actions.id is not null', # data check. should not be needed
43
+ 'cards.id is not null', # ditto
44
+ 'draft is not true',
45
+ Card::Query::SqlStatement.new.permission_conditions('cards')
46
+ ].compact.join ' AND '
47
+
48
+ joins(joins).where(where).uniq
49
+ end
30
50
  end
31
51
 
32
52
  def set_actor
@@ -54,8 +74,8 @@ class Card
54
74
 
55
75
  def relevant_actions_for card
56
76
  actions.select do |action|
57
- card.included_card_ids.include?(action.card_id) ||
58
- (card.id == action.card_id)
77
+ (card.id == action.card_id) ||
78
+ card.included_card_ids.include?(action.card_id)
59
79
  end
60
80
  end
61
81
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  class Card
4
4
  class Action < ActiveRecord::Base
5
- belongs_to :card
6
5
  belongs_to :act, foreign_key: :card_act_id, inverse_of: :actions
7
6
  has_many :card_changes, foreign_key: :card_action_id, inverse_of: :action,
8
7
  dependent: :delete_all, class_name: 'Card::Change'
@@ -29,14 +28,23 @@ class Card
29
28
  end
30
29
 
31
30
  def fetch id
32
- cache.read(id.to_s) || begin
33
- cache.write id.to_s, Action.find(id.to_i)
31
+ cache.fetch id.to_s do
32
+ find id.to_i
34
33
  end
35
34
  end
36
35
 
37
36
  def delete_cardless
38
37
  left_join = 'LEFT JOIN cards ON card_actions.card_id = cards.id'
39
- Card::Action.joins(left_join).where('cards.id IS NULL').delete_all
38
+ joins(left_join).where('cards.id IS NULL').delete_all
39
+ end
40
+
41
+ def delete_changeless
42
+ joins(
43
+ 'LEFT JOIN card_changes '\
44
+ 'ON card_changes.card_action_id = card_actions.id'
45
+ ).where(
46
+ 'card_changes.id IS NULL'
47
+ ).delete_all
40
48
  end
41
49
 
42
50
  def delete_old
@@ -61,76 +69,44 @@ class Card
61
69
  # writing here (disabled history), we still have to generate change stream
62
70
  # events in another way.
63
71
 
64
- def changed_fields obj, changed_fields
65
- changed_fields.each do |f|
66
- Card::Change.create field: f, value: obj[f], card_action_id: id
67
- end
68
- end
69
-
70
- def edit_info
71
- @edit_info ||= {
72
- action_type: "#{action_type}d",
73
- new_content: new_values[:content],
74
- new_name: new_values[:name],
75
- new_cardtype: new_values[:cardtype],
76
- old_content: old_values[:content],
77
- old_name: old_values[:name],
78
- old_cardtype: old_values[:cardtype]
79
- }
80
- end
81
-
82
- def new_values
83
- @new_values ||=
84
- {
85
- content: new_value_for(:db_content),
86
- name: new_value_for(:name),
87
- cardtype: ((typecard = Card[new_value_for(:type_id).to_i]) &&
88
- typecard.name.capitalize)
89
- }
90
- end
91
-
92
- def old_values
93
- @old_values ||= {
94
- content: last_value_for(:db_content),
95
- name: last_value_for(:name),
96
- cardtype: ((value = last_value_for(:type_id)) &&
97
- (typecard = Card.find(value)) &&
98
- typecard.name.capitalize)
99
- }
100
- end
72
+ # def changed_fields obj, changed_fields
73
+ # changed_fields.each do |f|
74
+ # Card::Change.create field: f, value: obj[f], card_action_id: id
75
+ # end
76
+ # end
101
77
 
102
- def last_value_for field
103
- ch = card.last_change_on(field, before: self)
104
- ch && ch.value
78
+ def value field
79
+ return unless (change = change field)
80
+ interpret_value field, change.value
105
81
  end
106
82
 
107
- def field_index field
108
- if field.is_a? Integer
109
- field
110
- else
111
- Card::TRACKED_FIELDS.index(field.to_s)
112
- end
83
+ def change field
84
+ changes[interpret_field field]
113
85
  end
114
86
 
115
- def new_value_for field
116
- ch = card_changes.find_by(field: field_index(field))
117
- ch && ch.value
87
+ def changes
88
+ @changes ||=
89
+ card_changes.each_with_object({}) do |change, hash|
90
+ hash[change.field.to_sym] = change
91
+ end
118
92
  end
119
93
 
120
- def change_for field
121
- card_changes.where 'card_changes.field = ?', field_index(field)
94
+ def previous_value field
95
+ return if action_type == :create
96
+ return unless (previous_change = previous_change field)
97
+ interpret_value field, previous_change.value
122
98
  end
123
99
 
124
100
  def new_type?
125
- new_value_for :type_id
101
+ value :type_id
126
102
  end
127
103
 
128
104
  def new_content?
129
- new_value_for :db_content
105
+ value :db_content
130
106
  end
131
107
 
132
108
  def new_name?
133
- new_value_for :name
109
+ value :name
134
110
  end
135
111
 
136
112
  def action_type= value
@@ -141,10 +117,6 @@ class Card
141
117
  TYPE[read_attribute(:action_type)]
142
118
  end
143
119
 
144
- def set_act
145
- self.set_act ||= acts.last
146
- end
147
-
148
120
  def revision_nr
149
121
  card.actions.index_of self
150
122
  end
@@ -157,18 +129,14 @@ class Card
157
129
  content_diff_object.green?
158
130
  end
159
131
 
160
- # def diff
161
- # @diff ||= { cardtype: type_diff, content: content_diff, name: name_diff}
162
- # end
163
-
164
132
  def name_diff opts={}
165
133
  return unless new_name?
166
- Card::Diff.complete old_values[:name], new_values[:name], opts
134
+ Card::Diff.complete previous_value(:name), value(:name), opts
167
135
  end
168
136
 
169
137
  def cardtype_diff opts={}
170
138
  return unless new_type?
171
- Card::Diff.complete old_values[:cardtype], new_values[:cardtype], opts
139
+ Card::Diff.complete previous_value(:cardtype), value(:cardtype), opts
172
140
  end
173
141
 
174
142
  def content_diff diff_type=:expanded, opts=nil
@@ -180,15 +148,46 @@ class Card
180
148
  end
181
149
  end
182
150
 
151
+ def card
152
+ Card.fetch card_id, look_in_trash: true, skip_modules: true
153
+ end
154
+
155
+ private
156
+
183
157
  def content_diff_object opts=nil
184
158
  @diff ||= begin
185
159
  diff_args = opts || card.include_set_modules.diff_args
186
- Card::Diff.new old_values[:content], new_values[:content], diff_args
160
+ Card::Diff.new previous_value(:content), value(:content), diff_args
187
161
  end
188
162
  end
189
163
 
190
- def card
191
- Card.fetch card_id, look_in_trash: true
164
+ def previous_change field
165
+ field = interpret_field field
166
+ if @previous_changes && @previous_changes.key?(field)
167
+ @previous_changes[field]
168
+ else
169
+ @previous_changes ||= {}
170
+ @previous_changes[field] = card.last_change_on field, before: self
171
+ end
172
+ end
173
+
174
+ def interpret_field field
175
+ case field
176
+ when :content then :db_content
177
+ when :cardtype then :type_id
178
+ else field.to_sym
179
+ end
180
+ end
181
+
182
+ def interpret_value field, value
183
+ case field.to_sym
184
+ when :type_id
185
+ value && value.to_i
186
+ when :cardtype
187
+ type_card = value && Card.quick_fetch(value.to_i)
188
+ type_card && type_card.name.capitalize
189
+ else value
190
+ end
192
191
  end
193
192
  end
194
193
  end