Skip to content

Instantly share code, notes, and snippets.

@emfluenceindia
Last active June 10, 2025 12:31
Show Gist options
  • Save emfluenceindia/70028975a8b3a15b3fccb867b6213eb4 to your computer and use it in GitHub Desktop.
Save emfluenceindia/70028975a8b3a15b3fccb867b6213eb4 to your computer and use it in GitHub Desktop.
Allows administrators to disable comments on selected post types (e.g., Pages, custom post types).
=== Disable Comments by Type ===
Contributors: subrataemfluence
Requires at least: 6.5
Tested up to: 6.8.1
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Allows administrators to disable comments on selected post types (e.g., Pages, custom post types).
== Description ==
This simple plugin gives you the ability to enable or disable the comments section on your Pages, Posts, and Custom Post Types. When installed and activated the plugin creates an admin-menu under settings called "Disable Comments". On this page, you can choose for which post types you want comments to be enabled and which post types you do not, and you do not require to write a single line of code.
== Installation ==
Login to you dashboard and navigate to Plugins page. Click on Add Plugin. In the search box, type in "Disable Comments By Type". Once it appears, click on the Install button and Activate it.
<?php
/**
* Plugin Name: Disable Comments By Type
* Description: Allows administrators to disable comments on selected post types (e.g., Pages, custom post types).
* Version: 1.0.1
* Author: Subrata Sarkar
* Author URI: https://profiles.wordpress.org/subrataemfluence/
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: disable-comments-by-type
*/
// Exit if accessed directly to prevent direct file access.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class Disable_Comments_By_Type_Plugin
*
* Manages the functionality to disable comments on specific post types.
*/
class Disable_Comments_By_Type_Plugin {
/**
* Constructor.
* Initializes the plugin by hooking into WordPress actions.
*/
public function __construct() {
add_action( 'admin_menu', array( $this, 'disable_comments_by_type_add_plugin_admin_page' ) );
add_action( 'admin_init', array( $this, 'disable_comments_by_type_register_plugin_settings' ) );
// Hook to modify comments status for specific post types.
add_action( 'init', array( $this, 'disable_comments_by_type_disable_comments_on_selected_types' ) );
add_action( 'admin_init', array( $this, 'disable_comments_by_type_remove_comments_menu_items' ) );
add_filter( 'comments_open', array( $this, 'disable_comments_by_type_filter_comments_status' ), 10, 2 );
add_filter( 'pings_open', array( $this, 'disable_comments_by_type_filter_comments_status' ), 10, 2 );
add_filter( 'pre_option_default_comment_status', array( $this, 'disable_comments_by_type_always_close_comments_globally' ) );
add_filter( 'wp_count_comments', array( $this, 'disable_comments_by_type_hide_comments_count_on_dashboard' ) );
}
/**
* Adds the plugin's admin page to the WordPress admin menu.
* It will appear under the "Settings" menu.
*/
public function disable_comments_by_type_add_plugin_admin_page() {
add_options_page(
__( 'Disable Comments', 'disable-comments-by-type' ), // Page title
__( 'Disable Comments', 'disable-comments-by-type' ), // Menu title
'manage_options', // Capability required to access
'disable-comments-by-type', // Menu slug
array( $this, 'disable_comments_by_type_display_plugin_admin_page' ) // Callback function to render the page
);
}
/**
* Registers the plugin's settings using the WordPress Settings API.
* This handles saving and retrieving the selected post types.
*/
public function disable_comments_by_type_register_plugin_settings() {
// Register a setting group.
register_setting(
'disable_comments_by_type_options_group', // Option group name
'disable_comments_by_type_selected_post_types', // Option name for selected post types
array( $this, 'disable_comments_by_type_sanitize_selected_post_types' ) // Sanitization callback
);
// Add a settings section.
add_settings_section(
'disable_comments_by_type_main_section', // Section ID
__( 'Select Post Types to Disable Comments', 'disable-comments-by-type' ), // Section title
array( $this, 'disable_comments_by_type_section_callback' ), // Callback for section content
'disable-comments-by-type' // Page slug
);
// Add a settings field for selecting post types.
add_settings_field(
'disable_comments_by_type_field', // Field ID
__( 'Disable comments on:', 'disable-comments-by-type' ), // Field title (label)
array( $this, 'disable_comments_by_type_field_callback' ), // Callback to render the field
'disable-comments-by-type', // Page slug
'disable_comments_by_type_main_section' // Section ID
);
}
/**
* Callback function for the settings section.
* Displays a brief description.
*/
public function disable_comments_by_type_section_callback() {
echo '<p>' . esc_html__( 'Choose the post types for which you want to disable comments globally. Existing comments will be hidden.', 'disable-comments-by-type' ) . '</p>';
}
/**
* Callback function to render the post type selection checkboxes.
*/
public function disable_comments_by_type_field_callback() {
// Get all public post types.
$post_types = get_post_types( array( 'public' => true ), 'objects' );
// Get currently selected post types.
$selected_post_types = get_option( 'disable_comments_by_type_selected_post_types', array() );
if ( ! is_array( $selected_post_types ) ) {
$selected_post_types = array();
}
foreach ( $post_types as $post_type ) {
// Skip attachment post type as it often doesn't have comments in a meaningful way.
if ( 'attachment' === $post_type->name ) {
continue;
}
?>
<label>
<input
type="checkbox"
name="disable_comments_by_type_selected_post_types[]"
value="<?php echo esc_attr( $post_type->name ); ?>"
<?php checked( in_array( $post_type->name, $selected_post_types, true ), true ); ?>
/>
<?php echo esc_html( $post_type->labels->singular_name ); ?>
</label><br/>
<?php
}
}
/**
* Sanitizes the selected post types array.
*
* @param array $input The raw input array of selected post types.
* @return array Sanitized array of post type slugs.
*/
public function disable_comments_by_type_sanitize_selected_post_types( $input ) {
$sanitized_input = array();
if ( is_array( $input ) ) {
foreach ( $input as $post_type_slug ) {
// Ensure that the slug is a valid string.
$sanitized_input[] = sanitize_key( $post_type_slug );
}
}
return array_unique( $sanitized_input ); // Ensure no duplicate slugs.
}
/**
* Displays the main admin page for the plugin.
*/
public function disable_comments_by_type_display_plugin_admin_page() {
// Check user capabilities.
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<form action="options.php" method="post">
<?php
// Output security fields and the settings sections.
settings_fields( 'disable_comments_by_type_options_group' );
do_settings_sections( 'disable-comments-by-type' );
submit_button( __( 'Save Changes', 'disable-comments-by-type' ) );
?>
</form>
</div>
<?php
}
/**
* Disables comments on the selected post types.
* This modifies the 'comment_status' and 'ping_status' in the database directly
* for existing posts of the selected types.
*/
public function disable_comments_by_type_disable_comments_on_selected_types() {
$selected_post_types = get_option( 'disable_comments_by_type_selected_post_types', array() );
if ( empty( $selected_post_types ) ) {
return;
}
foreach ( $selected_post_types as $post_type ) {
// Remove comment support from the post type itself.
// This affects future posts and the "Discussion" meta box visibility.
remove_post_type_support( $post_type, 'comments' );
remove_post_type_support( $post_type, 'trackbacks' );
// Optionally, close existing comments.
// Be careful with this for large sites, as it can be resource-intensive.
// For a beginner plugin, we'll keep it simple by just hiding/filtering them.
// If you want to update existing comments, you'd need a separate mechanism,
// perhaps triggered on plugin activation or a dedicated button.
}
}
/**
* Filters 'comments_open' and 'pings_open' to always return false
* for selected post types. This hides the comment form.
*
* @param bool $open Whether comments are open.
* @param int $post_id The post ID.
* @return bool True if comments are open, false otherwise.
*/
public function disable_comments_by_type_filter_comments_status( $open, $post_id ) {
$selected_post_types = get_option( 'disable_comments_by_type_selected_post_types', array() );
if ( ! empty( $selected_post_types ) ) {
$post = get_post( $post_id );
if ( $post && in_array( $post->post_type, $selected_post_types, true ) ) {
return false; // Close comments.
}
}
return $open; // Return original status for other post types.
}
/**
* Remove 'Comments' from the admin menu and dashboard widgets if selected.
* This hides the entire comments section in the admin for a cleaner UI.
*/
public function disable_comments_by_type_remove_comments_menu_items() {
$selected_post_types = get_option( 'disable_comments_by_type_selected_post_types', array() );
$all_public_post_types = array_keys( get_post_types( array( 'public' => true ), 'objects' ) );
$all_comments_disabled = count( array_diff( $all_public_post_types, $selected_post_types ) ) === 0;
// If all public post types are selected (meaning comments are effectively disabled site-wide),
// or if 'post' and 'page' are selected, we can hide the global comments menu items.
// We'll simplify this for a beginner plugin: if 'post' and 'page' are selected, hide it.
// A more robust solution might check if ALL commentable post types are selected.
$is_post_disabled = in_array( 'post', $selected_post_types, true );
$is_page_disabled = in_array( 'page', $selected_post_types, true );
if ( $is_post_disabled && $is_page_disabled ) {
remove_menu_page( 'edit-comments.php' ); // Removes the main 'Comments' menu item.
remove_meta_box( 'dashboard_recent_comments', 'dashboard', 'normal' ); // Removes 'Recent Comments' dashboard widget.
}
}
/**
* Filters the default comment status for new posts/pages.
* This helps prevent comments on new content of selected types by default.
*
* @param string $status The default comment status ('open' or 'closed').
* @return string The filtered status.
*/
public function disable_comments_by_type_always_close_comments_globally( $status ) {
// This filter affects the *default* status when creating *any* new post type.
// It's more aggressive than disabling by specific type.
// For this plugin, it's safer to only rely on `remove_post_type_support`
// and `comments_open` filter, which are more specific to selected types.
// This filter is included here for completeness of "disabling comments",
// but its use should be considered carefully in a multi-purpose "disable comments" plugin.
// For this plugin, we will rely on it only if all relevant post types are selected.
$selected_post_types = get_option( 'disable_comments_by_type_selected_post_types', array() );
$all_public_commentable_types = get_post_types( array( 'public' => true, 'supports' => 'comments' ), 'objects' );
$all_default_commentable_types_disabled = true;
foreach ( $all_public_commentable_types as $type_obj ) {
if ( ! in_array( $type_obj->name, $selected_post_types, true ) ) {
$all_default_commentable_types_disabled = false;
break;
}
}
if ( $all_default_commentable_types_disabled && ! empty( $selected_post_types ) ) {
return 'closed';
}
return $status;
}
/**
* Hides the comments count on the dashboard if comments are mostly disabled.
* Prevents displaying comment counts from post types where comments are disabled.
*
* @param object $counts An array of comment counts.
* @return array Filtered comment counts.
*/
public function disable_comments_by_type_hide_comments_count_on_dashboard( $counts ) {
$selected_post_types = get_option( 'disable_comments_by_type_selected_post_types', array() );
if ( empty( $selected_post_types ) ) {
return $counts; // No types selected, return original counts.
}
// If 'post' and 'page' are selected, we assume most of the "active" comments are gone.
// This is a simplification for a beginner plugin. A more advanced solution
// would iterate through all comment types and only show counts for enabled ones.
$is_post_disabled = in_array( 'post', $selected_post_types, true );
$is_page_disabled = in_array( 'page', $selected_post_types, true );
if ( $is_post_disabled && $is_page_disabled ) {
// Set all counts to zero to effectively hide them.
foreach ( $counts as $key => $value ) {
$counts->$key = 0;
}
}
return $counts;
}
}
// Instantiate the plugin class to run it.
new Disable_Comments_By_Type_Plugin();
Build pluin readme file:
https://generatewp.com/plugin-readme/
WordPress Coding Standards (WPCS):
https://developer.wordpress.org/coding-standards/
Plugin Activation and Deactivation Hooks:
https://developer.wordpress.org/plugins/plugin-basics/activation-deactivation-hooks/
Plugin Submission Guideline:
https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/
Plugin Add Page (Must log in before uploading):
https://wordpress.org/plugins/developers/add/
Create a WordPress.org Account:
If you don't have one, go to https://wordpress.org/ and create an account. This username will be the one you put in the Contributors field of your readme.txt.
Review the Official Plugin Submission Guidelines (Again!):
This is the most critical step. Before submitting, read every word of the official guidelines. They are updated periodically, so always check the latest versions:
Plugin Developer FAQ
Detailed Plugin Guidelines
Pay particular attention to:
Prohibited Functionality: (e.g., spam, malicious code, hidden links, unconsented tracking, excessive advertising).
External Services and APIs: How to handle API keys, data privacy, and user consent.
Copyright, Licensing, and Trademark: Ensuring your plugin is GPL-compatible and respects existing trademarks.
Security & Data Privacy: Confirming your plugin adheres to WordPress's robust security standards and respects user data (e.g., GDPR considerations).
Commercialism: Rules around promoting premium versions or external products.
Submit Your Plugin:
Go to the "Add Your Plugin" page: https://wordpress.org/plugins/add/
Prepare your .zip file: Create a .zip archive of your entire plugin directory. Ensure that your main plugin file (e.g., my-awesome-plugin.php) and your readme.txt file are directly in the root of this .zip file (i.e., not inside an extra folder within the zip).
Fill out the form: Provide the required details, including your chosen plugin name and description.
Confirmation: After a successful submission, you will receive an email confirming receipt of your plugin and its pending review status.
Phase 3: Review Process & Initial Release
Wait for Review:
The WordPress Plugin Review Team is comprised of volunteers. The review time can vary greatly, from a few days to several weeks, depending on the current submission queue and the complexity/scope of your plugin. Be patient!
You'll typically receive an email when the review begins.
Address Review Feedback:
Expect Feedback: It's very common to receive feedback, questions, or requests for changes from the review team. This is a crucial part of the process designed to ensure plugin quality, security, and adherence to guidelines.
Respond Promptly & Respectfully: Read their feedback carefully. Make all the requested changes to your plugin's code and/or readme.txt. Reply to the reviewer's email clearly detailing how you've addressed each point. If you have questions or respectfully disagree with a point, ask for clarification. Don't take feedback personally; they are helping you make your plugin better and safer for the community.
Approval and SVN Access:
Once your plugin is approved, you'll receive an email granting you SVN (Subversion) access to your plugin's dedicated repository on WordPress.org. This SVN repository is the only way you will manage all future updates and releases for your plugin.
The email will provide your unique SVN repository URL (e.g., https://plugins.svn.wordpress.org/your-plugin-slug/).
Upload Your Plugin via SVN:
Install an SVN client: If you don't have one, you'll need to install a command-line SVN client (e.g., by using your OS package manager like sudo apt-get install subversion on Linux or via Homebrew on macOS) or a GUI client (e.g., TortoiseSVN on Windows, Versions on macOS).
Checkout the repository: Open your terminal or command prompt and navigate to a convenient location on your computer (e.g., your desktop or a development folder). Then, run:
svn co https://plugins.svn.wordpress.org/your-plugin-slug/ your-plugin-slug-svn
(Replace your-plugin-slug with your actual plugin's slug/folder name). This command creates a new local directory (e.g., your-plugin-slug-svn) containing the empty SVN repository structure (trunk, tags, assets folders).
Copy Your Plugin Files:
Navigate into the newly created your-plugin-slug-svn directory.
Copy all the files and subdirectories from your local plugin development directory (e.g., my-awesome-plugin/) into the trunk directory within your SVN checkout (your-plugin-slug-svn/trunk/).
Crucial: Exclude development-related files and directories like .git, node_modules, build/ (unless your build output is what you want to ship), .DS_Store, etc. Only include files necessary for the plugin to function.
Also copy your readme.txt and screenshot-*.png/.jpg files directly into the trunk directory.
Add Assets (Optional but Highly Recommended):
The assets folder within your SVN checkout (your-plugin-slug-svn/assets/) is where you'll place special media that appears on your plugin's public directory page.
Header Banner: banner-772x250.png or banner-1544x500.png (for retina displays).
Plugin Icon: icon-128x128.png or icon-256x256.png (for retina).
Copy these images to the assets folder.
Add (svn add) and Commit (svn commit):
Navigate into your your-plugin-slug-svn directory in your terminal.
Add all the new files and folders to SVN's tracking:
svn add trunk/*
svn add assets/*
# If you added new subdirectories:
svn add trunk --force # This command adds new files and directories recursively
Commit your changes to the repository:
svn commit -m "Initial commit of My Awesome Plugin version 1.0.0"
You will be prompted for your WordPress.org username and password.
Create a Tag (CRITICAL for Public Release):
This is the final step that makes your plugin visible and installable by users. The tag name must exactly match the Stable tag you specified in your readme.txt and the Version in your main plugin file.
From the your-plugin-slug-svn directory:
svn cp trunk tags/1.0.0
svn commit -m "Tagging version 1.0.0"
(Replace 1.0.0 with your actual version number).
Go Live!
After you commit the tag to SVN, the WordPress.org system will process it. Your plugin should appear in the WordPress Plugin Directory within a few minutes to an hour.
Check your plugin's dedicated page on WordPress.org (e.g., https://wordpress.org/plugins/your-plugin-slug/) to see it live!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment