Plugin::Instance
These methods are available for use within plugin.rb
:
activate!()
note, we need to be able to parse separately to activation. this allows us to present information about a plugin in the UI prior to activations
add_admin_route(label, location, opts = {})
add_api_key_scope(resource, action)
Register a new API key scope.
Example: add_api_key_scope
(:groups, { delete: { actions: %w, params: %i } })
This scope lets you add members to a group. Additionally, you can specify which group ids are allowed. The delete action is added to the groups resource.
add_api_parameter_route(methods: nil, actions: nil, formats: nil)
Register a route which can be authenticated using an api key or user api key in a query parameter rather than a header. For example:
methods: :get,
actions: "users#bookmarks",
formats: :ics
)
See Auth::DefaultCurrentUserProvider::PARAMETER_API_PATTERNS for more examples and Auth::DefaultCurrentUserProvider#api_parameter_allowed? for implementation
add_body_class(class_name)
Applies to all sites in a multisite environment. Ignores plugin.enabled?
add_class_method(klass_name, attr, &block)
Adds a class method to a class, respecting if plugin is enabled
add_custom_reviewable_filter(filter)
Receives an array with two elements:
A symbol that represents the name of the value to filter.
A Proc that takes the existing ActiveRecord::Relation and the value received from the front-end.
add_directory_column(column_name, query:, icon: nil)
add_model_callback(klass_name, callback, options = {}, &block)
add_permitted_post_create_param(name, type = :string)
Add a permitted_create_param to Post, respecting if the plugin is enabled
add_permitted_post_update_param(attribute, &block)
Add a permitted_update_param to Post, respecting if the plugin is enabled
add_permitted_reviewable_param(type, param)
add_post_revision_notifier_recipients(&block)
Allows to add additional user_ids to the list of people notified when doing a post revision
add_preloaded_group_custom_field(field)
Applies to all sites in a multisite environment. Ignores plugin.enabled?
add_preloaded_topic_list_custom_field(field)
Applies to all sites in a multisite environment. Ignores plugin.enabled?
add_report(name, &block)
Applies to all sites in a multisite environment. Ignores plugin.enabled?
add_reviewable_score_link(reason, setting_name)
Register a ReviewableScore setting_name associated with a reason. We’ll use this to build a site setting link and add it to the reason’s translation.
If your plugin has a reason translation looking like this:
my_plugin_reason: "This is the reason this post was flagged. See %{link}."
And you associate the reason with a setting:
add\_reviewable\_score\_link(:my\_plugin\_reason,'a\_plugin\_setting')
We’ll generate the following link and attach it to the translation:
<a href="/admin/site_settings/category/all_results?filter=a_plugin_setting">
a plugin setting
</a>
add_to_class(class_name, attr, &block)
Extend a class but check that the plugin is enabled for class methods use ‘add_class_method`
add_to_serializer( serializer, attr, deprecated_respect_plugin_enabled = nil, respect_plugin_enabled: true, include_condition: nil, &block )
add_topic_static_page(page, options = {}, &blk)
Allows customizing existing topic-backed static pages, like: faq, tos, privacy (see: StaticController) The block passed to this method has to return a SiteSetting name that contains a topic id.
add\_topic\_static\_page("faq")do|controller|current\_user&.locale=="pl"?"polish\_faq\_topic\_id":"faq\_topic\_id"end
You can also add new pages in a plugin, but remember to add a route, for example:
get"contact"=\>"static#show",id:"contact"
add_user_api_key_scope(scope_name, matcher_parameters)
Register a new UserApiKey scope, and its allowed routes. Scope will be prefixed with the (parameterized) plugin name followed by a colon.
For example, if discourse-awesome-plugin registered this:
add_user_api_key_scope
(:read_my_route,
methods: :get,
actions: "mycontroller#myaction",
formats: :ics,
params: :testparam
)
The scope registered would be ‘discourse-awesome-plugin:read_my_route`
Multiple matchers can be attached by supplying an array of parameter hashes
See UserApiKeyScope::SCOPES for more examples And lib/route_matcher.rb for the route matching logic
admin_js_asset_exists?()
after_initialize(&block)
allow_public_user_custom_field(field)
allow_staff_user_custom_field(field)
auth_provider(opts)
auto_generated_path()
automatic_assets()
commit_hash()
commit_url()
configurable?()
css_asset_exists?(target = nil)
custom_avatar_column(column)
delete_extra_automatic_assets(good_paths)
directory()
directory_name()
discourse_owned?()
enabled?()
enabled_site_setting(setting = nil)
ensure_directory(path)
extend_content_security_policy(extension)
extend_list_method(klass, method, new_attributes)
extra_js_asset_exists?()
gem(name, version, opts = {})
shotgun approach to gem loading, in future we need to hack bundler
to at least determine dependencies do not clash before loading
Additionally we want to support multiple ruby versions correctly and so on
This is a very rough initial implementation
generate_automatic_assets!()
will make sure all the assets this plugin needs are registered
git_repo()
hide_plugin()
humanized_name()
javascript_includes()
js_asset_exists?()
listen_for(event_name)
notify_after_initialize()
on(event_name, &block)
A proxy to ‘DiscourseEvent.on` which does nothing if the plugin is disabled
register_anonymous_cache_key(key, &block)
register_asset(file, opts = nil)
register_asset_filter(&blk)
Register a block to run when adding css and js assets Two arguments will be passed: (type, request) Type is :css or :js. ‘request` is an instance of Rack::Request When using this, make sure to consider the effect on AnonymousCache
register_bookmarkable(klass)
Register a class that implements [BaseBookmarkable], which represents another
- ActiveRecord::Model
that may be bookmarked via the [Bookmark] model’s
polymorphic association. The class handles create and destroy hooks, querying, and reminders among other things.
register_category_custom_field_type(name, type, max_length: nil)
Applies to all sites in a multisite environment. Ignores plugin.enabled?
register_color_scheme(name, colors)
register_css(style)
register_custom_filter_by_status(status, &block)
Allows to define custom “status:” filter. Example usage:
register\_custom\_filter\_by\_status("foobar")do|scope|scope.where("word\_count = 42")end
register_custom_html(hash)
register_demon_process(demon_class)
Register a new demon process to be forked by the Unicorn master. The demon_class should inherit from Demon::Base. With great power comes great responsibility - this method should be used with extreme caution. See ‘config/unicorn.conf.rb`.
register_editable_group_custom_field(field)
register_editable_topic_custom_field(field, staff_only: false)
register_editable_user_custom_field(field, staff_only: false)
register_email_notification_filter(&block)
Registers a new email notification filter. Notification is passed into block, and if all filters return ‘true`, the email notification will be sent.
register_email_poller(poller)
register_email_unsubscriber(type, unsubscriber)
Let plugin define custom unsubscribe keys, set custom instance variables on the ‘EmailController#unsubscribe` action, and describe what unsubscribing for that key does.
The method receives a class that inherits from ‘Email::BaseEmailUnsubscriber`. Take a look at it to know how to implement your child class.
In conjunction with this, you’ll have to:
- Register a new connector under app/views/connectors/unsubscribe_options.
We'll include the HTML inside the unsubscribe form, so you can add your fields using the
instance variables you set in the controller previously. When the form is submitted,
it sends the updated preferences to `EmailController#perform_unsubscribe`.
- Your code is responsible for creating the custom key by calling `UnsubscribeKey#create_key_for`.
register_emoji(name, url, group = Emoji::DEFAULT_GROUP)
register_group_custom_field_type(name, type, max_length: nil)
Applies to all sites in a multisite environment. Ignores plugin.enabled?
register_group_param(param)
Add a permitted_param to Group, respecting if the plugin is enabled Used in GroupsController#update and Admin::GroupsController#create
register_groups_callback_for_users_search_controller_action(callback, &block)
Add a custom callback for search to Group Callback is called in UsersController#search_users Block takes groups and optional current_user For example: plugin.register_groups_callback_for_users_search_controller_action(:admins_filter) do |groups, user|
groups.where(name:"admins")
end
register_hashtag_data_source(klass)
Used to register data sources for HashtagAutocompleteService to look up results based on a hashtag string.
@param {Class} klass - Must be a class that implements methods with the following signatures:
Roughly corresponding to a model, this is used as a unique
key for the datasource and is also used when allowing different
contexts to search for and lookup these types. The `category`
and `tag` types are registered by default.
def self.type
end
The FontAwesome icon to use for the data source in the search results
and cooked markdown.
def self.icon
end
@param {Guardian} guardian - Current user's guardian, used for permission-based filtering
@param {Array} slugs - An array of strings that represent slugs to search this type for,
e.g. category slugs.
@returns {Hash} A hash with the slug as the key and the URL of the record as the value.
def self.lookup(guardian, slugs)
end
@param {Guardian} guardian - Current user's guardian, used for permission-based filtering
@param {String} term - The search term used to filter results
@param {Integer} limit - The number of search results that should be returned by the query
@returns {Array} An Array of HashtagAutocompleteService::HashtagItem
def self.search(guardian, term, limit)
end
@param {Array} search_results - An array of HashtagAutocompleteService::HashtagItem to sort
@param {String} term - The search term which was used, which may help with sorting.
@returns {Array} An Array of HashtagAutocompleteService::HashtagItem
def self.search_sort(search_results, term)
end
@param {Guardian} guardian - Current user's guardian, used for permission-based filtering
@param {Integer} limit - The number of search results that should be returned by the query
@returns {Array} An Array of HashtagAutocompleteService::HashtagItem
def self.search_without_term(guardian, limit)
end
register_hashtag_type_priority_for_context(type, context, priority)
Used to set up the priority ordering of hashtag autocomplete results by type using HashtagAutocompleteService.
@param {String} type - Roughly corresponding to a model, can only be registered once
per context. The `category` and `tag` types are registered
for the `topic-composer` context by default in that priority order.
@param {String} context - The context in which the hashtag lookup or search is happening
in. For example, the Discourse composer context is `topic-composer`.
Different contexts may want to have different priority orderings
for certain types of hashtag result.
@param {Integer} priority - A number value for ordering type results when hashtag searches
or lookups occur. Priority is ordered by DESCENDING order.
register_html_builder(name, &block)
register_javascript(js)
register_locale(locale, opts = {})
@option opts [String] :name @option opts [String] :nativeName @option opts [String] :fallbackLocale @option opts [Hash] :plural
register_modifier(modifier_name, &blk)
register_notification_consolidation_plan(plan)
If your plugin creates notifications, and you’d like to consolidate/collapse similar ones, you’re in the right place. This method receives a plan object, which must be an instance of ‘Notifications::ConsolidateNotifications`.
Instead of using ‘Notification#create!, you should use
Notification#consolidate_or_save!`, which will automatically pick your plan and apply it, updating an already consolidated notification, consolidating multiple ones, or creating a regular one.
The rule object is quite complex. We strongly recommend you write tests to ensure your plugin consolidates notifications correctly.
Threshold and time window consolidation plan: github.com/discourse/discourse/blob/main/app/services/notifications/consolidate_notifications.rb
Create a new notification and delete previous versions plan: github.com/discourse/discourse/blob/main/app/services/notifications/delete_previous_notifications.rb
Base plans: github.com/discourse/discourse/blob/main/app/services/notifications/consolidation_planner.rb
register_post_action_notify_user_handler(handler)
Register a block that will be called when PostActionCreator is going to notify a user of a post action. If any of these handlers returns false the default PostCreator call will be skipped.
register_post_custom_field_type(name, type, max_length: nil)
Applies to all sites in a multisite environment. Ignores plugin.enabled?
register_post_stripper(&block)
We strip posts before detecting mentions, oneboxes, attachments etc. We strip those elements that shouldn’t be detected. For example, a mention inside a quote should be ignored, so we strip it off. Using this API plugins can register their own post strippers.
register_preloaded_category_custom_fields(field)
Registers a category custom field to be loaded when rendering a category list Example usage:
register\_preloaded\_category\_custom\_fields("custom\_field")
register_presence_channel_prefix(prefix, &block)
Register a new PresenceChannel prefix. See {PresenceChannel.register_prefix} for usage instructions
register_problem_check(klass)
register_push_notification_filter(&block)
Registers a new push notification filter. User and notification payload are passed into block, and if all filters return ‘true`, the push notification will be sent.
register_reviewable_type(reviewable_type_class)
register_search_advanced_filter(trigger, &block)
Allows to define custom search filters. Example usage:
Search.advanced\_filter(/^min\_chars:(\d+)$/)do|posts,match|posts.where("(SELECT LENGTH(p2.raw) FROM posts p2 WHERE p2.id = posts.id) \>= ?",match.to\_i)end
register_search_advanced_order(trigger, &block)
Allows to define custom search order. Example usage:
Search.advanced\_order(:chars)do|posts|posts.reorder("(SELECT LENGTH(raw) FROM posts WHERE posts.topic\_id = subquery.topic\_id) DESC")end
register_search_group_query_callback(callback)
register_search_topic_eager_load(tables = nil, &block)
Allow to eager load additional tables in Search. Useful to avoid N+1 performance problems. Example usage:
register\_search\_topic\_eager\_loaddo|opts|%i(example\_table)end
OR
register\_search\_topic\_eager\_load(%i(example\_table))
register_seed_data(key, value)
register_seed_path_builder(&block)
register_seedfu_filter(filter = nil)
register_seedfu_fixtures(paths)
register_service_worker(file, opts = nil)
register_site_categories_callback(&block)
Register a callback to add custom payload to Site#categories Example usage:
register\_site\_categories\_callbackdo|categories|categories.eachdo|category|category[:some\_field] ='test'endend
register_stat(name, show_in_ui: false, expose_via_api: false, &block)
Allows the plugin to export additional site stats via the About class which will be shown on the /about route. The stats returned by the block should be in the following format (these four keys are required):
{
last_day: 1,
7_days: 10,
30_days: 100,
count: 1000
}
Only keys above will be shown on the /about page in the UI, but all stats will be shown on the /about.json route. For example take this usage:
register_stat
(“chat_messages”) do
{last\_day:1,"7\_days"=\>10,"30\_days"=\>100,count:1000,previous\_30\_days:150}
end
In the UI we will show a table like this:
| 24h | 7 days | 30 days | all time|
Chat Messages | 1 | 10 | 100 | 1000 |
But the JSON will be like this:
{
"chat_messages_last_day": 1,
"chat_messages_7_days": 10,
"chat_messages_30_days": 100,
"chat_messages_count": 1000,
}
The show_in_ui option (default false) is used to determine whether the group of stats is shown on the site About page in the Site Statistics table. Some stats may be needed purely for reporting purposes and thus do not need to be shown in the UI to admins/users.
register_summarization_strategy(strategy)
Register an object that inherits from [Summarization::Base], which provides a way to summarize content. Staff can select which strategy to use through the ‘summarization_strategy` setting.
register_svg_icon(icon)
register_topic_custom_field_type(name, type, max_length: nil)
Applies to all sites in a multisite environment. Ignores plugin.enabled?
register_topic_list_preload_user_ids(&block)
Allows to add more user IDs to the list of preloaded users. This can be useful to efficiently change the list of posters or participants. Example usage:
register\_topic\_list\_preload\_user\_idsdo|topics,user\_ids,topic\_list|user\_ids\<\<Discourse::SYSTEM\_USER\_IDend
register_topic_thumbnail_size(size)
Request a new size for topic thumbnails Will respect plugin enabled setting is enabled Size should be an array with two elements [max_width, max_height]
register_topic_view_posts_filter(trigger, &block)
Allows to define TopicView posts filters. Example usage:
TopicView.advanced\_filterdo|posts,opts|posts.where(wiki:true)end
register_upload_in_use(&block)
register_upload_unused(&block)
register_user_custom_field_type(name, type, max_length: nil)
Applies to all sites in a multisite environment. Ignores plugin.enabled?
register_user_destroyer_on_content_deletion_callback(callback)
Register a block that will be called when the UserDestroyer runs with the :delete_posts opt set to true. It’s important to note that the block will execute before any other :delete_posts actions, it allows us to manipulate flags before agreeing with them. For example, discourse-akismet makes use of this
@param {Block} callback to be called with the user, guardian, and the destroyer opts as arguments
replace_flags(settings: ::FlagSettings.new, score_type_names: []) { |settings, next_flag_id| ... }
Applies to all sites in a multisite environment. Ignores plugin.enabled?
rescue_from(exception, &block)
root_dir()
seed_data()
seed_fu_filter(filter = nil)
topic_view_post_custom_fields_allowlister(&block)
Add a post_custom_fields_allowlister block to the TopicView, respecting if the plugin is enabled
translate_emoji(from, to)
validate(klass, name, &block)
Add validation method but check that the plugin is enabled