spontaneous 0.2.0.alpha7 → 0.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (247) hide show
  1. data/Gemfile +10 -4
  2. data/Readme.markdown +1 -1
  3. data/application/css/definitions.css.scss +5 -0
  4. data/application/css/dialogue.css.scss +62 -0
  5. data/application/js/content.js +1 -1
  6. data/application/js/dom.js +1 -1
  7. data/application/js/event_source.js +3 -0
  8. data/application/js/{field_types/date_field.js → field/date.js} +2 -2
  9. data/application/js/{field_types/file_field.js → field/file.js} +2 -2
  10. data/application/js/{field_types/image_field.js → field/image.js} +54 -20
  11. data/application/js/{field_types/long_string_field.js → field/long_string.js} +2 -2
  12. data/application/js/{field_types/markdown_field.js → field/markdown.js} +2 -2
  13. data/application/js/{field_types/select_field.js → field/select.js} +2 -2
  14. data/application/js/{field_types/string_field.js → field/string.js} +21 -7
  15. data/application/js/{field_types/webvideo_field.js → field/webvideo.js} +2 -2
  16. data/application/js/field.js +2 -2
  17. data/application/js/publish.js +99 -19
  18. data/application/js/spontaneous.js +8 -8
  19. data/application/js/top_bar.js +6 -4
  20. data/db/migrations/20130109125023_add_page_publish_lock.rb +17 -0
  21. data/db/migrations/20130111161934_convert_bcrypt_passwords.rb +22 -0
  22. data/db/migrations/20130114120000_create_revision_tables.rb +106 -0
  23. data/db/migrations/20130116220423_add_index_to_archive.rb +9 -0
  24. data/lib/spontaneous/box.rb +53 -18
  25. data/lib/spontaneous/box_style.rb +2 -3
  26. data/lib/spontaneous/change.rb +39 -13
  27. data/lib/spontaneous/cli/fields.rb +29 -0
  28. data/lib/spontaneous/cli/init.rb +2 -2
  29. data/lib/spontaneous/cli/migrate.rb +0 -1
  30. data/lib/spontaneous/cli/server.rb +14 -10
  31. data/lib/spontaneous/cli/site.rb +20 -9
  32. data/lib/spontaneous/cli.rb +8 -6
  33. data/lib/spontaneous/collections/box_set.rb +11 -0
  34. data/lib/spontaneous/collections/field_set.rb +24 -1
  35. data/lib/spontaneous/concern.rb +37 -0
  36. data/lib/spontaneous/config.rb +3 -4
  37. data/lib/spontaneous/crypt/version.rb +130 -0
  38. data/lib/spontaneous/crypt.rb +84 -0
  39. data/lib/spontaneous/data_mapper/content_model/associations.rb +199 -0
  40. data/lib/spontaneous/data_mapper/content_model/column_accessors.rb +52 -0
  41. data/lib/spontaneous/data_mapper/content_model/instance_hooks.rb +34 -0
  42. data/lib/spontaneous/data_mapper/content_model/serialization.rb +54 -0
  43. data/lib/spontaneous/data_mapper/content_model/timestamps.rb +39 -0
  44. data/lib/spontaneous/data_mapper/content_model.rb +343 -0
  45. data/lib/spontaneous/data_mapper/content_table.rb +103 -0
  46. data/lib/spontaneous/data_mapper/dataset.rb +194 -0
  47. data/lib/spontaneous/data_mapper/scope.rb +195 -0
  48. data/lib/spontaneous/data_mapper.rb +161 -0
  49. data/lib/spontaneous/facet.rb +2 -2
  50. data/lib/spontaneous/field/base.rb +418 -0
  51. data/lib/spontaneous/field/date.rb +54 -0
  52. data/lib/spontaneous/{field_version.rb → field/field_version.rb} +1 -1
  53. data/lib/spontaneous/field/file.rb +100 -0
  54. data/lib/spontaneous/{field_types/image_field.rb → field/image.rb} +33 -33
  55. data/lib/spontaneous/{field_types/location_field.rb → field/location.rb} +2 -2
  56. data/lib/spontaneous/{field_types/long_string_field.rb → field/long_string.rb} +3 -3
  57. data/lib/spontaneous/field/markdown.rb +36 -0
  58. data/lib/spontaneous/{field_types/select_field.rb → field/select.rb} +4 -5
  59. data/lib/spontaneous/field/string.rb +17 -0
  60. data/lib/spontaneous/field/update.rb +156 -0
  61. data/lib/spontaneous/field/webvideo.rb +310 -0
  62. data/lib/spontaneous/field.rb +80 -0
  63. data/lib/spontaneous/generators/site/Gemfile.tt +2 -2
  64. data/lib/spontaneous/generators/site/config/environments/development.rb.tt +1 -1
  65. data/lib/spontaneous/generators/site/config/environments/production.rb.tt +1 -1
  66. data/lib/spontaneous/generators/site/lib/content.rb.tt +6 -0
  67. data/lib/spontaneous/generators/site/schema/box.rb.tt +3 -2
  68. data/lib/spontaneous/generators/site/schema/page.rb.tt +3 -1
  69. data/lib/spontaneous/generators/site/schema/piece.rb.tt +3 -1
  70. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +3 -1
  71. data/lib/spontaneous/generators/site.rb +4 -3
  72. data/lib/spontaneous/image_size.rb +8 -1
  73. data/lib/spontaneous/layout.rb +5 -1
  74. data/lib/spontaneous/loader.rb +2 -5
  75. data/lib/spontaneous/media/file.rb +11 -2
  76. data/lib/spontaneous/media/temp_file.rb +23 -0
  77. data/lib/spontaneous/media.rb +20 -39
  78. data/lib/spontaneous/{plugins → model/box}/allowed_types.rb +38 -17
  79. data/lib/spontaneous/model/box.rb +18 -0
  80. data/lib/spontaneous/{plugins → model/core}/aliases.rb +10 -14
  81. data/lib/spontaneous/{plugins → model/core}/boxes.rb +2 -2
  82. data/lib/spontaneous/{plugins → model/core}/content_groups.rb +2 -2
  83. data/lib/spontaneous/model/core/editor_class.rb +4 -0
  84. data/lib/spontaneous/{plugins → model/core}/entries.rb +19 -7
  85. data/lib/spontaneous/{plugins → model/core}/entry.rb +3 -3
  86. data/lib/spontaneous/{plugins → model/core}/fields.rb +38 -5
  87. data/lib/spontaneous/{plugins → model/core}/instance_code.rb +2 -2
  88. data/lib/spontaneous/{plugins → model/core}/media.rb +2 -12
  89. data/lib/spontaneous/{plugins → model/core}/modifications.rb +7 -6
  90. data/lib/spontaneous/model/core/page_search.rb +36 -0
  91. data/lib/spontaneous/{plugins → model/core}/permissions.rb +4 -4
  92. data/lib/spontaneous/{plugins → model/core}/prototypes.rb +4 -4
  93. data/lib/spontaneous/{plugins → model/core}/publishing.rb +93 -115
  94. data/lib/spontaneous/{plugins → model/core}/render.rb +2 -2
  95. data/lib/spontaneous/{plugins → model/core}/schema_hierarchy.rb +7 -11
  96. data/lib/spontaneous/model/core/schema_id.rb +65 -0
  97. data/lib/spontaneous/{plugins → model/core}/schema_title.rb +2 -2
  98. data/lib/spontaneous/{plugins → model/core}/serialisation.rb +2 -2
  99. data/lib/spontaneous/{plugins → model/core}/styles.rb +2 -2
  100. data/lib/spontaneous/{plugins → model/core}/supertype.rb +2 -2
  101. data/lib/spontaneous/{plugins → model/core}/visibility.rb +7 -48
  102. data/lib/spontaneous/model/core.rb +143 -0
  103. data/lib/spontaneous/{plugins → model/page}/controllers.rb +3 -3
  104. data/lib/spontaneous/{plugins → model}/page/formats.rb +2 -2
  105. data/lib/spontaneous/{plugins → model/page}/layouts.rb +2 -2
  106. data/lib/spontaneous/model/page/locks.rb +14 -0
  107. data/lib/spontaneous/{plugins → model/page}/page_tree.rb +3 -3
  108. data/lib/spontaneous/{plugins → model/page}/paths.rb +30 -12
  109. data/lib/spontaneous/{plugins → model}/page/request.rb +2 -2
  110. data/lib/spontaneous/{plugins → model/page}/site_map.rb +2 -2
  111. data/lib/spontaneous/model/page/site_timestamps.rb +44 -0
  112. data/lib/spontaneous/{page.rb → model/page.rb} +49 -28
  113. data/lib/spontaneous/{piece.rb → model/piece.rb} +7 -6
  114. data/lib/spontaneous/model.rb +97 -0
  115. data/lib/spontaneous/output/context.rb +1 -1
  116. data/lib/spontaneous/output/format.rb +4 -0
  117. data/lib/spontaneous/output/template/renderer.rb +2 -2
  118. data/lib/spontaneous/output.rb +2 -2
  119. data/lib/spontaneous/page_lock.rb +62 -0
  120. data/lib/spontaneous/page_piece.rb +1 -1
  121. data/lib/spontaneous/permissions/access_key.rb +9 -4
  122. data/lib/spontaneous/permissions/user.rb +19 -9
  123. data/lib/spontaneous/permissions.rb +2 -5
  124. data/lib/spontaneous/plugins/application/facets.rb +1 -2
  125. data/lib/spontaneous/plugins/application/features.rb +1 -1
  126. data/lib/spontaneous/plugins/application/paths.rb +1 -1
  127. data/lib/spontaneous/plugins/application/render.rb +1 -1
  128. data/lib/spontaneous/plugins/application/serialisation.rb +1 -1
  129. data/lib/spontaneous/plugins/application/state.rb +30 -1
  130. data/lib/spontaneous/plugins/application/system.rb +12 -12
  131. data/lib/spontaneous/prototypes/box_prototype.rb +1 -1
  132. data/lib/spontaneous/prototypes/field_prototype.rb +3 -6
  133. data/lib/spontaneous/prototypes/style_prototype.rb +1 -1
  134. data/lib/spontaneous/publishing/immediate.rb +77 -49
  135. data/lib/spontaneous/publishing/revision.rb +355 -0
  136. data/lib/spontaneous/publishing/simultaneous.rb +10 -49
  137. data/lib/spontaneous/publishing.rb +1 -0
  138. data/lib/spontaneous/rack/around_back.rb +1 -1
  139. data/lib/spontaneous/rack/around_front.rb +2 -4
  140. data/lib/spontaneous/rack/around_preview.rb +1 -1
  141. data/lib/spontaneous/rack/back.rb +80 -63
  142. data/lib/spontaneous/rack/cacheable_file.rb +2 -2
  143. data/lib/spontaneous/rack/cookie_authentication.rb +1 -1
  144. data/lib/spontaneous/rack/front.rb +1 -1
  145. data/lib/spontaneous/rack/helpers.rb +8 -9
  146. data/lib/spontaneous/{page_controller.rb → rack/page_controller.rb} +1 -1
  147. data/lib/spontaneous/rack/public.rb +3 -3
  148. data/lib/spontaneous/rack.rb +15 -15
  149. data/lib/spontaneous/schema/uid.rb +4 -1
  150. data/lib/spontaneous/schema.rb +57 -24
  151. data/lib/spontaneous/search/database.rb +12 -1
  152. data/lib/spontaneous/search/index.rb +34 -6
  153. data/lib/spontaneous/search/results.rb +1 -1
  154. data/lib/spontaneous/server.rb +3 -3
  155. data/lib/spontaneous/simultaneous.rb +53 -0
  156. data/lib/spontaneous/{plugins/site → site}/features.rb +2 -2
  157. data/lib/spontaneous/{plugins/site → site}/helpers.rb +2 -3
  158. data/lib/spontaneous/{plugins/site → site}/hooks.rb +2 -2
  159. data/lib/spontaneous/{plugins/site → site}/instance.rb +4 -6
  160. data/lib/spontaneous/{plugins/site → site}/level.rb +2 -2
  161. data/lib/spontaneous/{plugins/site → site}/map.rb +4 -4
  162. data/lib/spontaneous/{plugins/site → site}/paths.rb +2 -2
  163. data/lib/spontaneous/site/publishing.rb +89 -0
  164. data/lib/spontaneous/{plugins/site → site}/schema.rb +4 -4
  165. data/lib/spontaneous/{plugins/site → site}/search.rb +2 -2
  166. data/lib/spontaneous/{plugins/site → site}/selectors.rb +15 -7
  167. data/lib/spontaneous/{plugins/site → site}/state.rb +2 -2
  168. data/lib/spontaneous/{plugins/site → site}/storage.rb +2 -2
  169. data/lib/spontaneous/{plugins/site → site}/url.rb +2 -2
  170. data/lib/spontaneous/site.rb +31 -14
  171. data/lib/spontaneous/state.rb +5 -6
  172. data/lib/spontaneous/style.rb +3 -2
  173. data/lib/spontaneous/utils/database/mysql_dumper.rb +13 -0
  174. data/lib/spontaneous/utils/database/postgres_dumper.rb +5 -0
  175. data/lib/spontaneous/version.rb +1 -1
  176. data/lib/spontaneous.rb +34 -89
  177. data/spontaneous.gemspec +112 -114
  178. data/test/experimental/test_crypt.rb +158 -0
  179. data/test/experimental/test_features.rb +3 -3
  180. data/test/fixtures/example_application/config/environments/development.rb +1 -1
  181. data/test/fixtures/example_application/lib/content.rb +5 -0
  182. data/test/fixtures/example_application/schema/page.rb +2 -1
  183. data/test/fixtures/example_application/schema/piece.rb +3 -2
  184. data/test/fixtures/serialisation/class_hash.yaml.erb +5 -5
  185. data/test/fixtures/serialisation/root_hash.yaml.erb +8 -0
  186. data/test/functional/test_application.rb +12 -1
  187. data/test/functional/test_back.rb +80 -48
  188. data/test/functional/test_front.rb +39 -46
  189. data/test/functional/test_user_manager.rb +3 -9
  190. data/test/javascript/test_markdown.rb +2 -2
  191. data/test/test_helper.rb +78 -23
  192. data/test/unit/test_alias.rb +21 -15
  193. data/test/unit/test_asset_bundler.rb +3 -3
  194. data/test/unit/test_assets.rb +2 -2
  195. data/test/unit/test_async.rb +7 -6
  196. data/test/unit/test_authentication.rb +43 -37
  197. data/test/unit/test_boxes.rb +46 -21
  198. data/test/unit/test_changesets.rb +65 -20
  199. data/test/unit/test_config.rb +9 -9
  200. data/test/unit/test_content.rb +50 -51
  201. data/test/unit/test_content_inheritance.rb +6 -20
  202. data/test/unit/test_datamapper.rb +1330 -0
  203. data/test/unit/test_datamapper_content.rb +214 -0
  204. data/test/unit/test_fields.rb +543 -54
  205. data/test/unit/test_formats.rb +2 -3
  206. data/test/unit/test_generators.rb +6 -6
  207. data/test/unit/test_helpers.rb +1 -1
  208. data/test/unit/test_image_size.rb +10 -5
  209. data/test/unit/test_images.rb +17 -18
  210. data/test/unit/test_layouts.rb +18 -3
  211. data/test/unit/test_media.rb +74 -49
  212. data/test/unit/test_modifications.rb +43 -43
  213. data/test/unit/test_page.rb +7 -10
  214. data/test/unit/test_permissions.rb +3 -10
  215. data/test/unit/test_piece.rb +5 -6
  216. data/test/unit/test_plugins.rb +7 -14
  217. data/test/unit/test_prototypes.rb +3 -3
  218. data/test/unit/test_publishing.rb +49 -27
  219. data/test/unit/test_render.rb +46 -15
  220. data/test/unit/test_revisions.rb +124 -127
  221. data/test/unit/test_schema.rb +53 -58
  222. data/test/unit/test_search.rb +64 -16
  223. data/test/unit/test_serialisation.rb +4 -11
  224. data/test/unit/test_site.rb +11 -12
  225. data/test/unit/test_structure.rb +2 -5
  226. data/test/unit/test_styles.rb +22 -24
  227. data/test/unit/test_type_hierarchy.rb +7 -5
  228. data/test/unit/test_visibility.rb +79 -55
  229. metadata +128 -102
  230. data/lib/sequel/plugins/content_table_inheritance.rb +0 -203
  231. data/lib/sequel/plugins/scoped_table_name.rb +0 -54
  232. data/lib/spontaneous/content.rb +0 -129
  233. data/lib/spontaneous/field_types/date_field.rb +0 -56
  234. data/lib/spontaneous/field_types/field.rb +0 -302
  235. data/lib/spontaneous/field_types/file_field.rb +0 -68
  236. data/lib/spontaneous/field_types/markdown_field.rb +0 -38
  237. data/lib/spontaneous/field_types/string_field.rb +0 -19
  238. data/lib/spontaneous/field_types/webvideo_field.rb +0 -313
  239. data/lib/spontaneous/field_types.rb +0 -38
  240. data/lib/spontaneous/generators/site/lib/site.rb.tt +0 -4
  241. data/lib/spontaneous/plugins/field/editor_class.rb +0 -13
  242. data/lib/spontaneous/plugins/page/site_timestamps.rb +0 -28
  243. data/lib/spontaneous/plugins/page_search.rb +0 -63
  244. data/lib/spontaneous/plugins/schema_id.rb +0 -68
  245. data/lib/spontaneous/plugins/site/publishing.rb +0 -75
  246. data/lib/spontaneous/rack/fiber_pool.rb +0 -26
  247. data/test/unit/test_table_scoping.rb +0 -80
@@ -10,14 +10,21 @@ module Spontaneous
10
10
  include Assets
11
11
 
12
12
  def self.messenger
13
- @messenger ||= ::Spontaneous::Rack::EventSource.new
13
+ @messenger ||= event_source
14
+ end
15
+
16
+ def self.event_source
17
+ messenger = ::Spontaneous::Rack::EventSource.new
14
18
  # Find a way to move this into a more de-centralised place
15
19
  # at some point we are going to want to have some configurable, extendable
16
20
  # list of event handlers
17
- Simultaneous.on_event("publish_progress") { |event|
18
- @messenger.deliver_event(event)
21
+ ::Simultaneous.on_event("publish_progress") { |event|
22
+ messenger.deliver_event(event)
23
+ }
24
+ ::Simultaneous.on_event("page_lock_status") { |event|
25
+ messenger.deliver_event(event)
19
26
  }
20
- @messenger
27
+ messenger
21
28
  end
22
29
 
23
30
  class EventSource < ServerBase
@@ -36,7 +43,6 @@ module Spontaneous
36
43
 
37
44
  def self.editing_app
38
45
  ::Rack::Builder.app do
39
- use Spontaneous::Rack::FiberPool, :size => 15
40
46
  use ::Rack::Lint
41
47
  use Spontaneous::Rack::Static, :root => Spontaneous.application_dir, :urls => %W(/static)
42
48
  use Spontaneous::Rack::Static, :root => Spontaneous.root / "public/@spontaneous", :urls => %W(/assets)
@@ -216,53 +222,63 @@ module Spontaneous
216
222
  end
217
223
 
218
224
  class EditingInterface < AuthenticatedHandler
219
- use Reloader if Site.config.reload_classes
225
+ use Reloader if Spontaneous::Site.config.reload_classes
220
226
 
221
227
  set :views, Proc.new { Spontaneous.application_dir + '/views' }
222
228
 
223
229
 
224
230
  def update_fields(model, field_data)
225
- conflicts = []
226
- if field_data
227
- field_data.each do |id, values|
228
- field = model.fields.sid(id)
229
- if model.field_writable?(user, field.name.to_sym)
230
- # version = values.delete("version").to_i
231
- # if version == field.version
232
- field.update(values)
233
- # else
234
- # conflicts << [field, values]
235
- # end
236
- else
237
- unauthorised!
238
- end
239
- end
240
- end
241
- if conflicts.empty?
242
- if model.save
243
- json(model)
244
- end
245
- else
246
- errors = conflicts.map do |field, new_value|
247
- [field.schema_id.to_s, [field.version, field.conflicted_value, new_value["unprocessed_value"]]]
248
- end
249
- [409, json(Hash[errors])]
250
- end
231
+ return unless field_data
232
+ Spontaneous::Field.update_asynchronously(model, field_data, user)
233
+ json(model)
234
+ end
235
+
236
+ # def update_fields(model, field_data)
237
+ # conflicts = []
238
+ # if field_data
239
+ # field_data.each do |id, values|
240
+ # field = model.fields.sid(id)
241
+ # if model.field_writable?(user, field.name.to_sym)
242
+ # # version = values.delete("version").to_i
243
+ # # if version == field.version
244
+ # field.update(values)
245
+ # # else
246
+ # # conflicts << [field, values]
247
+ # # end
248
+ # else
249
+ # unauthorised!
250
+ # end
251
+ # end
252
+ # end
253
+ # if conflicts.empty?
254
+ # if model.save
255
+ # json(model)
256
+ # end
257
+ # else
258
+ # errors = conflicts.map do |field, new_value|
259
+ # [field.schema_id.to_s, [field.version, field.conflicted_value, new_value["unprocessed_value"]]]
260
+ # end
261
+ # [409, json(Hash[errors])]
262
+ # end
263
+ # end
264
+
265
+ def content_model
266
+ Spontaneous::Content
251
267
  end
252
268
 
253
269
  def content_for_request(lock = false)
254
- Content.db.transaction {
255
- dataset = lock ? Content.for_update : Content
256
- content = dataset.first(:id => params[:id])
270
+ content_model.db.transaction do
271
+ dataset = lock ? content_model.for_update : content_model
272
+ content = dataset.get(params[:id])
257
273
  halt 404 if content.nil?
258
274
  content.current_editor = user
259
- if box_id = Spontaneous.schema.uids[params[:box_id]]
275
+ if box_id = content_model.schema.uids[params[:box_id]]
260
276
  box = content.boxes.detect { |b| b.schema_id == box_id }
261
277
  yield(content, box)
262
278
  else
263
279
  yield(content)
264
280
  end
265
- }
281
+ end
266
282
  end
267
283
 
268
284
  def set_authentication_cookie(key)
@@ -325,7 +341,7 @@ module Spontaneous
325
341
  end
326
342
 
327
343
  get '/root' do
328
- json Site.root
344
+ json Spontaneous::Site.root
329
345
  end
330
346
 
331
347
  get '/page/:id' do
@@ -334,15 +350,15 @@ module Spontaneous
334
350
 
335
351
  get '/metadata' do
336
352
  json({
337
- :types => Site.schema.export(user),
353
+ :types => Spontaneous::Site.schema.export(user),
338
354
  :user => user.export,
339
- :services => (Site.config.services || [])
355
+ :services => (Spontaneous::Site.config.services || [])
340
356
  })
341
357
  end
342
358
 
343
359
  get '/map/?:id?' do
344
- last_modified(Site.modified_at)
345
- map = Site.map(params[:id])
360
+ last_modified(Spontaneous::Site.modified_at)
361
+ map = Spontaneous::Site.map(params[:id])
346
362
  if map
347
363
  json(map)
348
364
  else
@@ -351,19 +367,19 @@ module Spontaneous
351
367
  end
352
368
 
353
369
  get '/location*' do
354
- last_modified(Site.modified_at)
355
- if Page.count == 0
370
+ last_modified(Spontaneous::Site.modified_at)
371
+ if content_model::Page.count == 0
356
372
  406
357
373
  else
358
374
  path = params[:splat].first
359
- page = Site[path]
360
- json Site.map(page.id)
375
+ page = Spontaneous::Site[path]
376
+ json Spontaneous::Site.map(page.id)
361
377
  end
362
378
  end
363
379
 
364
380
  post '/root' do
365
- if Site.root.nil?
366
- type = Spontaneous.schema[params[:type]]
381
+ if Spontaneous::Site.root.nil?
382
+ type = content_model.schema.to_class(params[:type])
367
383
  root = type.create(:title => "Home")
368
384
  json({:id => root.id})
369
385
  else
@@ -389,7 +405,7 @@ module Spontaneous
389
405
  conflicts = []
390
406
  field_versions.each do |schema_id, version|
391
407
  field = content.fields.sid(schema_id)
392
- unless field.version == version.to_i
408
+ if field.matches_version?(version.to_i)
393
409
  conflicts << field
394
410
  end
395
411
  end
@@ -450,8 +466,7 @@ module Spontaneous
450
466
  if target.field_writable?(user, field.name)
451
467
  # version = params[:version].to_i
452
468
  # if version == field.version
453
- field.value = file
454
- content.save
469
+ Spontaneous::Field.set_asynchronously(field, file, user)
455
470
  json(field.export(user))
456
471
  # else
457
472
  # errors = [[field.schema_id.to_s, [field.version, field.conflicted_value]]]
@@ -474,8 +489,7 @@ module Spontaneous
474
489
  instance = type.new
475
490
  box.insert(position, instance)
476
491
  field = instance.field_for_mime_type(file[:type])
477
- field.value = file
478
- instance.save
492
+ Spontaneous::Field.set_asynchronously(field, file, user)
479
493
  content.save
480
494
  json({
481
495
  :position => position,
@@ -491,7 +505,7 @@ module Spontaneous
491
505
  post '/add/:id/:box_id/:type_name' do
492
506
  content_for_request(true) do |content, box|
493
507
  position = (params[:position] || 0).to_i
494
- type = Spontaneous.schema[params[:type_name]]#.constantize
508
+ type = content_model.schema.to_class(params[:type_name])#.constantize
495
509
 
496
510
  if box.writable?(user, type)
497
511
  instance = type.new(:created_by => user)
@@ -561,7 +575,7 @@ module Spontaneous
561
575
  end
562
576
 
563
577
  get '/targets/:schema_id/:id/:box_id' do
564
- klass = Spontaneous.schema[params[:schema_id]]
578
+ klass = content_model.schema.to_class(params[:schema_id])
565
579
  if klass.alias?
566
580
  content_for_request do |content, box|
567
581
  options = {}
@@ -585,7 +599,7 @@ module Spontaneous
585
599
 
586
600
  post '/alias/:id/:box_id' do
587
601
  content_for_request(true) do |content, box|
588
- type = Spontaneous.schema[params[:alias_id]]
602
+ type = content_model.schema.to_class(params[:alias_id])
589
603
  position = (params[:position] || 0).to_i
590
604
  if box.writable?(user, type)
591
605
  instance = type.for_target(params[:target_id])
@@ -619,7 +633,7 @@ module Spontaneous
619
633
  400
620
634
  else
621
635
  if user.level.can_publish?
622
- Site.publish_pages(pages)
636
+ Spontaneous::Site.publish_pages(pages)
623
637
  json({})
624
638
  else
625
639
  unauthorised!
@@ -664,11 +678,10 @@ module Spontaneous
664
678
  # version = params[:version].to_i
665
679
  # if version == field.version
666
680
  Spontaneous::Media.combine_shards(params[:shards]) do |combined|
667
- field.value = {
681
+ Spontaneous::Field.set_asynchronously(field, {
668
682
  :filename => params[:filename],
669
683
  :tempfile => combined
670
- }
671
- target.save
684
+ }, user)
672
685
  end
673
686
  json(field.export(user))
674
687
  # else
@@ -691,11 +704,15 @@ module Spontaneous
691
704
  box.insert(position, instance)
692
705
  field = instance.field_for_mime_type(params[:mime_type])
693
706
  Spontaneous::Media.combine_shards(params[:shards]) do |combined|
694
- field.value = {
707
+ Spontaneous::Field.set_asynchronously(field, {
695
708
  :filename => params[:filename],
696
709
  :tempfile => combined
697
- }
710
+ }, user)
698
711
  content.save
712
+ # field.value = {
713
+ # :filename => params[:filename],
714
+ # :tempfile => combined
715
+ # }
699
716
  end
700
717
  json({
701
718
  :position => position,
@@ -757,7 +774,7 @@ module Spontaneous
757
774
  class Preview < Sinatra::Base
758
775
  use CookieAuthentication
759
776
  use AroundPreview
760
- use Reloader if Site.config.reload_classes
777
+ use Reloader if Spontaneous::Site.config.reload_classes
761
778
  include Spontaneous::Rack::Public
762
779
  helpers Spontaneous::Rack::UserHelpers
763
780
 
@@ -3,7 +3,7 @@ module Spontaneous::Rack
3
3
  class CacheableFile < ::Rack::File
4
4
  include HTTP
5
5
 
6
- TEN_YEARS = 10*365*24*3600
6
+ TEN_YEARS = 10*365.25*24*3600
7
7
  MAX_AGE = "max-age=#{TEN_YEARS}, public".freeze
8
8
 
9
9
  def initialize(file_root)
@@ -20,7 +20,7 @@ module Spontaneous::Rack
20
20
  def caching_headers(headers)
21
21
  headers.merge({
22
22
  HTTP_CACHE_CONTROL => MAX_AGE,
23
- HTTP_EXPIRES => (Time.now + TEN_YEARS).httpdate
23
+ HTTP_EXPIRES => (Time.now.advance(:years => 10)).httpdate
24
24
  })
25
25
  end
26
26
  end
@@ -9,7 +9,7 @@ module Spontaneous
9
9
 
10
10
  def access_key(env)
11
11
  if login = Site.config.auto_login
12
- user = Spontaneous::Permissions::User[:login => login]
12
+ user = Spontaneous::Permissions::User.login(login)
13
13
  if user.access_keys.empty?
14
14
  user.generate_access_key(env["REMOTE_ADDR"])
15
15
  else
@@ -8,7 +8,7 @@ module Spontaneous
8
8
  def self.front_app
9
9
  ::Rack::Builder.app do
10
10
  use AroundFront
11
- use Reloader if Site.config.reload_classes
11
+ use Reloader if Spontaneous::Site.config.reload_classes
12
12
  run Server.new
13
13
  end
14
14
  end
@@ -15,22 +15,21 @@ module Spontaneous
15
15
  end
16
16
 
17
17
  def style_url(style)
18
- style = "#{style}.css" unless style =~ /\.css$/
19
- if (compiled_asset = application_assets.manifest.assets[style])
20
- return "#{NAMESPACE}/assets/#{compiled_asset}"
21
- end
22
- # TODO: use the sprockets environment to append a modification time to the non-compiled URL
23
- "#{NAMESPACE}/css/#{style}"
18
+ asset_url(style, "css")
24
19
  end
25
20
 
26
21
  def script_url(script)
27
- script = "#{script}.js" unless script =~ /\.js$/
22
+ asset_url(script, "js")
23
+ end
24
+
25
+ def asset_url(file, type)
26
+ file = "#{file}.#{type}" unless file =~ /\.#{type}$/
28
27
 
29
- if (compiled_asset = application_assets.manifest.assets[script])
28
+ if (compiled_asset = application_assets.manifest.assets[file])
30
29
  return "#{NAMESPACE}/assets/#{compiled_asset}"
31
30
  end
32
31
  # TODO: use the sprockets environment to append a modification time to the non-compiled URL
33
- "#{NAMESPACE}/js/#{script}"
32
+ "#{NAMESPACE}/#{type}/#{file}"
34
33
  end
35
34
 
36
35
  def script_list(scripts)
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'sinatra/base'
4
4
 
5
- module Spontaneous
5
+ module Spontaneous::Rack
6
6
  class PageController < Sinatra::Base
7
7
  attr_reader :content, :format
8
8
 
@@ -81,7 +81,7 @@ module Spontaneous
81
81
  end
82
82
 
83
83
  DOT = '.'.freeze
84
- ACTION = "/#{S::Plugins::Controllers::ACTION_SEPARATOR}".freeze
84
+ ACTION = "/#{S::Model::Page::Controllers::ACTION_SEPARATOR}".freeze
85
85
 
86
86
  def show(page, status=200)
87
87
  page = Spontaneous::Site[page] if String === page
@@ -101,7 +101,7 @@ module Spontaneous
101
101
 
102
102
  def redirect(location, redirect_code=:temporary)
103
103
  if String === location
104
- destination = Site[location]
104
+ destination = Spontaneous::Site[location]
105
105
  location = destination.path if destination and destination.respond_to?(:path)
106
106
  else
107
107
  location = location.path if location.respond_to?(:path)
@@ -129,7 +129,7 @@ module Spontaneous
129
129
 
130
130
  def find_page!(path)
131
131
  @path, @output, @action = parse_path(path)
132
- @page = Site[@path]
132
+ @page = Spontaneous::Site[@path]
133
133
  end
134
134
 
135
135
  def output
@@ -45,27 +45,27 @@ module Spontaneous
45
45
  set :environment, Proc.new { Spontaneous.environment }
46
46
  end
47
47
 
48
- autoload :HTTP, 'spontaneous/rack/http'
48
+ autoload :AroundBack, 'spontaneous/rack/around_back'
49
+ autoload :AroundFront, 'spontaneous/rack/around_front'
50
+ autoload :AroundPreview, 'spontaneous/rack/around_preview'
49
51
  autoload :Assets, 'spontaneous/rack/assets'
50
- autoload :Back, 'spontaneous/rack/back'
51
- autoload :Front, 'spontaneous/rack/front'
52
- autoload :Public, 'spontaneous/rack/public'
53
52
  autoload :Authentication, 'spontaneous/rack/authentication'
53
+ autoload :Back, 'spontaneous/rack/back'
54
+ autoload :CSS, 'spontaneous/rack/css'
54
55
  autoload :CacheableFile, 'spontaneous/rack/cacheable_file'
55
- autoload :Static, 'spontaneous/rack/static'
56
- autoload :UserHelpers, 'spontaneous/rack/user_helpers'
57
- autoload :UserAdmin, 'spontaneous/rack/user_admin'
58
- autoload :Helpers, 'spontaneous/rack/helpers'
59
56
  autoload :CookieAuthentication, 'spontaneous/rack/cookie_authentication'
60
- autoload :QueryAuthentication, 'spontaneous/rack/query_authentication'
61
- autoload :AroundBack, 'spontaneous/rack/around_back'
62
- autoload :AroundFront, 'spontaneous/rack/around_front'
63
- autoload :AroundPreview, 'spontaneous/rack/around_preview'
64
- autoload :Reloader, 'spontaneous/rack/reloader'
65
57
  autoload :EventSource, 'spontaneous/rack/event_source'
66
- autoload :CSS, 'spontaneous/rack/css'
58
+ autoload :Front, 'spontaneous/rack/front'
59
+ autoload :HTTP, 'spontaneous/rack/http'
60
+ autoload :Helpers, 'spontaneous/rack/helpers'
67
61
  autoload :JS, 'spontaneous/rack/js'
62
+ autoload :PageController, "spontaneous/rack/page_controller"
63
+ autoload :Public, 'spontaneous/rack/public'
64
+ autoload :QueryAuthentication, 'spontaneous/rack/query_authentication'
65
+ autoload :Reloader, 'spontaneous/rack/reloader'
68
66
  autoload :SSE, 'spontaneous/rack/sse'
69
- autoload :FiberPool, 'spontaneous/rack/fiber_pool'
67
+ autoload :Static, 'spontaneous/rack/static'
68
+ autoload :UserAdmin, 'spontaneous/rack/user_admin'
69
+ autoload :UserHelpers, 'spontaneous/rack/user_helpers'
70
70
  end
71
71
  end
@@ -124,6 +124,10 @@ module Spontaneous
124
124
  @id
125
125
  end
126
126
 
127
+ def sql_literal(dataset)
128
+ dataset.literal @id
129
+ end
130
+
127
131
  def <=>(other)
128
132
  self.to_s <=> other.to_s
129
133
  end
@@ -132,6 +136,5 @@ module Spontaneous
132
136
  %(#<#{self.class}:"#{@id}" => "#{reference}">)
133
137
  end
134
138
  end
135
-
136
139
  end
137
140
  end
@@ -16,7 +16,7 @@ module Spontaneous
16
16
  load_map
17
17
  end
18
18
 
19
- def schema_id(obj)
19
+ def to_id(obj)
20
20
  reference_to_id(obj.schema_name)
21
21
  end
22
22
 
@@ -24,7 +24,7 @@ module Spontaneous
24
24
  uids.get_id(reference)
25
25
  end
26
26
 
27
- def [](id)
27
+ def to_class(id)
28
28
  if uid = uids[id]
29
29
  uid.target
30
30
  else
@@ -78,7 +78,7 @@ module Spontaneous
78
78
  @uids = uids
79
79
  end
80
80
 
81
- def schema_id(obj)
81
+ def to_id(obj)
82
82
  if id = super
83
83
  id
84
84
  else
@@ -99,12 +99,18 @@ module Spontaneous
99
99
  end
100
100
  end
101
101
 
102
+ def self.new(root, schema_loader_class = Spontaneous::Schema::PersistentMap)
103
+ Schema.new(root, schema_loader_class)
104
+ end
105
+
102
106
  class Schema
103
- attr_reader :schema_loader_class, :uids
107
+ attr_accessor :schema_loader_class
108
+ attr_reader :uids
104
109
 
105
110
  def initialize(root, schema_loader_class = Spontaneous::Schema::PersistentMap)
106
111
  @root = root
107
112
  @schema_loader_class = schema_loader_class
113
+ @subclass_map = Hash.new { |h, k| h[k] = [] }
108
114
  initialize_uid_map
109
115
  end
110
116
 
@@ -250,38 +256,53 @@ module Spontaneous
250
256
  Spontaneous.serialise_http(export(user))
251
257
  end
252
258
 
259
+ def unfiltered_classes
260
+ @classes ||= []
261
+ end
262
+
253
263
  # all classes including boxes
254
264
  def classes
255
- @classes ||= []
265
+ unfiltered_classes.reject { |c| is_excluded_type?(c) }
256
266
  end
257
267
 
258
- def add_class(supertype, type)
268
+ def inherited(supertype, type)
259
269
  inheritance_map[supertype.to_s] << type
260
- classes << type unless classes.include?(type)
270
+ unfiltered_classes << type
271
+ end
272
+
273
+ def is_excluded_type?(type)
274
+ excluded_types.include?(type)
275
+ end
276
+
277
+ def excluded_types
278
+ [Spontaneous::Content, Spontaneous::Content::Page, Spontaneous::Content::Piece]
261
279
  end
262
280
 
263
281
  def inheritance_map
264
- @inheritance_map ||= Hash.new { |h, k| h[k] = [] }
282
+ @inheritance_map ||= empty_inheritance_map
265
283
  end
266
284
 
285
+ def empty_inheritance_map
286
+ Hash.new { |h, k| h[k] = [] }
287
+ end
267
288
 
268
289
  def subclasses_of(type)
269
290
  inheritance_map[type.to_s].map { |subclass| subclass }
270
291
  end
271
292
 
272
293
  def descendents_of(type)
273
- subclasses_of(type).map{ |x| [x] + descendents_of(x) }.flatten
294
+ subclasses_of(type).flat_map{ |x| [x] + descendents_of(x) }
274
295
  end
275
296
 
297
+ alias_method :subclasses, :descendents_of
298
+
276
299
  # just subclasses of Content (excluding boxes)
277
300
  # only need this for the serialisation (which doesn't include boxes)
301
+ #
302
+ # TODO: Find a way to filter out the top-level classes without hard-coding
303
+ # them here.
278
304
  def content_classes
279
- classes = []
280
- self.classes.reject { |k| k.is_box? }.each do |klass|
281
- classes << klass unless [Spontaneous::Page, Spontaneous::Piece].include?(klass)
282
- # recurse_classes(klass, classes)
283
- end
284
- classes.uniq
305
+ classes.reject { |k| k.is_box? }.uniq
285
306
  end
286
307
 
287
308
  def recurse_classes(root_class, list)
@@ -291,16 +312,14 @@ module Spontaneous
291
312
  end
292
313
  end
293
314
 
294
- # should only be used in tests
295
315
  def reset!
296
- Content.schema_reset!
297
- @classes = []
316
+ @classes = []
298
317
  @inheritance_map = nil
299
318
  reload!
300
319
  end
301
320
 
302
321
  def reload!
303
- @map = nil
322
+ @map = nil
304
323
  initialize_uid_map
305
324
  end
306
325
 
@@ -308,8 +327,22 @@ module Spontaneous
308
327
  @uids = Spontaneous::Schema::UIDMap.new
309
328
  end
310
329
 
330
+ # It's obvious from this method that schema classes are
331
+ # stored in too many ways
311
332
  def delete(klass)
312
- classes.delete(klass)
333
+ constants_of(klass).each { |const| delete(const) }
334
+ unfiltered_classes.delete(klass)
335
+ remove_group_members(klass)
336
+ inheritance_map.delete(klass.to_s)
337
+ inheritance_map.each do |supertype, subtypes|
338
+ subtypes.delete(klass)
339
+ end
340
+ end
341
+
342
+ def constants_of(klass)
343
+ klass.constants.
344
+ select { |c| klass.const_defined?(c, false) }.
345
+ map { |c| klass.const_get(c) }
313
346
  end
314
347
 
315
348
  def schema_map_file
@@ -326,12 +359,12 @@ module Spontaneous
326
359
  @map ||= self.schema_loader_class.new(@uids, schema_map_file)
327
360
  end
328
361
 
329
- def schema_id(obj)
330
- map.schema_id(obj)
362
+ def to_id(obj)
363
+ map.to_id(obj)
331
364
  end
332
365
 
333
- def [](schema_id)
334
- map[schema_id]
366
+ def to_class(id)
367
+ map.to_class(id)
335
368
  end
336
369
 
337
370
  def groups
@@ -26,12 +26,22 @@ module Spontaneous::Search
26
26
  options = { :dir => directory,
27
27
  :language => @index.language,
28
28
  :fields => @index.fields,
29
- :spelling => true }
29
+ :spelling => true,
30
+ :weights => weighting_proc
31
+ }
30
32
  options[:stemmer] = @index.stemmer unless @index.stemmer.nil?
31
33
  options[:stopper] = @index.stopper unless @index.stopper.nil?
32
34
  options
33
35
  end
34
36
 
37
+ def weighting_proc
38
+ Proc.new { |key, value, fields| field_weighting(key, fields) }
39
+ end
40
+
41
+ def field_weighting(key, fields)
42
+ @weights[key]
43
+ end
44
+
35
45
  def database
36
46
  @database ||= open_database
37
47
  end
@@ -42,6 +52,7 @@ module Spontaneous::Search
42
52
 
43
53
  def add(page)
44
54
  if @index.include?(page)
55
+ @weights = @index.weights(page)
45
56
  database << @index.indexable_content(page)
46
57
  end
47
58
  end