spontaneous 0.2.0.beta4 → 0.2.0.beta5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/Gemfile +11 -6
- data/Readme.markdown +136 -69
- data/application/css/core.css.scss +27 -7
- data/application/css/editing.css.scss +4 -26
- data/application/css/schema_error.css.scss +22 -0
- data/application/js/content.js +11 -3
- data/application/js/edit_panel.js +1 -4
- data/application/js/field/file.js +17 -0
- data/application/js/field/image.js +30 -21
- data/application/js/field/string.js +4 -1
- data/application/js/field_preview.js +21 -16
- data/application/js/publish.js +6 -6
- data/application/js/types.js +5 -13
- data/application/js/views.js +2 -2
- data/application/js/views/box_view.js +3 -2
- data/application/js/views/page_piece_view.js +1 -1
- data/application/js/views/piece_view.js +1 -1
- data/application/views/schema_modification_error.html.erb +13 -3
- data/db/migrations/20131104101935_site_must_publish_all.rb +14 -0
- data/lib/spontaneous.rb +0 -1
- data/lib/spontaneous/box_style.rb +15 -9
- data/lib/spontaneous/capistrano/deploy.rb +13 -1
- data/lib/spontaneous/change.rb +11 -13
- data/lib/spontaneous/cli.rb +5 -2
- data/lib/spontaneous/cli/assets.rb +7 -1
- data/lib/spontaneous/cli/console.rb +7 -1
- data/lib/spontaneous/cli/content.rb +35 -0
- data/lib/spontaneous/cli/fields.rb +3 -2
- data/lib/spontaneous/cli/generate.rb +5 -2
- data/lib/spontaneous/cli/server.rb +12 -8
- data/lib/spontaneous/cli/site.rb +12 -12
- data/lib/spontaneous/cli/user.rb +28 -14
- data/lib/spontaneous/collections/box_set.rb +4 -4
- data/lib/spontaneous/collections/field_set.rb +4 -4
- data/lib/spontaneous/collections/prototype_set.rb +12 -4
- data/lib/spontaneous/data_mapper.rb +11 -7
- data/lib/spontaneous/data_mapper/content_model.rb +8 -0
- data/lib/spontaneous/data_mapper/content_model/associations.rb +1 -1
- data/lib/spontaneous/data_mapper/dataset.rb +14 -2
- data/lib/spontaneous/data_mapper/scope.rb +33 -13
- data/lib/spontaneous/facet.rb +4 -0
- data/lib/spontaneous/field.rb +12 -12
- data/lib/spontaneous/field/base.rb +27 -22
- data/lib/spontaneous/field/boolean.rb +4 -4
- data/lib/spontaneous/field/date.rb +2 -2
- data/lib/spontaneous/field/file.rb +24 -18
- data/lib/spontaneous/field/html.rb +1 -1
- data/lib/spontaneous/field/image.rb +6 -19
- data/lib/spontaneous/field/location.rb +1 -1
- data/lib/spontaneous/field/long_string.rb +3 -3
- data/lib/spontaneous/field/markdown.rb +3 -3
- data/lib/spontaneous/field/select.rb +2 -2
- data/lib/spontaneous/field/string.rb +2 -2
- data/lib/spontaneous/field/tags.rb +2 -2
- data/lib/spontaneous/field/update.rb +21 -20
- data/lib/spontaneous/field/webvideo.rb +6 -6
- data/lib/spontaneous/field/webvideo/fallback.rb +2 -2
- data/lib/spontaneous/field/webvideo/vimeo.rb +7 -7
- data/lib/spontaneous/generators/site.rb +2 -2
- data/lib/spontaneous/generators/site/Gemfile.tt +5 -1
- data/lib/spontaneous/layout.rb +2 -2
- data/lib/spontaneous/media.rb +1 -0
- data/lib/spontaneous/media/file.rb +6 -5
- data/lib/spontaneous/media/image/attributes.rb +4 -0
- data/lib/spontaneous/media/image/renderable.rb +4 -4
- data/lib/spontaneous/media/store.rb +22 -0
- data/lib/spontaneous/{storage → media/store}/backend.rb +1 -1
- data/lib/spontaneous/{storage → media/store}/cloud.rb +1 -1
- data/lib/spontaneous/{storage → media/store}/local.rb +1 -1
- data/lib/spontaneous/media/temp_file.rb +1 -1
- data/lib/spontaneous/model.rb +10 -7
- data/lib/spontaneous/model/action.rb +7 -0
- data/lib/spontaneous/model/action/clean.rb +87 -0
- data/lib/spontaneous/model/box/allowed_types.rb +15 -1
- data/lib/spontaneous/model/core.rb +10 -0
- data/lib/spontaneous/model/core/aliases.rb +1 -1
- data/lib/spontaneous/model/core/content_groups.rb +1 -1
- data/lib/spontaneous/model/core/fields.rb +1 -1
- data/lib/spontaneous/model/core/modifications.rb +2 -2
- data/lib/spontaneous/model/core/page_search.rb +4 -0
- data/lib/spontaneous/model/core/publishing.rb +4 -17
- data/lib/spontaneous/model/core/render.rb +4 -4
- data/lib/spontaneous/model/core/styles.rb +2 -2
- data/lib/spontaneous/model/core/visibility.rb +6 -2
- data/lib/spontaneous/model/page.rb +6 -2
- data/lib/spontaneous/model/page/controllers.rb +55 -17
- data/lib/spontaneous/model/page/formats.rb +12 -7
- data/lib/spontaneous/model/page/layouts.rb +2 -2
- data/lib/spontaneous/model/page/locks.rb +4 -1
- data/lib/spontaneous/model/page/page_tree.rb +40 -6
- data/lib/spontaneous/output.rb +14 -52
- data/lib/spontaneous/output/context.rb +11 -39
- data/lib/spontaneous/output/context/navigation.rb +31 -0
- data/lib/spontaneous/output/format.rb +15 -19
- data/lib/spontaneous/output/renderable.rb +99 -0
- data/lib/spontaneous/output/store.rb +24 -0
- data/lib/spontaneous/output/store/backend.rb +52 -0
- data/lib/spontaneous/output/store/file.rb +77 -0
- data/lib/spontaneous/output/store/moneta.rb +117 -0
- data/lib/spontaneous/output/store/revision.rb +34 -0
- data/lib/spontaneous/output/store/store.rb +15 -0
- data/lib/spontaneous/output/store/transaction.rb +44 -0
- data/lib/spontaneous/output/template/engine.rb +17 -7
- data/lib/spontaneous/output/template/renderer.rb +66 -40
- data/lib/spontaneous/page_lock.rb +5 -7
- data/lib/spontaneous/page_piece.rb +2 -2
- data/lib/spontaneous/permissions/user.rb +14 -7
- data/lib/spontaneous/plugins/application/features.rb +8 -4
- data/lib/spontaneous/plugins/application/state.rb +12 -6
- data/lib/spontaneous/prototypes/box_prototype.rb +9 -10
- data/lib/spontaneous/prototypes/field_prototype.rb +66 -15
- data/lib/spontaneous/publishing/immediate.rb +30 -26
- data/lib/spontaneous/rack.rb +12 -7
- data/lib/spontaneous/rack/back.rb +43 -37
- data/lib/spontaneous/rack/back/base.rb +4 -4
- data/lib/spontaneous/rack/back/changes.rb +2 -2
- data/lib/spontaneous/rack/back/file.rb +16 -24
- data/lib/spontaneous/rack/back/map.rb +5 -5
- data/lib/spontaneous/rack/back/preview.rb +3 -4
- data/lib/spontaneous/rack/back/schema.rb +1 -1
- data/lib/spontaneous/rack/back/site.rb +6 -7
- data/lib/spontaneous/rack/front.rb +19 -16
- data/lib/spontaneous/rack/middleware/authenticate.rb +3 -3
- data/lib/spontaneous/rack/middleware/reloader.rb +3 -2
- data/lib/spontaneous/rack/middleware/scope.rb +25 -19
- data/lib/spontaneous/rack/page_controller.rb +164 -13
- data/lib/spontaneous/rack/public.rb +23 -62
- data/lib/spontaneous/rack/static.rb +2 -3
- data/lib/spontaneous/schema.rb +27 -8
- data/lib/spontaneous/schema/schema_modification.rb +9 -1
- data/lib/spontaneous/schema/uid.rb +2 -2
- data/lib/spontaneous/schema/uid_map.rb +3 -2
- data/lib/spontaneous/search/database.rb +2 -2
- data/lib/spontaneous/search/field.rb +5 -3
- data/lib/spontaneous/search/index.rb +12 -7
- data/lib/spontaneous/search/results.rb +5 -3
- data/lib/spontaneous/server.rb +2 -2
- data/lib/spontaneous/site.rb +10 -3
- data/lib/spontaneous/site/features.rb +26 -6
- data/lib/spontaneous/site/helpers.rb +9 -12
- data/lib/spontaneous/site/level.rb +7 -9
- data/lib/spontaneous/site/map.rb +9 -11
- data/lib/spontaneous/site/paths.rb +5 -5
- data/lib/spontaneous/site/publishing.rb +83 -80
- data/lib/spontaneous/site/schema.rb +1 -7
- data/lib/spontaneous/site/search.rb +8 -18
- data/lib/spontaneous/site/selectors.rb +60 -54
- data/lib/spontaneous/site/state.rb +36 -30
- data/lib/spontaneous/site/storage.rb +10 -16
- data/lib/spontaneous/state.rb +8 -0
- data/lib/spontaneous/style.rb +32 -33
- data/lib/spontaneous/version.rb +1 -1
- data/spontaneous.gemspec +22 -21
- data/test/fixtures/public/templates/layouts/default.html.cut +1 -1
- data/test/fixtures/public/templates/layouts/default.pdf.cut +1 -1
- data/test/fixtures/public/templates/layouts/default.rss.cut +1 -1
- data/test/fixtures/search/config/indexes.rb +1 -1
- data/test/fixtures/serialisation/class_hash.yaml.erb +13 -1
- data/test/fixtures/serialisation/root_hash.yaml.erb +10 -0
- data/test/functional/test_application.rb +20 -24
- data/test/functional/test_back.rb +26 -27
- data/test/functional/test_cli.rb +146 -0
- data/test/functional/test_front.rb +287 -216
- data/test/functional/test_user_manager.rb +1 -1
- data/test/test_helper.rb +15 -11
- data/test/unit/test_alias.rb +32 -25
- data/test/unit/test_asset_bundler.rb +1 -1
- data/test/unit/test_assets.rb +34 -33
- data/test/unit/test_authentication.rb +1 -1
- data/test/unit/test_boxes.rb +16 -2
- data/test/unit/test_changesets.rb +23 -11
- data/test/unit/test_content.rb +15 -0
- data/test/unit/test_context.rb +139 -0
- data/test/unit/test_controllers.rb +374 -0
- data/test/{experimental → unit}/test_crypt.rb +0 -0
- data/test/unit/test_datamapper.rb +260 -237
- data/test/unit/test_datamapper_content.rb +42 -12
- data/test/{experimental → unit}/test_features.rb +85 -3
- data/test/unit/test_fields.rb +117 -42
- data/test/unit/test_formats.rb +11 -1
- data/test/unit/test_generators.rb +2 -2
- data/test/unit/test_helpers.rb +7 -8
- data/test/unit/test_images.rb +39 -2
- data/test/unit/test_layouts.rb +14 -12
- data/test/unit/test_media.rb +32 -23
- data/test/unit/test_output_store.rb +342 -0
- data/test/unit/test_page.rb +8 -1
- data/test/unit/test_permissions.rb +11 -7
- data/test/unit/test_plugins.rb +3 -3
- data/test/unit/test_prototype_set.rb +8 -1
- data/test/unit/test_publishing.rb +67 -54
- data/test/unit/test_render.rb +91 -38
- data/test/unit/test_revisions.rb +4 -4
- data/test/unit/test_schema.rb +109 -84
- data/test/unit/test_search.rb +42 -42
- data/test/unit/test_serialisation.rb +3 -2
- data/test/unit/test_site.rb +39 -27
- data/test/unit/test_storage.rb +9 -6
- data/test/unit/test_styles.rb +25 -32
- data/test/unit/test_templates.rb +8 -4
- metadata +89 -54
- data/lib/spontaneous/model/page/request.rb +0 -105
- data/lib/spontaneous/storage.rb +0 -22
@@ -6,9 +6,6 @@ module Spontaneous
|
|
6
6
|
|
7
7
|
plugin :timestamps
|
8
8
|
|
9
|
-
many_to_one :page, :class => "Spontaneous::Content", :key => :page_id
|
10
|
-
many_to_one :content, :class => "Spontaneous::Content", :key => :content_id
|
11
|
-
|
12
9
|
def self.lock_field(field)
|
13
10
|
create(field_attributes(field).merge(
|
14
11
|
:description => field.page_lock_description
|
@@ -40,7 +37,7 @@ module Spontaneous
|
|
40
37
|
end
|
41
38
|
|
42
39
|
def field
|
43
|
-
@field ||= Spontaneous::Field.find(field_id)
|
40
|
+
@field ||= Spontaneous::Field.find(content.model, field_id)
|
44
41
|
end
|
45
42
|
|
46
43
|
def field_name
|
@@ -49,12 +46,13 @@ module Spontaneous
|
|
49
46
|
|
50
47
|
def location
|
51
48
|
field, owner = self.field, self.field.owner
|
49
|
+
model = owner.model.content_model
|
52
50
|
case owner
|
53
|
-
when
|
51
|
+
when model::Box
|
54
52
|
"Field ‘#{field.name}’ of box ‘#{owner.box_name}’"
|
55
|
-
when
|
53
|
+
when model::Page
|
56
54
|
"Field ‘#{field.name}’"
|
57
|
-
when
|
55
|
+
when model::Piece
|
58
56
|
"Field ‘#{field.name}’ of entry #{owner.position + 1} in box ‘#{owner.container.box_name}’"
|
59
57
|
end
|
60
58
|
end
|
@@ -72,8 +72,8 @@ module Spontaneous
|
|
72
72
|
target.resolve_style(style_id)
|
73
73
|
end
|
74
74
|
|
75
|
-
def template(format = :html)
|
76
|
-
style.template(format)
|
75
|
+
def template(format = :html, renderer = Spontaneous::Output.default_renderer)
|
76
|
+
style.template(format, renderer)
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
@@ -10,7 +10,7 @@ module Spontaneous::Permissions
|
|
10
10
|
many_to_many :groups, :class => :'Spontaneous::Permissions::AccessGroup', :join_table => :spontaneous_groups_users
|
11
11
|
one_to_many :access_keys, :class => :'Spontaneous::Permissions::AccessKey', :reciprocal => :user
|
12
12
|
|
13
|
-
|
13
|
+
set_allowed_columns(:name, :login, :email, :disabled, :password, :level)
|
14
14
|
|
15
15
|
def_delegators :group, :level, :access_selector
|
16
16
|
|
@@ -188,17 +188,24 @@ module Spontaneous::Permissions
|
|
188
188
|
errors.add(:email, 'is required') if email.blank?
|
189
189
|
errors.add(:email, 'is invalid') unless email.blank? or email =~ /\A[^@]+@.+\z/
|
190
190
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
errors.add(:login, 'should be at least 3 letters long') if login.length < 3
|
196
|
-
end
|
191
|
+
validate_login
|
192
|
+
validate_login_uniqueness
|
193
|
+
validate_password
|
194
|
+
end
|
197
195
|
|
196
|
+
def validate_login
|
197
|
+
return errors.add(:login, 'is required') if login.blank?
|
198
|
+
errors.add(:login, 'should only contain letters, numbers & underscore') unless login =~ /\A[a-zA-Z0-9_]+\z/
|
199
|
+
errors.add(:login, 'should be at least 3 letters long') if login.length < 3
|
200
|
+
end
|
201
|
+
|
202
|
+
def validate_login_uniqueness
|
198
203
|
if (u = User[:login => login]) && (u.id != id)
|
199
204
|
errors.add(:login, "must be unique, login '#{login}' already exists")
|
200
205
|
end
|
206
|
+
end
|
201
207
|
|
208
|
+
def validate_password
|
202
209
|
if new? || updating_password?
|
203
210
|
if password.blank?
|
204
211
|
errors.add(:password, 'is required')
|
@@ -5,12 +5,16 @@ module Spontaneous::Plugins::Application
|
|
5
5
|
extend Spontaneous::Concern
|
6
6
|
|
7
7
|
module ClassMethods
|
8
|
-
def register_back_controller(namespace, controller_class)
|
9
|
-
instance.register_back_controller(namespace, controller_class)
|
8
|
+
def register_back_controller(namespace, controller_class, opts = {})
|
9
|
+
instance.register_back_controller(namespace, controller_class, opts)
|
10
10
|
end
|
11
11
|
|
12
|
-
def register_front_controller(namespace, controller_class)
|
13
|
-
instance.register_front_controller(namespace, controller_class)
|
12
|
+
def register_front_controller(namespace, controller_class, opts = {})
|
13
|
+
instance.register_front_controller(namespace, controller_class, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
def front
|
17
|
+
instance.front
|
14
18
|
end
|
15
19
|
end # ClassMethods
|
16
20
|
end # Features
|
@@ -24,6 +24,7 @@ module Spontaneous::Plugins::Application
|
|
24
24
|
" 'auto_login' setting from your environment file."
|
25
25
|
end
|
26
26
|
Thread.current[:spontaneous_loaded] = true
|
27
|
+
site
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
@@ -39,7 +40,7 @@ module Spontaneous::Plugins::Application
|
|
39
40
|
# a nice way to create the ::Site constant in the user/site code
|
40
41
|
def site(content_model)
|
41
42
|
site!(content_model) unless defined?(Spontaneous::Content)
|
42
|
-
Spontaneous::Site
|
43
|
+
Spontaneous::Site.instance
|
43
44
|
end
|
44
45
|
|
45
46
|
# This forces the assignment of Spontaneous::Content, overwriting any
|
@@ -48,10 +49,11 @@ module Spontaneous::Plugins::Application
|
|
48
49
|
# Used in tests.
|
49
50
|
#
|
50
51
|
def site!(content_model)
|
51
|
-
|
52
|
-
Spontaneous.send :remove_const, :Content if defined?(Spontaneous::Content)
|
53
|
-
Spontaneous.const_set(:Content, content_model)
|
54
|
-
|
52
|
+
site = Spontaneous::Site.instance
|
53
|
+
# Spontaneous.send :remove_const, :Content if defined?(Spontaneous::Content)
|
54
|
+
# Spontaneous.const_set(:Content, content_model)
|
55
|
+
site.model = content_model
|
56
|
+
site
|
55
57
|
end
|
56
58
|
|
57
59
|
def loaded?
|
@@ -59,8 +61,12 @@ module Spontaneous::Plugins::Application
|
|
59
61
|
end
|
60
62
|
|
61
63
|
|
64
|
+
def instance
|
65
|
+
Spontaneous::Site.instance
|
66
|
+
end
|
67
|
+
|
62
68
|
def config
|
63
|
-
|
69
|
+
instance.config
|
64
70
|
end
|
65
71
|
|
66
72
|
def db_settings
|
@@ -176,19 +176,18 @@ module Spontaneous::Prototypes
|
|
176
176
|
end
|
177
177
|
|
178
178
|
def allowed_types(user)
|
179
|
-
|
180
|
-
types = []
|
181
|
-
instance_class.allowed.select { |a| a.readable?(user) }.each do |a|
|
182
|
-
types.concat(a.instance_classes)
|
183
|
-
end
|
184
|
-
types
|
185
|
-
else
|
186
|
-
[]
|
187
|
-
end
|
179
|
+
_allowed(user).flat_map { |allow| allow.instance_classes }
|
188
180
|
end
|
189
181
|
|
182
|
+
def _allowed(user)
|
183
|
+
return [] unless writable?(user)
|
184
|
+
instance_class.allowed.select { |a| a.readable?(user) }
|
185
|
+
end
|
186
|
+
|
187
|
+
private :_allowed
|
188
|
+
|
190
189
|
def export(user)
|
191
|
-
allowed =
|
190
|
+
allowed = _allowed(user).flat_map { |a| a.export }
|
192
191
|
{
|
193
192
|
:name => name.to_s,
|
194
193
|
:id => schema_id.to_s,
|
@@ -2,6 +2,49 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
module Spontaneous::Prototypes
|
5
|
+
# FieldPrototype represents the class-level view of a type field.
|
6
|
+
# It contains information on the type of the field and the options
|
7
|
+
# passed in the type declaration and is responsible for transforming
|
8
|
+
# serialized field data from the db into a field instance.
|
9
|
+
#
|
10
|
+
# options - A hash containing options that control the behaviour of the
|
11
|
+
# field (default: {})
|
12
|
+
#
|
13
|
+
# :default - The default value for new fields. This accepts either a
|
14
|
+
# value (which is either a String or responds to #to_s)
|
15
|
+
# or a Proc value generator which can accept 1 argument
|
16
|
+
# that is the instance that the field is attached to.
|
17
|
+
# :title - The title that should be used to label the field in the UI.
|
18
|
+
# This defaults to the 'titleized' version of the field name,
|
19
|
+
# e.g. ':field_name' becomes 'Field Name'.
|
20
|
+
# :comment - An optional String comment to be displayed in the UI
|
21
|
+
# (default: "").
|
22
|
+
# :list - A Boolean flag determining whether to show the field in the
|
23
|
+
# list view (default: true).
|
24
|
+
# :fallback - Provides a way of supplying a fallback value for an empty
|
25
|
+
# field.
|
26
|
+
#
|
27
|
+
# Other options are dependent on the type of field.
|
28
|
+
#
|
29
|
+
# Examples
|
30
|
+
#
|
31
|
+
# Pass a Proc as the default value for a field:
|
32
|
+
#
|
33
|
+
# field :title, default: proc { |page| "This is page #{page.slug}" }
|
34
|
+
#
|
35
|
+
# Assign a field with a fallback:
|
36
|
+
#
|
37
|
+
# class Something < Piece
|
38
|
+
# field :a
|
39
|
+
# field :b, fallback: :a
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# instance = Something.new(a: "The value of A")
|
43
|
+
# instance.a.value #=> "The value of A"
|
44
|
+
# instance.b.value #=> "The value of A"
|
45
|
+
# instance.b = "Now B"
|
46
|
+
# instance.b.value #=> "Now B"
|
47
|
+
#
|
5
48
|
class FieldPrototype
|
6
49
|
attr_reader :owner, :name, :options
|
7
50
|
|
@@ -59,7 +102,7 @@ module Spontaneous::Prototypes
|
|
59
102
|
end
|
60
103
|
|
61
104
|
def default_options(field_class)
|
62
|
-
{:
|
105
|
+
{default: '', comment: false, list: true}.merge(field_class.default_options)
|
63
106
|
end
|
64
107
|
|
65
108
|
def instance_class
|
@@ -116,19 +159,26 @@ module Spontaneous::Prototypes
|
|
116
159
|
end
|
117
160
|
|
118
161
|
def in_index?(index)
|
119
|
-
search.in_index?(index)
|
162
|
+
search(index.site).in_index?(index)
|
120
163
|
end
|
121
164
|
|
122
165
|
def index_id(index)
|
123
|
-
search.index_id(index)
|
166
|
+
search(index.site).index_id(index)
|
124
167
|
end
|
125
168
|
|
126
169
|
def options_for_index(index)
|
127
|
-
search.field_definition(index)
|
170
|
+
search(index.site).field_definition(index)
|
128
171
|
end
|
129
172
|
|
130
|
-
|
131
|
-
|
173
|
+
# TODO: it's wrong to have to be passing the site to this call
|
174
|
+
# as there's only ever one site and we shouldn't be memoizing
|
175
|
+
# a method call with a param.
|
176
|
+
# Must centralize the testing of a prototype for inclusion into
|
177
|
+
# an index - either into the index or the site itself.
|
178
|
+
# We can't just recalculate this on the fly because indexing
|
179
|
+
# needs to be reasonably performant.
|
180
|
+
def search(site)
|
181
|
+
@search ||= S::Search::Field.new(site, self, @options[:index])
|
132
182
|
end
|
133
183
|
|
134
184
|
def inherit_schema_id(schema_id)
|
@@ -148,19 +198,20 @@ module Spontaneous::Prototypes
|
|
148
198
|
values = { :name => self.name }
|
149
199
|
values[:unprocessed_value] = default(instance) if using_default_values
|
150
200
|
values.update(database_values || {})
|
151
|
-
self.instance_class.new(values, using_default_values)
|
152
|
-
|
153
|
-
|
201
|
+
field = self.instance_class.new(values, using_default_values)
|
202
|
+
field.prototype = self
|
203
|
+
field
|
154
204
|
end
|
155
205
|
|
156
206
|
def export(user)
|
157
207
|
{
|
158
|
-
:
|
159
|
-
:
|
160
|
-
:
|
161
|
-
:
|
162
|
-
:
|
163
|
-
:
|
208
|
+
name: name.to_s,
|
209
|
+
schema_id: schema_id.to_s,
|
210
|
+
type: instance_class.editor_class,
|
211
|
+
title: title,
|
212
|
+
comment: comment || "",
|
213
|
+
list: @options[:list] || false,
|
214
|
+
writable: Spontaneous::Permissions.has_level?(user, write_level)
|
164
215
|
}.merge(instance_class.export(user))
|
165
216
|
end
|
166
217
|
end
|
@@ -12,14 +12,14 @@ module Spontaneous
|
|
12
12
|
|
13
13
|
attr_reader :revision, :now
|
14
14
|
|
15
|
-
def initialize(
|
16
|
-
@revision, @content_model = revision,
|
17
|
-
@previous_revision =
|
15
|
+
def initialize(site, revision)
|
16
|
+
@site, @revision, @content_model = site, revision, site.model
|
17
|
+
@previous_revision = @site.published_revision
|
18
18
|
@now = Time.now
|
19
19
|
end
|
20
20
|
|
21
21
|
def renderer
|
22
|
-
@renderer ||= Spontaneous::Output::Template::PublishRenderer.new(true)
|
22
|
+
@renderer ||= Spontaneous::Output::Template::PublishRenderer.new(@site, true)
|
23
23
|
end
|
24
24
|
|
25
25
|
def publish_pages(page_list)
|
@@ -71,14 +71,14 @@ module Spontaneous
|
|
71
71
|
|
72
72
|
|
73
73
|
def pages
|
74
|
-
@pages ||=
|
74
|
+
@pages ||= @site.pages
|
75
75
|
end
|
76
76
|
|
77
77
|
# The number of times the publisher has to run through the site's pages
|
78
78
|
# in order to generate the search indexes.
|
79
79
|
# Returns either 0 or 1
|
80
80
|
def index_stages
|
81
|
-
[1,
|
81
|
+
[1, @site.indexes.length].min
|
82
82
|
end
|
83
83
|
|
84
84
|
def publish(modified_page_list)
|
@@ -97,7 +97,6 @@ module Spontaneous
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def render_revision
|
100
|
-
S::Output.renderer = renderer
|
101
100
|
update_progress("rendering", 0)
|
102
101
|
@pages_rendered = 0
|
103
102
|
@content_model.scope(@revision, true) do
|
@@ -109,24 +108,27 @@ module Spontaneous
|
|
109
108
|
end
|
110
109
|
|
111
110
|
def render_pages
|
112
|
-
|
113
|
-
|
111
|
+
template_revision = @site.output_store.revision(@revision)
|
112
|
+
@render_transaction = template_revision.transaction
|
113
|
+
delay = @site.config.publishing_delay # the delay is purely used in interface testing
|
114
114
|
pages.each do |page|
|
115
115
|
page.outputs.each do |output|
|
116
|
-
render_page(page, output)
|
116
|
+
render_page(page, output, @render_transaction)
|
117
117
|
end
|
118
118
|
sleep(delay) if delay
|
119
119
|
end
|
120
|
+
@render_transaction.commit
|
121
|
+
@render_transaction = nil
|
120
122
|
end
|
121
123
|
|
122
|
-
def render_page(page, output)
|
124
|
+
def render_page(page, output, transaction)
|
123
125
|
logger.info { "#{page.path}" }
|
124
|
-
output.publish_page(renderer, revision)
|
126
|
+
output.publish_page(renderer, revision, transaction)
|
125
127
|
page_rendered(page, "rendering", output.format)
|
126
128
|
end
|
127
129
|
|
128
130
|
def index_pages
|
129
|
-
|
131
|
+
@site.indexer(revision) do |indexer|
|
130
132
|
pages.each { |page|
|
131
133
|
indexer << page
|
132
134
|
page_rendered(page, 'indexing')
|
@@ -283,7 +285,7 @@ module Spontaneous
|
|
283
285
|
# when working with multiple instances it's possible to rollback the revision number
|
284
286
|
# leaving behind old revisions > the current published_revision.
|
285
287
|
@content_model.delete_revision(revision)
|
286
|
-
|
288
|
+
@site.send(:pending_revision=, revision)
|
287
289
|
end
|
288
290
|
|
289
291
|
def after_publish
|
@@ -292,28 +294,29 @@ module Spontaneous
|
|
292
294
|
tmp = Spontaneous.revision_dir(revision) / "tmp"
|
293
295
|
FileUtils.mkdir_p(tmp) unless ::File.exists?(tmp)
|
294
296
|
activate_revision
|
297
|
+
@site.must_publish_all!(false)
|
295
298
|
update_progress("complete")
|
296
299
|
rescue => e
|
297
300
|
# if a post publish hook raises an exception then we want to roll everything back
|
298
|
-
deactivate_revision
|
301
|
+
deactivate_revision(e)
|
299
302
|
raise e
|
300
303
|
end
|
301
304
|
end
|
302
305
|
|
303
306
|
def activate_revision
|
304
307
|
S::PublishedRevision.create(:revision => revision, :published_at => now)
|
305
|
-
|
308
|
+
@site.send(:set_published_revision, revision)
|
306
309
|
write_revision(revision)
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
+
@site.trigger(:after_publish, revision)
|
311
|
+
@site.send(:pending_revision=, nil)
|
312
|
+
@content_model.cleanup_revisions(revision, keep_revisions)
|
310
313
|
end
|
311
314
|
|
312
|
-
def deactivate_revision
|
315
|
+
def deactivate_revision(exception)
|
313
316
|
S::PublishedRevision.filter(:revision => revision).delete
|
314
|
-
|
317
|
+
@site.send(:set_published_revision, @previous_revision)
|
315
318
|
write_revision(@previous_revision)
|
316
|
-
abort_publish(
|
319
|
+
abort_publish(exception)
|
317
320
|
end
|
318
321
|
|
319
322
|
# Makes the revision live on the filesystem by symlinking the revisions/current
|
@@ -333,17 +336,18 @@ module Spontaneous
|
|
333
336
|
end
|
334
337
|
|
335
338
|
def abort_publish(exception)
|
336
|
-
if (r =
|
339
|
+
if (r = @site.pending_revision)
|
337
340
|
update_progress("aborting")
|
338
|
-
|
339
|
-
|
341
|
+
@render_transaction.rollback if @render_transaction
|
342
|
+
@site.output_store.revision(r).delete # we might have committed the transaction
|
343
|
+
@site.send(:pending_revision=, nil)
|
340
344
|
@content_model.delete_revision(revision)
|
341
345
|
puts exception.backtrace.join("\n") if exception
|
342
346
|
end
|
343
347
|
end
|
344
348
|
|
345
349
|
def keep_revisions
|
346
|
-
|
350
|
+
@site.config.keep_revisions || KEEP_REVISIONS
|
347
351
|
end
|
348
352
|
end # Immediate
|
349
353
|
end # Publishing
|