publify_core 9.0.0.pre1

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 (372) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +35 -0
  5. data/app/assets/fonts/open-sans-bold.woff +0 -0
  6. data/app/assets/fonts/open-sans.woff +0 -0
  7. data/app/assets/images/admin/loading.gif +0 -0
  8. data/app/assets/images/admin/typologo.gif +0 -0
  9. data/app/assets/images/calendar_date_select/calendar.gif +0 -0
  10. data/app/assets/images/close.gif +0 -0
  11. data/app/assets/images/closelabel.gif +0 -0
  12. data/app/assets/images/go.png +0 -0
  13. data/app/assets/images/loading.gif +0 -0
  14. data/app/assets/images/nextlabel.gif +0 -0
  15. data/app/assets/images/overlay.png +0 -0
  16. data/app/assets/images/powered.gif +0 -0
  17. data/app/assets/images/prevlabel.gif +0 -0
  18. data/app/assets/images/spinner-blue.gif +0 -0
  19. data/app/assets/images/spinner.gif +0 -0
  20. data/app/assets/images/thumb_blank.jpg +0 -0
  21. data/app/assets/javascripts/application.js +2 -0
  22. data/app/assets/javascripts/cookies.js +60 -0
  23. data/app/assets/javascripts/datetimepicker.js +1470 -0
  24. data/app/assets/javascripts/lang/da_DK.js +17 -0
  25. data/app/assets/javascripts/lang/default.js +21 -0
  26. data/app/assets/javascripts/lang/en_US.js +21 -0
  27. data/app/assets/javascripts/lang/fr_FR.js +21 -0
  28. data/app/assets/javascripts/lang/nl_NL.js +21 -0
  29. data/app/assets/javascripts/lang/zh_TW.js +17 -0
  30. data/app/assets/javascripts/lightbox.js +350 -0
  31. data/app/assets/javascripts/observe.js +28 -0
  32. data/app/assets/javascripts/publify.js +11 -0
  33. data/app/assets/javascripts/publify_admin.js +138 -0
  34. data/app/assets/javascripts/quicktags.js +440 -0
  35. data/app/assets/javascripts/set-timeago-lang.js +3 -0
  36. data/app/assets/javascripts/sidebar.js +28 -0
  37. data/app/assets/javascripts/spinnable.js +5 -0
  38. data/app/assets/javascripts/tagmanager.js +481 -0
  39. data/app/assets/javascripts/typeahead.js +1139 -0
  40. data/app/assets/javascripts/widearea.js +486 -0
  41. data/app/assets/stylesheets/accounts.css.scss +7 -0
  42. data/app/assets/stylesheets/administration_structure.css.scss +239 -0
  43. data/app/assets/stylesheets/coderay.css +135 -0
  44. data/app/assets/stylesheets/datetimepicker.css +306 -0
  45. data/app/assets/stylesheets/lightbox.css +63 -0
  46. data/app/assets/stylesheets/publify.css.scss +9 -0
  47. data/app/assets/stylesheets/publify_admin.css.scss +11 -0
  48. data/app/assets/stylesheets/rss.css +53 -0
  49. data/app/assets/stylesheets/sidebar_admin.css.scss +36 -0
  50. data/app/assets/stylesheets/tagmanager.css +102 -0
  51. data/app/assets/stylesheets/user-styles.css +29 -0
  52. data/app/assets/stylesheets/widearea.css +133 -0
  53. data/app/controllers/accounts_controller.rb +2 -0
  54. data/app/controllers/admin/base_controller.rb +41 -0
  55. data/app/controllers/admin/cache_controller.rb +33 -0
  56. data/app/controllers/admin/content_controller.rb +174 -0
  57. data/app/controllers/admin/dashboard_controller.rb +87 -0
  58. data/app/controllers/admin/feedback_controller.rb +159 -0
  59. data/app/controllers/admin/migrations_controller.rb +20 -0
  60. data/app/controllers/admin/notes_controller.rb +69 -0
  61. data/app/controllers/admin/pages_controller.rb +88 -0
  62. data/app/controllers/admin/post_types_controller.rb +56 -0
  63. data/app/controllers/admin/profiles_controller.rb +48 -0
  64. data/app/controllers/admin/redirects_controller.rb +47 -0
  65. data/app/controllers/admin/resources_controller.rb +30 -0
  66. data/app/controllers/admin/seo_controller.rb +45 -0
  67. data/app/controllers/admin/settings_controller.rb +53 -0
  68. data/app/controllers/admin/sidebar_controller.rb +66 -0
  69. data/app/controllers/admin/tags_controller.rb +53 -0
  70. data/app/controllers/admin/textfilters_controller.rb +6 -0
  71. data/app/controllers/admin/themes_controller.rb +37 -0
  72. data/app/controllers/admin/users_controller.rb +65 -0
  73. data/app/controllers/articles_controller.rb +205 -0
  74. data/app/controllers/authors_controller.rb +27 -0
  75. data/app/controllers/base_controller.rb +45 -0
  76. data/app/controllers/comments_controller.rb +69 -0
  77. data/app/controllers/content_controller.rb +31 -0
  78. data/app/controllers/feedback_controller.rb +47 -0
  79. data/app/controllers/notes_controller.rb +37 -0
  80. data/app/controllers/setup_controller.rb +62 -0
  81. data/app/controllers/tags_controller.rb +55 -0
  82. data/app/controllers/text_controller.rb +9 -0
  83. data/app/controllers/textfilter_controller.rb +3 -0
  84. data/app/controllers/theme_controller.rb +59 -0
  85. data/app/controllers/trackbacks_controller.rb +36 -0
  86. data/app/controllers/xml_controller.rb +70 -0
  87. data/app/helpers/admin/base_helper.rb +87 -0
  88. data/app/helpers/admin/feedback_helper.rb +42 -0
  89. data/app/helpers/articles_helper.rb +8 -0
  90. data/app/helpers/authors_helper.rb +39 -0
  91. data/app/helpers/base_helper.rb +246 -0
  92. data/app/helpers/blog_helper.rb +12 -0
  93. data/app/helpers/xml_helper.rb +16 -0
  94. data/app/mailers/notification_mailer.rb +38 -0
  95. data/app/models/ability.rb +52 -0
  96. data/app/models/archives_sidebar.rb +45 -0
  97. data/app/models/article/factory.rb +56 -0
  98. data/app/models/article/states.rb +178 -0
  99. data/app/models/article.rb +321 -0
  100. data/app/models/blog.rb +290 -0
  101. data/app/models/blog_sweeper.rb +86 -0
  102. data/app/models/comment.rb +53 -0
  103. data/app/models/config_manager.rb +81 -0
  104. data/app/models/content.rb +138 -0
  105. data/app/models/content_base.rb +95 -0
  106. data/app/models/feedback/states.rb +256 -0
  107. data/app/models/feedback.rb +225 -0
  108. data/app/models/meta_sidebar.rb +8 -0
  109. data/app/models/note.rb +144 -0
  110. data/app/models/page.rb +36 -0
  111. data/app/models/page_cache.rb +33 -0
  112. data/app/models/page_sidebar.rb +12 -0
  113. data/app/models/ping.rb +116 -0
  114. data/app/models/post_type.rb +15 -0
  115. data/app/models/redirect.rb +45 -0
  116. data/app/models/redirection.rb +4 -0
  117. data/app/models/resource.rb +28 -0
  118. data/app/models/search_sidebar.rb +7 -0
  119. data/app/models/sidebar.rb +138 -0
  120. data/app/models/static_sidebar.rb +20 -0
  121. data/app/models/tag.rb +63 -0
  122. data/app/models/tag_sidebar.rb +27 -0
  123. data/app/models/text_filter.rb +61 -0
  124. data/app/models/trackback.rb +58 -0
  125. data/app/models/trigger.rb +45 -0
  126. data/app/models/user.rb +148 -0
  127. data/app/services/migrator.rb +25 -0
  128. data/app/services/title_builder.rb +80 -0
  129. data/app/uploaders/resource_uploader.rb +30 -0
  130. data/app/views/accounts/confirm.html.erb +8 -0
  131. data/app/views/admin/cache/show.html.erb +18 -0
  132. data/app/views/admin/content/_article_list.html.erb +26 -0
  133. data/app/views/admin/content/_form.html.erb +165 -0
  134. data/app/views/admin/content/autosave.js.erb +5 -0
  135. data/app/views/admin/content/edit.html.erb +3 -0
  136. data/app/views/admin/content/index.html.erb +48 -0
  137. data/app/views/admin/content/index.js.erb +1 -0
  138. data/app/views/admin/content/new.html.erb +3 -0
  139. data/app/views/admin/dashboard/_comment.html.erb +18 -0
  140. data/app/views/admin/dashboard/_comments.html.erb +10 -0
  141. data/app/views/admin/dashboard/_drafts.html.erb +25 -0
  142. data/app/views/admin/dashboard/_inbound.html.erb +31 -0
  143. data/app/views/admin/dashboard/_overview.html.erb +23 -0
  144. data/app/views/admin/dashboard/_welcome.html.erb +28 -0
  145. data/app/views/admin/dashboard/index.html.erb +17 -0
  146. data/app/views/admin/feedback/_button.html.erb +19 -0
  147. data/app/views/admin/feedback/_feedback.html.erb +7 -0
  148. data/app/views/admin/feedback/_ham.html.erb +17 -0
  149. data/app/views/admin/feedback/_spam.html.erb +23 -0
  150. data/app/views/admin/feedback/article.html.erb +69 -0
  151. data/app/views/admin/feedback/edit.html.erb +48 -0
  152. data/app/views/admin/feedback/ham.js +1 -0
  153. data/app/views/admin/feedback/index.html.erb +53 -0
  154. data/app/views/admin/feedback/spam.js +1 -0
  155. data/app/views/admin/migrations/show.html.erb +39 -0
  156. data/app/views/admin/notes/_form.html.erb +37 -0
  157. data/app/views/admin/notes/_header.html.erb +6 -0
  158. data/app/views/admin/notes/_list.html.erb +13 -0
  159. data/app/views/admin/notes/_note.html.erb +14 -0
  160. data/app/views/admin/notes/edit.html.erb +11 -0
  161. data/app/views/admin/notes/index.html.erb +11 -0
  162. data/app/views/admin/notes/show.html.erb +14 -0
  163. data/app/views/admin/pages/_form.html.erb +101 -0
  164. data/app/views/admin/pages/_pages.html.erb +21 -0
  165. data/app/views/admin/pages/edit.html.erb +1 -0
  166. data/app/views/admin/pages/index.html.erb +17 -0
  167. data/app/views/admin/pages/new.html.erb +1 -0
  168. data/app/views/admin/post_types/_index_and_form.html.erb +65 -0
  169. data/app/views/admin/post_types/edit.html.erb +1 -0
  170. data/app/views/admin/post_types/index.html.erb +1 -0
  171. data/app/views/admin/profiles/index.html.erb +10 -0
  172. data/app/views/admin/redirects/_index_and_form.html.erb +68 -0
  173. data/app/views/admin/redirects/edit.html.erb +1 -0
  174. data/app/views/admin/redirects/index.html.erb +1 -0
  175. data/app/views/admin/resources/index.html.erb +68 -0
  176. data/app/views/admin/seo/_general.html.erb +123 -0
  177. data/app/views/admin/seo/_permalinks.html.erb +53 -0
  178. data/app/views/admin/seo/_titles.html.erb +210 -0
  179. data/app/views/admin/seo/show.html.erb +32 -0
  180. data/app/views/admin/settings/display.html.erb +110 -0
  181. data/app/views/admin/settings/feedback.html.erb +125 -0
  182. data/app/views/admin/settings/index.html.erb +73 -0
  183. data/app/views/admin/settings/write.html.erb +87 -0
  184. data/app/views/admin/shared/_edit.html.erb +4 -0
  185. data/app/views/admin/shared/_menu.html.erb +122 -0
  186. data/app/views/admin/shared/_twitter_alert.html.erb +3 -0
  187. data/app/views/admin/sidebar/_available.html.erb +6 -0
  188. data/app/views/admin/sidebar/_available.json.erb +6 -0
  189. data/app/views/admin/sidebar/_config.html.erb +27 -0
  190. data/app/views/admin/sidebar/_target.html.erb +9 -0
  191. data/app/views/admin/sidebar/_target_sidebar.html.erb +20 -0
  192. data/app/views/admin/sidebar/destroy.js.erb +1 -0
  193. data/app/views/admin/sidebar/index.html.erb +31 -0
  194. data/app/views/admin/sidebar/sortable.js.erb +3 -0
  195. data/app/views/admin/sidebar/update.js.erb +2 -0
  196. data/app/views/admin/tags/_index_and_form.html.erb +59 -0
  197. data/app/views/admin/tags/edit.html.erb +1 -0
  198. data/app/views/admin/tags/index.html.erb +1 -0
  199. data/app/views/admin/themes/index.html.erb +27 -0
  200. data/app/views/admin/users/_form.html.erb +215 -0
  201. data/app/views/admin/users/edit.html.erb +8 -0
  202. data/app/views/admin/users/index.html.erb +39 -0
  203. data/app/views/admin/users/new.html.erb +8 -0
  204. data/app/views/archives_sidebar/_content.html.erb +13 -0
  205. data/app/views/articles/_article.html.erb +9 -0
  206. data/app/views/articles/_article_collection.html.erb +8 -0
  207. data/app/views/articles/_article_content.html.erb +5 -0
  208. data/app/views/articles/_article_excerpt.html.erb +13 -0
  209. data/app/views/articles/_article_links.html.erb +10 -0
  210. data/app/views/articles/_comment.html.erb +1 -0
  211. data/app/views/articles/_comment_errors.html.erb +2 -0
  212. data/app/views/articles/_comment_form.html.erb +48 -0
  213. data/app/views/articles/_comment_list.html.erb +5 -0
  214. data/app/views/articles/_comment_preview.html.erb +4 -0
  215. data/app/views/articles/_full_article_content.html.erb +2 -0
  216. data/app/views/articles/_password_form.html.erb +10 -0
  217. data/app/views/articles/_protected_article_content.html.erb +6 -0
  218. data/app/views/articles/_trackback.html.erb +6 -0
  219. data/app/views/articles/archives.html.erb +25 -0
  220. data/app/views/articles/comment.js.erb +5 -0
  221. data/app/views/articles/comment_failed.js.erb +3 -0
  222. data/app/views/articles/error.html.erb +3 -0
  223. data/app/views/articles/feedback_atom_feed.atom.builder +8 -0
  224. data/app/views/articles/feedback_rss_feed.rss.builder +21 -0
  225. data/app/views/articles/index.html.erb +1 -0
  226. data/app/views/articles/index_atom_feed.atom.builder +8 -0
  227. data/app/views/articles/index_rss_feed.rss.builder +20 -0
  228. data/app/views/articles/live_search.html.erb +10 -0
  229. data/app/views/articles/read.html.erb +61 -0
  230. data/app/views/articles/search.html.erb +8 -0
  231. data/app/views/articles/trackback.xml.builder +5 -0
  232. data/app/views/articles/view_page.html.erb +3 -0
  233. data/app/views/authors/show.html.erb +40 -0
  234. data/app/views/authors/show_atom_feed.atom.builder +8 -0
  235. data/app/views/authors/show_rss_feed.rss.builder +20 -0
  236. data/app/views/comments/_comment.html.erb +16 -0
  237. data/app/views/comments/index.html.erb +1 -0
  238. data/app/views/comments/index_atom_feed.atom.builder +8 -0
  239. data/app/views/comments/index_rss_feed.rss.builder +20 -0
  240. data/app/views/comments/preview.html.erb +1 -0
  241. data/app/views/comments/preview.js.erb +3 -0
  242. data/app/views/devise/mailer/reset_password_instructions.html.erb +13 -0
  243. data/app/views/devise/passwords/edit.html.erb +28 -0
  244. data/app/views/devise/passwords/new.html.erb +20 -0
  245. data/app/views/devise/registrations/new.html.erb +36 -0
  246. data/app/views/devise/sessions/new.html.erb +32 -0
  247. data/app/views/devise/shared/_links.html.erb +15 -0
  248. data/app/views/errors/404.html.erb +2 -0
  249. data/app/views/layouts/accounts.html.erb +33 -0
  250. data/app/views/layouts/administration.html.erb +37 -0
  251. data/app/views/layouts/default.html.erb +32 -0
  252. data/app/views/layouts/editor.html.erb +31 -0
  253. data/app/views/meta_sidebar/_content.html.erb +8 -0
  254. data/app/views/notes/_note.html.erb +15 -0
  255. data/app/views/notes/error.html.erb +3 -0
  256. data/app/views/notes/index.html.erb +15 -0
  257. data/app/views/notes/show.html.erb +5 -0
  258. data/app/views/notes/show_in_reply.html.erb +16 -0
  259. data/app/views/notification_mailer/_mail_footer.html.erb +7 -0
  260. data/app/views/notification_mailer/_mail_header.html.erb +1 -0
  261. data/app/views/notification_mailer/article.html.erb +6 -0
  262. data/app/views/notification_mailer/comment.html.erb +11 -0
  263. data/app/views/notification_mailer/notif_user.html.erb +14 -0
  264. data/app/views/page_sidebar/_content.html.erb +12 -0
  265. data/app/views/search_sidebar/_content.html.erb +10 -0
  266. data/app/views/settings/done.html.erb +2 -0
  267. data/app/views/settings/install.html.erb +12 -0
  268. data/app/views/setup/index.html.erb +13 -0
  269. data/app/views/shared/_atom_header.atom.builder +6 -0
  270. data/app/views/shared/_atom_item_article.atom.builder +39 -0
  271. data/app/views/shared/_atom_item_comment.atom.builder +10 -0
  272. data/app/views/shared/_atom_item_trackback.atom.builder +9 -0
  273. data/app/views/shared/_flash.erb +10 -0
  274. data/app/views/shared/_page_header.html.erb +26 -0
  275. data/app/views/shared/_rss_item_article.rss.builder +35 -0
  276. data/app/views/shared/_rss_item_comment.rss.builder +8 -0
  277. data/app/views/shared/_rss_item_trackback.rss.builder +7 -0
  278. data/app/views/sidebar/_row.html.erb +1 -0
  279. data/app/views/sidebar/_sidebar.html.erb +5 -0
  280. data/app/views/sidebar/display_plugins.html.erb +5 -0
  281. data/app/views/sidebar/show.html.erb +1 -0
  282. data/app/views/static_sidebar/_content.html.erb +2 -0
  283. data/app/views/tag_sidebar/_content.html.erb +10 -0
  284. data/app/views/tags/index.html.erb +15 -0
  285. data/app/views/tags/show.html.erb +1 -0
  286. data/app/views/theme/static_view_test.html.erb +1 -0
  287. data/app/views/trackbacks/index_atom_feed.atom.builder +7 -0
  288. data/app/views/trackbacks/index_rss_feed.rss.builder +20 -0
  289. data/app/views/trackbacks/trackback.xml.builder +4 -0
  290. data/app/views/xml/_googlesitemap_item_article.googlesitemap.builder +5 -0
  291. data/app/views/xml/_googlesitemap_item_category.googlesitemap.builder +4 -0
  292. data/app/views/xml/_googlesitemap_item_page.googlesitemap.builder +4 -0
  293. data/app/views/xml/_googlesitemap_item_tag.googlesitemap.builder +4 -0
  294. data/app/views/xml/feed.googlesitemap.builder +7 -0
  295. data/app/views/xml/rsd.rsd.builder +8 -0
  296. data/config/i18n-tasks.yml +49 -0
  297. data/config/initializers/devise.rb +265 -0
  298. data/config/initializers/mime_types.rb +6 -0
  299. data/config/locales/da.yml +827 -0
  300. data/config/locales/de.yml +827 -0
  301. data/config/locales/en.yml +827 -0
  302. data/config/locales/es-MX.yml +827 -0
  303. data/config/locales/fr.yml +827 -0
  304. data/config/locales/he.yml +827 -0
  305. data/config/locales/it.yml +827 -0
  306. data/config/locales/ja.yml +827 -0
  307. data/config/locales/lt.yml +827 -0
  308. data/config/locales/nb-NO.yml +827 -0
  309. data/config/locales/nl.yml +827 -0
  310. data/config/locales/pl.yml +827 -0
  311. data/config/locales/pt-BR.yml +827 -0
  312. data/config/locales/ro.yml +827 -0
  313. data/config/locales/ru.yml +827 -0
  314. data/config/locales/sidebars.da.yml +20 -0
  315. data/config/locales/sidebars.de.yml +20 -0
  316. data/config/locales/sidebars.en.yml +20 -0
  317. data/config/locales/sidebars.es-MX.yml +20 -0
  318. data/config/locales/sidebars.fr.yml +20 -0
  319. data/config/locales/sidebars.he.yml +20 -0
  320. data/config/locales/sidebars.it.yml +20 -0
  321. data/config/locales/sidebars.ja.yml +20 -0
  322. data/config/locales/sidebars.lt.yml +20 -0
  323. data/config/locales/sidebars.nb-NO.yml +20 -0
  324. data/config/locales/sidebars.nl.yml +20 -0
  325. data/config/locales/sidebars.pl.yml +20 -0
  326. data/config/locales/sidebars.pt-BR.yml +20 -0
  327. data/config/locales/sidebars.ro.yml +20 -0
  328. data/config/locales/sidebars.ru.yml +20 -0
  329. data/config/locales/sidebars.zh-CN.yml +20 -0
  330. data/config/locales/sidebars.zh-TW.yml +20 -0
  331. data/config/locales/zh-CN.yml +827 -0
  332. data/config/locales/zh-TW.yml +827 -0
  333. data/config/routes.rb +177 -0
  334. data/db/migrate/113_initial_schema.rb +205 -0
  335. data/db/migrate/114_fixes_buggy_articles_and_notes.rb +52 -0
  336. data/db/migrate/115_drops_categories_for_tags.rb +34 -0
  337. data/db/migrate/20150207131657_add_missing_indexes.rb +19 -0
  338. data/db/migrate/20150807134129_simplify_redirect_relations.rb +38 -0
  339. data/db/migrate/20150808052637_add_blog_ids.rb +33 -0
  340. data/db/migrate/20150808191127_add_blog_id_to_redirects.rb +15 -0
  341. data/db/migrate/20150810094754_add_blog_id_to_tags.rb +15 -0
  342. data/db/migrate/20160108111120_add_devise_to_users.rb +53 -0
  343. data/db/migrate/20160108184201_move_last_connection_to_last_sign_in_at.rb +16 -0
  344. data/db/migrate/20160110094906_remove_profiles_rights.rb +14 -0
  345. data/db/migrate/20160605103918_replace_profile_id_with_string.rb +30 -0
  346. data/db/migrate/20160605154632_remove_profiles.rb +24 -0
  347. data/db/migrate/20160701061851_demand_blog_id_on_contents.rb +9 -0
  348. data/db/migrate/20160701062604_add_blog_id_to_resources.rb +28 -0
  349. data/db/seeds.rb +37 -0
  350. data/lib/email_notify.rb +26 -0
  351. data/lib/format.rb +17 -0
  352. data/lib/publify_core/engine.rb +23 -0
  353. data/lib/publify_core/lang.rb +5 -0
  354. data/lib/publify_core/version.rb +3 -0
  355. data/lib/publify_core.rb +56 -0
  356. data/lib/publify_guid.rb +9 -0
  357. data/lib/publify_plugins.rb +72 -0
  358. data/lib/publify_textfilter_markdown.rb +44 -0
  359. data/lib/publify_textfilter_none.rb +14 -0
  360. data/lib/publify_textfilter_smartypants.rb +14 -0
  361. data/lib/publify_textfilter_textile.rb +21 -0
  362. data/lib/publify_textfilter_twitterfilter.rb +33 -0
  363. data/lib/publify_time.rb +30 -0
  364. data/lib/sidebar_field.rb +115 -0
  365. data/lib/sidebar_registry.rb +33 -0
  366. data/lib/spam_protection.rb +101 -0
  367. data/lib/stateful.rb +106 -0
  368. data/lib/tasks/publify_core_tasks.rake +4 -0
  369. data/lib/text_filter_plugin.rb +182 -0
  370. data/lib/theme.rb +72 -0
  371. data/lib/transforms.rb +45 -0
  372. metadata +865 -0
@@ -0,0 +1,53 @@
1
+ class Admin::SettingsController < Admin::BaseController
2
+ cache_sweeper :blog_sweeper
3
+
4
+ def index
5
+ this_blog.base_url = blog_base_url if this_blog.base_url.blank?
6
+ load_settings
7
+ end
8
+
9
+ def write
10
+ load_settings
11
+ end
12
+
13
+ def feedback
14
+ load_settings
15
+ end
16
+
17
+ def display
18
+ load_settings
19
+ end
20
+
21
+ def update
22
+ load_settings
23
+ if @setting.update_attributes(settings_params)
24
+ load_lang
25
+ flash[:success] = I18n.t('admin.settings.update.success')
26
+ redirect_to action: action_param
27
+ else
28
+ flash[:error] = I18n.t('admin.settings.update.error',
29
+ messages: this_blog.errors.full_messages.join(', '))
30
+ render action_param
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ VALID_ACTIONS = %w(index write feedback display).freeze
37
+
38
+ def settings_params
39
+ @settings_params ||= params.require(:setting).permit!
40
+ end
41
+
42
+ def action_param
43
+ @action_param ||=
44
+ begin
45
+ value = params[:from]
46
+ VALID_ACTIONS.include?(value) ? value : 'index'
47
+ end
48
+ end
49
+
50
+ def load_settings
51
+ @setting = this_blog
52
+ end
53
+ end
@@ -0,0 +1,66 @@
1
+ # coding: utf-8
2
+ class Admin::SidebarController < Admin::BaseController
3
+ def index
4
+ @available = SidebarRegistry.available_sidebars
5
+ @ordered_sidebars = Sidebar.ordered_sidebars
6
+ end
7
+
8
+ # Just update a single active Sidebar instance at once
9
+ def update
10
+ @sidebar = Sidebar.where(id: params[:id]).first
11
+ @old_s_index = @sidebar.staged_position || @sidebar.active_position
12
+ @sidebar.update_attributes params[:configure][@sidebar.id.to_s].permit!
13
+ respond_to do |format|
14
+ format.js
15
+ format.html do
16
+ return redirect_to(admin_sidebar_index_path)
17
+ end
18
+ end
19
+ end
20
+
21
+ def destroy
22
+ @sidebar = Sidebar.where(id: params[:id]).first
23
+ @sidebar && @sidebar.destroy
24
+ respond_to do |format|
25
+ format.html { return redirect_to(admin_sidebar_index_path) }
26
+ format.js
27
+ end
28
+ end
29
+
30
+ def publish
31
+ Sidebar.apply_staging_on_active!
32
+ PageCache.sweep_all
33
+ redirect_to admin_sidebar_index_path
34
+ end
35
+
36
+ # Callback for admin sidebar sortable plugin
37
+ def sortable
38
+ sorted = params[:sidebar].map(&:to_i)
39
+
40
+ Sidebar.transaction do
41
+ sorted.each_with_index do |sidebar_id, staged_index|
42
+ # DEV NOTE : Ok, that's a HUGE hack. Sidebar.available are Class, not
43
+ # Sidebar instances. In order to use jQuery.sortable we need that hack:
44
+ # Sidebar.available is an Array, so it's ordered. I arbitrary shift by?
45
+ # IT'S OVER NINE THOUSAND! considering we'll never reach 9K Sidebar
46
+ # instances or Sidebar specializations
47
+ sidebar = if sidebar_id >= 9000
48
+ SidebarRegistry.available_sidebars[sidebar_id - 9000].new(blog: this_blog)
49
+ else
50
+ Sidebar.valid.find(sidebar_id)
51
+ end
52
+ sidebar.update_attributes(staged_position: staged_index)
53
+ end
54
+ end
55
+
56
+ @ordered_sidebars = Sidebar.ordered_sidebars
57
+ @available = SidebarRegistry.available_sidebars
58
+
59
+ respond_to do |format|
60
+ format.js
61
+ format.html do
62
+ return redirect_to admin_sidebar_index_path
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,53 @@
1
+ class Admin::TagsController < Admin::BaseController
2
+ before_action :fetch_tags, only: [:index, :edit]
3
+ before_action :set_tag, only: [:edit, :update, :destroy]
4
+ cache_sweeper :blog_sweeper
5
+
6
+ def index
7
+ @tag = Tag.new
8
+ end
9
+
10
+ def edit
11
+ end
12
+
13
+ def create
14
+ @tag = this_blog.tags.new(tag_params)
15
+
16
+ if @tag.save
17
+ redirect_to admin_tags_url, notice: 'Tag was successfully created.'
18
+ else
19
+ fetch_tags
20
+ render :index
21
+ end
22
+ end
23
+
24
+ def update
25
+ old_name = @tag.name
26
+ if @tag.update(tag_params)
27
+ Redirect.create(from_path: "/tag/#{old_name}", to_path: @tag.permalink_url(nil, true))
28
+ redirect_to admin_tags_url, notice: I18n.t('admin.tags.edit.success')
29
+ else
30
+ render :edit
31
+ end
32
+ end
33
+
34
+ def destroy
35
+ destroy_a(Tag)
36
+ end
37
+
38
+ private
39
+
40
+ # Use callbacks to share common setup or constraints between actions.
41
+ def set_tag
42
+ @tag = Tag.find(params[:id])
43
+ end
44
+
45
+ # Never trust parameters from the scary internet, only allow the white list through.
46
+ def tag_params
47
+ params.require(:tag).permit(:display_name)
48
+ end
49
+
50
+ def fetch_tags
51
+ @tags = Tag.order('display_name').page(params[:page]).per(this_blog.admin_display_elements)
52
+ end
53
+ end
@@ -0,0 +1,6 @@
1
+ class Admin::TextfiltersController < Admin::BaseController
2
+ def macro_help
3
+ @macro = TextFilterPlugin.available_filters.find { |filter| filter.short_name == params[:id] }
4
+ render text: BlueCloth.new(@macro.help_text).to_html
5
+ end
6
+ end
@@ -0,0 +1,37 @@
1
+ require 'open-uri'
2
+ require 'time'
3
+ require 'rexml/document'
4
+
5
+ class Admin::ThemesController < Admin::BaseController
6
+ cache_sweeper :blog_sweeper
7
+
8
+ def index
9
+ @themes = Theme.find_all
10
+ @themes.each do |theme|
11
+ # TODO: Move to Theme
12
+ theme.description_html = TextFilter.filter_text(theme.description, [:markdown, :smartypants])
13
+ end
14
+ @active = this_blog.current_theme
15
+ end
16
+
17
+ def preview
18
+ theme = Theme.find(params[:theme])
19
+ send_file File.join(theme.path, 'preview.png'),
20
+ type: 'image/png', disposition: 'inline', stream: false
21
+ end
22
+
23
+ def switchto
24
+ this_blog.theme = params[:theme]
25
+ this_blog.save
26
+ zap_theme_caches
27
+ this_blog.current_theme(:reload)
28
+ flash[:success] = I18n.t('admin.themes.switchto.success')
29
+ redirect_to admin_themes_url
30
+ end
31
+
32
+ protected
33
+
34
+ def zap_theme_caches
35
+ FileUtils.rm_rf(%w(stylesheets javascript images).map { |v| page_cache_directory + "/#{v}/theme" })
36
+ end
37
+ end
@@ -0,0 +1,65 @@
1
+ class Admin::UsersController < Admin::BaseController
2
+ before_action :set_user, only: [:edit, :update, :destroy]
3
+ cache_sweeper :blog_sweeper
4
+
5
+ def index
6
+ @users = User.order('login asc').page(params[:page]).per(this_blog.admin_display_elements)
7
+ end
8
+
9
+ def new
10
+ @user = User.new
11
+ @user.text_filter = TextFilter.find_by(name: this_blog.text_filter)
12
+ end
13
+
14
+ def edit
15
+ @user = params[:id] ? User.find_by(id: params[:id]) : current_user
16
+ end
17
+
18
+ def create
19
+ @user = User.new(user_params)
20
+ @user.name = @user.login
21
+ if @user.save
22
+ redirect_to admin_users_url, notice: I18n.t('admin.users.new.success')
23
+ else
24
+ render :new
25
+ end
26
+ end
27
+
28
+ def update
29
+ if @user.update(update_params)
30
+ redirect_to admin_users_url, notice: 'User was successfully updated.'
31
+ else
32
+ render :edit
33
+ end
34
+ end
35
+
36
+ def destroy
37
+ @user.destroy if User.where('profile = ? and id != ?', User::ADMIN, @user.id).count > 1
38
+ redirect_to admin_users_url
39
+ end
40
+
41
+ private
42
+
43
+ def set_user
44
+ @user = User.find(params[:id])
45
+ end
46
+
47
+ def user_params
48
+ params.require(:user).permit(:login, :password, :password_confirmation,
49
+ :email, :firstname, :lastname, :nickname,
50
+ :display_name, :notify_via_email,
51
+ :notify_on_new_articles, :notify_on_comments,
52
+ :profile, :text_filter, :state,
53
+ :twitter_account, :twitter_oauth_token,
54
+ :twitter_oauth_token_secret, :description,
55
+ :url, :msn, :yahoo, :jabber, :aim, :twitter)
56
+ end
57
+
58
+ def update_params
59
+ if user_params[:password].blank? && user_params[:password_confirmation].blank?
60
+ user_params.except(:password_confirmation, :password)
61
+ else
62
+ user_params
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,205 @@
1
+ class ArticlesController < ContentController
2
+ before_action :login_required, only: [:preview, :preview_page]
3
+ before_action :auto_discovery_feed, only: [:show, :index]
4
+ before_action :verify_config
5
+
6
+ layout :theme_layout, except: [:trackback]
7
+
8
+ cache_sweeper :blog_sweeper
9
+ caches_page :index, :archives, :read, :view_page, :redirect, if: proc { |c| c.request.query_string == '' }
10
+
11
+ helper :'admin/base'
12
+
13
+ def index
14
+ conditions = this_blog.statuses_in_timeline ? ['type in (?, ?)', 'Article', 'Note'] : ['type = ?', 'Article']
15
+
16
+ limit = this_blog.per_page(params[:format])
17
+ @articles = if params[:year].blank?
18
+ this_blog.contents.published.where(conditions).page(params[:page]).per(limit)
19
+ else
20
+ this_blog.contents.published_at(params.values_at(:year, :month, :day)).where(conditions).page(params[:page]).per(limit)
21
+ end
22
+
23
+ @page_title = this_blog.home_title_template
24
+ @description = this_blog.home_desc_template
25
+ if params[:year]
26
+ @page_title = this_blog.archives_title_template
27
+ @description = this_blog.archives_desc_template
28
+ elsif params[:page]
29
+ @page_title = this_blog.paginated_title_template
30
+ @description = this_blog.paginated_desc_template
31
+ end
32
+ @page_title = @page_title.to_title(@articles, this_blog, params)
33
+ @description = @description.to_title(@articles, this_blog, params)
34
+
35
+ @keywords = this_blog.meta_keywords
36
+
37
+ respond_to do |format|
38
+ format.html { render_paginated_index }
39
+ format.atom do
40
+ render_articles_feed('atom')
41
+ end
42
+ format.rss do
43
+ auto_discovery_feed(only_path: false)
44
+ render_articles_feed('rss')
45
+ end
46
+ end
47
+ end
48
+
49
+ def search
50
+ @articles = this_blog.articles_matching(params[:q], page: params[:page], per_page: this_blog.per_page(params[:format]))
51
+ return error! if @articles.empty?
52
+ @page_title = this_blog.search_title_template.to_title(@articles, this_blog, params)
53
+ @description = this_blog.search_desc_template.to_title(@articles, this_blog, params)
54
+ respond_to do |format|
55
+ format.html { render 'search' }
56
+ format.rss { render 'index_rss_feed', layout: false }
57
+ format.atom { render 'index_atom_feed', layout: false }
58
+ end
59
+ end
60
+
61
+ def live_search
62
+ @search = params[:q]
63
+ @articles = Article.search(@search)
64
+ render :live_search, layout: false
65
+ end
66
+
67
+ def preview
68
+ @article = Article.last_draft(params[:id])
69
+ @page_title = this_blog.article_title_template.to_title(@article, this_blog, params)
70
+ render 'read'
71
+ end
72
+
73
+ def check_password
74
+ return unless request.xhr?
75
+ @article = Article.find(params[:article][:id])
76
+ if @article.password == params[:article][:password]
77
+ render partial: 'articles/full_article_content', locals: { article: @article }
78
+ else
79
+ render partial: 'articles/password_form', locals: { article: @article }
80
+ end
81
+ end
82
+
83
+ def redirect
84
+ from = extract_feed_format(params[:from])
85
+ factory = Article::Factory.new(this_blog, current_user)
86
+
87
+ @article = factory.match_permalink_format(from, this_blog.permalink_format)
88
+ return show_article if @article
89
+
90
+ # Redirect old version with /:year/:month/:day/:title to new format,
91
+ # because it's changed
92
+ ['%year%/%month%/%day%/%title%', 'articles/%year%/%month%/%day%/%title%'].each do |part|
93
+ @article = factory.match_permalink_format(from, part)
94
+ return redirect_to URI.parse(@article.permalink_url).path, status: 301 if @article
95
+ end
96
+
97
+ r = Redirect.find_by(from_path: from)
98
+ return redirect_to r.full_to_path, status: 301 if r # Let redirection made outside of the blog on purpose (deal with it, Brakeman!)
99
+
100
+ render 'errors/404', status: 404
101
+ end
102
+
103
+ def archives
104
+ limit = this_blog.limit_archives_display
105
+ @articles = this_blog.published_articles.page(params[:page]).per(limit)
106
+ @page_title = this_blog.archives_title_template.to_title(@articles, this_blog, params)
107
+ @keywords = this_blog.meta_keywords
108
+ @description = this_blog.archives_desc_template.to_title(@articles, this_blog, params)
109
+ end
110
+
111
+ def tag
112
+ redirect_to tags_path, status: 301
113
+ end
114
+
115
+ def preview_page
116
+ @page = Page.find(params[:id])
117
+ render 'view_page'
118
+ end
119
+
120
+ def view_page
121
+ if (@page = Page.find_by(name: Array(params[:name]).join('/'))) && @page.published?
122
+ @page_title = @page.title
123
+ @description = this_blog.meta_description
124
+ @keywords = this_blog.meta_keywords
125
+ else
126
+ render 'errors/404', status: 404
127
+ end
128
+ end
129
+
130
+ # TODO: Move to TextfilterController?
131
+ def markup_help
132
+ render text: TextFilter.find(params[:id]).commenthelp
133
+ end
134
+
135
+ private
136
+
137
+ def verify_config
138
+ if !this_blog.configured?
139
+ redirect_to controller: 'setup', action: 'index'
140
+ elsif User.count == 0
141
+ redirect_to new_user_registration_path
142
+ else
143
+ true
144
+ end
145
+ end
146
+
147
+ # See an article We need define @article before
148
+ def show_article
149
+ @comment = Comment.new
150
+ @page_title = this_blog.article_title_template.to_title(@article, this_blog, params)
151
+ @description = this_blog.article_desc_template.to_title(@article, this_blog, params)
152
+ groupings = @article.tags
153
+ @keywords = groupings.map(&:name).join(', ')
154
+
155
+ auto_discovery_feed
156
+ respond_to do |format|
157
+ format.html { render "articles/#{@article.post_type}" }
158
+ format.atom { render_feedback_feed('atom') }
159
+ format.rss { render_feedback_feed('rss') }
160
+ format.xml { render_feedback_feed('atom') }
161
+ end
162
+ rescue ActiveRecord::RecordNotFound
163
+ error!
164
+ end
165
+
166
+ def render_articles_feed(format)
167
+ if this_blog.feedburner_url.empty? || request.env['HTTP_USER_AGENT'] =~ /FeedBurner/i
168
+ render "index_#{format}_feed", layout: false
169
+ else
170
+ redirect_to "http://feeds2.feedburner.com/#{this_blog.feedburner_url}"
171
+ end
172
+ end
173
+
174
+ def render_feedback_feed(format)
175
+ @feedback = @article.published_feedback
176
+ render "feedback_#{format}_feed", layout: false
177
+ end
178
+
179
+ def render_paginated_index
180
+ return error! if @articles.empty?
181
+ if this_blog.feedburner_url.empty?
182
+ auto_discovery_feed(only_path: false)
183
+ else
184
+ @auto_discovery_url_rss = "http://feeds2.feedburner.com/#{this_blog.feedburner_url}"
185
+ @auto_discovery_url_atom = "http://feeds2.feedburner.com/#{this_blog.feedburner_url}"
186
+ end
187
+ render 'index'
188
+ end
189
+
190
+ def extract_feed_format(from)
191
+ if from =~ /^.*\.rss$/
192
+ request.format = 'rss'
193
+ from = from.gsub(/\.rss/, '')
194
+ elsif from =~ /^.*\.atom$/
195
+ request.format = 'atom'
196
+ from = from.gsub(/\.atom$/, '')
197
+ end
198
+ from
199
+ end
200
+
201
+ def error!
202
+ @message = I18n.t('errors.no_posts_found')
203
+ render 'articles/error', status: 200
204
+ end
205
+ end
@@ -0,0 +1,27 @@
1
+ class AuthorsController < ContentController
2
+ layout :theme_layout
3
+
4
+ def show
5
+ @author = User.find_by(login: params[:id])
6
+ raise ActiveRecord::RecordNotFound unless @author
7
+
8
+ @articles = @author.articles.published.page(params[:page]).per(this_blog.per_page(params[:format]))
9
+ @page_title = this_blog.author_title_template.to_title(@author, this_blog, params)
10
+ @keywords = this_blog.meta_keywords
11
+ @description = this_blog.author_desc_template.to_title(@author, this_blog, params)
12
+
13
+ auto_discovery_feed(only_path: false)
14
+
15
+ respond_to do |format|
16
+ format.rss { render_feed 'rss' }
17
+ format.atom { render_feed 'atom' }
18
+ format.html
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def render_feed(format)
25
+ render "show_#{format}_feed", layout: false
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ require 'cancancan'
2
+
3
+ class BaseController < ApplicationController
4
+ before_action :fire_triggers, :load_lang, :set_paths
5
+ before_action :configure_permitted_parameters, if: :devise_controller?
6
+
7
+ private
8
+
9
+ def configure_permitted_parameters
10
+ # TODO: Check if this is still needed
11
+ devise_parameter_sanitizer.permit(:sign_up, keys: [:email])
12
+ end
13
+
14
+ def login_required
15
+ authenticate_user! && authorize!(params[:action], params[:controller])
16
+ end
17
+
18
+ def set_paths
19
+ prepend_view_path this_blog.current_theme.view_path
20
+ Dir.glob(File.join(::Rails.root.to_s, 'lib', '*_sidebar/app/views')).select do |file|
21
+ append_view_path file
22
+ end
23
+ end
24
+
25
+ def fire_triggers
26
+ Trigger.fire
27
+ end
28
+
29
+ def load_lang
30
+ if I18n.available_locales.include?(this_blog.lang.to_sym)
31
+ I18n.locale = this_blog.lang
32
+ elsif I18n.available_locales.include?(this_blog.lang[0..1].to_sym)
33
+ I18n.locale = this_blog.lang[0..1]
34
+ # for the same language used in different areas, e.g. zh_CN, zh_TW
35
+ elsif I18n.available_locales.include?(this_blog.lang.sub('_', '-').to_sym)
36
+ I18n.locale = this_blog.lang.sub('_', '-')
37
+ end
38
+ end
39
+
40
+ def add_to_cookies(name, value, path = nil, _expires = nil)
41
+ cookies[name] = { value: value, path: path || "/#{controller_name}", expires: 6.weeks.from_now }
42
+ end
43
+
44
+ include BlogHelper
45
+ end
@@ -0,0 +1,69 @@
1
+ class CommentsController < FeedbackController
2
+ before_action :get_article, only: [:create, :preview]
3
+
4
+ def create
5
+ @comment = @article.with_options(new_comment_defaults) do |art|
6
+ art.add_comment(params[:comment].slice(:body, :author, :email, :url))
7
+ end
8
+
9
+ unless current_user.nil? || session[:user_id].nil?
10
+ # maybe useless, but who knows ?
11
+ @comment.user_id = current_user.id if current_user.id == session[:user_id]
12
+ end
13
+
14
+ set_cookies_for @comment
15
+
16
+ partial = '/articles/comment_failed'
17
+ if recaptcha_ok_for?(@comment) && @comment.save
18
+ partial = '/articles/comment'
19
+ end
20
+ respond_to do |format|
21
+ format.js { render partial }
22
+ format.html { redirect_to URI.parse(@article.permalink_url).path }
23
+ end
24
+ end
25
+
26
+ def preview
27
+ return render text: 'Comments are closed' if @article.comments_closed?
28
+
29
+ if comment_params[:body].blank?
30
+ render nothing: true
31
+ return
32
+ end
33
+
34
+ @comment = Comment.new(comment_params)
35
+ end
36
+
37
+ protected
38
+
39
+ def recaptcha_ok_for?(comment)
40
+ use_recaptcha = comment.blog.use_recaptcha
41
+ ((use_recaptcha && verify_recaptcha(model: comment)) || !use_recaptcha)
42
+ end
43
+
44
+ def new_comment_defaults
45
+ { ip: request.remote_ip,
46
+ author: 'Anonymous',
47
+ published: true,
48
+ user: @current_user,
49
+ user_agent: request.env['HTTP_USER_AGENT'],
50
+ referrer: request.env['HTTP_REFERER'],
51
+ permalink: @article.permalink_url }.stringify_keys
52
+ end
53
+
54
+ def set_cookies_for(comment)
55
+ add_to_cookies(:author, comment.author)
56
+ add_to_cookies(:url, comment.url)
57
+ unless comment.email.blank?
58
+ add_to_cookies(:gravatar_id, Digest::MD5.hexdigest(comment.email.strip))
59
+ end
60
+ end
61
+
62
+ def get_article
63
+ @article = Article.find(params[:article_id])
64
+ end
65
+
66
+ def comment_params
67
+ @comment_params ||= params.require(:comment).permit(:body, :author, :email, :url)
68
+ end
69
+ end
@@ -0,0 +1,31 @@
1
+ class ContentController < BaseController
2
+ class ExpiryFilter
3
+ def before(_controller)
4
+ @request_time = Time.now
5
+ end
6
+
7
+ def after(controller)
8
+ future_article =
9
+ this_blog.articles.where('published = ? AND published_at > ?', true, @request_time).
10
+ order('published_at ASC').first
11
+ if future_article
12
+ delta = future_article.published_at - Time.now
13
+ controller.response.lifetime = delta <= 0 ? 0 : delta
14
+ end
15
+ end
16
+ end
17
+
18
+ protected
19
+
20
+ # TODO: Make this work for all content.
21
+ def auto_discovery_feed(options = {})
22
+ with_options(options.reverse_merge(only_path: true)) do |opts|
23
+ @auto_discovery_url_rss = opts.url_for(format: 'rss', only_path: false)
24
+ @auto_discovery_url_atom = opts.url_for(format: 'atom', only_path: false)
25
+ end
26
+ end
27
+
28
+ def theme_layout
29
+ this_blog.current_theme.layout(action_name)
30
+ end
31
+ end