spontaneous 0.1.0.alpha1

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 (556) hide show
  1. data/Gemfile +49 -0
  2. data/Gemfile.lock +146 -0
  3. data/LICENSE +0 -0
  4. data/README +0 -0
  5. data/Rakefile +284 -0
  6. data/Readme.markdown +7 -0
  7. data/application/css/add_alias_dialogue.scss +27 -0
  8. data/application/css/definitions.scss +249 -0
  9. data/application/css/developer.scss +9 -0
  10. data/application/css/editing.scss +649 -0
  11. data/application/css/login.scss +91 -0
  12. data/application/css/min/54ee0ed3c7fac7632bd5c020d69e9a2503e0c88c.css +1 -0
  13. data/application/css/min/c256adc144e2bdd0b0539356b04eb62db01e1dc3.css +1 -0
  14. data/application/css/popover.scss +335 -0
  15. data/application/css/schema_error.scss +90 -0
  16. data/application/css/spontaneous.scss +111 -0
  17. data/application/css/unsupported.scss +16 -0
  18. data/application/css/v2.scss +1606 -0
  19. data/application/css/variables.scss +80 -0
  20. data/application/js/add_alias_dialogue.js +59 -0
  21. data/application/js/add_home_dialogue.js +59 -0
  22. data/application/js/ajax.js +99 -0
  23. data/application/js/authentication.js +22 -0
  24. data/application/js/box.js +104 -0
  25. data/application/js/box_container.js +82 -0
  26. data/application/js/compatibility.js +132 -0
  27. data/application/js/conflicted_field_dialogue.js +92 -0
  28. data/application/js/content.js +224 -0
  29. data/application/js/content_area.js +44 -0
  30. data/application/js/dialogue.js +196 -0
  31. data/application/js/dom.js +71 -0
  32. data/application/js/edit_dialogue.js +137 -0
  33. data/application/js/edit_panel.js +232 -0
  34. data/application/js/editing.js +42 -0
  35. data/application/js/entry.js +13 -0
  36. data/application/js/extensions.js +104 -0
  37. data/application/js/field.js +4 -0
  38. data/application/js/field_preview.js +55 -0
  39. data/application/js/field_types/date_field.js +16 -0
  40. data/application/js/field_types/file_field.js +71 -0
  41. data/application/js/field_types/image_field.js +358 -0
  42. data/application/js/field_types/markdown_field.js +656 -0
  43. data/application/js/field_types/string_field.js +185 -0
  44. data/application/js/image.js +72 -0
  45. data/application/js/init.js +34 -0
  46. data/application/js/load.js +4 -0
  47. data/application/js/location.js +157 -0
  48. data/application/js/login.js +53 -0
  49. data/application/js/min/492a209de8ee955fa9c729a765377495001e11b1.js +17 -0
  50. data/application/js/min/80f684d77c940887a1d4a63e3a96102e993baa98.js +88 -0
  51. data/application/js/min/b8abf302a824c35385ff517b34111e1710ff3b37.js +2 -0
  52. data/application/js/min/c7140ec9475e5bf868b901e0621338d7d162358b.js +3 -0
  53. data/application/js/min/f07f2bd6630ee31e1c2288ec223383d8f0658ba6.js +2 -0
  54. data/application/js/page.js +43 -0
  55. data/application/js/page_browser.js +147 -0
  56. data/application/js/page_entry.js +47 -0
  57. data/application/js/popover.js +99 -0
  58. data/application/js/popover_view.js +56 -0
  59. data/application/js/preview.js +64 -0
  60. data/application/js/progress.js +358 -0
  61. data/application/js/properties.js +90 -0
  62. data/application/js/publish.js +187 -0
  63. data/application/js/require.js +129 -0
  64. data/application/js/sharded_upload.js +206 -0
  65. data/application/js/side_bar.js +30 -0
  66. data/application/js/spontaneous.js +6 -0
  67. data/application/js/state.js +64 -0
  68. data/application/js/status_bar.js +47 -0
  69. data/application/js/top_bar.js +368 -0
  70. data/application/js/types.js +98 -0
  71. data/application/js/upload.js +88 -0
  72. data/application/js/upload_manager.js +319 -0
  73. data/application/js/user.js +37 -0
  74. data/application/js/vendor/.DS_Store +0 -0
  75. data/application/js/vendor/JS.Class-2.1.5/CHANGELOG +283 -0
  76. data/application/js/vendor/JS.Class-2.1.5/MIT-LICENSE +30 -0
  77. data/application/js/vendor/JS.Class-2.1.5/README +30 -0
  78. data/application/js/vendor/JS.Class-2.1.5/min/command.js +1 -0
  79. data/application/js/vendor/JS.Class-2.1.5/min/comparable.js +1 -0
  80. data/application/js/vendor/JS.Class-2.1.5/min/constant_scope.js +1 -0
  81. data/application/js/vendor/JS.Class-2.1.5/min/core.js +1 -0
  82. data/application/js/vendor/JS.Class-2.1.5/min/decorator.js +1 -0
  83. data/application/js/vendor/JS.Class-2.1.5/min/enumerable.js +1 -0
  84. data/application/js/vendor/JS.Class-2.1.5/min/forwardable.js +1 -0
  85. data/application/js/vendor/JS.Class-2.1.5/min/hash.js +1 -0
  86. data/application/js/vendor/JS.Class-2.1.5/min/linked_list.js +1 -0
  87. data/application/js/vendor/JS.Class-2.1.5/min/loader.js +1 -0
  88. data/application/js/vendor/JS.Class-2.1.5/min/method_chain.js +1 -0
  89. data/application/js/vendor/JS.Class-2.1.5/min/observable.js +1 -0
  90. data/application/js/vendor/JS.Class-2.1.5/min/package.js +1 -0
  91. data/application/js/vendor/JS.Class-2.1.5/min/proxy.js +1 -0
  92. data/application/js/vendor/JS.Class-2.1.5/min/ruby.js +1 -0
  93. data/application/js/vendor/JS.Class-2.1.5/min/set.js +1 -0
  94. data/application/js/vendor/JS.Class-2.1.5/min/stack_trace.js +1 -0
  95. data/application/js/vendor/JS.Class-2.1.5/min/state.js +1 -0
  96. data/application/js/vendor/JS.Class-2.1.5/min/stdlib.js +16 -0
  97. data/application/js/vendor/JS.Class-2.1.5/src/command.js +93 -0
  98. data/application/js/vendor/JS.Class-2.1.5/src/comparable.js +37 -0
  99. data/application/js/vendor/JS.Class-2.1.5/src/constant_scope.js +48 -0
  100. data/application/js/vendor/JS.Class-2.1.5/src/core.js +1060 -0
  101. data/application/js/vendor/JS.Class-2.1.5/src/decorator.js +50 -0
  102. data/application/js/vendor/JS.Class-2.1.5/src/enumerable.js +505 -0
  103. data/application/js/vendor/JS.Class-2.1.5/src/forwardable.js +22 -0
  104. data/application/js/vendor/JS.Class-2.1.5/src/hash.js +334 -0
  105. data/application/js/vendor/JS.Class-2.1.5/src/linked_list.js +114 -0
  106. data/application/js/vendor/JS.Class-2.1.5/src/loader.js +553 -0
  107. data/application/js/vendor/JS.Class-2.1.5/src/method_chain.js +172 -0
  108. data/application/js/vendor/JS.Class-2.1.5/src/observable.js +55 -0
  109. data/application/js/vendor/JS.Class-2.1.5/src/package.js +472 -0
  110. data/application/js/vendor/JS.Class-2.1.5/src/proxy.js +58 -0
  111. data/application/js/vendor/JS.Class-2.1.5/src/ruby.js +44 -0
  112. data/application/js/vendor/JS.Class-2.1.5/src/set.js +332 -0
  113. data/application/js/vendor/JS.Class-2.1.5/src/stack_trace.js +151 -0
  114. data/application/js/vendor/JS.Class-2.1.5/src/state.js +95 -0
  115. data/application/js/vendor/JS.Class-2.1.5/src/stdlib.js +2612 -0
  116. data/application/js/vendor/crypto-2.3.0-crypto.js +160 -0
  117. data/application/js/vendor/crypto-2.3.0-sha1.js +91 -0
  118. data/application/js/vendor/diff_match_patch.js +2153 -0
  119. data/application/js/vendor/jquery-1.4.2.min.js +154 -0
  120. data/application/js/vendor/jquery-1.4.3.min.js +166 -0
  121. data/application/js/vendor/jquery-1.5.1.min.js +16 -0
  122. data/application/js/vendor/jquery-1.5.1rc1.min.js +24 -0
  123. data/application/js/vendor/jquery-1.6.2.min.js +18 -0
  124. data/application/js/vendor/jquery-ui-1.8.6.custom.min.js +265 -0
  125. data/application/js/vendor/jquery-ui-1.8.9.custom.min.js +415 -0
  126. data/application/js/vendor/jquery-ui-1.8.custom.min.js +106 -0
  127. data/application/js/vendor/jquery.hotkeys-0.7.9.js +248 -0
  128. data/application/js/vendor/jquery.hotkeys-0.7.9.min.js +19 -0
  129. data/application/js/vendor/jsdiff.js +169 -0
  130. data/application/js/views/box_view.js +229 -0
  131. data/application/js/views/page_piece_view.js +45 -0
  132. data/application/js/views/page_view.js +238 -0
  133. data/application/js/views/piece_view.js +178 -0
  134. data/application/js/views.js +110 -0
  135. data/application/static/editing-0-noise.png +0 -0
  136. data/application/static/editing-1-noise.png +0 -0
  137. data/application/static/editing-texture-1.png +0 -0
  138. data/application/static/editing-texture.png +0 -0
  139. data/application/static/editing-toolbar-shadow-bottom.png +0 -0
  140. data/application/static/editing-toolbar-shadow-top.png +0 -0
  141. data/application/static/favicon.ico +0 -0
  142. data/application/static/inner-glow.png +0 -0
  143. data/application/static/item-buttons.png +0 -0
  144. data/application/static/location-arrow.png +0 -0
  145. data/application/static/logo-400px-transparent.png +0 -0
  146. data/application/static/missing.png +0 -0
  147. data/application/static/orange-down-arrow.png +0 -0
  148. data/application/static/page-browser-next.png +0 -0
  149. data/application/static/paper-texture-dark.png +0 -0
  150. data/application/static/px.gif +0 -0
  151. data/application/static/select-arrow-root.png +0 -0
  152. data/application/static/select-arrow.png +0 -0
  153. data/application/static/slot-down-arrow.png +0 -0
  154. data/application/static/splash.png +0 -0
  155. data/application/static/spontaneous.png +0 -0
  156. data/application/static/spot.png +0 -0
  157. data/application/static/spot.svg +40 -0
  158. data/application/static/texture.png +0 -0
  159. data/application/views/index.erubis +46 -0
  160. data/application/views/login.erubis +69 -0
  161. data/application/views/schema_modification_error.html.erb +61 -0
  162. data/application/views/unsupported.erubis +23 -0
  163. data/bin/limit-upload +5 -0
  164. data/bin/spot +10 -0
  165. data/bin/unlimit-upload +3 -0
  166. data/config/nginx.conf +60 -0
  167. data/db/migrations/20100610142136_init.rb +66 -0
  168. data/db/migrations/20101130104334_timestamps.rb +44 -0
  169. data/db/migrations/20101202113205_site_publishing_flags.rb +12 -0
  170. data/db/migrations/20101206124543_aliases.rb +16 -0
  171. data/db/migrations/20110201133550_visibility.rb +27 -0
  172. data/db/migrations/20110209152710_users_and_groups.rb +58 -0
  173. data/db/migrations/20110215133910_boxes.rb +25 -0
  174. data/db/migrations/20110521114145_remove_slots_and_entries.rb +21 -0
  175. data/db/migrations/20110604192145_rename_schema_id_columns.rb +22 -0
  176. data/db/migrations/20110805141925_rename_site_to_state.rb +11 -0
  177. data/lib/cutaneous/context_helper.rb +82 -0
  178. data/lib/cutaneous/first_pass_parser.rb +23 -0
  179. data/lib/cutaneous/first_pass_renderer.rb +18 -0
  180. data/lib/cutaneous/parser_core.rb +18 -0
  181. data/lib/cutaneous/preview_context.rb +31 -0
  182. data/lib/cutaneous/preview_renderer.rb +15 -0
  183. data/lib/cutaneous/publish_context.rb +9 -0
  184. data/lib/cutaneous/renderer.rb +122 -0
  185. data/lib/cutaneous/request_context.rb +8 -0
  186. data/lib/cutaneous/second_pass_parser.rb +23 -0
  187. data/lib/cutaneous/second_pass_renderer.rb +18 -0
  188. data/lib/cutaneous.rb +47 -0
  189. data/lib/sequel/plugins/content_table_inheritance.rb +196 -0
  190. data/lib/sequel/plugins/yajl_serialization.rb +154 -0
  191. data/lib/spontaneous/application/feature.rb +9 -0
  192. data/lib/spontaneous/application/plugin.rb +13 -0
  193. data/lib/spontaneous/application.rb +8 -0
  194. data/lib/spontaneous/box.rb +232 -0
  195. data/lib/spontaneous/box_style.rb +64 -0
  196. data/lib/spontaneous/change.rb +107 -0
  197. data/lib/spontaneous/cli/adapter.rb +13 -0
  198. data/lib/spontaneous/cli/base.rb +184 -0
  199. data/lib/spontaneous/cli/console.rb +0 -0
  200. data/lib/spontaneous/cli/media.rb +13 -0
  201. data/lib/spontaneous/cli/server.rb +50 -0
  202. data/lib/spontaneous/cli/site.rb +46 -0
  203. data/lib/spontaneous/cli/sync.rb +42 -0
  204. data/lib/spontaneous/cli/tasks.rb +9 -0
  205. data/lib/spontaneous/cli.rb +83 -0
  206. data/lib/spontaneous/collections/box_set.rb +56 -0
  207. data/lib/spontaneous/collections/change_set.rb +43 -0
  208. data/lib/spontaneous/collections/entry_set.rb +83 -0
  209. data/lib/spontaneous/collections/field_set.rb +53 -0
  210. data/lib/spontaneous/collections/prototype_set.rb +131 -0
  211. data/lib/spontaneous/collections/style_set.rb +13 -0
  212. data/lib/spontaneous/config.rb +156 -0
  213. data/lib/spontaneous/constants.rb +24 -0
  214. data/lib/spontaneous/content.rb +113 -0
  215. data/lib/spontaneous/content_query.rb +17 -0
  216. data/lib/spontaneous/errors.rb +48 -0
  217. data/lib/spontaneous/extensions/array.rb +18 -0
  218. data/lib/spontaneous/extensions/class.rb +17 -0
  219. data/lib/spontaneous/extensions/hash.rb +18 -0
  220. data/lib/spontaneous/extensions/json.rb +26 -0
  221. data/lib/spontaneous/extensions/kernel.rb +7 -0
  222. data/lib/spontaneous/extensions/object.rb +30 -0
  223. data/lib/spontaneous/extensions/object_space.rb +12 -0
  224. data/lib/spontaneous/extensions/string.rb +44 -0
  225. data/lib/spontaneous/facet.rb +47 -0
  226. data/lib/spontaneous/field_types/date_field.rb +12 -0
  227. data/lib/spontaneous/field_types/field.rb +252 -0
  228. data/lib/spontaneous/field_types/image_field.rb +329 -0
  229. data/lib/spontaneous/field_types/markdown_field.rb +37 -0
  230. data/lib/spontaneous/field_types/string_field.rb +14 -0
  231. data/lib/spontaneous/field_types.rb +40 -0
  232. data/lib/spontaneous/generators/page/inline.html.cut +1 -0
  233. data/lib/spontaneous/generators/page/page.html.cut.tt +4 -0
  234. data/lib/spontaneous/generators/page/page.rb.tt +9 -0
  235. data/lib/spontaneous/generators/page.rb +38 -0
  236. data/lib/spontaneous/generators/site/.gitignore +4 -0
  237. data/lib/spontaneous/generators/site/Gemfile.tt +31 -0
  238. data/lib/spontaneous/generators/site/Rakefile.tt +6 -0
  239. data/lib/spontaneous/generators/site/config/back.ru +7 -0
  240. data/lib/spontaneous/generators/site/config/boot.rb +19 -0
  241. data/lib/spontaneous/generators/site/config/database.yml.tt +21 -0
  242. data/lib/spontaneous/generators/site/config/deploy.rb.tt +0 -0
  243. data/lib/spontaneous/generators/site/config/environment.rb.tt +8 -0
  244. data/lib/spontaneous/generators/site/config/environments/development.rb.tt +15 -0
  245. data/lib/spontaneous/generators/site/config/environments/production.rb.tt +5 -0
  246. data/lib/spontaneous/generators/site/config/front.ru +8 -0
  247. data/lib/spontaneous/generators/site/config/user_levels.yml +22 -0
  248. data/lib/spontaneous/generators/site/lib/site.rb.tt +4 -0
  249. data/lib/spontaneous/generators/site/lib/tasks/site.rake.tt +8 -0
  250. data/lib/spontaneous/generators/site/public/css/site.css +0 -0
  251. data/lib/spontaneous/generators/site/public/favicon.ico +0 -0
  252. data/lib/spontaneous/generators/site/public/js/.empty_directory +0 -0
  253. data/lib/spontaneous/generators/site/public/js/site.js +0 -0
  254. data/lib/spontaneous/generators/site/public/robots.txt +0 -0
  255. data/lib/spontaneous/generators/site/schema/.map +1 -0
  256. data/lib/spontaneous/generators/site/schema/page.rb.tt +8 -0
  257. data/lib/spontaneous/generators/site/schema/piece.rb.tt +4 -0
  258. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +13 -0
  259. data/lib/spontaneous/generators/site.rb +77 -0
  260. data/lib/spontaneous/generators.rb +23 -0
  261. data/lib/spontaneous/image_size.rb +117 -0
  262. data/lib/spontaneous/json.rb +33 -0
  263. data/lib/spontaneous/layout.rb +15 -0
  264. data/lib/spontaneous/loader.rb +280 -0
  265. data/lib/spontaneous/logger.rb +369 -0
  266. data/lib/spontaneous/media.rb +84 -0
  267. data/lib/spontaneous/page.rb +92 -0
  268. data/lib/spontaneous/page_controller.rb +18 -0
  269. data/lib/spontaneous/page_piece.rb +77 -0
  270. data/lib/spontaneous/paths.rb +30 -0
  271. data/lib/spontaneous/permissions/access_group.rb +50 -0
  272. data/lib/spontaneous/permissions/access_key.rb +35 -0
  273. data/lib/spontaneous/permissions/user.rb +167 -0
  274. data/lib/spontaneous/permissions/user_level.rb +177 -0
  275. data/lib/spontaneous/permissions.rb +55 -0
  276. data/lib/spontaneous/piece.rb +30 -0
  277. data/lib/spontaneous/plugins/aliases.rb +128 -0
  278. data/lib/spontaneous/plugins/allowed_types.rb +173 -0
  279. data/lib/spontaneous/plugins/application/facets.rb +25 -0
  280. data/lib/spontaneous/plugins/application/paths.rb +137 -0
  281. data/lib/spontaneous/plugins/application/render.rb +29 -0
  282. data/lib/spontaneous/plugins/application/serialisation.rb +16 -0
  283. data/lib/spontaneous/plugins/application/state.rb +86 -0
  284. data/lib/spontaneous/plugins/boxes.rb +84 -0
  285. data/lib/spontaneous/plugins/controllers.rb +52 -0
  286. data/lib/spontaneous/plugins/entries.rb +193 -0
  287. data/lib/spontaneous/plugins/entry.rb +51 -0
  288. data/lib/spontaneous/plugins/fields.rb +103 -0
  289. data/lib/spontaneous/plugins/instance_code.rb +18 -0
  290. data/lib/spontaneous/plugins/layouts.rb +87 -0
  291. data/lib/spontaneous/plugins/media.rb +41 -0
  292. data/lib/spontaneous/plugins/page/formats.rb +67 -0
  293. data/lib/spontaneous/plugins/page/request.rb +89 -0
  294. data/lib/spontaneous/plugins/page_search.rb +64 -0
  295. data/lib/spontaneous/plugins/page_tree.rb +25 -0
  296. data/lib/spontaneous/plugins/paths.rb +125 -0
  297. data/lib/spontaneous/plugins/permissions.rb +63 -0
  298. data/lib/spontaneous/plugins/prototypes.rb +84 -0
  299. data/lib/spontaneous/plugins/publishing.rb +255 -0
  300. data/lib/spontaneous/plugins/render.rb +24 -0
  301. data/lib/spontaneous/plugins/schema_hierarchy.rb +76 -0
  302. data/lib/spontaneous/plugins/schema_id.rb +60 -0
  303. data/lib/spontaneous/plugins/schema_title.rb +33 -0
  304. data/lib/spontaneous/plugins/serialisation.rb +67 -0
  305. data/lib/spontaneous/plugins/site/instance.rb +22 -0
  306. data/lib/spontaneous/plugins/site/map.rb +19 -0
  307. data/lib/spontaneous/plugins/site/publishing.rb +74 -0
  308. data/lib/spontaneous/plugins/site/revisions.rb +28 -0
  309. data/lib/spontaneous/plugins/site/selectors.rb +41 -0
  310. data/lib/spontaneous/plugins/site_map.rb +34 -0
  311. data/lib/spontaneous/plugins/styles.rb +119 -0
  312. data/lib/spontaneous/plugins/supertype.rb +11 -0
  313. data/lib/spontaneous/plugins/visibility.rb +151 -0
  314. data/lib/spontaneous/plugins.rb +20 -0
  315. data/lib/spontaneous/prototypes/box_prototype.rb +168 -0
  316. data/lib/spontaneous/prototypes/field_prototype.rb +112 -0
  317. data/lib/spontaneous/prototypes/layout_prototype.rb +17 -0
  318. data/lib/spontaneous/prototypes/style_prototype.rb +42 -0
  319. data/lib/spontaneous/proxy_object.rb +12 -0
  320. data/lib/spontaneous/publishing/fire_and_forget.rb +57 -0
  321. data/lib/spontaneous/publishing/immediate.rb +197 -0
  322. data/lib/spontaneous/publishing/threaded.rb +25 -0
  323. data/lib/spontaneous/publishing.rb +10 -0
  324. data/lib/spontaneous/rack/around_back.rb +44 -0
  325. data/lib/spontaneous/rack/around_front.rb +29 -0
  326. data/lib/spontaneous/rack/around_preview.rb +26 -0
  327. data/lib/spontaneous/rack/assets.rb +98 -0
  328. data/lib/spontaneous/rack/back.rb +729 -0
  329. data/lib/spontaneous/rack/front.rb +41 -0
  330. data/lib/spontaneous/rack/http.rb +18 -0
  331. data/lib/spontaneous/rack/media.rb +29 -0
  332. data/lib/spontaneous/rack/public.rb +232 -0
  333. data/lib/spontaneous/rack/reloader.rb +42 -0
  334. data/lib/spontaneous/rack/static.rb +25 -0
  335. data/lib/spontaneous/rack.rb +55 -0
  336. data/lib/spontaneous/render/context.rb +100 -0
  337. data/lib/spontaneous/render/development_renderer.rb +14 -0
  338. data/lib/spontaneous/render/engine.rb +19 -0
  339. data/lib/spontaneous/render/format/html.rb +5 -0
  340. data/lib/spontaneous/render/format.rb +70 -0
  341. data/lib/spontaneous/render/preview_renderer.rb +18 -0
  342. data/lib/spontaneous/render/published_renderer.rb +54 -0
  343. data/lib/spontaneous/render/publishing_renderer.rb +13 -0
  344. data/lib/spontaneous/render/renderer.rb +46 -0
  345. data/lib/spontaneous/render.rb +173 -0
  346. data/lib/spontaneous/revision.rb +7 -0
  347. data/lib/spontaneous/schema/schema_modification.rb +260 -0
  348. data/lib/spontaneous/schema/uid.rb +221 -0
  349. data/lib/spontaneous/schema.rb +295 -0
  350. data/lib/spontaneous/server.rb +65 -0
  351. data/lib/spontaneous/site.rb +87 -0
  352. data/lib/spontaneous/state.rb +53 -0
  353. data/lib/spontaneous/style.rb +144 -0
  354. data/lib/spontaneous/tasks/database.rake +9 -0
  355. data/lib/spontaneous/tasks.rb +5 -0
  356. data/lib/spontaneous/version.rb +6 -0
  357. data/lib/spontaneous.rb +179 -0
  358. data/spontaneous.gemspec.tmpl +66 -0
  359. data/test/disabled/test_slots.rb +287 -0
  360. data/test/experimental/test_formats.rb +92 -0
  361. data/test/experimental/test_plugins.rb +64 -0
  362. data/test/fixtures/application/css/test.less +5 -0
  363. data/test/fixtures/application/js/test.js +1 -0
  364. data/test/fixtures/application/static/favicon.ico +1 -0
  365. data/test/fixtures/application/static/test.html +1 -0
  366. data/test/fixtures/application/views/index.erubis +1 -0
  367. data/test/fixtures/back/public/test.html +1 -0
  368. data/test/fixtures/back/templates/layouts/standard.html.cut +1 -0
  369. data/test/fixtures/config/config/environment.rb +4 -0
  370. data/test/fixtures/config/config/environments/development.rb +13 -0
  371. data/test/fixtures/config/config/environments/production.rb +22 -0
  372. data/test/fixtures/config/config/environments/staging.rb +2 -0
  373. data/test/fixtures/example_application/Gemfile +6 -0
  374. data/test/fixtures/example_application/Gemfile.lock +76 -0
  375. data/test/fixtures/example_application/Rakefile +6 -0
  376. data/test/fixtures/example_application/config/back.rb +15 -0
  377. data/test/fixtures/example_application/config/back.ru +8 -0
  378. data/test/fixtures/example_application/config/back.yml +8 -0
  379. data/test/fixtures/example_application/config/boot.rb +16 -0
  380. data/test/fixtures/example_application/config/database.yml +24 -0
  381. data/test/fixtures/example_application/config/environment.rb +4 -0
  382. data/test/fixtures/example_application/config/environments/development.rb +16 -0
  383. data/test/fixtures/example_application/config/environments/production.rb +21 -0
  384. data/test/fixtures/example_application/config/environments/staging.rb +1 -0
  385. data/test/fixtures/example_application/config/front.rb +8 -0
  386. data/test/fixtures/example_application/config/front.ru +8 -0
  387. data/test/fixtures/example_application/config/front.yml +8 -0
  388. data/test/fixtures/example_application/config/schema.yml +48 -0
  389. data/test/fixtures/example_application/config/unicorn.rb +1 -0
  390. data/test/fixtures/example_application/config/user_levels.yml +19 -0
  391. data/test/fixtures/example_application/public/css/test.css +0 -0
  392. data/test/fixtures/example_application/public/favicon.ico +1 -0
  393. data/test/fixtures/example_application/public/js/test.js +0 -0
  394. data/test/fixtures/example_application/public/test.html +1 -0
  395. data/test/fixtures/example_application/schema/client_project.rb +18 -0
  396. data/test/fixtures/example_application/schema/client_projects.rb +8 -0
  397. data/test/fixtures/example_application/schema/home_page.rb +22 -0
  398. data/test/fixtures/example_application/schema/info_page.rb +13 -0
  399. data/test/fixtures/example_application/schema/inline_image.rb +11 -0
  400. data/test/fixtures/example_application/schema/page.rb +4 -0
  401. data/test/fixtures/example_application/schema/piece.rb +3 -0
  402. data/test/fixtures/example_application/schema/project.rb +21 -0
  403. data/test/fixtures/example_application/schema/project_image.rb +18 -0
  404. data/test/fixtures/example_application/schema/projects_page.rb +12 -0
  405. data/test/fixtures/example_application/schema/text.rb +8 -0
  406. data/test/fixtures/example_application/templates/client_project/images.html.cut +1 -0
  407. data/test/fixtures/example_application/templates/client_project.html.cut +4 -0
  408. data/test/fixtures/example_application/templates/client_projects.html.cut +6 -0
  409. data/test/fixtures/example_application/templates/info_page/inline.html.cut +0 -0
  410. data/test/fixtures/example_application/templates/inline_image.html.cut +1 -0
  411. data/test/fixtures/example_application/templates/layouts/home.html.cut +15 -0
  412. data/test/fixtures/example_application/templates/layouts/info.html.cut +3 -0
  413. data/test/fixtures/example_application/templates/layouts/project.html.cut +13 -0
  414. data/test/fixtures/example_application/templates/layouts/projects.html.cut +11 -0
  415. data/test/fixtures/example_application/templates/layouts/standard.html.cut +0 -0
  416. data/test/fixtures/example_application/templates/project/inline.html.cut +5 -0
  417. data/test/fixtures/example_application/templates/project.html.cut +5 -0
  418. data/test/fixtures/example_application/templates/project_image.html.cut +1 -0
  419. data/test/fixtures/example_application/templates/text.html.cut +1 -0
  420. data/test/fixtures/images/rose.greyscale.jpg +0 -0
  421. data/test/fixtures/images/rose.jpg +0 -0
  422. data/test/fixtures/images/size.gif +0 -0
  423. data/test/fixtures/images/size.jpg +0 -0
  424. data/test/fixtures/images/size.png24 +0 -0
  425. data/test/fixtures/images/size.png8 +0 -0
  426. data/test/fixtures/layouts/layouts/custom1.html.cut +1 -0
  427. data/test/fixtures/layouts/layouts/custom1.pdf.cut +0 -0
  428. data/test/fixtures/layouts/layouts/custom1.xml.cut +0 -0
  429. data/test/fixtures/layouts/layouts/custom2.html.cut +1 -0
  430. data/test/fixtures/layouts/layouts/custom3.html.cut +0 -0
  431. data/test/fixtures/layouts/layouts/standard.html.cut +1 -0
  432. data/test/fixtures/media/101/003/rose.jpg +0 -0
  433. data/test/fixtures/permissions/config/user_levels.yml +9 -0
  434. data/test/fixtures/permissions/media/image.jpg +0 -0
  435. data/test/fixtures/plugins/schema_plugin/init.rb +1 -0
  436. data/test/fixtures/plugins/schema_plugin/schema/external.rb +5 -0
  437. data/test/fixtures/plugins/schema_plugin/templates/external.html.cut +1 -0
  438. data/test/fixtures/plugins/schema_plugin/templates/from_plugin.html.cut +0 -0
  439. data/test/fixtures/plugins/schema_plugin/templates/layouts/from_plugin.html.cut +0 -0
  440. data/test/fixtures/public/templates/layouts/default.html.cut +1 -0
  441. data/test/fixtures/public/templates/layouts/default.pdf.cut +1 -0
  442. data/test/fixtures/public/templates/layouts/default.rss.cut +1 -0
  443. data/test/fixtures/public/templates/layouts/dynamic.html.cut +1 -0
  444. data/test/fixtures/public/templates/layouts/standard.html.cut +0 -0
  445. data/test/fixtures/schema/before.yml +24 -0
  446. data/test/fixtures/schema/resolvable.yml +12 -0
  447. data/test/fixtures/schema/schema.yml +7 -0
  448. data/test/fixtures/serialisation/class_hash.yaml.erb +53 -0
  449. data/test/fixtures/serialisation/root_hash.yaml.erb +184 -0
  450. data/test/fixtures/sharding/rose.jpg +0 -0
  451. data/test/fixtures/sharding/xaa +0 -0
  452. data/test/fixtures/sharding/xab +0 -0
  453. data/test/fixtures/sharding/xac +0 -0
  454. data/test/fixtures/sharding/xad +0 -0
  455. data/test/fixtures/sharding/xae +0 -0
  456. data/test/fixtures/sharding/xaf +0 -0
  457. data/test/fixtures/sharding/xag +0 -0
  458. data/test/fixtures/styles/box_a/runny.html.cut +0 -0
  459. data/test/fixtures/styles/box_a.html.cut +1 -0
  460. data/test/fixtures/styles/named2.html.cut +1 -0
  461. data/test/fixtures/styles/orange/apple.html.cut +1 -0
  462. data/test/fixtures/styles/template_class/named1.html.cut +1 -0
  463. data/test/fixtures/styles/template_class/results.html.cut +1 -0
  464. data/test/fixtures/styles/template_class/walky.html.cut +0 -0
  465. data/test/fixtures/styles/template_class.epub.cut +0 -0
  466. data/test/fixtures/styles/template_class.html.cut +1 -0
  467. data/test/fixtures/styles/template_class.pdf.cut +0 -0
  468. data/test/fixtures/styles/template_sub_class1.html.cut +1 -0
  469. data/test/fixtures/templates/aliases/a/a_style.html.cut +0 -0
  470. data/test/fixtures/templates/aliases/a/page.html.cut +0 -0
  471. data/test/fixtures/templates/aliases/a_alias/a_alias_style.html.cut +0 -0
  472. data/test/fixtures/templates/aliases/layouts/b.html.cut +1 -0
  473. data/test/fixtures/templates/aliases/layouts/b_alias.html.cut +1 -0
  474. data/test/fixtures/templates/aliases/layouts/c_alias.html.cut +1 -0
  475. data/test/fixtures/templates/boxes/blank_content/things.html.cut +1 -0
  476. data/test/fixtures/templates/boxes/my_box_class/christy.html.cut +1 -0
  477. data/test/fixtures/templates/boxes/thangs.html.cut +1 -0
  478. data/test/fixtures/templates/boxes/with_template_box.html.cut +1 -0
  479. data/test/fixtures/templates/content/include.html.cut +1 -0
  480. data/test/fixtures/templates/content/include_dir.html.cut +1 -0
  481. data/test/fixtures/templates/content/included.epub.cut +1 -0
  482. data/test/fixtures/templates/content/included.html.cut +1 -0
  483. data/test/fixtures/templates/content/partial/included.html.cut +1 -0
  484. data/test/fixtures/templates/content/preprocess.html.cut +1 -0
  485. data/test/fixtures/templates/content/second.html.cut +1 -0
  486. data/test/fixtures/templates/content/template.epub.cut +1 -0
  487. data/test/fixtures/templates/content/template.html.cut +1 -0
  488. data/test/fixtures/templates/default_style_class.html.cut +1 -0
  489. data/test/fixtures/templates/direct.html.cut +1 -0
  490. data/test/fixtures/templates/extended/grandparent.html.cut +10 -0
  491. data/test/fixtures/templates/extended/main.html.cut +6 -0
  492. data/test/fixtures/templates/extended/parent.html.cut +10 -0
  493. data/test/fixtures/templates/layouts/entries.html.cut +7 -0
  494. data/test/fixtures/templates/layouts/page_style.html.cut +1 -0
  495. data/test/fixtures/templates/layouts/params.html.cut +1 -0
  496. data/test/fixtures/templates/layouts/preview_render.html.cut +2 -0
  497. data/test/fixtures/templates/layouts/standard_page.html.cut +1 -0
  498. data/test/fixtures/templates/layouts/subdir_style.html.cut +1 -0
  499. data/test/fixtures/templates/layouts/template_params.html.cut +1 -0
  500. data/test/fixtures/templates/page_class/inline_style.html.cut +1 -0
  501. data/test/fixtures/templates/preview_render/inline.html.cut +0 -0
  502. data/test/fixtures/templates/publishing/layouts/dynamic.html.cut +1 -0
  503. data/test/fixtures/templates/publishing/layouts/static.html.cut +1 -0
  504. data/test/fixtures/templates/template_class/anonymous_style.html.cut +4 -0
  505. data/test/fixtures/templates/template_class/another_template.html.cut +0 -0
  506. data/test/fixtures/templates/template_class/complex_template.html.cut +6 -0
  507. data/test/fixtures/templates/template_class/complex_template.pdf.cut +6 -0
  508. data/test/fixtures/templates/template_class/default_template_style.html.cut +4 -0
  509. data/test/fixtures/templates/template_class/images_with_template.html.cut +5 -0
  510. data/test/fixtures/templates/template_class/slots_template.html.cut +5 -0
  511. data/test/fixtures/templates/template_class/slots_template.pdf.cut +5 -0
  512. data/test/fixtures/templates/template_class/this_template.epub.cut +1 -0
  513. data/test/fixtures/templates/template_class/this_template.html.cut +1 -0
  514. data/test/fixtures/templates/template_class/this_template.pdf.cut +1 -0
  515. data/test/fixtures/templates/with_default_style_class.html.cut +1 -0
  516. data/test/functional/test_application.rb +176 -0
  517. data/test/functional/test_back.rb +902 -0
  518. data/test/functional/test_front.rb +571 -0
  519. data/test/javascript/test_dom.rb +94 -0
  520. data/test/javascript/test_markdown.rb +97 -0
  521. data/test/slow/test_publishing.rb +987 -0
  522. data/test/slow/test_visibility.rb +250 -0
  523. data/test/support/custom_matchers.rb +77 -0
  524. data/test/support/timing.rb +23 -0
  525. data/test/test_helper.rb +164 -0
  526. data/test/test_javascript.rb +34 -0
  527. data/test/ui/test_page_editing.rb +167 -0
  528. data/test/ui_helper.rb +114 -0
  529. data/test/unit/test_alias.rb +254 -0
  530. data/test/unit/test_authentication.rb +510 -0
  531. data/test/unit/test_boxes.rb +497 -0
  532. data/test/unit/test_config.rb +156 -0
  533. data/test/unit/test_content.rb +221 -0
  534. data/test/unit/test_content_inheritance.rb +103 -0
  535. data/test/unit/test_extensions.rb +14 -0
  536. data/test/unit/test_fields.rb +392 -0
  537. data/test/unit/test_generators.rb +97 -0
  538. data/test/unit/test_image_size.rb +25 -0
  539. data/test/unit/test_images.rb +265 -0
  540. data/test/unit/test_layouts.rb +111 -0
  541. data/test/unit/test_logger.rb +80 -0
  542. data/test/unit/test_media.rb +70 -0
  543. data/test/unit/test_page.rb +244 -0
  544. data/test/unit/test_permissions.rb +834 -0
  545. data/test/unit/test_piece.rb +80 -0
  546. data/test/unit/test_prototype_set.rb +192 -0
  547. data/test/unit/test_prototypes.rb +102 -0
  548. data/test/unit/test_render.rb +359 -0
  549. data/test/unit/test_schema.rb +1009 -0
  550. data/test/unit/test_serialisation.rb +215 -0
  551. data/test/unit/test_site.rb +145 -0
  552. data/test/unit/test_structure.rb +85 -0
  553. data/test/unit/test_styles.rb +417 -0
  554. data/test/unit/test_templates.rb +224 -0
  555. data/test/unit/test_type_hierarchy.rb +28 -0
  556. metadata +1017 -0
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Plugins
4
+ module PageTree
5
+
6
+ module InstanceMethods
7
+ def ancestors
8
+ ancestor_path.map { |id| Spontaneous::Content[id] }
9
+ end
10
+
11
+ def ancestor(depth)
12
+ ancestors[depth]
13
+ end
14
+
15
+ def generation
16
+ parent ? parent.children : [root]
17
+ end
18
+
19
+ def siblings
20
+ generation.reject { |p| p === self }
21
+ end
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,125 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ module Spontaneous::Plugins
5
+ module Paths
6
+
7
+ module ClassMethods
8
+ def generate_default_slug
9
+ "page-#{Time.now.strftime('%Y%m%d-%H%M%S')}"
10
+ end
11
+
12
+ def is_default_slug?(slug)
13
+ /^page-\d{8}-\d{6}$/ === slug
14
+ end
15
+ end
16
+
17
+ module InstanceMethods
18
+ ANCESTOR_SEP = "."
19
+
20
+ def after_initialize
21
+ super
22
+ self.slug = default_slug if slug.nil?
23
+ end
24
+
25
+ def before_create
26
+ place_in_page_tree
27
+ super
28
+ end
29
+
30
+ def before_save
31
+ unless new?
32
+ if title = self.fields[:title]
33
+ if title.modified? and !title.blank? and self.class.is_default_slug?(slug)
34
+ self.slug = title.value
35
+ end
36
+ end
37
+ end
38
+ super
39
+ end
40
+
41
+ def after_save
42
+ super
43
+ check_for_path_changes
44
+ end
45
+
46
+ def default_slug
47
+ self.class.generate_default_slug
48
+ end
49
+
50
+ def parent=(parent)
51
+ super
52
+ end
53
+
54
+ def place_in_page_tree
55
+ if self.parent_id.nil?
56
+ if Spontaneous::Page.root.nil?
57
+ make_root
58
+ end
59
+ else
60
+ update_path
61
+ end
62
+ end
63
+
64
+ def make_root
65
+ self[:path] = "/"
66
+ self[:slug] = ""
67
+ self[:ancestor_path] = ""
68
+ end
69
+
70
+ def ancestor_path
71
+ (self[:ancestor_path] || "").split(ANCESTOR_SEP).map { |id| id.to_i }
72
+ end
73
+
74
+ def root?
75
+ path == Spontaneous::SLASH
76
+ end
77
+ alias_method :is_root?, :root?
78
+
79
+ def root
80
+ Spontaneous::Page.root
81
+ end
82
+
83
+ def update_path
84
+ self.path = calculate_path
85
+ if parent
86
+ self[:ancestor_path] = parent.ancestor_path.push(parent.id).join(ANCESTOR_SEP)
87
+ end
88
+ end
89
+
90
+
91
+ def calculate_path
92
+ if parent.nil?
93
+ root? ? Spontaneous::SLASH : '' # bad case, no parent but not root
94
+ else
95
+ File.join(parent.path, slug)
96
+ end
97
+ end
98
+
99
+ def slug=(s)
100
+ if (new_slug = s.to_url) != self.slug
101
+ @__slug_changed = true
102
+ self[:slug] = new_slug
103
+ self.update_path
104
+ end
105
+ end
106
+
107
+ def check_for_path_changes
108
+ if @__slug_changed
109
+ @__slug_changed = false
110
+ children.each do |child|
111
+ child.propagate_path_changes
112
+ end
113
+ end
114
+ end
115
+
116
+ def propagate_path_changes
117
+ self.update_path
118
+ self.save
119
+ children.each do |child|
120
+ child.propagate_path_changes
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ module Spontaneous::Plugins
5
+ module Permissions
6
+
7
+ module ClassMethods
8
+ def box_readable?(box_name)
9
+ box_permission(box_name, :read_level)
10
+ end
11
+ def box_writable?(box_name)
12
+ box_permission(box_name, :write_level)
13
+ end
14
+
15
+ def field_readable?(field_name)
16
+ field_permission(field_name, :read_level)
17
+ end
18
+
19
+ def field_writable?(field_name)
20
+ field_permission(field_name, :write_level)
21
+ end
22
+
23
+ def field_permission(field_name, test)
24
+ return true unless user = Spontaneous::Permissions.active_user
25
+ if field = field_prototypes[field_name.to_sym]
26
+ user.level >= field.__send__(test)
27
+ else
28
+ nil # or perhaps throw error
29
+ end
30
+ end
31
+
32
+ def box_permission(box_name, test)
33
+ return true unless user = Spontaneous::Permissions.active_user
34
+ if box = boxes[box_name.to_sym]
35
+ user.level >= box.__send__(test)
36
+ else
37
+ nil # or perhaps throw error
38
+ end
39
+ end
40
+ end # ClassMethods
41
+
42
+
43
+ module InstanceMethods
44
+ def field_readable?(field_name)
45
+ self.class.field_readable?(field_name)
46
+ end
47
+
48
+ def field_writable?(field_name)
49
+ self.class.field_writable?(field_name)
50
+ end
51
+
52
+ def box_writable?(box_name)
53
+ self.class.box_writable?(box_name)
54
+ end
55
+
56
+ def box_readable?(box_name)
57
+ self.class.box_readable?(box_name)
58
+ end
59
+ end # InstanceMethods
60
+
61
+ end # Permissions
62
+ end # Spontaneous::Plugins
63
+
@@ -0,0 +1,84 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ module Spontaneous::Plugins
5
+ module Prototypes
6
+ S = Spontaneous unless defined?(S)
7
+
8
+ def self.configure(base)
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ ## this is the Sequel default:
14
+ #
15
+ # def create(values = {}, &block)
16
+ # new(values, &block).save
17
+ # end
18
+
19
+ def create_without_prototype(values = {}, &block)
20
+ create(false, values, &block)
21
+ end
22
+
23
+ ##
24
+ # Create a new content instance
25
+ def create(*args, &block)
26
+ first = args.shift
27
+ prototype = values = nil
28
+ case first
29
+ when Symbol, false
30
+ prototype = first
31
+ values = args.shift || {}
32
+ when Hash
33
+ values = first
34
+ else
35
+ values = {}
36
+ end
37
+ new(values.merge(:_prototype => prototype), &block).save
38
+ end
39
+ end # ClassMethods
40
+
41
+ module InstanceMethods
42
+
43
+ def after_create
44
+ super
45
+ apply_prototype
46
+ end
47
+
48
+ protected
49
+
50
+ DEFAULT_PROTOTYPE_METHOD = :prototype unless defined?(DEFAULT_PROTOTYPE_METHOD)
51
+
52
+ def apply_prototype
53
+ return if _prototype == false
54
+ prototype_method = DEFAULT_PROTOTYPE_METHOD
55
+ unless _prototype.blank?
56
+ prototype_method = "#{_prototype}_prototype".to_sym
57
+ end
58
+
59
+ if respond_to?(prototype_method)
60
+ self.__send__(prototype_method)
61
+ save
62
+ else
63
+ logger.warn {
64
+ "Invalid prototype name '#{_prototype}' being passed to class #{self.class}. No method #{prototype_method} available."
65
+ } unless prototype_method == DEFAULT_PROTOTYPE_METHOD
66
+ end
67
+ end
68
+
69
+ def _prototype=(prototype)
70
+ @_prototype = prototype
71
+ end
72
+
73
+ def _prototype
74
+ @_prototype
75
+ end
76
+
77
+ end # InstanceMethods
78
+
79
+ end
80
+ end
81
+
82
+
83
+
84
+
@@ -0,0 +1,255 @@
1
+ # encoding: UTF-8
2
+
3
+ # is this unforgivable?
4
+ # i think it's kinda neat, if a tad fragile (to columns named 'content'...)
5
+ module Sequel
6
+ class Dataset
7
+ alias_method :sequel_quote_identifier, :quote_identifier
8
+
9
+
10
+ def quote_identifier(name)
11
+ if name == :content or name == "content"
12
+ name = Spontaneous::Content.current_revision_table
13
+ end
14
+ sequel_quote_identifier(name)
15
+ end
16
+ end
17
+ end
18
+
19
+ module Spontaneous::Plugins
20
+ module Publishing
21
+
22
+ module ClassMethods
23
+ @@dataset = nil
24
+ @@revision = nil
25
+
26
+ def current_revision_table
27
+ revision_table(@@revision)
28
+ end
29
+
30
+ def base_table
31
+ 'content'
32
+ end
33
+
34
+ # make sure that the table name is always the correct revision
35
+ def simple_table
36
+ current_revision_table
37
+ end
38
+
39
+ def revision_table(revision=nil)
40
+ return base_table if revision.nil?
41
+ "__r#{revision.to_s.rjust(5, '0')}_content"
42
+ end
43
+
44
+ def revision_table?(table_name)
45
+ /^__r\d{5}_content$/ === table_name.to_s
46
+ end
47
+
48
+ def revision_exists?(revision)
49
+ database.tables.include?(revision_table(revision).to_sym)
50
+ end
51
+
52
+ def revision
53
+ @@revision
54
+ end
55
+
56
+ def reset_revision
57
+ @@revision, @@dataset = revision_stack.first
58
+ revision_stack.clear
59
+ end
60
+
61
+ def with_revision(revision=nil)
62
+ revision_push(revision)
63
+ begin
64
+ yield
65
+ ensure
66
+ revision_pop
67
+ end if block_given?
68
+ end
69
+
70
+ def with_editable(&block)
71
+ with_revision(nil, &block)
72
+ end
73
+
74
+ def with_published(&block)
75
+ revision = Spontaneous::Site.published_revision
76
+ with_revision(revision, &block)
77
+ end
78
+
79
+ def revision_push(revision)
80
+ revision_stack.push([@@revision, (@@dataset || self.dataset)])
81
+ @@dataset = revision_dataset(revision)
82
+ @@revision = revision
83
+ end
84
+
85
+ def database
86
+ Spontaneous.database
87
+ end
88
+
89
+ ##
90
+ # Publish a revision
91
+ #
92
+ # If content is a non-empty list of Content ids then this will only publish changes to those
93
+ # rows (taking the rest of the content from the previous revision)
94
+ # Pass in a block if you want to tie some bit of post processing to the success or failure
95
+ # of the publish step (used in the site render stage for example)
96
+ def publish(revision, content=nil)
97
+ mark_first_published = Proc.new do |dataset|
98
+ dataset.update(:first_published_at => Sequel.datetime_class.now, :first_published_revision => revision)
99
+ end
100
+
101
+ mark_published = Proc.new do |dataset|
102
+ dataset.update(:last_published_at => Sequel.datetime_class.now)
103
+ end
104
+ first_published = published = nil
105
+
106
+ with_editable do
107
+ first_published = self.filter(:first_published_at => nil)
108
+ published = self.filter
109
+
110
+ must_publish_all = (content.nil? || (!revision_exists?(revision-1)) || \
111
+ (content.is_a?(Array) && content.empty?))
112
+
113
+ if must_publish_all
114
+ create_revision(revision)
115
+ else
116
+ content = content.map do |c|
117
+ c.is_a?(Spontaneous::Content) ? c.reload : Spontaneous::Content[c]
118
+ end.compact
119
+
120
+ first_published = first_published.filter(:id => content.map { |c| c.id })
121
+ published = published.filter(:id => content.map { |c| c.id })
122
+
123
+ create_revision(revision, revision-1)
124
+ content.each do |c|
125
+ c.sync_to_revision(revision)
126
+ end
127
+ end
128
+
129
+ # run any passed code and if it fails revert the publish step
130
+ if block_given?
131
+ begin
132
+ with_revision(revision) { yield }
133
+ rescue Exception => e
134
+ delete_revision(revision)
135
+ raise e
136
+ end
137
+ end
138
+
139
+ with_editable do
140
+ mark_first_published[first_published]
141
+ mark_published[published]
142
+ end
143
+ with_revision(revision) do
144
+ mark_first_published[first_published]
145
+ mark_published[published]
146
+ end
147
+ end
148
+ end
149
+
150
+ def publish_all(revision, &block)
151
+ publish(revision, nil, &block)
152
+ end
153
+
154
+ def create_revision(revision, from_revision=nil)
155
+ dest_table = revision_table(revision)
156
+ src_table = revision_table(from_revision)
157
+ sql = "CREATE TABLE #{dataset.quote_identifier(dest_table)} AS SELECT * FROM #{dataset.quote_identifier(src_table)}"
158
+ database.run(sql)
159
+ indexes = database.indexes(base_table)
160
+ indexes.each do |name, options|
161
+ columns = options.delete(:columns)
162
+ database.add_index(dest_table, columns, options)
163
+ end
164
+ end
165
+
166
+ def delete_revision(revision)
167
+ return if revision.nil?
168
+ database.drop_table(revision_table(revision)) if revision_exists?(revision)
169
+ end
170
+
171
+ def delete_all_revisions!
172
+ database.tables.each do |table|
173
+ database.drop_table(table) if revision_table?(table)
174
+ end
175
+ end
176
+
177
+ def revision_pop
178
+ @@revision, @@dataset = revision_stack.pop
179
+ end
180
+
181
+ def revision_stack
182
+ @revision_stack ||= []
183
+ end
184
+
185
+ def revision_dataset(revision=nil)
186
+ Spontaneous.database.dataset.from(revision_table(revision))
187
+ end
188
+ end
189
+
190
+ module InstanceMethods
191
+ def after_update
192
+ super
193
+ page.modified!(page?) if page
194
+ end
195
+
196
+ # def after_create
197
+ # super
198
+ # push_page_change
199
+ # end
200
+
201
+ def modified!(caller_is_page)
202
+ unless caller_is_page
203
+ self.model.where(:id => self.id).update(:modified_at => Sequel.datetime_class.now)
204
+ end
205
+ push_page_change
206
+ end
207
+
208
+ def push_page_change
209
+ Spontaneous::Change.push(self) if page?
210
+ end
211
+
212
+
213
+ def with_revision(revision, &block)
214
+ self.class.with_revision(revision, &block)
215
+ end
216
+ def with_editable(&block)
217
+ self.class.with_editable(&block)
218
+ end
219
+
220
+ def sync_to_revision(revision, origin=true)
221
+ # 'publish' is a lock to make sure the duplication doesn't cross
222
+ # page boundaries unless that's necessary (such as in the case
223
+ # of a page addition)
224
+ publish = origin || !self.page?
225
+
226
+ with_revision(revision) do
227
+ published_copy = Spontaneous::Content[self.id]
228
+ if published_copy
229
+ if publish and published_copy.entry_store
230
+ pieces_to_delete = published_copy.entry_store - self.entry_store
231
+ pieces_to_delete.each do |entry|
232
+ if c = Spontaneous::Content[entry[0]]
233
+ c.destroy(false)
234
+ end
235
+ end
236
+ end
237
+ else # missing content (so force a publish)
238
+ Spontaneous::Content.insert({:id => self.id})
239
+ publish = true
240
+ end
241
+
242
+ if publish
243
+ with_editable do
244
+ self.pieces.each do |entry|
245
+ entry.sync_to_revision(revision, false)
246
+ end
247
+ end
248
+ Spontaneous::Content.where(:id => self.id).update(self.values)
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
255
+
@@ -0,0 +1,24 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Plugins
4
+ module Render
5
+
6
+ module ClassMethods
7
+ end
8
+
9
+ module InstanceMethods
10
+ def render(format=:html, params={}, *args)
11
+ if format.is_a?(Hash)
12
+ params = format
13
+ format = :html
14
+ end
15
+ Spontaneous::Render.render(self, format, params)
16
+ end
17
+
18
+ # [:html].each do |format|
19
+ # module_eval("def to_#{format}(*args); render(:#{format}, *args); end")
20
+ # end
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,76 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Plugins
4
+ module SchemaHierarchy
5
+ module ClassMethods
6
+ def schema_validate
7
+ if schema_id.nil?
8
+ Spontaneous::Schema.missing_id!(:type, self)
9
+ else
10
+ # only need to check internal consistency if class already existed
11
+ fields.each do |field|
12
+ if field.schema_id.nil?
13
+ Spontaneous::Schema.missing_id!(:field, field)
14
+ end
15
+ end
16
+ # boxes don't have boxes
17
+ if respond_to?(:boxes)
18
+ boxes.each do |box|
19
+ if box.schema_id.nil?
20
+ Spontaneous::Schema.missing_id!(:box, box)
21
+ end
22
+ end
23
+ end
24
+
25
+ styles.each do |style|
26
+ if style.schema_id.nil?
27
+ Spontaneous::Schema.missing_id!(:style, style)
28
+ end
29
+ end
30
+ if respond_to?(:layouts)
31
+ layouts.each do |layout|
32
+ if layout.schema_id.nil?
33
+ Spontaneous::Schema.missing_id!(:layout, layout)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def schema_reset!
41
+ @subclasses = nil
42
+ end
43
+
44
+ def subclasses
45
+ @subclasses ||= []
46
+ end
47
+
48
+ def __source_file=(path)
49
+ @__source_file = path
50
+ end
51
+
52
+ protected(:__source_file=)
53
+
54
+ def __source_file
55
+ @__source_file
56
+ end
57
+
58
+ def descendents
59
+ subclasses.map{ |x| [x] + x.descendents}.flatten
60
+ end
61
+
62
+ def inherited(subclass, real_caller = nil)
63
+ subclass.__source_file = File.expand_path((real_caller || caller[0]).split(':')[0])
64
+ Spontaneous::Schema.classes << subclass if subclass.schema_class?
65
+ subclasses << subclass
66
+ super(subclass)
67
+ end
68
+
69
+ def schema_class?
70
+ true
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+
@@ -0,0 +1,60 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Plugins
4
+ module SchemaId
5
+
6
+ module ClassMethods
7
+ def schema_id
8
+ Spontaneous::Schema.schema_id(self)
9
+ end
10
+
11
+ def schema_name
12
+ "type//#{self.name}"
13
+ end
14
+
15
+ def schema_owner
16
+ nil
17
+ end
18
+
19
+ def owner_sid
20
+ nil
21
+ end
22
+ end # ClassMethods
23
+
24
+ module InstanceMethods
25
+ [:type, :style, :box].each do |c|
26
+ column = "#{c}_sid"
27
+ self.class_eval(<<-RUBY)
28
+ def #{column}
29
+ @_#{column} ||= Spontaneous::Schema::UID[@values[:#{column}]]
30
+ end
31
+
32
+ def #{column}=(sid)
33
+ @_#{column} = Spontaneous::Schema::UID[sid]
34
+ @values[:#{column}] = @_#{column}.to_s
35
+ @_#{column}
36
+ end
37
+ RUBY
38
+ end
39
+
40
+ def schema_id
41
+ self.class.schema_id
42
+ end
43
+
44
+ def schema_name
45
+ self.class.schema_name
46
+ end
47
+
48
+ def schema_owner
49
+ self.class.schema_owner
50
+ end
51
+
52
+ def owner_sid
53
+ self.class.owner_sid
54
+ end
55
+ end # InstanceMethods
56
+ end # SchemaId
57
+ end
58
+
59
+
60
+