porthos 3.0.0.beta

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 (388) hide show
  1. data/Gemfile +6 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +26 -0
  4. data/Rakefile +28 -0
  5. data/app/assets/images/Jcrop.gif +0 -0
  6. data/app/assets/images/button_grey_bg.png +0 -0
  7. data/app/assets/images/icons/avatar.png +0 -0
  8. data/app/assets/images/icons/filetypes/ai.png +0 -0
  9. data/app/assets/images/icons/filetypes/default.png +0 -0
  10. data/app/assets/images/icons/filetypes/doc.png +0 -0
  11. data/app/assets/images/icons/filetypes/eps.png +0 -0
  12. data/app/assets/images/icons/filetypes/mp3.png +0 -0
  13. data/app/assets/images/icons/filetypes/pdf.png +0 -0
  14. data/app/assets/images/icons/filetypes/psd.png +0 -0
  15. data/app/assets/images/icons/filetypes/swf.png +0 -0
  16. data/app/assets/images/icons/filetypes/wav.png +0 -0
  17. data/app/assets/images/icons/filetypes/zip.png +0 -0
  18. data/app/assets/images/layout2_bg_shadow.png +0 -0
  19. data/app/assets/images/layout3_bg_shadow.png +0 -0
  20. data/app/assets/images/ui_new.png +0 -0
  21. data/app/assets/images/wymeditor/icons.png +0 -0
  22. data/app/assets/javascripts/admin.js +7 -0
  23. data/app/assets/javascripts/admin/assets.js +147 -0
  24. data/app/assets/javascripts/admin/editor.js +2 -0
  25. data/app/assets/javascripts/admin/helpers.js +169 -0
  26. data/app/assets/javascripts/admin/items.js +267 -0
  27. data/app/assets/javascripts/admin/nodes.js +73 -0
  28. data/app/assets/javascripts/admin/settings.js +1 -0
  29. data/app/assets/javascripts/admin_extension.js +0 -0
  30. data/app/assets/javascripts/lib/ckeditor/LICENSE.html +1334 -0
  31. data/app/assets/javascripts/lib/ckeditor/adapters/jquery.js +6 -0
  32. data/app/assets/javascripts/lib/ckeditor/ckeditor.js +141 -0
  33. data/app/assets/javascripts/lib/ckeditor/ckeditor_basic.js +8 -0
  34. data/app/assets/javascripts/lib/ckeditor/ckeditor_basic_source.js +20 -0
  35. data/app/assets/javascripts/lib/ckeditor/config.js +26 -0
  36. data/app/assets/javascripts/lib/ckeditor/contents.css +50 -0
  37. data/app/assets/javascripts/lib/ckeditor/images/spacer.gif +0 -0
  38. data/app/assets/javascripts/lib/ckeditor/lang/_languages.js +6 -0
  39. data/app/assets/javascripts/lib/ckeditor/lang/_translationstatus.txt +60 -0
  40. data/app/assets/javascripts/lib/ckeditor/lang/en.js +6 -0
  41. data/app/assets/javascripts/lib/ckeditor/lang/sv.js +6 -0
  42. data/app/assets/javascripts/lib/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js +7 -0
  43. data/app/assets/javascripts/lib/ckeditor/plugins/a11yhelp/lang/en.js +6 -0
  44. data/app/assets/javascripts/lib/ckeditor/plugins/a11yhelp/lang/he.js +6 -0
  45. data/app/assets/javascripts/lib/ckeditor/plugins/about/dialogs/about.js +6 -0
  46. data/app/assets/javascripts/lib/ckeditor/plugins/about/dialogs/logo_ckeditor.png +0 -0
  47. data/app/assets/javascripts/lib/ckeditor/plugins/adobeair/plugin.js +6 -0
  48. data/app/assets/javascripts/lib/ckeditor/plugins/autogrow/plugin.js +6 -0
  49. data/app/assets/javascripts/lib/ckeditor/plugins/clipboard/dialogs/paste.js +7 -0
  50. data/app/assets/javascripts/lib/ckeditor/plugins/colordialog/dialogs/colordialog.js +7 -0
  51. data/app/assets/javascripts/lib/ckeditor/plugins/dialog/dialogDefinition.js +4 -0
  52. data/app/assets/javascripts/lib/ckeditor/plugins/div/dialogs/div.js +8 -0
  53. data/app/assets/javascripts/lib/ckeditor/plugins/find/dialogs/find.js +9 -0
  54. data/app/assets/javascripts/lib/ckeditor/plugins/flash/dialogs/flash.js +9 -0
  55. data/app/assets/javascripts/lib/ckeditor/plugins/flash/images/placeholder.png +0 -0
  56. data/app/assets/javascripts/lib/ckeditor/plugins/forms/dialogs/button.js +6 -0
  57. data/app/assets/javascripts/lib/ckeditor/plugins/forms/dialogs/checkbox.js +6 -0
  58. data/app/assets/javascripts/lib/ckeditor/plugins/forms/dialogs/form.js +6 -0
  59. data/app/assets/javascripts/lib/ckeditor/plugins/forms/dialogs/hiddenfield.js +6 -0
  60. data/app/assets/javascripts/lib/ckeditor/plugins/forms/dialogs/radio.js +6 -0
  61. data/app/assets/javascripts/lib/ckeditor/plugins/forms/dialogs/select.js +9 -0
  62. data/app/assets/javascripts/lib/ckeditor/plugins/forms/dialogs/textarea.js +6 -0
  63. data/app/assets/javascripts/lib/ckeditor/plugins/forms/dialogs/textfield.js +6 -0
  64. data/app/assets/javascripts/lib/ckeditor/plugins/forms/images/hiddenfield.gif +0 -0
  65. data/app/assets/javascripts/lib/ckeditor/plugins/iframe/dialogs/iframe.js +7 -0
  66. data/app/assets/javascripts/lib/ckeditor/plugins/iframe/images/placeholder.png +0 -0
  67. data/app/assets/javascripts/lib/ckeditor/plugins/iframedialog/plugin.js +6 -0
  68. data/app/assets/javascripts/lib/ckeditor/plugins/image/dialogs/image.js +13 -0
  69. data/app/assets/javascripts/lib/ckeditor/plugins/link/dialogs/anchor.js +6 -0
  70. data/app/assets/javascripts/lib/ckeditor/plugins/link/dialogs/link.js +11 -0
  71. data/app/assets/javascripts/lib/ckeditor/plugins/link/images/anchor.gif +0 -0
  72. data/app/assets/javascripts/lib/ckeditor/plugins/liststyle/dialogs/liststyle.js +6 -0
  73. data/app/assets/javascripts/lib/ckeditor/plugins/pagebreak/images/pagebreak.gif +0 -0
  74. data/app/assets/javascripts/lib/ckeditor/plugins/pastefromword/filter/default.js +10 -0
  75. data/app/assets/javascripts/lib/ckeditor/plugins/pastetext/dialogs/pastetext.js +6 -0
  76. data/app/assets/javascripts/lib/ckeditor/plugins/placeholder/dialogs/placeholder.js +6 -0
  77. data/app/assets/javascripts/lib/ckeditor/plugins/placeholder/lang/en.js +6 -0
  78. data/app/assets/javascripts/lib/ckeditor/plugins/placeholder/placeholder.gif +0 -0
  79. data/app/assets/javascripts/lib/ckeditor/plugins/placeholder/plugin.js +6 -0
  80. data/app/assets/javascripts/lib/ckeditor/plugins/scayt/dialogs/options.js +8 -0
  81. data/app/assets/javascripts/lib/ckeditor/plugins/scayt/dialogs/toolbar.css +6 -0
  82. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_address.png +0 -0
  83. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_blockquote.png +0 -0
  84. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_div.png +0 -0
  85. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_h1.png +0 -0
  86. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_h2.png +0 -0
  87. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_h3.png +0 -0
  88. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_h4.png +0 -0
  89. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_h5.png +0 -0
  90. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_h6.png +0 -0
  91. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_p.png +0 -0
  92. data/app/assets/javascripts/lib/ckeditor/plugins/showblocks/images/block_pre.png +0 -0
  93. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/dialogs/smiley.js +7 -0
  94. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/angel_smile.gif +0 -0
  95. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/angry_smile.gif +0 -0
  96. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/broken_heart.gif +0 -0
  97. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/confused_smile.gif +0 -0
  98. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/cry_smile.gif +0 -0
  99. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/devil_smile.gif +0 -0
  100. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/embaressed_smile.gif +0 -0
  101. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/envelope.gif +0 -0
  102. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/heart.gif +0 -0
  103. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/kiss.gif +0 -0
  104. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/lightbulb.gif +0 -0
  105. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/omg_smile.gif +0 -0
  106. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/regular_smile.gif +0 -0
  107. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/sad_smile.gif +0 -0
  108. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/shades_smile.gif +0 -0
  109. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/teeth_smile.gif +0 -0
  110. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/thumbs_down.gif +0 -0
  111. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/thumbs_up.gif +0 -0
  112. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/tounge_smile.gif +0 -0
  113. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/whatchutalkingabout_smile.gif +0 -0
  114. data/app/assets/javascripts/lib/ckeditor/plugins/smiley/images/wink_smile.gif +0 -0
  115. data/app/assets/javascripts/lib/ckeditor/plugins/specialchar/dialogs/specialchar.js +7 -0
  116. data/app/assets/javascripts/lib/ckeditor/plugins/specialchar/lang/en.js +6 -0
  117. data/app/assets/javascripts/lib/ckeditor/plugins/styles/styles/default.js +6 -0
  118. data/app/assets/javascripts/lib/ckeditor/plugins/table/dialogs/table.js +9 -0
  119. data/app/assets/javascripts/lib/ckeditor/plugins/tableresize/plugin.js +7 -0
  120. data/app/assets/javascripts/lib/ckeditor/plugins/tabletools/dialogs/tableCell.js +8 -0
  121. data/app/assets/javascripts/lib/ckeditor/plugins/templates/dialogs/templates.js +7 -0
  122. data/app/assets/javascripts/lib/ckeditor/plugins/templates/templates/default.js +6 -0
  123. data/app/assets/javascripts/lib/ckeditor/plugins/templates/templates/images/template1.gif +0 -0
  124. data/app/assets/javascripts/lib/ckeditor/plugins/templates/templates/images/template2.gif +0 -0
  125. data/app/assets/javascripts/lib/ckeditor/plugins/templates/templates/images/template3.gif +0 -0
  126. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/dialogs/uicolor.js +7 -0
  127. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/lang/en.js +6 -0
  128. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/lang/he.js +6 -0
  129. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/plugin.js +6 -0
  130. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/uicolor.gif +0 -0
  131. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/yui/assets/hue_bg.png +0 -0
  132. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/yui/assets/hue_thumb.png +0 -0
  133. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/yui/assets/picker_mask.png +0 -0
  134. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/yui/assets/picker_thumb.png +0 -0
  135. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/yui/assets/yui.css +6 -0
  136. data/app/assets/javascripts/lib/ckeditor/plugins/uicolor/yui/yui.js +76 -0
  137. data/app/assets/javascripts/lib/ckeditor/plugins/wsc/dialogs/ciframe.html +49 -0
  138. data/app/assets/javascripts/lib/ckeditor/plugins/wsc/dialogs/tmpFrameset.html +52 -0
  139. data/app/assets/javascripts/lib/ckeditor/plugins/wsc/dialogs/wsc.css +6 -0
  140. data/app/assets/javascripts/lib/ckeditor/plugins/wsc/dialogs/wsc.js +7 -0
  141. data/app/assets/javascripts/lib/ckeditor/skins/kama/dialog.css +515 -0
  142. data/app/assets/javascripts/lib/ckeditor/skins/kama/editor.css +1115 -0
  143. data/app/assets/javascripts/lib/ckeditor/skins/kama/icons.png +0 -0
  144. data/app/assets/javascripts/lib/ckeditor/skins/kama/icons_rtl.png +0 -0
  145. data/app/assets/javascripts/lib/ckeditor/skins/kama/images/dialog_sides.gif +0 -0
  146. data/app/assets/javascripts/lib/ckeditor/skins/kama/images/dialog_sides.png +0 -0
  147. data/app/assets/javascripts/lib/ckeditor/skins/kama/images/dialog_sides_rtl.png +0 -0
  148. data/app/assets/javascripts/lib/ckeditor/skins/kama/images/mini.gif +0 -0
  149. data/app/assets/javascripts/lib/ckeditor/skins/kama/images/noimage.png +0 -0
  150. data/app/assets/javascripts/lib/ckeditor/skins/kama/images/sprites.png +0 -0
  151. data/app/assets/javascripts/lib/ckeditor/skins/kama/images/sprites_ie6.png +0 -0
  152. data/app/assets/javascripts/lib/ckeditor/skins/kama/images/toolbar_start.gif +0 -0
  153. data/app/assets/javascripts/lib/ckeditor/skins/kama/skin.js +7 -0
  154. data/app/assets/javascripts/lib/ckeditor/skins/kama/templates.css +65 -0
  155. data/app/assets/javascripts/lib/ckeditor/themes/default/theme.js +8 -0
  156. data/app/assets/javascripts/lib/jquery-1.6.1.min.js +18 -0
  157. data/app/assets/javascripts/lib/jquery-ui-1.8.13.min.js +407 -0
  158. data/app/assets/javascripts/lib/jquery.jcrop.min.js +246 -0
  159. data/app/assets/javascripts/lib/jquery.smart_autocomplete.js +519 -0
  160. data/app/assets/javascripts/lib/underscore.min.js +26 -0
  161. data/app/assets/javascripts/lib/underscore.string.min.js +8 -0
  162. data/app/assets/javascripts/rails.js +148 -0
  163. data/app/assets/stylesheets/admin.css +9 -0
  164. data/app/assets/stylesheets/admin_extensions.css.scss +0 -0
  165. data/app/assets/stylesheets/clearing.css +28 -0
  166. data/app/assets/stylesheets/elements.css.erb +335 -0
  167. data/app/assets/stylesheets/forms.css.scss +118 -0
  168. data/app/assets/stylesheets/jquery.jcrop.css +28 -0
  169. data/app/assets/stylesheets/layout.css.erb +269 -0
  170. data/app/assets/stylesheets/views/assets.css.erb +112 -0
  171. data/app/assets/stylesheets/views/nodes.css +47 -0
  172. data/app/assets/stylesheets/views/pages.css.scss +136 -0
  173. data/app/assets/stylesheets/views/sessions.css +22 -0
  174. data/app/assets/stylesheets/views/tags.css +15 -0
  175. data/app/assets/stylesheets/views/users.css +16 -0
  176. data/app/controllers/admin/assets_controller.rb +132 -0
  177. data/app/controllers/admin/content_templates_controller.rb +56 -0
  178. data/app/controllers/admin/data_controller.rb +93 -0
  179. data/app/controllers/admin/datum_templates_controller.rb +59 -0
  180. data/app/controllers/admin/items_controller.rb +114 -0
  181. data/app/controllers/admin/link_lists_controller.rb +41 -0
  182. data/app/controllers/admin/links_controller.rb +65 -0
  183. data/app/controllers/admin/nodes_controller.rb +114 -0
  184. data/app/controllers/admin/page_templates_controller.rb +56 -0
  185. data/app/controllers/admin/redirects_controller.rb +58 -0
  186. data/app/controllers/admin/sessions_controller.rb +27 -0
  187. data/app/controllers/admin/site_settings_controller.rb +58 -0
  188. data/app/controllers/admin/tags_controller.rb +71 -0
  189. data/app/controllers/admin/users_controller.rb +55 -0
  190. data/app/controllers/application_controller.rb +8 -0
  191. data/app/controllers/pages_controller.rb +115 -0
  192. data/app/helpers/data_helper.rb +11 -0
  193. data/app/helpers/link_lists_helper.rb +16 -0
  194. data/app/models/asset.rb +189 -0
  195. data/app/models/custom_page.rb +33 -0
  196. data/app/models/data/asset_association.rb +73 -0
  197. data/app/models/data/datum_collection.rb +46 -0
  198. data/app/models/data/field.rb +26 -0
  199. data/app/models/data/field_set.rb +37 -0
  200. data/app/models/data/link_field.rb +7 -0
  201. data/app/models/data/page_association.rb +26 -0
  202. data/app/models/data/string_field.rb +13 -0
  203. data/app/models/datum.rb +22 -0
  204. data/app/models/datum_template.rb +143 -0
  205. data/app/models/datum_templates/asset_association_template.rb +3 -0
  206. data/app/models/datum_templates/association_field_template.rb +2 -0
  207. data/app/models/datum_templates/datum_collection_template.rb +15 -0
  208. data/app/models/datum_templates/field_set_template.rb +5 -0
  209. data/app/models/datum_templates/field_template.rb +6 -0
  210. data/app/models/datum_templates/link_field_template.rb +2 -0
  211. data/app/models/datum_templates/page_association_template.rb +4 -0
  212. data/app/models/datum_templates/string_field_template.rb +4 -0
  213. data/app/models/file_template.rb +105 -0
  214. data/app/models/file_templates/field_set_file_template.rb +7 -0
  215. data/app/models/file_templates/page_file_template.rb +14 -0
  216. data/app/models/image_asset.rb +102 -0
  217. data/app/models/item.rb +115 -0
  218. data/app/models/link.rb +46 -0
  219. data/app/models/link_list.rb +30 -0
  220. data/app/models/node.rb +106 -0
  221. data/app/models/observers/node_observer.rb +9 -0
  222. data/app/models/page.rb +167 -0
  223. data/app/models/redirect.rb +16 -0
  224. data/app/models/section.rb +30 -0
  225. data/app/models/setting.rb +4 -0
  226. data/app/models/site_setting.rb +11 -0
  227. data/app/models/template.rb +25 -0
  228. data/app/models/templates/content_template.rb +101 -0
  229. data/app/models/templates/page_template.rb +59 -0
  230. data/app/models/user.rb +67 -0
  231. data/app/views/admin/assets/_create_callback_form.html.erb +11 -0
  232. data/app/views/admin/assets/_sub_nav.html.erb +45 -0
  233. data/app/views/admin/assets/create.html.erb +10 -0
  234. data/app/views/admin/assets/edit.html.erb +91 -0
  235. data/app/views/admin/assets/edit_cropping.html.erb +44 -0
  236. data/app/views/admin/assets/incomplete.html.erb +39 -0
  237. data/app/views/admin/assets/index.html.erb +76 -0
  238. data/app/views/admin/assets/new.html.erb +20 -0
  239. data/app/views/admin/assets/search.html.erb +60 -0
  240. data/app/views/admin/assets/show.html.erb +45 -0
  241. data/app/views/admin/content_templates/_form.html.erb +18 -0
  242. data/app/views/admin/content_templates/edit.html.erb +14 -0
  243. data/app/views/admin/content_templates/index.html.erb +36 -0
  244. data/app/views/admin/content_templates/new.html.erb +14 -0
  245. data/app/views/admin/content_templates/show.html.erb +57 -0
  246. data/app/views/admin/data/_asset_association.html.erb +59 -0
  247. data/app/views/admin/data/_asset_association_form.html.erb +21 -0
  248. data/app/views/admin/data/_field.html.erb +7 -0
  249. data/app/views/admin/data/_field_form.html.erb +27 -0
  250. data/app/views/admin/data/_field_set.html.erb +7 -0
  251. data/app/views/admin/data/_field_set_form.html.erb +14 -0
  252. data/app/views/admin/data/_form.html.erb +14 -0
  253. data/app/views/admin/data/_link_field.html.erb +9 -0
  254. data/app/views/admin/data/_link_field_form.html.erb +22 -0
  255. data/app/views/admin/data/_page_association.html.erb +3 -0
  256. data/app/views/admin/data/_page_association_form.html.erb +8 -0
  257. data/app/views/admin/data/edit.html.erb +20 -0
  258. data/app/views/admin/data/index.html.erb +61 -0
  259. data/app/views/admin/data/new.html.erb +20 -0
  260. data/app/views/admin/datum_templates/_asset_association_template_form.html.erb +2 -0
  261. data/app/views/admin/datum_templates/_datum_collection_template_form.html.erb +23 -0
  262. data/app/views/admin/datum_templates/_field_set_template_form.html.erb +7 -0
  263. data/app/views/admin/datum_templates/_field_template_form.html.erb +1 -0
  264. data/app/views/admin/datum_templates/_form.html.erb +25 -0
  265. data/app/views/admin/datum_templates/_page_association_template_form.html.erb +2 -0
  266. data/app/views/admin/datum_templates/_string_field_template_form.html.erb +12 -0
  267. data/app/views/admin/datum_templates/edit.html.erb +14 -0
  268. data/app/views/admin/datum_templates/new.html.erb +14 -0
  269. data/app/views/admin/items/_asset_association.html.erb +6 -0
  270. data/app/views/admin/items/_details.html.erb +95 -0
  271. data/app/views/admin/items/_form.html.erb +20 -0
  272. data/app/views/admin/items/_page_form.html.erb +27 -0
  273. data/app/views/admin/items/_row.html.erb +47 -0
  274. data/app/views/admin/items/_sub_nav.html.erb +60 -0
  275. data/app/views/admin/items/index.html.erb +75 -0
  276. data/app/views/admin/items/new.html.erb +5 -0
  277. data/app/views/admin/items/page.html.erb +155 -0
  278. data/app/views/admin/items/search.html.erb +26 -0
  279. data/app/views/admin/items/section.html.erb +152 -0
  280. data/app/views/admin/link_lists/_form.html.erb +8 -0
  281. data/app/views/admin/link_lists/edit.html.erb +11 -0
  282. data/app/views/admin/link_lists/show.html.erb +45 -0
  283. data/app/views/admin/links/_form.html.erb +14 -0
  284. data/app/views/admin/links/edit.html.erb +11 -0
  285. data/app/views/admin/links/new.html.erb +11 -0
  286. data/app/views/admin/nodes/_form.html.erb +88 -0
  287. data/app/views/admin/nodes/_list_of_nodes.html.erb +11 -0
  288. data/app/views/admin/nodes/_node.html.erb +23 -0
  289. data/app/views/admin/nodes/_nodes_tree.html.erb +7 -0
  290. data/app/views/admin/nodes/_place_node.html.erb +11 -0
  291. data/app/views/admin/nodes/_sub_nav.html.erb +12 -0
  292. data/app/views/admin/nodes/edit.html.erb +10 -0
  293. data/app/views/admin/nodes/index.html.erb +26 -0
  294. data/app/views/admin/nodes/new.html.erb +10 -0
  295. data/app/views/admin/nodes/place.html.erb +37 -0
  296. data/app/views/admin/page_templates/_form.html.erb +51 -0
  297. data/app/views/admin/page_templates/edit.html.erb +14 -0
  298. data/app/views/admin/page_templates/index.html.erb +42 -0
  299. data/app/views/admin/page_templates/new.html.erb +14 -0
  300. data/app/views/admin/page_templates/pages.html.erb +28 -0
  301. data/app/views/admin/page_templates/show.html.erb +64 -0
  302. data/app/views/admin/redirects/edit.html.erb +25 -0
  303. data/app/views/admin/redirects/index.html.erb +38 -0
  304. data/app/views/admin/redirects/new.html.erb +25 -0
  305. data/app/views/admin/sessions/new.html.erb +17 -0
  306. data/app/views/admin/sessions/token.js.erb +1 -0
  307. data/app/views/admin/shared/_error_messages.html.erb +7 -0
  308. data/app/views/admin/shared/_settings_sub_nav.html.erb +8 -0
  309. data/app/views/admin/site_settings/_form.html.erb +5 -0
  310. data/app/views/admin/site_settings/edit.html.erb +20 -0
  311. data/app/views/admin/site_settings/index.html.erb +45 -0
  312. data/app/views/admin/site_settings/new.html.erb +20 -0
  313. data/app/views/admin/taggables/_asset.html.erb +10 -0
  314. data/app/views/admin/taggables/_page.html.erb +9 -0
  315. data/app/views/admin/taggables/_tag_collection.html.erb +2 -0
  316. data/app/views/admin/tags/edit.html.erb +18 -0
  317. data/app/views/admin/tags/index.html.erb +34 -0
  318. data/app/views/admin/tags/new.html.erb +18 -0
  319. data/app/views/admin/tags/search.js.erb +5 -0
  320. data/app/views/admin/tags/show.html.erb +29 -0
  321. data/app/views/admin/users/_form.html.erb +22 -0
  322. data/app/views/admin/users/_sub_nav.html.erb +12 -0
  323. data/app/views/admin/users/_user.html.erb +23 -0
  324. data/app/views/admin/users/edit.html.erb +18 -0
  325. data/app/views/admin/users/index.html.erb +22 -0
  326. data/app/views/admin/users/new.html.erb +15 -0
  327. data/app/views/admin/users/search.html.erb +19 -0
  328. data/app/views/field_set_templates/default/_show.html.erb +6 -0
  329. data/app/views/layouts/admin/_account_nav.html.erb +7 -0
  330. data/app/views/layouts/admin/_main_nav.html.erb +8 -0
  331. data/app/views/layouts/admin/application.html.erb +26 -0
  332. data/app/views/layouts/admin/sessions.html.erb +18 -0
  333. data/app/views/pages/_preview.html.erb +13 -0
  334. data/app/views/pages/contents/content_images/_collection.html.erb +26 -0
  335. data/app/views/pages/contents/content_images/_content_image.html.erb +19 -0
  336. data/app/views/pages/contents/content_teasers/_collection.html.erb +8 -0
  337. data/app/views/pages/contents/content_teasers/_content_teaser.html.erb +32 -0
  338. data/app/views/pages/contents/content_textfields/_content_textfield.html.erb +1 -0
  339. data/app/views/pages/contents/content_videos/_content_video.html.erb +1 -0
  340. data/app/views/pages/contents/modules/date_archive/_content.html.erb +23 -0
  341. data/app/views/pages/contents/modules/sub_navigation/_content.html.erb +5 -0
  342. data/app/views/pages/templates/default/_admin_in_list.html.erb +4 -0
  343. data/app/views/pages/templates/default/categories.html.erb +13 -0
  344. data/app/views/pages/templates/default/category.html.erb +13 -0
  345. data/app/views/pages/templates/default/default_renderer.rb +115 -0
  346. data/app/views/pages/templates/default/index.html.erb +13 -0
  347. data/app/views/pages/templates/default/index.rss.builder +19 -0
  348. data/app/views/pages/templates/default/search.html.erb +24 -0
  349. data/app/views/pages/templates/default/show.html.erb +6 -0
  350. data/app/views/shared/404.html.erb +1 -0
  351. data/config/initializers/locale.rb +1 -0
  352. data/config/initializers/mime_types.rb +13 -0
  353. data/config/initializers/overrides.rb +34 -0
  354. data/config/initializers/tanker.rb +1 -0
  355. data/config/locales/sv-SE.yml +543 -0
  356. data/config/routes.rb +97 -0
  357. data/lib/generators/porthos/USAGE +3 -0
  358. data/lib/generators/porthos/porthos_generator.rb +35 -0
  359. data/lib/generators/porthos/templates/mongo.yml +15 -0
  360. data/lib/porthos.rb +53 -0
  361. data/lib/porthos/active_record/restrictions.rb +36 -0
  362. data/lib/porthos/active_record/settingable.rb +49 -0
  363. data/lib/porthos/admin.rb +25 -0
  364. data/lib/porthos/authentication.rb +72 -0
  365. data/lib/porthos/config.rb +18 -0
  366. data/lib/porthos/datum_methods.rb +53 -0
  367. data/lib/porthos/engine.rb +56 -0
  368. data/lib/porthos/helpers/application_helper.rb +140 -0
  369. data/lib/porthos/mongo_mapper/acts_as_uri.rb +59 -0
  370. data/lib/porthos/mongo_mapper/callbacks.rb +13 -0
  371. data/lib/porthos/mongo_mapper/extensions.rb +58 -0
  372. data/lib/porthos/mongo_mapper/instructable.rb +36 -0
  373. data/lib/porthos/mongo_mapper/observer.rb +34 -0
  374. data/lib/porthos/mongo_mapper/taggable.rb +136 -0
  375. data/lib/porthos/page_renderer.rb +66 -0
  376. data/lib/porthos/public.rb +56 -0
  377. data/lib/porthos/redirects.rb +23 -0
  378. data/lib/porthos/routing.rb +256 -0
  379. data/lib/porthos/s3_storage.rb +61 -0
  380. data/lib/porthos/tags_autocomplete_app.rb +32 -0
  381. data/lib/porthos/tanking.rb +9 -0
  382. data/lib/porthos/test_helpers/assets_test_helper.rb +72 -0
  383. data/lib/porthos/test_helpers/pages_test_helper.rb +9 -0
  384. data/lib/porthos/url_resolver.rb +108 -0
  385. data/lib/porthos/validators.rb +14 -0
  386. data/lib/porthos/version.rb +3 -0
  387. data/lib/tasks/porthos_tasks.rake +217 -0
  388. metadata +774 -0
@@ -0,0 +1,56 @@
1
+ module Porthos
2
+ class Engine < Rails::Engine
3
+ config.autoload_paths += Dir[config.root.join('app', 'models', '{**}')]
4
+ config.i18n.default_locale = "sv-SE"
5
+ config.i18n.fallbacks = true
6
+ config.use_fulltext_search = false
7
+
8
+ config.active_record.identity_map = true
9
+
10
+ config.porthos = ::Porthos::Config
11
+
12
+ rake_tasks do
13
+ load Porthos.root.join("lib/tasks/porthos_tasks.rake")
14
+ end
15
+
16
+ initializer "porthos.redirects" do |app|
17
+ app.middleware.use Porthos::Redirects
18
+ end
19
+
20
+ initializer 'porthos.helpers' do |app|
21
+ ActiveSupport.on_load :action_view do
22
+ include Porthos::ApplicationHelper
23
+ end
24
+ end
25
+
26
+ initializer 'porthos.active_record' do |app|
27
+ ActiveSupport.on_load :active_record do
28
+ include Porthos::ActiveRecord::Restrictions
29
+ include Porthos::ActiveRecord::Settingable
30
+ end
31
+ end
32
+
33
+ initializer 'porthos.mongo_mapper' do |app|
34
+ ActiveSupport.on_load :mongo_mapper do
35
+ ::MongoMapper::Document.plugin ActiveModel::Observing
36
+ ::MongoMapper::Document.plugin Porthos::MongoMapper::Plugins::ActsAsUri
37
+ end
38
+ config.after_initialize do
39
+ ::Porthos.config.instantiate_observers
40
+ ActionDispatch::Callbacks.to_prepare do
41
+ ::Porthos.config.instantiate_observers
42
+ end
43
+ end
44
+ end
45
+
46
+ initializer 'porthos.authentication' do |app|
47
+ app.middleware.use ::Warden::Manager do |manager|
48
+ manager.default_strategies :password
49
+ manager.failure_app = Porthos::Authentication::UnauthorizedRequest
50
+ end
51
+ ActiveSupport.on_load :action_controller do
52
+ include Porthos::Authentication::Helpers
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,140 @@
1
+ module Porthos
2
+ module ApplicationHelper
3
+
4
+ def previous_view_path(default_path = '/')
5
+ params[:return_to] || default_path
6
+ end
7
+
8
+ def admin_assets_path_with_session_key(arguments = {})
9
+ session_key = Rails.application.config.session_options[:key]
10
+ admin_assets_path({session_key => cookies[session_key], request_forgery_protection_token => form_authenticity_token}.merge(arguments))
11
+ end
12
+
13
+ def nested_list_of(collection, options = {}, html_options = {}, &block)
14
+ options = {
15
+ :expand_all => false,
16
+ :allow_inactive => false,
17
+ :first_level => true,
18
+ :node_class => collection.first.class.to_s.underscore,
19
+ :end_points => [],
20
+ :trail => [],
21
+ :except => [],
22
+ :trailed_class => 'trailed'
23
+ }.merge(options)
24
+
25
+ html_options = {
26
+ :id => collection.first.class.to_s.underscore.pluralize
27
+ }.merge(html_options)
28
+
29
+ first_level = options.delete(:first_level)
30
+ if first_level
31
+ if options[:end_points]
32
+ options[:end_points] = [options[:end_points]] unless options[:end_points].is_a?(Array)
33
+ options[:end_points].collect { |item| options[:trail] += (item.ancestors << item) }
34
+ end
35
+ end
36
+ html_options.delete(:id) unless first_level
37
+
38
+ ret = collection.collect do |item|
39
+ next if (item.respond_to?(:access_status) and item.access_status == 'inactive') and not options[:allow_inactive] == true
40
+ next if item == options[:except] || (options[:except].respond_to?(:include?) && options[:except].include?(item))
41
+ in_trail = options[:trail].include?(item)
42
+ rendered_item = capture(item, &block)
43
+ if (options[:expand_all] and item.children.any?) or ( in_trail and item.children.any? )
44
+ rendered_item += nested_list_of(item.children, options.merge({ :first_level => false }), &block)
45
+ end
46
+ if item.respond_to?(:access_status)
47
+ status_class = unless in_trail
48
+ item.access_status
49
+ else
50
+ "#{item.access_status} #{options[:trailed_class]}"
51
+ end
52
+ end
53
+ node_container_options = {
54
+ :class => [
55
+ options[:node_class],
56
+ status_class
57
+ ].join(" ")
58
+ }
59
+ if options[:node_id].nil?
60
+ node_container_options[:id] = "#{item.class.to_s.underscore}_#{item.id}"
61
+ elsif not options[:node_id].blank?
62
+ node_container_options[:id] = "#{options[:node_id]}_#{item.id}"
63
+ end
64
+
65
+ content_tag('li', rendered_item, node_container_options)
66
+ end.join("\n").html_safe
67
+
68
+ #list = content_tag('ul', ret, html_options)
69
+ #first_level ? concat(list) : list
70
+ content_tag('ul', ret, html_options)
71
+ end
72
+
73
+ def page_id
74
+ @page_id ||= controller.class.to_s.underscore.gsub(/_controller$/, '').gsub(/admin\//, '')
75
+ ' id="'+@page_id+'_view"'.html_safe
76
+ end
77
+
78
+ def page_class(css_class = false)
79
+ body_class = []
80
+ body_class << css_class if css_class
81
+ body_class << @page_class if @page_class
82
+ body_class << controller.action_name.underscore
83
+ if Rails.env.development?
84
+ body_class << 'debug' if params[:debug]
85
+ body_class << 'grid' if params[:grid]
86
+ end
87
+ ' class="'+body_class.join(" ")+'"'.html_safe if body_class.size > 0
88
+ end
89
+
90
+ def body_attributes
91
+ "#{page_id}#{page_class}".html_safe
92
+ end
93
+
94
+ def flash_messages(type = "")
95
+ if type.blank?
96
+ flash.collect do |type, message|
97
+ content_tag('p', message, :class => "flash #{type}", :id => 'flash')
98
+ end.join("\n").html_safe
99
+ elsif flash[type.to_sym]
100
+ content_tag('p', flash[type.to_sym], :class => "flash #{type}", :id => 'flash').html_safe
101
+ end
102
+ end
103
+
104
+ def installation_specific_stylesheet_link_tag
105
+ path = File.join(Rails.root, 'public/stylesheets/porthos_extensions.css')
106
+ stylesheet_link_tag(js_file) if File.exists?(path)
107
+ end
108
+
109
+ # RIPPED FROM rails_admin (https://github.com/sferik/rails_admin)
110
+ # A Helper to load from a CDN but with fallbacks in case the primary source is unavailable
111
+ # The best of both worlds - fast clevery cached service from google when available and the
112
+ # ability to work offline too.
113
+ #
114
+ # @example Loading jquery from google
115
+ # javascript_fallback "http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js",
116
+ # "/javascripts/jquery-1.4.3.min.js",
117
+ # "typeof jQuery == 'undefined'"
118
+ # @param [String] primary a string to be passed to javascript_include_tag that represents the primary source e.g. A script on googles CDN.
119
+ # @param [String] fallback a path to the secondary javascript file that is (hopefully) more resilliant than the primary.
120
+ # @param [String] test a test written in javascript that evaluates to true if it is necessary to load the fallback javascript.
121
+ # @reurns [String] the resulting html to be inserted into your page.
122
+ def javascript_fallback(primary, fallback, test)
123
+ html = javascript_include_tag( primary )
124
+ html << "\n" << content_tag(:script, :type => "text/javascript") do
125
+ %Q{
126
+ if (#{test}) {
127
+ document.write(unescape("%3Cscript src='#{fallback}' type='text/javascript'%3E%3C/script%3E"));
128
+ }
129
+ }.gsub(/^ {8}/, '').html_safe
130
+ end
131
+ html+"\n"
132
+ end
133
+
134
+ def page_url_parent(page)
135
+ pages_url(:handle => page.handle).tap do |url|
136
+ url << '/' unless url.end_with?('/')
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,59 @@
1
+ require 'stringex'
2
+ module Porthos
3
+ module MongoMapper
4
+ module Plugins
5
+ module ActsAsUri
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def acts_as_uri(attribute, options = {})
10
+ class_attribute :attribute_to_uriify
11
+ class_attribute :acts_as_uri_options
12
+
13
+ self.acts_as_uri_options = options.to_options.reverse_merge({
14
+ :source => attribute,
15
+ :target => 'uri',
16
+ :duplicate_count_separator => '-',
17
+ :only_when_blank => false
18
+ })
19
+
20
+ if self.acts_as_uri_options[:sync_uri]
21
+ before_validation :generate_uri
22
+ else
23
+ before_validation :generate_uri, :on => :create
24
+ end
25
+
26
+ if embeddable?
27
+ validate :uniqueness_of_uri_among_siblings
28
+ else
29
+ validation_options = {
30
+ :case_sensitive => false,
31
+ :allow_nil => true
32
+ }
33
+ validation_options[:scope] = acts_as_uri_options[:scope] if acts_as_uri_options[:scope]
34
+ validates_uniqueness_of acts_as_uri_options[:target], validation_options
35
+ end
36
+ end
37
+ end
38
+
39
+ module InstanceMethods
40
+ private
41
+ def generate_uri
42
+ options = self.class.acts_as_uri_options
43
+ base_url = self.send options[:target]
44
+ base_url = self.send(options[:source]).to_s.to_url if base_url.blank? || !options[:only_when_blank]
45
+ write_attribute(options[:target], base_url)
46
+ end
47
+
48
+ def uniqueness_of_uri_among_siblings
49
+ options = self.class.acts_as_uri_options
50
+ current_uri = self.send options[:target]
51
+ if _parent_document && _parent_document.send(self.model_name.tableize).one? { |s| s.id != self.id && s.send(options[:target]) == current_uri }
52
+ errors.add(options[:target], :taken)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,13 @@
1
+ module Porthos
2
+ module MongoMapper
3
+ module Callbacks
4
+ CALLBACKS = [
5
+ :before_validation, :after_validation,
6
+ :before_create, :after_create,
7
+ :before_destroy, :after_destroy,
8
+ :before_save, :after_save,
9
+ :before_update, :after_update
10
+ ]
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,58 @@
1
+ module Porthos
2
+ module MongoMapper
3
+ module Extensions
4
+
5
+ module SymbolOperator
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ def to_mongo(value)
10
+ if value.is_a?(SymbolOperator)
11
+ value.to_mongo
12
+ else
13
+ typecasted = if value.acts_like?(:string)
14
+ field, operator = value.to_s.split('.')
15
+ field.present? ? self.new(field.to_sym, operator) : nil
16
+ elsif value.is_a?(Hash)
17
+ value.to_options!
18
+ if value[:field] && value[:operator]
19
+ self.new(value[:field].to_sym, value[:operator].to_s)
20
+ else
21
+ nil
22
+ end
23
+ end
24
+ typecasted.is_a?(self) ? typecasted.to_mongo : nil
25
+ end
26
+ end
27
+
28
+ def from_mongo(value)
29
+ if value.is_a?(self)
30
+ value
31
+ elsif value.nil? || value.to_s == ''
32
+ nil
33
+ else
34
+ field, operator = value.split('.')
35
+ field && operator ? self.new(field.to_sym, operator) : nil
36
+ end
37
+ end
38
+ end
39
+
40
+ module InstanceMethods
41
+ def to_mongo
42
+ "#{field.to_s}.#{operator}"
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+
51
+ class SymbolOperator
52
+ include Porthos::MongoMapper::Extensions::SymbolOperator
53
+
54
+ def ==(other)
55
+ other.class == SymbolOperator && field == other.field && operator == other.operator
56
+ end
57
+
58
+ end
@@ -0,0 +1,36 @@
1
+ module Porthos
2
+ module MongoMapper
3
+
4
+ class Instruction
5
+ include ::MongoMapper::Document
6
+ key :body, String
7
+ end
8
+
9
+ module Plugins
10
+ module Instructable
11
+ extend ActiveSupport::Concern
12
+
13
+ module InstanceMethods
14
+
15
+ def instruction_body
16
+ @instruction_body ||= instruction.body if instruction
17
+ end
18
+
19
+ def instruction_body=(body)
20
+ if instruction
21
+ instruction.update_attributes(:body => body)
22
+ else
23
+ self.instruction = Porthos::MongoMapper::Instruction.create(:body => body)
24
+ end
25
+ end
26
+ end
27
+
28
+ included do
29
+ key :instruction_id, ObjectId
30
+ belongs_to :instruction, :class_name => 'Porthos::MongoMapper::Instruction'
31
+ end
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ module Porthos
2
+ module MongoMapper
3
+ class Observer < ActiveModel::Observer
4
+
5
+ protected
6
+
7
+ def observed_classes
8
+ super.tap do |klasses|
9
+ klasses += klasses.map { |klass| klass.descendants }.flatten
10
+ end
11
+ end
12
+
13
+ def add_observer!(klass)
14
+ super and define_callbacks klass
15
+ end
16
+
17
+ def define_callbacks(klass)
18
+ observer = self
19
+ observer_name = observer.class.name.underscore.gsub('/', '__')
20
+ Porthos::MongoMapper::Callbacks::CALLBACKS.each do |callback|
21
+ next unless respond_to?(callback)
22
+ callback_meth = :"_notify_#{observer_name}_for_#{callback}"
23
+ unless klass.respond_to?(callback_meth)
24
+ klass.send(:define_method, callback_meth) do |&block|
25
+ observer.send(callback, self, &block)
26
+ end
27
+ klass.send(callback, callback_meth)
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,136 @@
1
+ require 'ostruct'
2
+
3
+ module Porthos
4
+ module MongoMapper
5
+ class Tag
6
+ include ::MongoMapper::EmbeddedDocument
7
+ key :name, String
8
+ key :namespace, String
9
+ end
10
+
11
+ module Taggable
12
+ mattr_accessor :delimiter
13
+ self.delimiter = ' '
14
+
15
+ module Plugin
16
+ extend ActiveSupport::Concern
17
+
18
+ module ClassMethods
19
+
20
+ def taggable(_options = {})
21
+ has_many :_tags, :class_name => 'Porthos::MongoMapper::Tag'
22
+ after_save :cache_tags_if_changed
23
+
24
+ class_eval <<-EOV
25
+ def assign_with_read_write_tag_names(attrs={})
26
+ attrs.each do |key, value|
27
+ if _match = match_tag_names_methods(key)
28
+ self.send(_match[2]+'=', value, _match[1])
29
+ attrs.delete(key)
30
+ end
31
+ end if attrs
32
+ assign_without_read_write_tag_names(attrs)
33
+ end
34
+ alias_method_chain :assign, :read_write_tag_names
35
+ EOV
36
+ end
37
+
38
+ def tagged_with(tags_list, options = {})
39
+ namespace = options.delete(:namespace)
40
+ self.where(:'_tags.name'.all => tags_list, :'_tags.namespace' => namespace)
41
+ end
42
+
43
+ def all_tags_collection_name
44
+ "#{self.name}_tags".downcase
45
+ end
46
+
47
+ def cache_tags!
48
+ options = { :raw => true, :out => { :merge => all_tags_collection_name } }
49
+ collection.map_reduce(self.tags_with_count_map, self.tags_with_count_reduce, options)
50
+ end
51
+
52
+ def all_tags(selector = {}, options = {})
53
+ database[all_tags_collection_name].find(selector, options).collect do |tag|
54
+ OpenStruct.new(:name => tag['value']['name'], :count => tag['value']['count'].to_i, :namespace => tag['value']['namespace'])
55
+ end
56
+ end
57
+
58
+ def tags_by_count(options = {})
59
+ all_tags({:'value.namespace' => options.delete(:namespace)}.merge(options), {:sort => ['value.count', :desc]})
60
+ end
61
+
62
+ def tags_with_count_map
63
+ "function() {
64
+ if (!this._tags) { return; }
65
+ for (index in this._tags) {
66
+ emit(this._tags[index].name+this._tags[index].namespace, {count: 1, name: this._tags[index].name, namespace: this._tags[index].namespace});
67
+ }
68
+ }"
69
+ end
70
+
71
+ def tags_with_count_reduce
72
+ "function(previous, current) {
73
+ var result = {count: 0, name: '', namespace: ''};
74
+ for (index in current) {
75
+ result.count += current[index].count;
76
+ result.name = current[index].name;
77
+ result.namespace = current[index].namespace;
78
+ }
79
+ return result;
80
+ }"
81
+ end
82
+ end
83
+
84
+ module InstanceMethods
85
+ def method_missing_with_read_write_tag_names(method, *args)
86
+ if _match = match_tag_names_methods(method)
87
+ self.send(_match[2].to_sym, *(args << _match[1]))
88
+ else
89
+ method_missing_without_read_write_tag_names(method, *args)
90
+ end
91
+ end
92
+ alias_method_chain :method_missing, :read_write_tag_names
93
+
94
+ def tags(namespace = nil)
95
+ _tags.find_all { |t| t.namespace == namespace }
96
+ end
97
+
98
+ def tag_names(namespace = nil)
99
+ tags(namespace).collect { |tag| tag.name.include?(Porthos::MongoMapper::Taggable.delimiter) ? "\"#{tag.name}\"" : tag.name }.join(Porthos::MongoMapper::Taggable.delimiter)
100
+ end
101
+
102
+ def tag_names=(in_tags, namespace = nil)
103
+ tags_array = in_tags.is_a?(String) ? split_tags(in_tags) : in_tags
104
+ self._tags.delete_if{|t| t.namespace == namespace}
105
+ self._tags += tags_array.collect { |tag_name| Porthos::MongoMapper::Tag.new(:name => tag_name, :namespace => namespace)}
106
+ @tags_changed = true
107
+ end
108
+
109
+ def tags_changed?
110
+ @tags_changed
111
+ end
112
+
113
+ protected
114
+ def split_tags(value)
115
+ tag_list = []
116
+ [/\s*#{Porthos::MongoMapper::Taggable.delimiter}\s*(['"])(.*?)\1\s*/, /^\s*(['"])(.*?)\1\s*#{Porthos::MongoMapper::Taggable.delimiter}?/].each do |exp|
117
+ value.gsub!(exp) { tag_list << $2; "" }
118
+ end
119
+ tag_list + value.strip.split(Porthos::MongoMapper::Taggable.delimiter).collect(&:strip).uniq.compact
120
+ end
121
+
122
+ def match_tag_names_methods(possible_method_name)
123
+ possible_method_name.to_s.match(/(.*)_(tag_names=|tag_names)$/)
124
+ end
125
+
126
+ def cache_tags_if_changed
127
+ if tags_changed?
128
+ Rails.env.production? ? self.class.delay.cache_tags! : self.class.cache_tags!
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ MongoMapper::Document.plugin(Porthos::MongoMapper::Taggable::Plugin)