From bed11dfa0e6319be5228687e78de4dacd92d3a93 Mon Sep 17 00:00:00 2001
From: Guo Xiang Tan <tgx_world@hotmail.com>
Date: Thu, 26 Jan 2017 13:29:43 +0800
Subject: [PATCH] FIX: Polls permanently broken if post requires approval.

---
 app/models/queued_post.rb                     |  2 +-
 plugins/poll/plugin.rb                        | 27 ++++++++++++--
 .../poll/spec/lib/new_post_manager_spec.rb    | 35 +++++++++++++++++++
 3 files changed, 61 insertions(+), 3 deletions(-)
 create mode 100644 plugins/poll/spec/lib/new_post_manager_spec.rb

diff --git a/app/models/queued_post.rb b/app/models/queued_post.rb
index 03db2e8001e..e1736c85488 100644
--- a/app/models/queued_post.rb
+++ b/app/models/queued_post.rb
@@ -78,7 +78,7 @@ class QueuedPost < ActiveRecord::Base
     # Do sidekiq work outside of the transaction
     creator.enqueue_jobs
 
-    DiscourseEvent.trigger(:approved_post, self)
+    DiscourseEvent.trigger(:approved_post, self, created_post)
     created_post
   end
 
diff --git a/plugins/poll/plugin.rb b/plugins/poll/plugin.rb
index 5a193b1ace9..026a2296827 100644
--- a/plugins/poll/plugin.rb
+++ b/plugins/poll/plugin.rb
@@ -247,11 +247,11 @@ after_initialize do
     end
   end
 
-  validate(:post, :validate_polls) do
+  validate(:post, :validate_polls) do |force=nil|
     return if !SiteSetting.poll_enabled? && (self.user && !self.user.staff?)
 
     # only care when raw has changed!
-    return unless self.raw_changed?
+    return unless self.raw_changed? || force
 
     validator = DiscoursePoll::PollsValidator.new(self)
     return unless (polls = validator.validate_polls)
@@ -268,6 +268,29 @@ after_initialize do
     true
   end
 
+  NewPostManager.add_handler(1) do |manager|
+    post = Post.new(raw: manager.args[:raw])
+
+    if !DiscoursePoll::PollsValidator.new(post).validate_polls
+      result = NewPostResult.new(:poll, false)
+
+      post.errors.full_messages.each do |message|
+        result.errors[:base] << message
+      end
+
+      result
+    else
+      manager.args["is_poll"] = true
+      nil
+    end
+  end
+
+  on(:approved_post) do |queued_post, created_post|
+    if queued_post.post_options["is_poll"]
+      created_post.validate_polls(true)
+    end
+  end
+
   Post.register_custom_field_type(DiscoursePoll::POLLS_CUSTOM_FIELD, :json)
   Post.register_custom_field_type(DiscoursePoll::VOTES_CUSTOM_FIELD, :json)
 
diff --git a/plugins/poll/spec/lib/new_post_manager_spec.rb b/plugins/poll/spec/lib/new_post_manager_spec.rb
new file mode 100644
index 00000000000..8f1a843d0bb
--- /dev/null
+++ b/plugins/poll/spec/lib/new_post_manager_spec.rb
@@ -0,0 +1,35 @@
+require 'rails_helper'
+
+describe NewPostManager do
+  let(:user) { Fabricate(:newuser) }
+  let(:admin) { Fabricate(:admin) }
+
+  describe 'when new post containing a poll is queued for approval' do
+    it 'should render the poll upon approval' do
+      params = {
+        raw: "[poll]\n* 1\n* 2\n* 3\n[/poll]",
+        archetype: "regular",
+        category: "",
+        typing_duration_msecs: "2700",
+        composer_open_duration_msecs: "12556",
+        visible: true,
+        image_sizes: nil,
+        is_warning: false,
+        title: "This is a test post with a poll",
+        ip_address: "127.0.0.1",
+        user_agent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
+        referrer: "http://localhost:3000/",
+        first_post_checks: true
+      }
+
+      expect { NewPostManager.new(user, params).perform }
+        .to change { QueuedPost.count }.by(1)
+
+      queued_post = QueuedPost.last
+      queued_post.approve!(admin)
+
+      expect(Post.last.custom_fields[DiscoursePoll::POLLS_CUSTOM_FIELD])
+        .to_not eq(nil)
+    end
+  end
+end