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,321 @@
1
+ # coding: utf-8
2
+ require 'uri'
3
+ require 'net/http'
4
+
5
+ class Article < Content
6
+ include PublifyGuid
7
+ include ConfigManager
8
+
9
+ serialize :settings, Hash
10
+
11
+ content_fields :body, :extended
12
+
13
+ validates :guid, uniqueness: true
14
+ validates :title, presence: true
15
+
16
+ has_many :pings, dependent: :destroy
17
+ has_many :trackbacks, dependent: :destroy
18
+ has_many :feedback
19
+ has_many :resources, dependent: :nullify
20
+ has_many :triggers, as: :pending_item
21
+ has_many :comments, dependent: :destroy
22
+
23
+ has_and_belongs_to_many :tags, join_table: 'articles_tags'
24
+
25
+ before_create :create_guid
26
+ before_save :set_published_at, :set_permalink
27
+ after_save :post_trigger, :keywords_to_tags, :shorten_url
28
+ after_save :send_pings
29
+ after_save :send_notifications
30
+
31
+ scope :drafts, -> { where(state: 'draft').order('created_at DESC') }
32
+ scope :child_of, ->(article_id) { where(parent_id: article_id) }
33
+ scope :published_at, ->(time_params) { published.where(published_at: PublifyTime.delta(*time_params)).order('published_at DESC') }
34
+ scope :published_since, ->(time) { published.where('published_at > ?', time).order('published_at DESC') }
35
+ scope :withdrawn, -> { where(state: 'withdrawn').order('published_at DESC') }
36
+ scope :pending, -> { where('state = ? and published_at > ?', 'publication_pending', Time.now).order('published_at DESC') }
37
+
38
+ scope :bestof, lambda {
39
+ joins(:feedback).
40
+ where('feedback.published' => true, 'feedback.type' => 'Comment',
41
+ 'contents.published' => true).
42
+ group('contents.id').
43
+ order('count(feedback.id) DESC').
44
+ select('contents.*, count(feedback.id) as comment_count').
45
+ limit(5)
46
+ }
47
+
48
+ setting :password, :string, ''
49
+
50
+ attr_accessor :draft, :keywords
51
+
52
+ include Article::States
53
+
54
+ has_state(:state, valid_states: [:new, :draft,
55
+ :publication_pending, :just_published, :published,
56
+ :just_withdrawn, :withdrawn],
57
+ initial_state: :new,
58
+ handles: [:withdraw,
59
+ :post_trigger,
60
+ :send_pings, :send_notifications,
61
+ :published_at=, :published=, :just_published?])
62
+
63
+ def set_permalink
64
+ return if state == 'draft' || permalink.present?
65
+ self.permalink = title.to_permalink
66
+ end
67
+
68
+ def has_child?
69
+ Article.exists?(parent_id: id)
70
+ end
71
+
72
+ def post_type
73
+ post_type = self[:post_type]
74
+ post_type = 'read' if post_type.blank?
75
+ post_type
76
+ end
77
+
78
+ def self.last_draft(article_id)
79
+ article = Article.find(article_id)
80
+ article = Article.child_of(article.id).first while article.has_child?
81
+ article
82
+ end
83
+
84
+ def self.search_with(params)
85
+ params ||= {}
86
+ scoped = super(params)
87
+ if %w(no_draft drafts published withdrawn pending).include?(params[:state])
88
+ scoped = scoped.send(params[:state])
89
+ end
90
+
91
+ scoped.order('created_at DESC')
92
+ end
93
+
94
+ # FIXME: Use keyword params to clean up call sites.
95
+ def permalink_url(anchor = nil, only_path = false)
96
+ @cached_permalink_url ||= {}
97
+ @cached_permalink_url["#{anchor}#{only_path}"] ||= blog.url_for(permalink_url_options, anchor: anchor, only_path: only_path)
98
+ end
99
+
100
+ def save_attachments!(files)
101
+ files ||= {}
102
+ files.values.each { |f| save_attachment!(f) }
103
+ end
104
+
105
+ def save_attachment!(file)
106
+ resources.create!(upload: file, blog: blog)
107
+ end
108
+
109
+ def trackback_url
110
+ blog.url_for("trackbacks?article_id=#{id}", only_path: false)
111
+ end
112
+
113
+ def comment_url
114
+ blog.url_for("comments?article_id=#{id}", only_path: true)
115
+ end
116
+
117
+ def preview_comment_url
118
+ blog.url_for("comments/preview?article_id=#{id}", only_path: true)
119
+ end
120
+
121
+ def feed_url(format)
122
+ "#{permalink_url}.#{format.gsub(/\d/, '')}"
123
+ end
124
+
125
+ def really_send_pings
126
+ return unless blog.send_outbound_pings
127
+
128
+ blog.urls_to_ping_for(self).each do |url_to_ping|
129
+ begin
130
+ url_to_ping.send_weblogupdatesping(blog.base_url, permalink_url)
131
+ rescue => e
132
+ logger.error(e)
133
+ # in case the remote server doesn't respond or gives an error,
134
+ # we should throw an xmlrpc error here.
135
+ end
136
+ end
137
+
138
+ html_urls_to_ping.each do |url_to_ping|
139
+ begin
140
+ url_to_ping.send_pingback_or_trackback(permalink_url)
141
+ rescue => e
142
+ logger.error(e)
143
+ # in case the remote server doesn't respond or gives an error,
144
+ # we should throw an xmlrpc error here.
145
+ end
146
+ end
147
+ end
148
+
149
+ def next
150
+ Article.where('published_at > ?', published_at).order('published_at asc').limit(1).first
151
+ end
152
+
153
+ def previous
154
+ Article.where('published_at < ?', published_at).order('published_at desc').limit(1).first
155
+ end
156
+
157
+ def self.publication_months
158
+ result = select('published_at').where('published_at is not NULL').where(type: 'Article')
159
+ result.map { |d| [d.published_at.strftime('%Y-%m')] }.uniq
160
+ end
161
+
162
+ # Finds one article which was posted on a certain date and matches the supplied dashed-title
163
+ # params is a Hash
164
+ def self.requested_article(params)
165
+ date_range = PublifyTime.delta(params[:year], params[:month], params[:day])
166
+
167
+ req_params = {}
168
+ req_params[:permalink] = params[:title] if params[:title]
169
+ req_params[:published_at] = date_range if date_range
170
+
171
+ return if req_params.empty? # no search if no params send
172
+ article = published.find_by(req_params)
173
+ return article if article
174
+
175
+ if params[:title]
176
+ req_params[:permalink] = CGI.escape(params[:title])
177
+ article = published.find_by(req_params)
178
+ return article if article
179
+ end
180
+ end
181
+
182
+ # Fulltext searches the body of published articles
183
+ def self.search(query, args = {})
184
+ query_s = query.to_s.strip
185
+ if !query_s.empty? && args.empty?
186
+ Article.searchstring(query)
187
+ elsif !query_s.empty? && !args.empty?
188
+ Article.searchstring(query).page(args[:page]).per(args[:per])
189
+ else
190
+ []
191
+ end
192
+ end
193
+
194
+ def keywords_to_tags
195
+ Tag.create_from_article!(self)
196
+ end
197
+
198
+ def interested_users
199
+ User.where(notify_on_new_articles: true)
200
+ end
201
+
202
+ def notify_user_via_email(user)
203
+ EmailNotify.send_article(self, user) if user.notify_via_email?
204
+ end
205
+
206
+ def comments_closed?
207
+ !(allow_comments? && in_feedback_window?)
208
+ end
209
+
210
+ def html_urls
211
+ urls = []
212
+ html.gsub(/<a\s+[^>]*>/) do |tag|
213
+ if tag =~ /\bhref=(["']?)([^ >"]+)\1/
214
+ urls.push(Regexp.last_match[2].strip)
215
+ end
216
+ end
217
+ urls.uniq
218
+ end
219
+
220
+ def pings_closed?
221
+ !(allow_pings? && in_feedback_window?)
222
+ end
223
+
224
+ # check if time to comment is open or not
225
+ def in_feedback_window?
226
+ blog.sp_article_auto_close.zero? ||
227
+ published_at.to_i > blog.sp_article_auto_close.days.ago.to_i
228
+ end
229
+
230
+ def content_fields
231
+ [:body, :extended]
232
+ end
233
+
234
+ # The web interface no longer distinguishes between separate "body" and
235
+ # "extended" fields, and instead edits everything in a single edit field,
236
+ # separating the extended content using "\<!--more-->".
237
+ def body_and_extended
238
+ if extended.blank?
239
+ body
240
+ else
241
+ body + "\n<!--more-->\n" + extended
242
+ end
243
+ end
244
+
245
+ # Split apart value around a "\<!--more-->" comment and assign it to our
246
+ # #body and #extended fields.
247
+ def body_and_extended=(value)
248
+ parts = value.split(/\n?<!--more-->\n?/, 2)
249
+ self.body = parts[0]
250
+ self.extended = parts[1] || ''
251
+ end
252
+
253
+ def password_protected?
254
+ !password.blank?
255
+ end
256
+
257
+ def add_comment(params)
258
+ comments.build(params)
259
+ end
260
+
261
+ def access_by?(user)
262
+ user.admin? || user_id == user.id
263
+ end
264
+
265
+ def already_ping?(url)
266
+ pings.map(&:url).include?(url)
267
+ end
268
+
269
+ def allow_comments?
270
+ return allow_comments unless allow_comments.nil?
271
+ blog.default_allow_comments
272
+ end
273
+
274
+ def allow_pings?
275
+ return allow_pings unless allow_pings.nil?
276
+ blog.default_allow_pings
277
+ end
278
+
279
+ def published_comments
280
+ comments.published.oldest_first
281
+ end
282
+
283
+ def published_trackbacks
284
+ trackbacks.published.oldest_first
285
+ end
286
+
287
+ def published_feedback
288
+ feedback.published.oldest_first
289
+ end
290
+
291
+ protected
292
+
293
+ def set_published_at
294
+ if published && self[:published_at].nil?
295
+ self[:published_at] = created_at || Time.now
296
+ end
297
+ end
298
+
299
+ private
300
+
301
+ def permalink_url_options
302
+ format_url = blog.permalink_format.dup
303
+ format_url.gsub!('%year%', published_at.year.to_s)
304
+ format_url.gsub!('%month%', sprintf('%.2d', published_at.month))
305
+ format_url.gsub!('%day%', sprintf('%.2d', published_at.day))
306
+ format_url.gsub!('%title%', URI.encode(permalink.to_s))
307
+ if format_url[0, 1] == '/'
308
+ format_url[1..-1]
309
+ else
310
+ format_url
311
+ end
312
+ end
313
+
314
+ def html_urls_to_ping
315
+ urls_to_ping = []
316
+ html_urls.delete_if { |url| already_ping?(url) }.uniq.each do |url_to_ping|
317
+ urls_to_ping << pings.build('url' => url_to_ping)
318
+ end
319
+ urls_to_ping
320
+ end
321
+ end
@@ -0,0 +1,290 @@
1
+ # The Blog class represents the one and only blog. It stores most
2
+ # configuration settings and is linked to most of the assorted content
3
+ # classes via has_many.
4
+ #
5
+ # Once upon a time, there were plans to make publify handle multiple blogs,
6
+ # but it never happened and publify is now firmly single-blog.
7
+ #
8
+ class Blog < ActiveRecord::Base
9
+ include ConfigManager
10
+ include Rails.application.routes.url_helpers
11
+
12
+ has_many :contents
13
+ has_many :articles
14
+ has_many :feedback, through: :articles
15
+
16
+ has_many(:published_articles,
17
+ ->() { includes(:tags).where(published: true).order('contents.published_at DESC') },
18
+ class_name: 'Article')
19
+
20
+ has_many :pages
21
+ has_many :tags
22
+ has_many :notes
23
+
24
+ has_many :redirects
25
+ has_many :sidebars, ->() { order('active_position ASC') }
26
+
27
+ attr_accessor :custom_permalink
28
+
29
+ default_scope -> { order('id') }
30
+
31
+ validates :blog_name, presence: true
32
+
33
+ serialize :settings, Hash
34
+
35
+ # Description
36
+ setting :blog_name, :string, 'My Shiny Weblog!'
37
+ setting :blog_subtitle, :string, ''
38
+ setting :geourl_location, :string, ''
39
+ setting :canonical_server_url, :string, '' # Deprecated
40
+ setting :lang, :string, 'en_US'
41
+ setting :title_prefix, :integer, 0 # Deprecated but needed for a migration
42
+
43
+ # Spam
44
+ setting :sp_global, :boolean, false
45
+ setting :sp_article_auto_close, :integer, 0
46
+ setting :sp_url_limit, :integer, 0
47
+ setting :sp_akismet_key, :string, ''
48
+ setting :use_recaptcha, :boolean, false
49
+
50
+ # Mostly Behaviour
51
+ setting :text_filter, :string, 'markdown smartypants'
52
+ setting :comment_text_filter, :string, 'markdown smartypants'
53
+ setting :limit_article_display, :integer, 10
54
+ setting :limit_archives_display, :integer, 20
55
+ setting :limit_rss_display, :integer, 10
56
+ setting :default_allow_pings, :boolean, false
57
+ setting :default_allow_comments, :boolean, true
58
+ setting :default_moderate_comments, :boolean, false
59
+ setting :link_to_author, :boolean, false
60
+ setting :show_extended_on_rss, :boolean, true # deprecated but still needed for backward compatibility
61
+ setting :hide_extended_on_rss, :boolean, false
62
+ setting :theme, :string, 'plain'
63
+ setting :plugin_avatar, :string, ''
64
+ setting :global_pings_disable, :boolean, false
65
+ setting :ping_urls, :string, "http://blogsearch.google.com/ping/RPC2\nhttp://rpc.technorati.com/rpc/ping\nhttp://ping.blo.gs/\nhttp://rpc.weblogs.com/RPC2"
66
+ setting :send_outbound_pings, :boolean, true
67
+ setting :email_from, :string, 'publify@example.com'
68
+ setting :allow_signup, :integer, 0
69
+ setting :date_format, :string, '%d/%m/%Y'
70
+ setting :time_format, :string, '%Hh%M'
71
+ setting :image_avatar_size, :integer, 48
72
+ setting :image_thumb_size, :integer, 125
73
+ setting :image_medium_size, :integer, 600
74
+
75
+ # SEO
76
+ setting :meta_description, :string, ''
77
+ setting :meta_keywords, :string, ''
78
+ setting :google_analytics, :string, ''
79
+ setting :feedburner_url, :string, ''
80
+ setting :rss_description, :boolean, false
81
+ setting :rss_description_text, :string, <<EOS
82
+ <hr />
83
+ <p><small>Original article written by %author% and published on <a href='%blog_url%'>%blog_name%</a>
84
+ | <a href='%permalink_url%'>direct link to this article</a>
85
+ | If you are reading this article anywhere other than on <a href='%blog_url%'>%blog_name%</a>,
86
+ it has been illegally reproduced and without proper authorization.</small></p>
87
+ EOS
88
+ setting :permalink_format, :string, '/%year%/%month%/%day%/%title%'
89
+ setting :robots, :string, 'User-agent: *\nAllow: /\nDisallow: /admin\n'
90
+ setting :humans, :string, <<EOS
91
+ /* TEAM */
92
+ Your title: Your name.
93
+ Site: email, link to a contact form, etc.
94
+ Twitter: your Twitter username.
95
+
96
+ /* SITE */
97
+ Software: Publify [http://publify.co] #{PublifyCore::VERSION}
98
+ EOS
99
+ setting :index_categories, :boolean, true # deprecated but still needed for backward compatibility
100
+ setting :unindex_categories, :boolean, false
101
+ setting :index_tags, :boolean, true # deprecated but still needed for backward compatibility
102
+ setting :unindex_tags, :boolean, false
103
+ setting :admin_display_elements, :integer, 10
104
+ setting :google_verification, :string, ''
105
+ setting :nofollowify, :boolean, true # deprecated but still needed for backward compatibility
106
+ setting :dofollowify, :boolean, false
107
+ setting :use_canonical_url, :boolean, false
108
+ setting :use_meta_keyword, :boolean, true
109
+ setting :home_title_template, :string, '%blog_name% | %blog_subtitle%' # spec OK
110
+ setting :home_desc_template, :string, '%blog_name% | %blog_subtitle% | %meta_keywords%' # OK
111
+ setting :article_title_template, :string, '%title% | %blog_name%'
112
+ setting :article_desc_template, :string, '%excerpt%'
113
+ setting :page_title_template, :string, '%title% | %blog_name%'
114
+ setting :page_desc_template, :string, '%excerpt%'
115
+ setting :paginated_title_template, :string, '%blog_name% | %blog_subtitle% %page%'
116
+ setting :paginated_desc_template, :string, '%blog_name% | %blog_subtitle% | %meta_keywords% %page%'
117
+ setting :tag_title_template, :string, 'Tag: %name% | %blog_name% %page%'
118
+ setting :tag_desc_template, :string, '%name% | %blog_name% | %blog_subtitle% %page%'
119
+ setting :author_title_template, :string, '%author% | %blog_name%'
120
+ setting :author_desc_template, :string, '%author% | %blog_name% | %blog_subtitle%'
121
+ setting :archives_title_template, :string, 'Archives for %blog_name% %date% %page%'
122
+ setting :archives_desc_template, :string, 'Archives for %blog_name% %date% %page% %blog_subtitle%'
123
+ setting :search_title_template, :string, 'Results for %search% | %blog_name% %page%'
124
+ setting :search_desc_template, :string, 'Results for %search% | %blog_name% | %blog_subtitle% %page%'
125
+ setting :statuses_title_template, :string, 'Notes | %blog_name% %page%'
126
+ setting :statuses_desc_template, :string, 'Notes | %blog_name% | %blog_subtitle% %page%'
127
+ setting :status_title_template, :string, '%body% | %blog_name%'
128
+ setting :status_desc_template, :string, '%excerpt%'
129
+
130
+ setting :custom_tracking_field, :string, ''
131
+ # setting :meta_author_template, :string, "%blog_name% | %nickname%"
132
+
133
+ setting :twitter_consumer_key, :string, ''
134
+ setting :twitter_consumer_secret, :string, ''
135
+ setting :custom_url_shortener, :string, ''
136
+ setting :statuses_in_timeline, :boolean, true
137
+
138
+ validate :permalink_has_identifier
139
+ # validates :base_url, presence: true
140
+
141
+ # Find the Blog that matches a specific base URL. If no Blog object is found
142
+ # that matches, then grab the first blog. If *that* fails, then create a new
143
+ # Blog. The last case should only be used when Publify is first installed.
144
+ def self.find_blog(base_url)
145
+ Blog.find_by(base_url: base_url) || Blog.first || Blog.new
146
+ end
147
+
148
+ # In settings with :article_id
149
+ def ping_article!(settings)
150
+ unless global_pings_enabled? && settings.key?(:url) && settings.key?(:article_id)
151
+ throw :error, 'Invalid trackback or trackbacks not enabled'
152
+ end
153
+ article = Article.find(settings[:article_id])
154
+ throw :error, 'Trackback not saved' unless article.allow_pings?
155
+ article.trackbacks.create!(settings)
156
+ end
157
+
158
+ def global_pings_enabled?
159
+ !global_pings_disable?
160
+ end
161
+
162
+ # Check that all required blog settings have a value.
163
+ def configured?
164
+ settings.key?('blog_name')
165
+ end
166
+
167
+ # The +Theme+ object for the current theme.
168
+ def current_theme(reload = nil)
169
+ @current_theme = nil if reload
170
+ @current_theme ||= Theme.find(theme) || Theme.new('', '')
171
+ end
172
+
173
+ # Generate a URL based on the +base_url+. This allows us to generate URLs
174
+ # without needing a controller handy, so we can produce URLs from within models
175
+ # where appropriate.
176
+ #
177
+ # It also caches the result in the Rails cache, so repeated URL generation
178
+ # requests should be fast, as they bypass all of Rails' route logic.
179
+ def url_for_with_base_url(options = {}, extra_params = {})
180
+ case options
181
+ when String
182
+ url_generated = if extra_params[:only_path]
183
+ root_path
184
+ else
185
+ base_url
186
+ end
187
+ url_generated += "/#{options}" # They asked for 'url_for "/some/path"', so return it unedited.
188
+ url_generated += "##{extra_params[:anchor]}" if extra_params[:anchor]
189
+ url_generated
190
+ when Hash
191
+ merged_opts = options.reverse_merge!(only_path: false, controller: '',
192
+ action: 'permalink',
193
+ host: host_with_port,
194
+ script_name: root_path)
195
+ cache_key = merged_opts.values.prepend('blog-urlfor-withbaseurl').join('-')
196
+ unless Rails.cache.exist?(cache_key)
197
+ Rails.cache.write(cache_key, url_for_without_base_url(merged_opts))
198
+ end
199
+ Rails.cache.read(cache_key)
200
+ else
201
+ raise "Invalid URL in url_for: #{options.inspect}"
202
+ end
203
+ end
204
+
205
+ alias_method_chain :url_for, :base_url
206
+
207
+ # The URL for a static file.
208
+ # FIXME: Let carrierwave handle this by itself
209
+ def file_url(filename)
210
+ if CarrierWave.configure { |config| config.storage == CarrierWave::Storage::Fog }
211
+ filename
212
+ else
213
+ url_for "files/#{filename}", only_path: false
214
+ end
215
+ end
216
+
217
+ def articles_matching(query, args = {})
218
+ Article.search(query, args)
219
+ end
220
+
221
+ def per_page(format)
222
+ return limit_article_display if format.nil? || format == 'html'
223
+ limit_rss_display
224
+ end
225
+
226
+ def rss_limit_params
227
+ limit = limit_rss_display.to_i
228
+ if limit.zero?
229
+ {}
230
+ else
231
+ { limit: limit }
232
+ end
233
+ end
234
+
235
+ def permalink_has_identifier
236
+ unless permalink_format =~ /(%title%)/
237
+ errors.add(:base, I18n.t('errors.permalink_need_a_title'))
238
+ end
239
+
240
+ if permalink_format =~ /\.(atom|rss)$/
241
+ errors.add(:permalink_format, I18n.t('errors.cant_end_with_rss_or_atom'))
242
+ end
243
+ end
244
+
245
+ def root_path
246
+ split_base_url[:root_path]
247
+ end
248
+
249
+ def text_filter_object
250
+ TextFilter.find_or_default(text_filter)
251
+ end
252
+
253
+ def urls_to_ping_for(article)
254
+ urls_to_ping = []
255
+ ping_urls.gsub(/ +/, '').split(/[\n\r]+/).map(&:strip).delete_if { |u| article.already_ping?(u) }.uniq.each do |url|
256
+ urls_to_ping << article.pings.build('url' => url)
257
+ end
258
+ urls_to_ping
259
+ end
260
+
261
+ def has_twitter_configured?
262
+ return false if twitter_consumer_key.nil? || twitter_consumer_secret.nil?
263
+ return false if twitter_consumer_key.empty? || twitter_consumer_secret.empty?
264
+ true
265
+ end
266
+
267
+ def allow_signup?
268
+ allow_signup == 1
269
+ end
270
+
271
+ def shortener_url
272
+ custom_url_shortener.present? ? custom_url_shortener : base_url
273
+ end
274
+
275
+ private
276
+
277
+ def host_with_port
278
+ split_base_url[:host_with_port]
279
+ end
280
+
281
+ def split_base_url
282
+ unless @split_base_url
283
+ unless base_url =~ /(https?):\/\/([^\/]*)(.*)/
284
+ raise "Invalid base_url: #{base_url}"
285
+ end
286
+ @split_base_url = { protocol: Regexp.last_match[1], host_with_port: Regexp.last_match[2], root_path: Regexp.last_match[3].gsub(%r{/$}, '') }
287
+ end
288
+ @split_base_url
289
+ end
290
+ end
@@ -0,0 +1,86 @@
1
+ class BlogSweeper < ActionController::Caching::Sweeper
2
+ observe Blog, User, Article, Page, Comment, Trackback, Note, Tag
3
+
4
+ def pending_sweeps
5
+ @pending_sweeps ||= Set.new
6
+ end
7
+
8
+ def run_pending_page_sweeps
9
+ pending_sweeps.each do |each|
10
+ send(each)
11
+ end
12
+ end
13
+
14
+ def after_comments_create
15
+ expire_for(controller.send(:instance_variable_get, :@comment))
16
+ end
17
+
18
+ alias after_comments_update after_comments_create
19
+ alias after_articles_comment after_comments_create
20
+
21
+ def after_comments_destroy
22
+ expire_for(controller.send(:instance_variable_get, :@comment), true)
23
+ end
24
+
25
+ alias after_articles_nuke_comment after_comments_destroy
26
+
27
+ def after_articles_trackback
28
+ expire_for(controller.send(:instance_variable_get, :@trackback))
29
+ end
30
+
31
+ def after_articles_nuke_trackback
32
+ expire_for(controller.send(:instance_variable_get, :@trackback), true)
33
+ end
34
+
35
+ def after_save(record)
36
+ expire_for(record) unless record.is_a?(Article) && record.state == :draft
37
+ end
38
+
39
+ def after_destroy(record)
40
+ expire_for(record, true)
41
+ end
42
+
43
+ # TODO: Simplify this. Almost every sweep amounts to a sweep_all.
44
+ def expire_for(record, destroying = false)
45
+ case record
46
+ when Page
47
+ pending_sweeps << :sweep_pages
48
+ when Content
49
+ if record.invalidates_cache?(destroying)
50
+ pending_sweeps << :sweep_articles << :sweep_pages
51
+ end
52
+ when Tag
53
+ pending_sweeps << :sweep_articles << :sweep_pages
54
+ when Blog, User, Comment, Trackback
55
+ pending_sweeps << :sweep_all << :sweep_theme
56
+ end
57
+ run_pending_page_sweeps unless controller
58
+ end
59
+
60
+ def sweep_all
61
+ PageCache.sweep_all
62
+ end
63
+
64
+ def sweep_theme
65
+ PageCache.sweep_theme_cache
66
+ end
67
+
68
+ def sweep_articles
69
+ PageCache.sweep_all
70
+ end
71
+
72
+ def sweep_pages
73
+ PageCache.zap_pages(%w(pages))
74
+ end
75
+
76
+ def logger
77
+ @logger ||= ::Rails.logger || Logger.new(STDERR)
78
+ end
79
+
80
+ private
81
+
82
+ def callback(timing)
83
+ super
84
+ run_pending_page_sweeps if timing == :after
85
+ end
86
+ end