alchemy_cms 3.3.3 → 3.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +42 -4
  4. data/README.md +7 -3
  5. data/alchemy_cms.gemspec +1 -0
  6. data/app/assets/javascripts/alchemy/{alchemy.js → admin.js} +1 -2
  7. data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +28 -25
  8. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +1 -0
  9. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +7 -1
  10. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +1 -1
  11. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +26 -0
  12. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +56 -1
  13. data/app/assets/stylesheets/alchemy/_variables.scss +1 -0
  14. data/app/assets/stylesheets/alchemy/admin.scss +2 -1
  15. data/app/assets/stylesheets/alchemy/archive.scss +7 -0
  16. data/app/assets/stylesheets/alchemy/base.scss +0 -42
  17. data/app/assets/stylesheets/alchemy/buttons.scss +2 -1
  18. data/app/assets/stylesheets/alchemy/form_fields.scss +9 -0
  19. data/app/assets/stylesheets/alchemy/forms.scss +36 -10
  20. data/app/assets/stylesheets/alchemy/frame.scss +12 -1
  21. data/app/assets/stylesheets/alchemy/icons.scss +1 -1
  22. data/app/assets/stylesheets/alchemy/jquery-ui.scss +0 -260
  23. data/app/assets/stylesheets/alchemy/jquery.datetimepicker.scss +507 -0
  24. data/app/assets/stylesheets/alchemy/lists.scss +62 -0
  25. data/app/assets/stylesheets/alchemy/selects.scss +9 -2
  26. data/app/assets/stylesheets/alchemy/sitemap.scss +28 -51
  27. data/app/assets/stylesheets/alchemy/toolbar.scss +0 -2
  28. data/app/controllers/alchemy/admin/attachments_controller.rb +4 -6
  29. data/app/controllers/alchemy/admin/base_controller.rb +2 -2
  30. data/app/controllers/alchemy/admin/dashboard_controller.rb +2 -2
  31. data/app/controllers/alchemy/admin/languages_controller.rb +5 -0
  32. data/app/controllers/alchemy/admin/pages_controller.rb +14 -5
  33. data/app/controllers/alchemy/admin/resources_controller.rb +17 -1
  34. data/app/controllers/alchemy/base_controller.rb +1 -0
  35. data/app/controllers/alchemy/messages_controller.rb +1 -1
  36. data/app/controllers/alchemy/pages_controller.rb +16 -26
  37. data/app/controllers/alchemy/pictures_controller.rb +23 -10
  38. data/app/controllers/concerns/alchemy/page_redirects.rb +7 -7
  39. data/app/helpers/alchemy/admin/base_helper.rb +22 -19
  40. data/app/helpers/alchemy/admin/essences_helper.rb +26 -11
  41. data/app/helpers/alchemy/admin/pages_helper.rb +2 -1
  42. data/app/helpers/alchemy/essences_helper.rb +0 -35
  43. data/app/helpers/alchemy/url_helper.rb +1 -1
  44. data/app/mailers/alchemy/base_mailer.rb +18 -0
  45. data/app/mailers/alchemy/{messages.rb → messages_mailer.rb} +1 -1
  46. data/app/models/alchemy/attachment.rb +9 -0
  47. data/app/models/alchemy/cell.rb +1 -1
  48. data/app/models/alchemy/essence_picture.rb +4 -1
  49. data/app/models/alchemy/essence_picture_view.rb +68 -0
  50. data/app/models/alchemy/language.rb +8 -10
  51. data/app/models/alchemy/language/code.rb +4 -1
  52. data/app/models/alchemy/page.rb +69 -26
  53. data/app/models/alchemy/page/page_natures.rb +22 -0
  54. data/app/models/alchemy/page/page_scopes.rb +20 -6
  55. data/app/models/alchemy/picture.rb +37 -4
  56. data/app/models/alchemy/site.rb +8 -0
  57. data/app/serializers/alchemy/page_tree_serializer.rb +1 -1
  58. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +9 -6
  59. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +11 -9
  60. data/app/views/alchemy/admin/attachments/_filter_bar.html.erb +32 -0
  61. data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +14 -2
  62. data/app/views/alchemy/admin/attachments/index.html.erb +10 -9
  63. data/app/views/alchemy/admin/dashboard/_locked_pages.html.erb +20 -9
  64. data/app/views/alchemy/admin/dashboard/_recent_pages.html.erb +11 -1
  65. data/app/views/alchemy/admin/languages/_form.html.erb +1 -0
  66. data/app/views/alchemy/admin/languages/index.html.erb +7 -8
  67. data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +1 -1
  68. data/app/views/alchemy/admin/layoutpages/index.html.erb +2 -2
  69. data/app/views/alchemy/admin/pages/_current_page.html.erb +4 -0
  70. data/app/views/alchemy/admin/pages/_form.html.erb +16 -1
  71. data/app/views/alchemy/admin/pages/_locked_page.html.erb +2 -12
  72. data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
  73. data/app/views/alchemy/admin/pages/_page_for_links.html.erb +2 -2
  74. data/app/views/alchemy/admin/pages/_page_status.html.erb +23 -11
  75. data/app/views/alchemy/admin/pages/edit.html.erb +2 -1
  76. data/app/views/alchemy/admin/pages/index.html.erb +2 -2
  77. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +3 -0
  78. data/app/views/alchemy/admin/partials/_site_select.html.erb +9 -0
  79. data/app/views/alchemy/admin/pictures/_picture.html.erb +6 -1
  80. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +2 -1
  81. data/app/views/alchemy/admin/pictures/show.html.erb +1 -1
  82. data/app/views/alchemy/admin/resources/_filter_bar.html.erb +31 -0
  83. data/app/views/alchemy/admin/resources/_form.html.erb +6 -0
  84. data/app/views/alchemy/admin/resources/_tag_list.html.erb +16 -0
  85. data/app/views/alchemy/admin/resources/index.html.erb +13 -1
  86. data/app/views/alchemy/essences/_essence_file_view.html.erb +2 -5
  87. data/app/views/alchemy/essences/_essence_picture_view.html.erb +5 -3
  88. data/app/views/alchemy/{messages → messages_mailer}/contact_form_mail.de.text.erb +0 -0
  89. data/app/views/alchemy/{messages → messages_mailer}/contact_form_mail.en.text.erb +0 -0
  90. data/app/views/alchemy/{messages → messages_mailer}/contact_form_mail.es.text.erb +0 -0
  91. data/app/views/alchemy/{messages → messages_mailer}/new.html.erb +0 -0
  92. data/app/views/layouts/alchemy/admin.html.erb +3 -8
  93. data/config/alchemy/config.yml +4 -3
  94. data/config/initializers/assets.rb +2 -2
  95. data/config/initializers/dragonfly.rb +3 -0
  96. data/config/initializers/mime_types.rb +1 -0
  97. data/config/locales/alchemy.de.yml +10 -2
  98. data/config/locales/alchemy.en.yml +6 -2
  99. data/config/locales/alchemy.es.yml +6 -3
  100. data/config/locales/alchemy.fr.yml +6 -2
  101. data/config/locales/alchemy.it.yml +937 -0
  102. data/config/locales/alchemy.nl.yml +6 -2
  103. data/config/locales/alchemy.ru.yml +3 -2
  104. data/config/locales/simple_form.it.yml +25 -0
  105. data/db/migrate/20160108174834_add_timebased_publishing_columns_to_pages.rb +32 -0
  106. data/db/migrate/20160422195310_add_image_file_format_to_alchemy_pictures.rb +21 -0
  107. data/db/migrate/20160617224938_change_alchemy_pages_locked_to_locked_at.rb +22 -0
  108. data/lib/alchemy/ability_helper.rb +23 -0
  109. data/lib/alchemy/configuration_methods.rb +2 -2
  110. data/lib/alchemy/controller_actions.rb +4 -33
  111. data/lib/alchemy/engine.rb +1 -0
  112. data/lib/alchemy/resource.rb +30 -13
  113. data/lib/alchemy/resources_helper.rb +17 -0
  114. data/lib/alchemy/test_support/factories/page_factory.rb +7 -2
  115. data/lib/alchemy/upgrader.rb +1 -0
  116. data/lib/alchemy/upgrader/tasks/install_asset_manifests.rb +15 -0
  117. data/lib/alchemy/upgrader/three_point_four.rb +16 -0
  118. data/lib/alchemy/version.rb +1 -1
  119. data/lib/rails/generators/alchemy/elements/elements_generator.rb +8 -7
  120. data/lib/rails/generators/alchemy/essence/essence_generator.rb +2 -6
  121. data/lib/rails/generators/alchemy/install/files/all.css +11 -0
  122. data/lib/rails/generators/alchemy/install/files/all.js +11 -0
  123. data/lib/rails/generators/alchemy/install/files/{alchemy.elements.css.scss → article.scss} +0 -0
  124. data/lib/rails/generators/alchemy/install/install_generator.rb +20 -19
  125. data/lib/rails/generators/alchemy/module/module_generator.rb +3 -5
  126. data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +7 -6
  127. data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +7 -6
  128. data/vendor/assets/javascripts/date-formatter.js +161 -0
  129. data/vendor/assets/javascripts/jquery_plugins/jquery.datetimepicker.full.min.js +2 -0
  130. data/vendor/assets/javascripts/tinymce/langs/it.js +219 -0
  131. metadata +48 -13
  132. data/app/assets/javascripts/alchemy/alchemy.custom.js +0 -1
  133. data/app/assets/stylesheets/alchemy/custom.scss +0 -1
@@ -0,0 +1,68 @@
1
+ module Alchemy
2
+ # Renders an essence picture view
3
+ class EssencePictureView
4
+ include ActionView::Helpers::AssetTagHelper
5
+ include ActionView::Helpers::UrlHelper
6
+ include Rails.application.routes.url_helpers
7
+
8
+ attr_reader :content, :essence, :html_options, :options, :picture
9
+
10
+ DEFAULT_OPTIONS = {
11
+ show_caption: true,
12
+ disable_link: false
13
+ }
14
+
15
+ def initialize(content, options = {}, html_options = {})
16
+ @content = content
17
+ @options = DEFAULT_OPTIONS.update(content.settings).update(options)
18
+ @html_options = html_options
19
+ @essence = content.essence
20
+ @picture = essence.picture
21
+ end
22
+
23
+ def render
24
+ return if picture.blank?
25
+
26
+ output = caption ? img_tag + caption : img_tag
27
+
28
+ if is_linked?
29
+ output = link_to(output, url_for(essence.link), {
30
+ title: essence.link_title.presence,
31
+ target: essence.link_target == "blank" ? "_blank" : nil,
32
+ data: {link_target: essence.link_target.presence}
33
+ })
34
+ end
35
+
36
+ if caption
37
+ content_tag(:figure, output, {class: essence.css_class.presence}.merge(html_options))
38
+ else
39
+ output
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def caption
46
+ return unless show_caption?
47
+ @_caption ||= content_tag(:figcaption, essence.caption)
48
+ end
49
+
50
+ def img_tag
51
+ @_img_tag ||= image_tag(
52
+ essence.picture_url(options), {
53
+ alt: essence.alt_tag.presence,
54
+ title: essence.title.presence,
55
+ class: caption ? nil : essence.css_class.presence
56
+ }.merge(caption ? {} : html_options)
57
+ )
58
+ end
59
+
60
+ def show_caption?
61
+ options[:show_caption] && essence.caption.present?
62
+ end
63
+
64
+ def is_linked?
65
+ !options[:disable_link] && essence.link.present?
66
+ end
67
+ end
68
+ end
@@ -19,7 +19,7 @@
19
19
 
20
20
  module Alchemy
21
21
  class Language < ActiveRecord::Base
22
- belongs_to :site
22
+ belongs_to :site, required: true
23
23
  has_many :pages
24
24
 
25
25
  before_validation :set_locale, if: -> { locale.blank? }
@@ -52,11 +52,10 @@ module Alchemy
52
52
  before_destroy :check_for_default
53
53
  after_destroy :delete_language_root_page
54
54
 
55
- default_scope { on_site(Site.current) }
56
-
57
- scope :published, -> { where(public: true) }
58
- scope :with_root_page, -> { joins(:pages).where(Page.table_name => {language_root: true}) }
59
- scope :on_site, ->(s) { s.present? ? where(site_id: s.id) : all }
55
+ scope :published, -> { where(public: true) }
56
+ scope :with_root_page, -> { joins(:pages).where(Page.table_name => {language_root: true}) }
57
+ scope :on_site, ->(s) { s ? where(site_id: s.id) : all }
58
+ scope :on_current_site, -> { on_site(Site.current) }
60
59
 
61
60
  class << self
62
61
  # Store the current language in the current thread.
@@ -74,11 +73,10 @@ module Alchemy
74
73
  current.pages.language_roots.first
75
74
  end
76
75
 
77
- # Default language
76
+ # Default language for current site
78
77
  def default
79
- find_by(default: true)
78
+ on_current_site.find_by(default: true)
80
79
  end
81
- alias_method :get_default, :default
82
80
  end
83
81
 
84
82
  def label(attrib)
@@ -165,7 +163,7 @@ module Alchemy
165
163
  end
166
164
 
167
165
  def unpublish_pages
168
- pages.update_all(public: false)
166
+ pages.update_all(public_on: nil, public_until: nil)
169
167
  end
170
168
  end
171
169
  end
@@ -13,7 +13,10 @@ module Alchemy::Language::Code
13
13
  def find_by_code(code)
14
14
  codes = code.split('-')
15
15
  codes << '' if codes.length == 1
16
- find_by_language_code_and_country_code(*codes)
16
+ on_current_site.find_by(
17
+ language_code: codes[0],
18
+ country_code: codes[1]
19
+ )
17
20
  end
18
21
  end
19
22
  end
@@ -3,12 +3,12 @@
3
3
  # Table name: alchemy_pages
4
4
  #
5
5
  # id :integer not null, primary key
6
- # name :string(255)
7
- # urlname :string(255)
8
- # title :string(255)
9
- # language_code :string(255)
6
+ # name :string
7
+ # urlname :string
8
+ # title :string
9
+ # language_code :string
10
10
  # language_root :boolean
11
- # page_layout :string(255)
11
+ # page_layout :string
12
12
  # meta_keywords :text
13
13
  # meta_description :text
14
14
  # lft :integer
@@ -17,7 +17,7 @@
17
17
  # depth :integer
18
18
  # visible :boolean default(FALSE)
19
19
  # public :boolean default(FALSE)
20
- # locked :boolean default(FALSE)
20
+ # locked_at :datetime
21
21
  # locked_by :integer
22
22
  # restricted :boolean default(FALSE)
23
23
  # robot_index :boolean default(TRUE)
@@ -31,6 +31,8 @@
31
31
  # language_id :integer
32
32
  # cached_tag_list :text
33
33
  # published_at :datetime
34
+ # public_on :datetime
35
+ # public_until :datetime
34
36
  #
35
37
 
36
38
  module Alchemy
@@ -43,17 +45,32 @@ module Alchemy
43
45
  do_not_autogenerate: true,
44
46
  do_not_sweep: true,
45
47
  visible: false,
46
- public: false,
47
- locked: false,
48
+ public_on: nil,
49
+ public_until: nil,
50
+ locked_at: nil,
48
51
  locked_by: nil
49
52
  }
50
- SKIPPED_ATTRIBUTES_ON_COPY = %w(id updated_at created_at creator_id updater_id lft rgt depth urlname cached_tag_list)
53
+
54
+ SKIPPED_ATTRIBUTES_ON_COPY = %w(
55
+ id
56
+ updated_at
57
+ created_at
58
+ creator_id
59
+ updater_id
60
+ lft
61
+ rgt
62
+ depth
63
+ urlname
64
+ cached_tag_list
65
+ )
66
+
51
67
  PERMITTED_ATTRIBUTES = [
52
68
  :meta_description,
53
69
  :meta_keywords,
54
70
  :name,
55
71
  :page_layout,
56
- :public,
72
+ :public_on,
73
+ :public_until,
57
74
  :restricted,
58
75
  :robot_index,
59
76
  :robot_follow,
@@ -73,6 +90,7 @@ module Alchemy
73
90
  belongs_to :language
74
91
 
75
92
  has_one :site, through: :language
93
+ has_many :site_languages, through: :site, source: :languages
76
94
  has_many :folded_pages
77
95
  has_many :legacy_urls, class_name: 'Alchemy::LegacyPageUrl'
78
96
 
@@ -84,12 +102,29 @@ module Alchemy
84
102
  attr_accessor :do_not_sweep
85
103
  attr_accessor :do_not_validate_language
86
104
 
87
- before_save :set_language_code, if: -> { language.present? }, unless: :systempage?
88
- before_save :set_restrictions_to_child_pages, if: :restricted_changed?, unless: :systempage?
89
- before_save :inherit_restricted_status, if: -> { parent && parent.restricted? }, unless: :systempage?
90
- before_save :update_published_at, if: -> { public && read_attribute(:published_at).nil? }, unless: :systempage?
91
- before_create :set_language_from_parent_or_default, if: -> { language_id.blank? }, unless: :systempage?
92
- after_update :create_legacy_url, if: :urlname_changed?, unless: :redirects_to_external?
105
+ before_save :set_language_code,
106
+ if: -> { language.present? },
107
+ unless: :systempage?
108
+
109
+ before_save :set_restrictions_to_child_pages,
110
+ if: :restricted_changed?,
111
+ unless: :systempage?
112
+
113
+ before_save :inherit_restricted_status,
114
+ if: -> { parent && parent.restricted? },
115
+ unless: :systempage?
116
+
117
+ before_save :set_published_at,
118
+ if: -> { public? && published_at.nil? },
119
+ unless: :systempage?
120
+
121
+ before_create :set_language_from_parent_or_default,
122
+ if: -> { language_id.blank? },
123
+ unless: :systempage?
124
+
125
+ after_update :create_legacy_url,
126
+ if: :urlname_changed?,
127
+ unless: :redirects_to_external?
93
128
 
94
129
  # Concerns
95
130
  include Alchemy::Page::PageScopes
@@ -99,6 +134,9 @@ module Alchemy
99
134
  include Alchemy::Page::PageCells
100
135
  include Alchemy::Page::PageElements
101
136
 
137
+ # site_name accessor
138
+ delegate :name, to: :site, prefix: true, allow_nil: true
139
+
102
140
  # Class methods
103
141
  #
104
142
  class << self
@@ -281,16 +319,16 @@ module Alchemy
281
319
  end
282
320
  alias_method :next_page, :next
283
321
 
284
- # Locks the page to given user without updating the timestamps
322
+ # Locks the page to given user
285
323
  #
286
324
  def lock_to!(user)
287
- update_columns(locked: true, locked_by: user.id)
325
+ update_columns(locked_at: Time.current, locked_by: user.id)
288
326
  end
289
327
 
290
328
  # Unlocks the page without updating the timestamps
291
329
  #
292
330
  def unlock!
293
- if update_columns(locked: false, locked_by: nil)
331
+ if update_columns(locked_at: nil, locked_by: nil)
294
332
  Page.current_preview = nil
295
333
  end
296
334
  end
@@ -335,12 +373,18 @@ module Alchemy
335
373
 
336
374
  # Publishes the page.
337
375
  #
338
- # Sets +public+ to true and the +published_at+ value to current time.
376
+ # Sets +public_on+ and the +published_at+ value to current time
377
+ # and resets +public_until+ to nil
339
378
  #
340
379
  # The +published_at+ attribute is used as +cache_key+.
341
380
  #
342
381
  def publish!
343
- update_columns(published_at: Time.current, public: true)
382
+ current_time = Time.current
383
+ update_columns(
384
+ published_at: current_time,
385
+ public_on: current_time,
386
+ public_until: nil
387
+ )
344
388
  end
345
389
 
346
390
  # Updates an Alchemy::Page based on a new ordering to be applied to it
@@ -380,10 +424,9 @@ module Alchemy
380
424
  public: true
381
425
  }.update(options)
382
426
 
383
- self_and_siblings
384
- .where(["#{self.class.table_name}.lft #{dir} ?", lft])
385
- .where(public: options[:public])
386
- .where(restricted: options[:restricted])
427
+ pages = self_and_siblings.where(["#{Page.table_name}.lft #{dir} ?", lft])
428
+ pages = options[:public] ? pages.published : pages.not_public
429
+ pages.where(restricted: options[:restricted])
387
430
  .reorder(dir == '>' ? 'lft' : 'lft DESC')
388
431
  .limit(1).first
389
432
  end
@@ -402,7 +445,7 @@ module Alchemy
402
445
  legacy_urls.find_or_create_by(urlname: urlname_was)
403
446
  end
404
447
 
405
- def update_published_at
448
+ def set_published_at
406
449
  self.published_at = Time.current
407
450
  end
408
451
  end
@@ -2,6 +2,15 @@ module Alchemy
2
2
  module Page::PageNatures
3
3
  extend ActiveSupport::Concern
4
4
 
5
+ def public?
6
+ current_time = Time.current
7
+ already_public_for?(current_time) && still_public_for?(current_time)
8
+ end
9
+
10
+ def expiration_time
11
+ public_until? ? public_until - Time.current : nil
12
+ end
13
+
5
14
  def taggable?
6
15
  definition['taggable'] == true
7
16
  end
@@ -33,6 +42,11 @@ module Alchemy
33
42
  !PageLayout.get(page_layout).nil? && !PageLayout.get(page_layout)["controller"].blank?
34
43
  end
35
44
 
45
+ # True if page locked_at timestamp and locked_by id are set
46
+ def locked?
47
+ locked_by? && locked_at?
48
+ end
49
+
36
50
  def controller_and_action
37
51
  if has_controller?
38
52
  {
@@ -144,5 +158,13 @@ module Alchemy
144
158
  Alchemy::Config.get(:cache_pages) &&
145
159
  Rails.application.config.action_controller.perform_caching
146
160
  end
161
+
162
+ def already_public_for?(time)
163
+ !public_on.nil? && public_on <= time
164
+ end
165
+
166
+ def still_public_for?(time)
167
+ public_until.nil? || public_until >= time
168
+ end
147
169
  end
148
170
  end
@@ -15,7 +15,7 @@ module Alchemy
15
15
 
16
16
  # All locked pages
17
17
  #
18
- scope :locked, -> { where(locked: true) }
18
+ scope :locked, -> { where.not(locked_at: nil, locked_by: nil) }
19
19
 
20
20
  # All pages locked by given user
21
21
  #
@@ -27,16 +27,12 @@ module Alchemy
27
27
 
28
28
  # All not locked pages
29
29
  #
30
- scope :not_locked, -> { where(locked: false) }
30
+ scope :not_locked, -> { where(locked_at: nil, locked_by: nil) }
31
31
 
32
32
  # All visible pages
33
33
  #
34
34
  scope :visible, -> { where(visible: true) }
35
35
 
36
- # All public pages
37
- #
38
- scope :published, -> { where(public: true) }
39
-
40
36
  # All not restricted pages
41
37
  #
42
38
  scope :not_restricted, -> { where(restricted: false) }
@@ -99,5 +95,23 @@ module Alchemy
99
95
  #
100
96
  scope :sitemap, -> { from_current_site.published.contentpages.where(sitemap: true) }
101
97
  end
98
+
99
+ module ClassMethods
100
+ # All public pages
101
+ #
102
+ def published
103
+ where("#{table_name}.public_on <= :time AND " \
104
+ "(#{table_name}.public_until IS NULL " \
105
+ "OR #{table_name}.public_until >= :time)", time: Time.current)
106
+ end
107
+
108
+ # All not public pages
109
+ #
110
+ def not_public
111
+ where("#{table_name}.public_on IS NULL OR " \
112
+ "#{table_name}.public_on >= :time OR " \
113
+ "#{table_name}.public_until <= :time", time: Time.current)
114
+ end
115
+ end
102
116
  end
103
117
  end
@@ -3,22 +3,25 @@
3
3
  # Table name: alchemy_pictures
4
4
  #
5
5
  # id :integer not null, primary key
6
- # name :string(255)
7
- # image_file_name :string(255)
6
+ # name :string
7
+ # image_file_name :string
8
8
  # image_file_width :integer
9
9
  # image_file_height :integer
10
10
  # created_at :datetime not null
11
11
  # updated_at :datetime not null
12
12
  # creator_id :integer
13
13
  # updater_id :integer
14
- # upload_hash :string(255)
14
+ # upload_hash :string
15
15
  # cached_tag_list :text
16
- # image_file_uid :string(255)
16
+ # image_file_uid :string
17
17
  # image_file_size :integer
18
+ # image_file_format :string
18
19
  #
19
20
 
20
21
  module Alchemy
21
22
  class Picture < ActiveRecord::Base
23
+ CONVERTIBLE_FILE_FORMATS = %w(gif jpg jpeg png).freeze
24
+
22
25
  include Alchemy::NameConversions
23
26
  include Alchemy::Touching
24
27
  include Alchemy::Picture::Sweeping
@@ -183,6 +186,36 @@ module Alchemy
183
186
  convert_to_humanized_name(image_file_name, suffix)
184
187
  end
185
188
 
189
+ # Returns the format the image should be rendered with
190
+ #
191
+ # Only returns a format differing from original if an +image_output_format+
192
+ # is set in config and the image has a convertible file format.
193
+ #
194
+ def default_render_format
195
+ if convertible?
196
+ Config.get(:image_output_format)
197
+ else
198
+ image_file_format
199
+ end
200
+ end
201
+
202
+ # Returns true if the image can be converted
203
+ #
204
+ # If the +image_output_format+ is set to +nil+ or +original+ or the
205
+ # image has not a convertible file format (i.e. SVG) this returns +false+
206
+ #
207
+ def convertible?
208
+ Config.get(:image_output_format) &&
209
+ Config.get(:image_output_format) != 'original' &&
210
+ has_convertible_format?
211
+ end
212
+
213
+ # Returns true if the image can be converted into other formats
214
+ #
215
+ def has_convertible_format?
216
+ image_file_format.in?(CONVERTIBLE_FILE_FORMATS)
217
+ end
218
+
186
219
  # Checks if the picture is restricted.
187
220
  #
188
221
  # A picture is only restricted if it's assigned on restricted pages only.