DEV: API for plugins to add post update params and handlers (#12505)

DEV: API for plugins to add post update params and handlers (#12505)

diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb
index 19e42aa..7123851 100644
--- a/app/controllers/posts_controller.rb
+++ b/app/controllers/posts_controller.rb
@@ -208,6 +208,10 @@ class PostsController < ApplicationController
       edit_reason: params[:post][:edit_reason]
     }
 
+    Post.plugin_permitted_update_params.keys.each do |param|
+      changes[param] = params[:post][param]
+    end
+
     raw_old = params[:post][:raw_old]
     if raw_old.present? && raw_old != post.raw
       return render_json_error(I18n.t('edit_conflict'), status: 409)
diff --git a/app/models/post.rb b/app/models/post.rb
index 7bdc472..306bf38 100644
--- a/app/models/post.rb
+++ b/app/models/post.rb
@@ -15,8 +15,9 @@ class Post < ActiveRecord::Base
     "image_url" # TODO(2021-06-01): remove
   ]
 
-  cattr_accessor :plugin_permitted_create_params
+  cattr_accessor :plugin_permitted_create_params, :plugin_permitted_update_params
   self.plugin_permitted_create_params = {}
+  self.plugin_permitted_update_params = {}
 
   # increase this number to force a system wide post rebake
   # Recreate `index_for_rebake_old` when the number is increased
diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb
index cf27db7..6551987 100644
--- a/lib/plugin/instance.rb
+++ b/lib/plugin/instance.rb
@@ -337,6 +337,13 @@ class Plugin::Instance
     end
   end
 
+  # Add a permitted_update_param to Post, respecting if the plugin is enabled
+  def add_permitted_post_update_param(attribute, &block)
+    reloadable_patch do |plugin|
+      ::Post.plugin_permitted_update_params[attribute] = { plugin: plugin, handler: block }
+    end
+  end
+
   # Add validation method but check that the plugin is enabled
   def validate(klass, name, &block)
     klass = klass.to_s.classify.constantize
diff --git a/lib/post_revisor.rb b/lib/post_revisor.rb
index eab76c3..29989c0 100644
--- a/lib/post_revisor.rb
+++ b/lib/post_revisor.rb
@@ -143,6 +143,12 @@ class PostRevisor
     # previous reasons are lost
     @fields.delete(:edit_reason) if @fields[:edit_reason].blank?
 
+    Post.plugin_permitted_update_params.each do |field, val|
+      if @fields.key?(field) && val[:plugin].enabled?
+        val[:handler].call(@post, @fields[field])
+      end
+    end
+
     return false unless should_revise?
 
     @post.acting_user = @editor
diff --git a/spec/requests/posts_controller_spec.rb b/spec/requests/posts_controller_spec.rb
index 1d22435..bbda989 100644
--- a/spec/requests/posts_controller_spec.rb
+++ b/spec/requests/posts_controller_spec.rb
@@ -527,6 +527,34 @@ describe PostsController do
       expect(response.status).to eq(403)
       expect(post.topic.reload.category_id).not_to eq(category.id)
     end
+
+    describe "with Post.plugin_permitted_update_params" do
+      before do
+        plugin = Plugin::Instance.new
+        plugin.add_permitted_post_update_param(:random_number) do |post, value|
+          post.custom_fields[:random_number] = value
+          post.save
+        end
+      end
+
+      after do
+        DiscoursePluginRegistry.reset!
+      end
+
+      it "calls blocks passed into `add_permitted_post_update_param`" do
+        sign_in(post.user)
+        put "/posts/#{post.id}.json", params: {
+          post: {
+            raw: "this is a random post",
+            raw_old: post.raw,
+            random_number: 244
+          }
+        }
+
+        expect(response.status).to eq(200)
+        expect(post.reload.custom_fields[:random_number]).to eq("244")
+      end
+    end
   end
 
   describe "#destroy_bookmark" do

GitHub sha: 371afc45