publify_core 9.0.0.pre6 → 9.0.0

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 (176) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/README.md +9 -0
  4. data/app/controllers/admin/base_controller.rb +0 -6
  5. data/app/controllers/admin/content_controller.rb +34 -15
  6. data/app/controllers/admin/dashboard_controller.rb +4 -9
  7. data/app/controllers/admin/feedback_controller.rb +1 -0
  8. data/app/controllers/admin/notes_controller.rb +1 -1
  9. data/app/controllers/admin/pages_controller.rb +3 -7
  10. data/app/controllers/admin/sidebar_controller.rb +1 -0
  11. data/app/controllers/admin/tags_controller.rb +1 -0
  12. data/app/controllers/articles_controller.rb +50 -55
  13. data/app/controllers/comments_controller.rb +2 -3
  14. data/app/controllers/content_controller.rb +8 -17
  15. data/app/controllers/feedback_controller.rb +5 -39
  16. data/app/controllers/notes_controller.rb +1 -3
  17. data/app/controllers/setup_controller.rb +14 -18
  18. data/app/controllers/tags_controller.rb +13 -15
  19. data/app/controllers/theme_controller.rb +7 -5
  20. data/app/controllers/xml_controller.rb +11 -59
  21. data/app/helpers/authors_helper.rb +2 -2
  22. data/app/helpers/base_helper.rb +11 -4
  23. data/app/helpers/xml_helper.rb +2 -2
  24. data/app/jobs/application_job.rb +2 -0
  25. data/app/models/archives_sidebar.rb +8 -11
  26. data/app/models/article.rb +53 -72
  27. data/app/models/article/factory.rb +1 -1
  28. data/app/models/blog.rb +17 -40
  29. data/app/models/comment.rb +4 -3
  30. data/app/models/content.rb +18 -21
  31. data/app/models/content_base.rb +0 -5
  32. data/app/models/feedback.rb +76 -54
  33. data/app/models/meta_sidebar.rb +1 -0
  34. data/app/models/note.rb +7 -0
  35. data/app/models/page.rb +10 -5
  36. data/app/models/ping.rb +0 -113
  37. data/app/models/post_type.rb +1 -0
  38. data/app/models/redirect.rb +1 -1
  39. data/app/models/resource.rb +1 -19
  40. data/app/models/sidebar.rb +1 -1
  41. data/app/models/static_sidebar.rb +1 -0
  42. data/app/models/tag.rb +13 -9
  43. data/app/models/tag_sidebar.rb +4 -4
  44. data/app/models/trackback.rb +1 -8
  45. data/app/models/trigger.rb +1 -15
  46. data/app/models/user.rb +2 -9
  47. data/app/uploaders/resource_uploader.rb +33 -2
  48. data/app/views/accounts/confirm.html.erb +0 -1
  49. data/app/views/admin/content/_article_list.html.erb +1 -1
  50. data/app/views/admin/content/_form.html.erb +3 -7
  51. data/app/views/admin/pages/_form.html.erb +2 -2
  52. data/app/views/admin/seo/_general.html.erb +33 -28
  53. data/app/views/admin/seo/_permalinks.html.erb +2 -2
  54. data/app/views/admin/seo/_titles.html.erb +36 -36
  55. data/app/views/admin/settings/display.html.erb +20 -27
  56. data/app/views/admin/settings/feedback.html.erb +44 -51
  57. data/app/views/admin/settings/index.html.erb +14 -14
  58. data/app/views/admin/settings/write.html.erb +12 -30
  59. data/app/views/admin/tags/_index_and_form.html.erb +1 -1
  60. data/app/views/articles/_archives_article.html.erb +9 -0
  61. data/app/views/articles/_article.html.erb +8 -6
  62. data/app/views/articles/_article_collection.html.erb +1 -1
  63. data/app/views/articles/_article_excerpt.html.erb +10 -8
  64. data/app/views/articles/_article_links.html.erb +4 -2
  65. data/app/views/articles/_comment_list.html.erb +5 -5
  66. data/app/views/articles/_full_article_content.html.erb +4 -2
  67. data/app/views/articles/archives.html.erb +10 -20
  68. data/app/views/articles/feedback_atom_feed.atom.builder +5 -5
  69. data/app/views/articles/feedback_rss_feed.rss.builder +12 -13
  70. data/app/views/articles/index_atom_feed.atom.builder +3 -4
  71. data/app/views/articles/index_rss_feed.rss.builder +9 -10
  72. data/app/views/articles/read.html.erb +5 -31
  73. data/app/views/articles/search.html.erb +1 -1
  74. data/app/views/articles/trackback.xml.builder +1 -1
  75. data/app/views/authors/show.html.erb +11 -21
  76. data/app/views/authors/show_atom_feed.atom.builder +3 -4
  77. data/app/views/authors/show_rss_feed.rss.builder +9 -10
  78. data/app/views/comments/_comment.html.erb +17 -16
  79. data/app/views/feedback/index.atom.builder +7 -0
  80. data/app/views/feedback/index.rss.builder +19 -0
  81. data/app/views/notes/_note.html.erb +16 -15
  82. data/app/views/notes/index.html.erb +1 -1
  83. data/app/views/notification_mailer/_mail_footer.html.erb +0 -2
  84. data/app/views/notification_mailer/_mail_header.html.erb +2 -0
  85. data/app/views/notification_mailer/article.html.erb +4 -3
  86. data/app/views/notification_mailer/comment.html.erb +7 -6
  87. data/app/views/notification_mailer/notif_user.html.erb +3 -8
  88. data/app/views/setup/index.html.erb +4 -0
  89. data/app/views/shared/_atom_header.atom.builder +3 -3
  90. data/app/views/shared/_atom_item_article.atom.builder +26 -19
  91. data/app/views/shared/_atom_item_comment.atom.builder +3 -5
  92. data/app/views/shared/_atom_item_trackback.atom.builder +3 -4
  93. data/app/views/shared/_page_header.html.erb +1 -1
  94. data/app/views/shared/_rss_item_article.rss.builder +10 -15
  95. data/app/views/shared/_rss_item_comment.rss.builder +1 -2
  96. data/app/views/shared/_rss_item_trackback.rss.builder +1 -1
  97. data/app/views/tags/index.html.erb +2 -2
  98. data/app/views/xml/sitemap.googlesitemap.builder +7 -0
  99. data/config/initializers/mime_types.rb +0 -1
  100. data/config/locales/da.yml +8 -37
  101. data/config/locales/de.yml +7 -36
  102. data/config/locales/en.yml +7 -36
  103. data/config/locales/es-MX.yml +8 -37
  104. data/config/locales/fr.yml +7 -36
  105. data/config/locales/he.yml +4 -33
  106. data/config/locales/it.yml +7 -36
  107. data/config/locales/ja.yml +5 -34
  108. data/config/locales/lt.yml +7 -36
  109. data/config/locales/nb-NO.yml +7 -36
  110. data/config/locales/nl.yml +9 -38
  111. data/config/locales/pl.yml +8 -37
  112. data/config/locales/pt-BR.yml +8 -37
  113. data/config/locales/ro.yml +9 -38
  114. data/config/locales/ru.yml +7 -36
  115. data/config/locales/zh-CN.yml +6 -35
  116. data/config/locales/zh-TW.yml +7 -36
  117. data/config/routes.rb +6 -28
  118. data/db/migrate/113_initial_schema.rb +191 -191
  119. data/db/migrate/114_fixes_buggy_articles_and_notes.rb +6 -7
  120. data/db/migrate/115_drops_categories_for_tags.rb +3 -3
  121. data/db/migrate/20150207131657_add_missing_indexes.rb +1 -1
  122. data/db/migrate/20150807134129_simplify_redirect_relations.rb +1 -1
  123. data/db/migrate/20150808052637_add_blog_ids.rb +3 -5
  124. data/db/migrate/20150808191127_add_blog_id_to_redirects.rb +1 -1
  125. data/db/migrate/20150810094754_add_blog_id_to_tags.rb +1 -1
  126. data/db/migrate/20160108111120_add_devise_to_users.rb +3 -3
  127. data/db/migrate/20160108184201_move_last_connection_to_last_sign_in_at.rb +1 -1
  128. data/db/migrate/20160110094906_remove_profiles_rights.rb +1 -1
  129. data/db/migrate/20160605103918_replace_profile_id_with_string.rb +1 -3
  130. data/db/migrate/20160605154632_remove_profiles.rb +2 -2
  131. data/db/migrate/20160701061851_demand_blog_id_on_contents.rb +1 -1
  132. data/db/migrate/20160701062604_add_blog_id_to_resources.rb +1 -1
  133. data/db/migrate/20170528093024_move_resources_to_content.rb +5 -0
  134. data/db/migrate/20170528094923_move_tags_to_content.rb +6 -0
  135. data/db/migrate/20170528201606_remove_separate_published_flag.rb +5 -0
  136. data/db/migrate/20170605071626_remove_extra_state_columns_from_feedback.rb +6 -0
  137. data/db/migrate/20170702105201_remove_published_at_from_feedback.rb +5 -0
  138. data/db/seeds.rb +1 -1
  139. data/lib/publify_core.rb +0 -1
  140. data/lib/publify_core/version.rb +1 -1
  141. data/lib/publify_guid.rb +1 -1
  142. data/lib/publify_time.rb +2 -2
  143. data/lib/sidebar_field.rb +19 -12
  144. data/lib/transforms.rb +1 -0
  145. metadata +102 -66
  146. data/.gitignore +0 -13
  147. data/.rspec +0 -2
  148. data/.rubocop.yml +0 -84
  149. data/.rubocop_todo.yml +0 -148
  150. data/.travis.yml +0 -27
  151. data/Gemfile +0 -17
  152. data/README.rdoc +0 -3
  153. data/Rakefile +0 -35
  154. data/app/assets/stylesheets/publify_core/.keep +0 -0
  155. data/app/controllers/.keep +0 -0
  156. data/app/controllers/admin/migrations_controller.rb +0 -19
  157. data/app/controllers/concerns/.keep +0 -0
  158. data/app/controllers/trackbacks_controller.rb +0 -36
  159. data/app/helpers/.keep +0 -0
  160. data/app/mailers/.keep +0 -0
  161. data/app/models/.keep +0 -0
  162. data/app/models/article/states.rb +0 -179
  163. data/app/models/concerns/.keep +0 -0
  164. data/app/models/feedback/states.rb +0 -256
  165. data/app/services/migrator.rb +0 -25
  166. data/app/views/.keep +0 -0
  167. data/app/views/comments/index.html.erb +0 -1
  168. data/app/views/comments/index_atom_feed.atom.builder +0 -8
  169. data/app/views/comments/index_rss_feed.rss.builder +0 -20
  170. data/app/views/trackbacks/index_atom_feed.atom.builder +0 -7
  171. data/app/views/trackbacks/index_rss_feed.rss.builder +0 -20
  172. data/app/views/trackbacks/trackback.xml.builder +0 -4
  173. data/app/views/xml/feed.googlesitemap.builder +0 -7
  174. data/app/views/xml/rsd.rsd.builder +0 -8
  175. data/lib/stateful.rb +0 -106
  176. data/publify_core.gemspec +0 -54
@@ -1,4 +1,6 @@
1
1
  # coding: utf-8
2
+
3
+ require 'aasm'
2
4
  require 'uri'
3
5
  require 'net/http'
4
6
 
@@ -16,29 +18,24 @@ class Article < Content
16
18
  has_many :pings, dependent: :destroy
17
19
  has_many :trackbacks, dependent: :destroy
18
20
  has_many :feedback
19
- has_many :resources, inverse_of: :article, dependent: :nullify
20
21
  has_many :triggers, as: :pending_item
21
22
  has_many :comments, dependent: :destroy
22
23
 
23
- has_and_belongs_to_many :tags, join_table: 'articles_tags'
24
-
25
24
  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
25
+ before_save :set_permalink
26
+ after_save :keywords_to_tags, :shorten_url
30
27
 
31
- scope :drafts, -> { where(state: 'draft').order('created_at DESC') }
32
28
  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') }
29
+ scope :published_since, ->(time) {
30
+ published.where('published_at > ?', time).order(default_order)
31
+ }
32
+ scope :withdrawn, -> { where(state: 'withdrawn').order(default_order) }
33
+ scope :pending, -> { where(state: 'publication_pending'). order(default_order) }
37
34
 
38
35
  scope :bestof, lambda {
39
36
  joins(:feedback).
40
- where('feedback.published' => true, 'feedback.type' => 'Comment',
41
- 'contents.published' => true).
37
+ where('feedback.type' => 'Comment',
38
+ 'contents.state' => 'published').
42
39
  group('contents.id').
43
40
  order('count(feedback.id) DESC').
44
41
  select('contents.*, count(feedback.id) as comment_count').
@@ -49,19 +46,41 @@ class Article < Content
49
46
 
50
47
  attr_accessor :draft, :keywords
51
48
 
52
- include Article::States
49
+ include AASM
50
+
51
+ aasm column: :state do
52
+ state :draft, initial: true
53
+ # TODO: Disallow if published_at in past
54
+ state :publication_pending, after_enter: :trigger_publication
55
+ state :published, after_enter: :really_send_notifications
56
+ state :withdrawn
57
+
58
+ event :withdraw do
59
+ transitions from: :published, to: :withdrawn
60
+ transitions from: :publication_pending, to: :draft
61
+ end
62
+
63
+ event :publish do
64
+ before do
65
+ self.published_at ||= Time.zone.now
66
+ end
67
+
68
+ transitions from: [:new, :draft], to: :publication_pending do
69
+ guard do
70
+ published_at > Time.zone.now
71
+ end
72
+ end
53
73
 
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?])
74
+ transitions from: [:new, :draft, :publication_pending], to: :published do
75
+ guard do
76
+ published_at <= Time.zone.now
77
+ end
78
+ end
79
+ end
80
+ end
62
81
 
63
82
  def set_permalink
64
- return if state == 'draft' || permalink.present?
83
+ return if draft? || permalink.present?
65
84
  self.permalink = title.to_permalink
66
85
  end
67
86
 
@@ -93,6 +112,7 @@ class Article < Content
93
112
 
94
113
  # FIXME: Use keyword params to clean up call sites.
95
114
  def permalink_url(anchor = nil, only_path = false)
115
+ return unless published?
96
116
  @cached_permalink_url ||= {}
97
117
  @cached_permalink_url["#{anchor}#{only_path}"] ||= blog.url_for(permalink_url_options, anchor: anchor, only_path: only_path)
98
118
  end
@@ -106,10 +126,6 @@ class Article < Content
106
126
  resources.create!(upload: file, blog: blog)
107
127
  end
108
128
 
109
- def trackback_url
110
- blog.url_for("trackbacks?article_id=#{id}", only_path: false)
111
- end
112
-
113
129
  def comment_url
114
130
  blog.url_for("comments?article_id=#{id}", only_path: true)
115
131
  end
@@ -122,30 +138,6 @@ class Article < Content
122
138
  "#{permalink_url}.#{format.gsub(/\d/, '')}"
123
139
  end
124
140
 
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
141
  def next
150
142
  Article.where('published_at > ?', published_at).order('published_at asc').limit(1).first
151
143
  end
@@ -154,9 +146,13 @@ class Article < Content
154
146
  Article.where('published_at < ?', published_at).order('published_at desc').limit(1).first
155
147
  end
156
148
 
149
+ def publication_month
150
+ published_at.strftime('%Y-%m')
151
+ end
152
+
157
153
  def self.publication_months
158
154
  result = select('published_at').where('published_at is not NULL').where(type: 'Article')
159
- result.map { |d| [d.published_at.strftime('%Y-%m')] }.uniq
155
+ result.map { |it| [it.publication_month] }.uniq
160
156
  end
161
157
 
162
158
  # Finds one article which was posted on a certain date and matches the supplied dashed-title
@@ -251,7 +247,7 @@ class Article < Content
251
247
  end
252
248
 
253
249
  def password_protected?
254
- !password.blank?
250
+ password.present?
255
251
  end
256
252
 
257
253
  def add_comment(params)
@@ -262,10 +258,6 @@ class Article < Content
262
258
  user.admin? || user_id == user.id
263
259
  end
264
260
 
265
- def already_ping?(url)
266
- pings.map(&:url).include?(url)
267
- end
268
-
269
261
  def allow_comments?
270
262
  return allow_comments unless allow_comments.nil?
271
263
  blog.default_allow_comments
@@ -288,14 +280,6 @@ class Article < Content
288
280
  feedback.published.oldest_first
289
281
  end
290
282
 
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
283
  private
300
284
 
301
285
  def permalink_url_options
@@ -311,11 +295,8 @@ class Article < Content
311
295
  end
312
296
  end
313
297
 
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
298
+ def trigger_publication
299
+ # TODO: Skip if already published, update when published_at changes
300
+ Trigger.post_action(published_at, self, 'publish!')
320
301
  end
321
302
  end
@@ -11,7 +11,7 @@ class Article::Factory
11
11
  art.allow_comments = blog.default_allow_comments
12
12
  art.allow_pings = blog.default_allow_pings
13
13
  art.text_filter = user.default_text_filter
14
- art.published = true
14
+ art.state = 'draft'
15
15
  end
16
16
  end
17
17
 
data/app/models/blog.rb CHANGED
@@ -13,9 +13,7 @@ class Blog < ActiveRecord::Base
13
13
  has_many :articles
14
14
  has_many :feedback, through: :articles
15
15
 
16
- has_many(:published_articles,
17
- ->() { includes(:tags).where(published: true).order('contents.published_at DESC') },
18
- class_name: 'Article')
16
+ has_many :published_articles, ->() { published }, class_name: 'Article'
19
17
 
20
18
  has_many :pages
21
19
  has_many :tags
@@ -62,7 +60,6 @@ class Blog < ActiveRecord::Base
62
60
  setting :theme, :string, 'plain'
63
61
  setting :plugin_avatar, :string, ''
64
62
  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
63
  setting :send_outbound_pings, :boolean, true
67
64
  setting :email_from, :string, 'publify@example.com'
68
65
  setting :allow_signup, :integer, 0
@@ -76,25 +73,24 @@ class Blog < ActiveRecord::Base
76
73
  setting :meta_description, :string, ''
77
74
  setting :meta_keywords, :string, ''
78
75
  setting :google_analytics, :string, ''
79
- setting :feedburner_url, :string, ''
80
76
  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>
77
+ setting :rss_description_text, :string, <<EOS.strip_heredoc
78
+ <hr />
79
+ <p><small>Original article written by %author% and published on <a href='%blog_url%'>%blog_name%</a>
80
+ | <a href='%permalink_url%'>direct link to this article</a>
81
+ | If you are reading this article anywhere other than on <a href='%blog_url%'>%blog_name%</a>,
82
+ it has been illegally reproduced and without proper authorization.</small></p>
87
83
  EOS
88
84
  setting :permalink_format, :string, '/%year%/%month%/%day%/%title%'
89
85
  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}
86
+ setting :humans, :string, <<EOS.strip_heredoc
87
+ /* TEAM */
88
+ Your title: Your name.
89
+ Site: email, link to a contact form, etc.
90
+ Twitter: your Twitter username.
91
+
92
+ /* SITE */
93
+ Software: Publify [http://publify.co] #{PublifyCore::VERSION}
98
94
  EOS
99
95
  setting :index_categories, :boolean, true # deprecated but still needed for backward compatibility
100
96
  setting :unindex_categories, :boolean, false
@@ -145,16 +141,6 @@ EOS
145
141
  Blog.find_by(base_url: base_url) || Blog.first || Blog.new
146
142
  end
147
143
 
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
144
  def global_pings_enabled?
159
145
  !global_pings_disable?
160
146
  end
@@ -207,12 +193,11 @@ EOS
207
193
  prepend BasedUrlFor
208
194
 
209
195
  # The URL for a static file.
210
- # FIXME: Let carrierwave handle this by itself
211
196
  def file_url(filename)
212
- if CarrierWave.configure { |config| config.storage == CarrierWave::Storage::Fog }
197
+ if CarrierWave.configure { |config| config.storage.name == 'CarrierWave::Storage::Fog' }
213
198
  filename
214
199
  else
215
- url_for "files/#{filename}", only_path: false
200
+ url_for filename, only_path: false
216
201
  end
217
202
  end
218
203
 
@@ -252,14 +237,6 @@ EOS
252
237
  TextFilter.find_or_default(text_filter)
253
238
  end
254
239
 
255
- def urls_to_ping_for(article)
256
- urls_to_ping = []
257
- ping_urls.gsub(/ +/, '').split(/[\n\r]+/).map(&:strip).delete_if { |u| article.already_ping?(u) }.uniq.each do |url|
258
- urls_to_ping << article.pings.build('url' => url)
259
- end
260
- urls_to_ping
261
- end
262
-
263
240
  def has_twitter_configured?
264
241
  return false if twitter_consumer_key.nil? || twitter_consumer_secret.nil?
265
242
  return false if twitter_consumer_key.empty? || twitter_consumer_secret.empty?
@@ -1,4 +1,3 @@
1
- require_dependency 'spam_protection'
2
1
  require 'timeout'
3
2
 
4
3
  class Comment < Feedback
@@ -6,8 +5,6 @@ class Comment < Feedback
6
5
  content_fields :body
7
6
  validates :author, :body, presence: true
8
7
 
9
- after_save :send_notifications
10
-
11
8
  attr_accessor :referrer, :permalink
12
9
 
13
10
  scope :spam, -> { where(state: 'spam') }
@@ -35,6 +32,10 @@ class Comment < Feedback
35
32
  "Comment on #{article.title} by #{author}"
36
33
  end
37
34
 
35
+ def send_notifications
36
+ really_send_notifications
37
+ end
38
+
38
39
  protected
39
40
 
40
41
  def article_allows_feedback?
@@ -2,12 +2,10 @@ require 'set'
2
2
  require 'uri'
3
3
 
4
4
  class Content < ActiveRecord::Base
5
- include Stateful
6
-
7
5
  include ContentBase
8
6
 
9
7
  belongs_to :text_filter, optional: true
10
- belongs_to :user, optional: true
8
+ belongs_to :user, optional: true, touch: true
11
9
  belongs_to :blog
12
10
 
13
11
  validates :blog, presence: true
@@ -15,19 +13,24 @@ class Content < ActiveRecord::Base
15
13
  has_one :redirect, dependent: :destroy, inverse_of: :contents
16
14
 
17
15
  has_many :triggers, as: :pending_item, dependent: :delete_all
16
+ has_many :resources, inverse_of: :content, dependent: :nullify
17
+ has_and_belongs_to_many :tags
18
18
 
19
19
  scope :user_id, ->(user_id) { where('user_id = ?', user_id) }
20
- scope :published, -> { where(published: true, published_at: Time.at(0)..Time.now).order('published_at DESC') }
21
- scope :published_at, ->(time_params) { published.where(published_at: PublifyTime.delta(*time_params)).order('published_at DESC') }
22
- scope :not_published, -> { where('published = ?', false) }
23
- scope :draft, -> { where('state = ?', 'draft') }
24
- scope :no_draft, -> { where('state <> ?', 'draft').order('published_at DESC') }
20
+ scope :published, -> { where(state: 'published'). order(default_order) }
21
+ scope :published_at, ->(time_params) {
22
+ published.
23
+ where(published_at: PublifyTime.delta(*time_params)).
24
+ order('published_at DESC')
25
+ }
26
+ scope :not_published, -> { where.not(state: 'published') }
27
+ scope :drafts, -> { where(state: 'draft').order('created_at DESC') }
28
+ scope :no_draft, -> { where.not(state: 'draft').order('published_at DESC') }
25
29
  scope :searchstring, lambda { |search_string|
26
30
  tokens = search_string.split(' ').map { |c| "%#{c.downcase}%" }
27
31
  where('state = ? AND ' + (['(LOWER(body) LIKE ? OR LOWER(extended) LIKE ? OR LOWER(title) LIKE ?)'] * tokens.size).join(' AND '),
28
32
  'published', *tokens.map { |token| [token] * 3 }.flatten)
29
33
  }
30
- scope :already_published, -> { where('published = ? AND published_at < ?', true, Time.now).order(default_order) }
31
34
 
32
35
  scope :published_at_like, ->(date_at) { where(published_at: PublifyTime.delta_like(date_at)) }
33
36
 
@@ -60,7 +63,7 @@ class Content < ActiveRecord::Base
60
63
  end
61
64
 
62
65
  def shorten_url
63
- return unless published
66
+ return unless published?
64
67
 
65
68
  if redirect.present?
66
69
  return if redirect.to_path == permalink_url
@@ -74,8 +77,9 @@ class Content < ActiveRecord::Base
74
77
  end
75
78
  end
76
79
 
77
- def self.find_already_published(_limit)
78
- where('published_at < ?', Time.now).limit(1000).order('created_at DESC')
80
+ # TODO: Inline this method
81
+ def self.find_already_published(limit)
82
+ published.limit(limit)
79
83
  end
80
84
 
81
85
  def self.search_with(params)
@@ -105,13 +109,8 @@ class Content < ActiveRecord::Base
105
109
  self[:whiteboard] ||= {}
106
110
  end
107
111
 
108
- def withdraw!
109
- withdraw
110
- save!
111
- end
112
-
113
112
  def link_to_author?
114
- !user.email.blank? && blog.link_to_author
113
+ user.email.present? && blog.link_to_author
115
114
  end
116
115
 
117
116
  def get_rss_description
@@ -127,8 +126,6 @@ class Content < ActiveRecord::Base
127
126
  end
128
127
 
129
128
  def short_url
130
- # Double check because of crappy data in my own old database
131
- return unless published && redirect.present?
132
- redirect.from_url
129
+ redirect.from_url if redirect.present?
133
130
  end
134
131
  end
@@ -64,11 +64,6 @@ module ContentBase
64
64
  (text.length > length ? '...' : '')
65
65
  end
66
66
 
67
- def publish!
68
- self.published = true
69
- save!
70
- end
71
-
72
67
  # The default text filter. Generally, this is the filter specified by blog.text_filter,
73
68
  # but comments may use a different default.
74
69
  def default_text_filter