alchemy_cms 3.0.4 → 3.1.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -6
  3. data/Gemfile +4 -7
  4. data/README.md +207 -115
  5. data/alchemy_cms.gemspec +10 -9
  6. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +2 -2
  7. data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +2 -2
  8. data/app/assets/javascripts/alchemy/alchemy.js +6 -7
  9. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +1 -43
  10. data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +1 -1
  11. data/app/assets/stylesheets/alchemy/_mixins.scss +2 -1
  12. data/app/assets/stylesheets/alchemy/buttons.scss +0 -5
  13. data/app/assets/stylesheets/alchemy/dialogs.scss +1 -0
  14. data/app/assets/stylesheets/alchemy/frame.scss +9 -12
  15. data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +11 -2
  16. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +9 -1
  17. data/app/controllers/alchemy/admin/attachments_controller.rb +2 -4
  18. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +34 -38
  19. data/app/controllers/alchemy/api/base_controller.rb +19 -0
  20. data/app/controllers/alchemy/api/contents_controller.rb +35 -0
  21. data/app/controllers/alchemy/api/elements_controller.rb +29 -0
  22. data/app/controllers/alchemy/api/pages_controller.rb +32 -0
  23. data/app/controllers/alchemy/contents_controller.rb +1 -0
  24. data/app/controllers/alchemy/elements_controller.rb +5 -2
  25. data/app/controllers/alchemy/pages_controller.rb +4 -1
  26. data/app/controllers/alchemy/pictures_controller.rb +4 -36
  27. data/app/helpers/alchemy/admin/essences_helper.rb +5 -2
  28. data/app/helpers/alchemy/essences_helper.rb +14 -1
  29. data/app/models/alchemy/content.rb +32 -4
  30. data/app/models/alchemy/element.rb +2 -16
  31. data/app/models/alchemy/element/presenters.rb +2 -2
  32. data/app/models/alchemy/essence_file.rb +5 -0
  33. data/app/models/alchemy/essence_picture.rb +12 -8
  34. data/app/models/alchemy/picture.rb +1 -74
  35. data/app/models/alchemy/picture/transformations.rb +249 -0
  36. data/app/serializers/alchemy/content_serializer.rb +3 -10
  37. data/app/serializers/alchemy/element_serializer.rb +6 -3
  38. data/app/serializers/alchemy/legacy_element_serializer.rb +17 -0
  39. data/app/views/alchemy/admin/dashboard/_sites.html.erb +14 -4
  40. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +8 -5
  41. data/app/views/alchemy/admin/pages/edit.html.erb +9 -9
  42. data/app/views/alchemy/admin/pictures/info.html.erb +2 -3
  43. data/app/views/alchemy/admin/tags/edit.html.erb +1 -1
  44. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +8 -7
  45. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +3 -3
  46. data/app/views/alchemy/essences/_essence_date_editor.html.erb +8 -2
  47. data/app/views/alchemy/essences/_essence_date_view.html.erb +10 -8
  48. data/app/views/alchemy/essences/_essence_file_editor.html.erb +48 -53
  49. data/app/views/alchemy/essences/_essence_file_view.html.erb +5 -5
  50. data/app/views/alchemy/essences/_essence_html_editor.html.erb +5 -4
  51. data/app/views/alchemy/essences/_essence_link_editor.html.erb +17 -15
  52. data/app/views/alchemy/essences/_essence_link_view.html.erb +11 -7
  53. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +4 -2
  54. data/app/views/alchemy/essences/_essence_picture_view.html.erb +4 -2
  55. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +5 -4
  56. data/app/views/alchemy/essences/_essence_select_editor.html.erb +22 -32
  57. data/app/views/alchemy/essences/_essence_text_view.html.erb +7 -6
  58. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +1 -1
  59. data/app/views/layouts/alchemy/admin.html.erb +5 -3
  60. data/config/initializers/inflections.rb +3 -0
  61. data/config/initializers/simple_form.rb +1 -1
  62. data/config/locales/alchemy.en.yml +0 -1
  63. data/config/routes.rb +14 -0
  64. data/lib/alchemy/capistrano.rb +71 -0
  65. data/lib/alchemy/engine.rb +0 -3
  66. data/lib/alchemy/essence.rb +1 -1
  67. data/lib/alchemy/permissions.rb +19 -5
  68. data/lib/alchemy/picture_attributes.rb +1 -1
  69. data/lib/alchemy/test_support/auth_helpers.rb +1 -1
  70. data/lib/alchemy/test_support/essence_shared_examples.rb +37 -22
  71. data/lib/alchemy/test_support/integration_helpers.rb +1 -1
  72. data/lib/alchemy/tinymce.rb +21 -4
  73. data/lib/alchemy/upgrader/three_point_one.rb +43 -0
  74. data/lib/alchemy/upgrader/three_point_zero.rb +13 -0
  75. data/lib/alchemy/version.rb +2 -1
  76. data/lib/rails/generators/alchemy/module/module_generator.rb +30 -0
  77. data/lib/rails/generators/alchemy/module/templates/ability.rb.tt +11 -0
  78. data/lib/rails/generators/alchemy/module/templates/controller.rb.tt +2 -0
  79. data/lib/rails/generators/alchemy/module/templates/module_config.rb.tt +15 -0
  80. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +0 -1
  81. data/lib/rails/templates/alchemy.rb +2 -2
  82. data/lib/tasks/alchemy/db.rake +7 -1
  83. data/spec/controllers/admin/attachments_controller_spec.rb +38 -38
  84. data/spec/controllers/admin/base_controller_spec.rb +18 -18
  85. data/spec/controllers/admin/clipboard_controller_spec.rb +23 -18
  86. data/spec/controllers/admin/contents_controller_spec.rb +33 -27
  87. data/spec/controllers/admin/dashboard_controller_spec.rb +14 -14
  88. data/spec/controllers/admin/elements_controller_spec.rb +125 -105
  89. data/spec/controllers/admin/essence_files_controller_spec.rb +6 -7
  90. data/spec/controllers/admin/essence_pictures_controller_spec.rb +52 -42
  91. data/spec/controllers/admin/languages_controller_spec.rb +3 -3
  92. data/spec/controllers/admin/pages_controller_spec.rb +81 -71
  93. data/spec/controllers/admin/pictures_controller_spec.rb +69 -72
  94. data/spec/controllers/admin/resources_controller_spec.rb +5 -5
  95. data/spec/controllers/admin/trash_controller_spec.rb +15 -12
  96. data/spec/controllers/alchemy/admin/tags_controller_spec.rb +8 -8
  97. data/spec/controllers/alchemy/api/contents_controller_spec.rb +73 -0
  98. data/spec/controllers/alchemy/api/elements_controller_spec.rb +69 -0
  99. data/spec/controllers/alchemy/api/pages_controller_spec.rb +86 -0
  100. data/spec/controllers/attachments_controller_spec.rb +8 -8
  101. data/spec/controllers/contents_controller_spec.rb +22 -0
  102. data/spec/controllers/elements_controller_spec.rb +10 -4
  103. data/spec/controllers/messages_controller_spec.rb +35 -34
  104. data/spec/controllers/pages_controller_spec.rb +37 -28
  105. data/spec/controllers/pictures_controller_spec.rb +90 -23
  106. data/spec/dummy/app/models/dummy_user.rb +0 -4
  107. data/spec/dummy/app/views/alchemy/elements/_all_you_can_eat_editor.html.erb +11 -0
  108. data/spec/dummy/config/alchemy/elements.yml +22 -1
  109. data/spec/dummy/config/alchemy/page_layouts.yml +4 -0
  110. data/spec/dummy/config/application.rb +2 -1
  111. data/spec/dummy/config/environments/test.rb +3 -1
  112. data/spec/features/admin/dashboard_spec.rb +41 -6
  113. data/spec/features/admin/language_tree_feature_spec.rb +3 -3
  114. data/spec/features/admin/legacy_page_url_management_spec.rb +1 -1
  115. data/spec/features/admin/link_overlay_spec.rb +7 -7
  116. data/spec/features/admin/locale_select_feature_spec.rb +5 -2
  117. data/spec/features/admin/modules_integration_spec.rb +1 -1
  118. data/spec/features/admin/page_creation_feature_spec.rb +3 -2
  119. data/spec/features/admin/page_editing_feature_spec.rb +66 -79
  120. data/spec/features/admin/picture_library_integration_spec.rb +8 -8
  121. data/spec/features/admin/resources_integration_spec.rb +21 -21
  122. data/spec/features/admin/tinymce_feature_spec.rb +36 -0
  123. data/spec/features/navigation_spec.rb +1 -1
  124. data/spec/features/page_feature_spec.rb +34 -34
  125. data/spec/features/picture_security_spec.rb +4 -4
  126. data/spec/features/security_spec.rb +1 -1
  127. data/spec/features/translation_integration_spec.rb +7 -7
  128. data/spec/helpers/admin/base_helper_spec.rb +51 -49
  129. data/spec/helpers/admin/contents_helper_spec.rb +11 -11
  130. data/spec/helpers/admin/elements_helper_spec.rb +20 -17
  131. data/spec/helpers/admin/essences_helper_spec.rb +42 -11
  132. data/spec/helpers/admin/navigation_helper_spec.rb +64 -54
  133. data/spec/helpers/admin/pages_helper_spec.rb +10 -10
  134. data/spec/helpers/admin/tags_helper_spec.rb +16 -16
  135. data/spec/helpers/base_helper_spec.rb +11 -11
  136. data/spec/helpers/elements_block_helper_spec.rb +24 -24
  137. data/spec/helpers/elements_helper_spec.rb +46 -46
  138. data/spec/helpers/essences_helper_spec.rb +90 -17
  139. data/spec/helpers/pages_helper_spec.rb +53 -53
  140. data/spec/helpers/picture_url_helpers_spec.rb +6 -6
  141. data/spec/helpers/url_helper_spec.rb +32 -32
  142. data/spec/libraries/config_spec.rb +9 -9
  143. data/spec/libraries/controller_actions_spec.rb +14 -14
  144. data/spec/libraries/i18n_spec.rb +6 -6
  145. data/spec/libraries/kaminari/scoped_pagination_url_helper_spec.rb +4 -4
  146. data/spec/libraries/modules_spec.rb +4 -4
  147. data/spec/libraries/mount_point_spec.rb +13 -13
  148. data/spec/libraries/page_layout_spec.rb +24 -24
  149. data/spec/libraries/permissions_spec.rb +97 -80
  150. data/spec/libraries/resource_spec.rb +37 -37
  151. data/spec/libraries/resources_helper_spec.rb +19 -19
  152. data/spec/libraries/shell_spec.rb +17 -17
  153. data/spec/libraries/template_tracker_spec.rb +14 -14
  154. data/spec/libraries/tinymce_spec.rb +8 -8
  155. data/spec/libraries/userstamp_spec.rb +2 -2
  156. data/spec/mailers/messages_spec.rb +4 -4
  157. data/spec/models/attachment_spec.rb +86 -30
  158. data/spec/models/cell_spec.rb +10 -10
  159. data/spec/models/content_spec.rb +106 -46
  160. data/spec/models/element_spec.rb +94 -115
  161. data/spec/models/essence_date_spec.rb +1 -1
  162. data/spec/models/essence_file_spec.rb +4 -4
  163. data/spec/models/essence_picture_spec.rb +56 -25
  164. data/spec/models/essence_richtext_spec.rb +1 -1
  165. data/spec/models/essence_text_spec.rb +7 -7
  166. data/spec/models/language_spec.rb +12 -12
  167. data/spec/models/legacy_page_url_spec.rb +2 -2
  168. data/spec/models/message_spec.rb +12 -5
  169. data/spec/models/page_spec.rb +259 -235
  170. data/spec/models/picture_spec.rb +72 -166
  171. data/spec/models/site_spec.rb +41 -41
  172. data/spec/models/tag_spec.rb +7 -7
  173. data/spec/routing/api_routing_spec.rb +150 -0
  174. data/spec/routing/routing_spec.rb +28 -28
  175. data/spec/spec_helper.rb +6 -5
  176. data/spec/support/hint_examples.rb +5 -5
  177. data/spec/support/transformation_examples.rb +173 -0
  178. data/spec/tasks/helpers_spec.rb +29 -29
  179. data/spec/views/essences/essence_boolean_editor_spec.rb +32 -0
  180. data/spec/views/essences/essence_boolean_view_spec.rb +2 -2
  181. data/spec/views/essences/essence_date_view_spec.rb +1 -1
  182. data/spec/views/essences/essence_link_view_spec.rb +11 -0
  183. data/spec/views/essences/essence_picture_view_spec.rb +56 -11
  184. data/spec/views/essences/essence_richtext_view_spec.rb +12 -0
  185. data/spec/views/essences/essence_text_view_spec.rb +12 -0
  186. data/vendor/assets/javascripts/tinymce/langs/de.js +20 -2
  187. data/vendor/assets/javascripts/tinymce/langs/fr.js +14 -1
  188. data/vendor/assets/javascripts/tinymce/langs/nl.js +22 -4
  189. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.min.js +1 -1
  190. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.min.js +1 -1
  191. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.min.js +1 -1
  192. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.min.js +1 -1
  193. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.min.js +1 -1
  194. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.min.js +1 -1
  195. data/vendor/assets/javascripts/tinymce/plugins/hr/plugin.min.js +1 -1
  196. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.min.js +1 -1
  197. data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.min.js +1 -1
  198. data/vendor/assets/javascripts/tinymce/plugins/tabfocus/plugin.min.js +1 -1
  199. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.min.js +1 -1
  200. data/vendor/assets/javascripts/tinymce/themes/modern/theme.min.js +1 -1
  201. data/vendor/assets/javascripts/tinymce/tinymce.min.js +11 -10
  202. metadata +72 -42
  203. data/app/views/alchemy/messages/contact_form_mail.es.text.erb +0 -12
  204. data/config/locales/alchemy.es.yml +0 -958
  205. data/config/locales/alchemy.ru.yml +0 -837
  206. data/config/locales/simple_form.es.yml +0 -6
  207. data/config/locales/simple_form.ru.yml +0 -25
  208. data/lib/rails/generators/alchemy/scaffold/files/alchemy.es.yml +0 -31
  209. data/vendor/assets/javascripts/tinymce/langs/es.js +0 -197
  210. data/vendor/assets/javascripts/tinymce/langs/ru.js +0 -197
@@ -85,9 +85,6 @@ module Alchemy
85
85
 
86
86
  config.after_initialize do
87
87
  require_relative './userstamp'
88
- end
89
-
90
- config.to_prepare do
91
88
  # In order to have Alchemy's helpers and basic controller methods
92
89
  # available in the host app, we patch the ApplicationController.
93
90
  ApplicationController.send(:include, Alchemy::ControllerActions)
@@ -113,7 +113,7 @@ module Alchemy #:nodoc:
113
113
  def validate_ingredient
114
114
  validations.each do |validation|
115
115
  if validation.respond_to?(:keys)
116
- validation.map {|key,value| self.send("validate_#{key}", validation) }
116
+ validation.map { |key, _value| self.send("validate_#{key}", validation) }
117
117
  else
118
118
  self.send("validate_#{validation}")
119
119
  end
@@ -36,8 +36,15 @@ module Alchemy
36
36
  module GuestUser
37
37
  def alchemy_guest_user_rules
38
38
  can([:show, :download], Alchemy::Attachment) { |a| !a.restricted? }
39
- can :show, Alchemy::Element, public: true, page: { restricted: false }
40
- can :show, Alchemy::Page, restricted: false, public: true
39
+ can :read, Alchemy::Content, Alchemy::Content.available.not_restricted do |c|
40
+ c.public? && !c.restricted? && !c.trashed?
41
+ end
42
+ can :read, Alchemy::Element, Alchemy::Element.available.not_restricted do |e|
43
+ e.public? && !e.restricted? && !e.trashed?
44
+ end
45
+ can :read, Alchemy::Page, Alchemy::Page.published.not_restricted do |p|
46
+ p.public? && !p.restricted?
47
+ end
41
48
  can :see, Alchemy::Page, restricted: false, visible: true
42
49
  can([:show, :download], Alchemy::Picture) { |p| !p.restricted? }
43
50
  end
@@ -55,8 +62,15 @@ module Alchemy
55
62
 
56
63
  # Resources
57
64
  can [:show, :download], Alchemy::Attachment
58
- can :show, Alchemy::Element, public: true, page: { restricted: true }
59
- can :show, Alchemy::Page, public: true
65
+ can :read, Alchemy::Content, Alchemy::Content.available do |c|
66
+ c.public? && !c.trashed?
67
+ end
68
+ can :read, Alchemy::Element, Alchemy::Element.available do |e|
69
+ e.public? && !e.trashed?
70
+ end
71
+ can :read, Alchemy::Page, Alchemy::Page.published do |p|
72
+ p.public?
73
+ end
60
74
  can :see, Alchemy::Page, restricted: true, visible: true
61
75
  can [:show, :download], Alchemy::Picture
62
76
  can [:read, :update], Alchemy.user_class, id: @user.id
@@ -130,7 +144,6 @@ module Alchemy
130
144
  :destroy,
131
145
  :flush,
132
146
  :order,
133
- :publish,
134
147
  :sort,
135
148
  :switch_language
136
149
  ], Alchemy::Page
@@ -183,6 +196,7 @@ module Alchemy
183
196
  :fold,
184
197
  :info,
185
198
  :link,
199
+ :publish,
186
200
  :read,
187
201
  :update,
188
202
  :unlock,
@@ -3,7 +3,7 @@ module Alchemy
3
3
  #
4
4
  class PictureAttributes
5
5
 
6
- SECURE_ATTRIBUTES = %w(id size crop crop_from crop_size quality).freeze
6
+ SECURE_ATTRIBUTES = %w(id size crop crop_from crop_size quality upsample).freeze
7
7
 
8
8
  class << self
9
9
 
@@ -6,7 +6,7 @@ module Alchemy
6
6
  module AuthHelpers
7
7
 
8
8
  def sign_in(user = admin_user)
9
- controller.stub current_alchemy_user: user
9
+ allow(controller).to receive(:current_alchemy_user).and_return user
10
10
  end
11
11
 
12
12
  def member_user
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  shared_examples_for "an essence" do
4
-
5
4
  let(:element) { Alchemy::Element.new }
6
5
  let(:content) { Alchemy::Content.new(name: 'foo') }
7
6
  let(:content_description) { {'name' => 'foo'} }
@@ -9,10 +8,10 @@ shared_examples_for "an essence" do
9
8
  it "touches the content after update" do
10
9
  essence.save
11
10
  content.update(essence: essence, essence_type: essence.class.name)
12
- d = content.updated_at
11
+ date = content.updated_at
13
12
  content.essence.update(essence.ingredient_column.to_sym => ingredient_value)
14
13
  content.reload
15
- content.updated_at.should_not eq(d)
14
+ expect(content.updated_at).not_to eq(date)
16
15
  end
17
16
 
18
17
  it "should have correct partial path" do
@@ -24,33 +23,39 @@ shared_examples_for "an essence" do
24
23
  subject { essence.description }
25
24
 
26
25
  context 'without element' do
27
- it { should eq({}) }
26
+ it { is_expected.to eq({}) }
28
27
  end
29
28
 
30
29
  context 'with element' do
31
- before { essence.stub(element: element) }
30
+ before do
31
+ expect(essence).to receive(:element).at_least(:once).and_return(element)
32
+ end
32
33
 
33
34
  context 'but without content descriptions' do
34
- it { should eq({}) }
35
+ it { is_expected.to eq({}) }
35
36
  end
36
37
 
37
38
  context 'and content descriptions' do
38
39
  before do
39
- essence.stub(content: content)
40
+ allow(essence).to receive(:content).and_return(content)
40
41
  end
41
42
 
42
43
  context 'containing the content name' do
43
- before { element.stub(content_descriptions: [content_description]) }
44
+ before do
45
+ expect(element).to receive(:content_descriptions).at_least(:once).and_return([content_description])
46
+ end
44
47
 
45
48
  it "returns the content description" do
46
- should eq(content_description)
49
+ is_expected.to eq(content_description)
47
50
  end
48
51
  end
49
52
 
50
53
  context 'not containing the content name' do
51
- before { element.stub(content_descriptions: []) }
54
+ before do
55
+ expect(element).to receive(:content_descriptions).at_least(:once).and_return([])
56
+ end
52
57
 
53
- it { should eq({}) }
58
+ it { is_expected.to eq({}) }
54
59
  end
55
60
  end
56
61
  end
@@ -66,25 +71,27 @@ shared_examples_for "an essence" do
66
71
  describe 'validations' do
67
72
  context 'without essence description in elements.yml' do
68
73
  it 'should return an empty array' do
69
- essence.stub(:description).and_return nil
74
+ allow(essence).to receive(:description).and_return nil
70
75
  expect(essence.validations).to eq([])
71
76
  end
72
77
  end
73
78
 
74
79
  context 'without validations defined in essence description in elements.yml' do
75
80
  it 'should return an empty array' do
76
- essence.stub(:description).and_return({name: 'test', type: 'EssenceText'})
81
+ allow(essence).to receive(:description).and_return({name: 'test', type: 'EssenceText'})
77
82
  expect(essence.validations).to eq([])
78
83
  end
79
84
  end
80
85
 
81
86
  describe 'presence' do
82
87
  before do
83
- essence.stub(:description).and_return({'validate' => ['presence']})
88
+ allow(essence).to receive(:description).and_return({'validate' => ['presence']})
84
89
  end
85
90
 
86
91
  context 'when the ingredient column is empty' do
87
- before { essence.update(essence.ingredient_column.to_sym => nil) }
92
+ before do
93
+ essence.update(essence.ingredient_column.to_sym => nil)
94
+ end
88
95
 
89
96
  it 'should not be valid' do
90
97
  expect(essence).to_not be_valid
@@ -92,7 +99,9 @@ shared_examples_for "an essence" do
92
99
  end
93
100
 
94
101
  context 'when the ingredient column is not nil' do
95
- before { essence.update(essence.ingredient_column.to_sym => ingredient_value) }
102
+ before do
103
+ essence.update(essence.ingredient_column.to_sym => ingredient_value)
104
+ end
96
105
 
97
106
  it 'should be valid' do
98
107
  expect(essence).to be_valid
@@ -102,20 +111,24 @@ shared_examples_for "an essence" do
102
111
 
103
112
  describe 'uniqueness' do
104
113
  before do
105
- essence.stub(element: build_stubbed(:element))
106
- essence.stub(:description).and_return({'validate' => ['uniqueness']})
114
+ allow(essence).to receive(:element).and_return(build_stubbed(:element))
115
+ expect(essence).to receive(:description).at_least(:once).and_return({'validate' => ['uniqueness']})
107
116
  essence.update(essence.ingredient_column.to_sym => ingredient_value)
108
117
  end
109
118
 
110
119
  context 'when a duplicate exists' do
111
- before { essence.stub(:duplicates).and_return([essence.dup]) }
120
+ before do
121
+ allow(essence).to receive(:duplicates).and_return([essence.dup])
122
+ end
112
123
 
113
124
  it 'should not be valid' do
114
125
  expect(essence).to_not be_valid
115
126
  end
116
127
 
117
128
  context 'when validated essence is not public' do
118
- before { essence.stub(public?: false) }
129
+ before do
130
+ expect(essence).to receive(:public?).and_return(false)
131
+ end
119
132
 
120
133
  it 'should be valid' do
121
134
  expect(essence).to be_valid
@@ -124,7 +137,9 @@ shared_examples_for "an essence" do
124
137
  end
125
138
 
126
139
  context 'when no duplicate exists' do
127
- before { essence.stub(:duplicates).and_return([]) }
140
+ before do
141
+ expect(essence).to receive(:duplicates).and_return([])
142
+ end
128
143
 
129
144
  it 'should be valid' do
130
145
  expect(essence).to be_valid
@@ -134,7 +149,7 @@ shared_examples_for "an essence" do
134
149
 
135
150
  describe '#acts_as_essence?' do
136
151
  it 'should return true' do
137
- expect(essence.acts_as_essence?).to be_true
152
+ expect(essence.acts_as_essence?).to be_truthy
138
153
  end
139
154
  end
140
155
  end
@@ -19,7 +19,7 @@ module Alchemy
19
19
  if !user
20
20
  user = mock_model('DummyUser', alchemy_roles: %w(admin), language: 'en')
21
21
  end
22
- ApplicationController.any_instance.stub(:current_user).and_return(user)
22
+ allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user)
23
23
  end
24
24
  end
25
25
 
@@ -12,15 +12,21 @@ module Alchemy
12
12
  autoresize_max_height: '480',
13
13
  menubar: false,
14
14
  statusbar: true,
15
- toolbar1: 'bold italic underline | strikethrough subscript superscript | numlist bullist indent outdent | removeformat | fullscreen',
16
- toolbar2: 'pastetext charmap hr | undo redo | alchemy_link unlink anchor | code',
15
+ toolbar: [
16
+ 'bold italic underline | strikethrough subscript superscript | numlist bullist indent outdent | removeformat | fullscreen',
17
+ 'pastetext charmap hr | undo redo | alchemy_link unlink anchor | code'
18
+ ],
17
19
  fix_list_elements: true,
18
20
  convert_urls: false,
19
21
  entity_encoding: 'raw',
22
+ paste_as_text: true,
20
23
  element_format: 'html'
21
24
  }
22
25
 
23
26
  def self.init=(settings)
27
+ if contains_old_tinymce_toolbar_config?('tinymce' => settings.stringify_keys)
28
+ warn_about_deprecation!
29
+ end
24
30
  @@init.merge!(settings)
25
31
  end
26
32
 
@@ -30,10 +36,14 @@ module Alchemy
30
36
 
31
37
  def self.custom_config_contents(page = nil)
32
38
  if page
33
- content_definitions_from_elements(page.element_definitions)
39
+ definitions = content_definitions_from_elements(page.element_definitions)
34
40
  else
35
- content_definitions_from_elements(Element.definitions)
41
+ definitions = content_definitions_from_elements(Element.definitions)
42
+ end
43
+ if definitions.any? { |d| contains_old_tinymce_toolbar_config?(d['settings']) }
44
+ warn_about_deprecation!
36
45
  end
46
+ definitions
37
47
  end
38
48
 
39
49
  private
@@ -47,5 +57,12 @@ module Alchemy
47
57
  end.flatten.compact
48
58
  end
49
59
 
60
+ def self.contains_old_tinymce_toolbar_config?(settings)
61
+ settings['tinymce'] && settings['tinymce'].keys.any? { |k| k.match(/toolbar[0-9]/) }
62
+ end
63
+
64
+ def self.warn_about_deprecation!
65
+ ActiveSupport::Deprecation.warn("You use old TinyMCE 4.0 based toolbar config! Please consider to upgrade it to 4.1 compatible syntax. I.e. don't use 'toolbarN', use 'toolbar' with array instead. Visit http://www.tinymce.com/wiki.php/Configuration:toolbar for more information.")
66
+ end
50
67
  end
51
68
  end
@@ -0,0 +1,43 @@
1
+ module Alchemy
2
+ module Upgrader::ThreePointOne
3
+ private
4
+
5
+ def alchemy_3_1_todos
6
+ notice = <<-NOTE
7
+
8
+ JSON API moved into '/api' namespace
9
+ ------------------------------------
10
+
11
+ The JSON API now lives under /api and not as additional format to default controllers.
12
+ Also the serialization changed into more useful payload.
13
+
14
+ Please upgrade your API calls to use the new /api namespace.
15
+
16
+
17
+ TinyMCE default paste behavior changed
18
+ --------------------------------------
19
+
20
+ Text is now always pasted in as plain text. To change this, the user has to
21
+ disable it with the toolbar button, as they had to before to enable it.
22
+
23
+ If you have a custom TinyMCE configuration you have to enable this by adding
24
+
25
+ paste_as_text: true
26
+
27
+ into you custom TinyMCE configuration.
28
+
29
+
30
+ TinyMCE toolbar config has changed
31
+ ----------------------------------
32
+
33
+ The 'toolbar' configuration now takes an array of toolbar rows, instead of
34
+ using 'toolbarN' syntax. Please update your TinyMCE configuration.
35
+
36
+ Visit http://www.tinymce.com/wiki.php/Configuration:toolbar for more information.
37
+
38
+ NOTE
39
+ todo notice, 'Alchemy v3.1 changes'
40
+ end
41
+
42
+ end
43
+ end
@@ -16,6 +16,19 @@ module Alchemy
16
16
  end
17
17
  end
18
18
 
19
+ def publish_unpublished_public_pages
20
+ desc 'Sets `published_at` of public pages without a `published_at` date set to their `updated_at` value'
21
+ public_pages = Alchemy::Page.published.where('published_at IS NULL')
22
+ if public_pages.any?
23
+ public_pages.each do |page|
24
+ page.update_column(:published_at, page.updated_at)
25
+ log "Sets `published_at` of #{page.name} to #{page.updated_at}"
26
+ end
27
+ else
28
+ log 'No unpublished public pages found.', :skip
29
+ end
30
+ end
31
+
19
32
  def alchemy_3_todos
20
33
  notice = <<-NOTE
21
34
 
@@ -1,7 +1,8 @@
1
1
  module Alchemy
2
- VERSION = "3.0.4"
2
+ VERSION = "3.1.0.beta1"
3
3
 
4
4
  def self.version
5
5
  VERSION
6
6
  end
7
+
7
8
  end
@@ -0,0 +1,30 @@
1
+ require 'rails'
2
+
3
+ module Alchemy
4
+ module Generators
5
+ class ModuleGenerator < ::Rails::Generators::Base
6
+ desc "This generator generates an Alchemy module for you."
7
+ argument :module_name, :banner => "your_module_name"
8
+ source_root File.expand_path('templates', File.dirname(__FILE__))
9
+
10
+ def init
11
+ @module_name = module_name.downcase
12
+ @class_name = @module_name.singularize.classify
13
+ @controller_name = @module_name.tableize
14
+ @controller_class = @controller_name.classify.pluralize
15
+ end
16
+
17
+ def make_route
18
+ route "namespace :admin do\n resources :#{@controller_name}\n end"
19
+ end
20
+
21
+ def copy_templates
22
+ empty_directory Rails.root.join("app/controllers/admin")
23
+
24
+ template "controller.rb.tt", Rails.root.join("app/controllers/admin/#{@controller_name}_controller.rb")
25
+ template "ability.rb.tt", Rails.root.join('app/models', "alchemy_#{@module_name}_ability.rb")
26
+ template "module_config.rb.tt", Rails.root.join("config/initializers/alchemy_#{@module_name}.rb")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,11 @@
1
+ class <%= @class_name %>Ability
2
+ include CanCan::Ability
3
+
4
+ def initialize(user)
5
+ if user.present? && user.is_admin?
6
+ can :manage, <%= @class_name %>
7
+ can :manage, :admin_<%= @controller_name %>
8
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,2 @@
1
+ class Admin::<%= @controller_class %>Controller < Alchemy::Admin::ResourcesController
2
+ end
@@ -0,0 +1,15 @@
1
+ Alchemy::Modules.register_module({
2
+ name: '<%= @module_name %>',
3
+ order: 1,
4
+ navigation: {
5
+ name: 'modules.<%= @module_name %>',
6
+ controller: '/admin/<%= @module_name %>',
7
+ action: 'index',
8
+ image: '/assets/<%= @module_name %>.png',
9
+ sub_navigation: [{
10
+ name: 'modules.<%= @module_name %>',
11
+ controller: '/admin/<%= @module_name %>',
12
+ action: 'index'
13
+ }]
14
+ }
15
+ })