Tag: function

  • Code Sweep: A Simple Approach to a Neater WordPress User List

    Code Sweep: A Simple Approach to a Neater WordPress User List

    Feel like clearing out your spam users? With the snippet below we can make your job much easier!

    /**
     * Adds a new column to the user management screen for displaying the number of comments.
     *
     * @param array $columns The existing columns in the user management screen.
     *
     * @return array The modified columns array with the new 'comments_count' column added.
     */
    function emrikol_add_comments_column( array $columns ): array {
    	$columns['comments_count'] = esc_html__( text: 'Comments', domain: 'default' );
    	return $columns;
    }
    add_filter( 'manage_users_columns', 'emrikol_add_comments_column' );
    
    /**
     * Displays the number of comments for a user in the custom column.
     *
     * @param string $output       The value to be displayed in the column.
     * @param string $column_name  The name of the custom column.
     * @param int    $user_id      The ID of the user.
     *
     * @return string              The updated value to be displayed in the column.
     */
    function emrikol_show_comments_count( string $output, string $column_name, int $user_id ): string {
    	if ( 'comments_count' == $column_name ) {
    		$args           = array(
    			'user_id' => $user_id,
    			'count'   => true,
    		);
    		$comments_count = get_comments( args: $args );
    		return number_format_i18n( number: $comments_count );
    	}
    
    	return $output;
    }
    add_action( 'manage_users_custom_column', 'emrikol_show_comments_count', 10, 3 );
    Code language: PHP (php)

    This will add a “Comments” count to the WordPress user list so you can easily determine which users you can delete:

    What a sad state this blarg is in…

  • Securing WordPress Plugins with more Plugins

    Securing WordPress Plugins with more Plugins

    I’ve written before about disabling plugin deactivation in WordPress, but I’ve finally used that knowledge in practice–on this site.

    The Problem

    Let’s say you’re going along your day, developing things, and fixing things, and making the world a better place when all of a sudden you get a call from a client that their website is broken!!  After a bit of panicking and digging around, it turns out that they’ve been “optimizing” things by disabling random, but critical, plugins on the site.

    The Solution

    One way that you might fix this is to not install the plugins via the WordPress UI and require() them either in the theme directory, or as an mu-plugin.  The downside with this is that you lose the ability to easily and auto-update the plugins (if you’re okay with that).  You also the ability to easily see what plugins are active and installed in the admin UI.

    The way I’ve got around this is to create this helper function inside an mu-plugin that allows the plugins to be installed and managed in the UI, but not disabled:

    <?php
    /**
     * Secures a plugin from accidental disabling in the UI.
     *
     * If a plugin is necessary for a site to function, it should not be disabled.
     * This functionc can also optionally "force" activate a plugin without having to
     * activate it in the plugin UI.  Forcing activation will cause it to skip all
     * core plugin activation hooks.
     *
     * @param string  $plugin              Plugin file to secure.
     * @param boolean $force_activation    Optional. Whether to force load the plugin. Default false.
     */
    function emrikol_secure_plugin( $plugin, $force_activation = false ) {
    	$proper_plugin_name = false;
    
    	// Match if properly named: wp-plugin (wp-plugin/wp-plugin.php).
    	if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin . '/' . $plugin . '.php' ) && is_file( WP_PLUGIN_DIR . '/' . $plugin . '/' . $plugin . '.php' ) ) {
    		$proper_plugin_name = $plugin . '/' . $plugin . '.php';
    	} else {
    		// Match if improperly named: wp-plugin/cool-plugin.php.
    		if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin ) && is_file( WP_PLUGIN_DIR . '/' . $plugin ) ) {
    			$proper_plugin_name = $plugin;
    		}
    	}
    
    	if ( false !== $proper_plugin_name ) {
    		if ( true === $force_activation ) {
    			// Always list the plugin as active.
    			add_filter( 'option_active_plugins', function( $active_plugins ) use ( $proper_plugin_name ) {
    				// Crappy hack to prevent infinite loops.  Surely there's a better way.
    				global $emrikol_is_updating_active_plugins;
    
    				if ( true === $emrikol_is_updating_active_plugins ) {
    					unset( $emrikol_is_updating_active_plugins );
    					return array_unique( $active_plugins );
    				}
    
    				if ( ! in_array( $proper_plugin_name, $active_plugins, true ) ) {
    					$active_plugins[]                   = $proper_plugin_name;
    					$emrikol_is_updating_active_plugins = true;
    
    					update_option( 'active_plugins', array_unique( $active_plugins ) );
    				}
    				return array_unique( $active_plugins );
    			}, 1000, 1 );
    		}
    
    		// Ensure the plugin doesn't get disabled somehow.
    		// TODO: Diff arrays.  Only run if the plugin is being removed.
    		add_filter( 'pre_update_option_active_plugins', function ( $active_plugins ) use ( $proper_plugin_name ) {
    			if ( ! in_array( $proper_plugin_name, $active_plugins, true ) ) {
    				$active_plugins[] = $proper_plugin_name;
    			}
    			return array_unique( $active_plugins );
    		}, 1000, 1 );
    
    		// Remove the disable button.
    		$plugin_basename = plugin_basename( $proper_plugin_name );
    		add_filter( "plugin_action_links_$plugin_basename", function( $links ) use ( $proper_plugin_name, $force_activation ) {
    			if ( isset( $links['deactivate'] ) ) {
    				$links['deactivate'] = sprintf(
    					'<span class="emrikol-secure-plugin wp-ui-text-primary">%s</span>',
    					$force_activation ? 'Plugin Activated via Theme Code' : 'Plugin Secured via Theme Code'
    				);
    			}
    			return $links;
    		}, 1000, 1 );
    	}
    }
    Code language: HTML, XML (xml)

    It’s not perfect, but it’s working for me right now.  Like, right now on this site as you’re reading this. I’ve added it as an mu-plugin like so:

    <?php
    require_once( plugin_dir_path( __FILE__ ) . 'emrikol-defaults/secure-plugins.php' );
    
    emrikol_secure_plugin( 'akismet' );
    emrikol_secure_plugin( 'amp' );
    emrikol_secure_plugin( 'jetpack' );
    emrikol_secure_plugin( 'wp-super-cache/wp-cache.php' );Code language: HTML, XML (xml)

    As you can see, this completely removes the “Deactivate” link in the UI:

    The emrikol_secure_plugin() function takes two arguments:

    • The plugin to secure.  This can either be the plugin slug (ex. jetpack) or the full plugin path if the plugin doesn’t follow standard naming conventions (wp-super-cache/wp-cache.php)
    • A boolean, defaults to false.  If it is true the plugin will be forced to activate without user intervention.  This can be used to activate a plugin on a new install without having to manually enable it in the UI or via WP-CLI
  • Disabling plugin deactivation in WordPress

    Disabling plugin deactivation in WordPress

    The problem came up recently about how to make sure plugins activated in the WordPress plugin UI don’t get deactivated if they are necessary for a site to function.  I thought that was an interesting thought puzzle worth spending 15 minutes on, so I came up with this function as a solution:

    function dt_force_plugin_active( $plugin ) {
    add_filter( 'pre_update_option_active_plugins', function ( $active_plugins ) use ( $plugin ) {
    // Match if properly named: wp-plugin (wp-plugin/wp-plugin.php).
    $proper_plugin_name = $plugin . '/' . $plugin . '.php';
    <pre><code>    if (
            file_exists( WP_PLUGIN_DIR . '/' . $proper_plugin_name )
            &amp;amp;&amp;amp; is_file( WP_PLUGIN_DIR . '/' . $proper_plugin_name )
            &amp;amp;&amp;amp; ! in_array( $proper_plugin_name, $active_plugins, true )
        ) {
            $active_plugins[] = $proper_plugin_name;
            return array_unique( $active_plugins );
        }
    
        // Match if improperly named: wp-plugin/cool-plugin.php.
        if (
            file_exists( WP_PLUGIN_DIR . '/' . $plugin )
            &amp;amp;&amp;amp; is_file( WP_PLUGIN_DIR . '/' . $plugin )
            &amp;amp;&amp;amp; ! in_array( $plugin, $active_plugins, true )
        ) {
            $active_plugins[] = $plugin;
            return array_unique( $active_plugins );
        }
    
        return array_unique( $active_plugins );
    }, 1000, 1 );Code language: PHP (php)

    Which can be activated in your theme’s functions.php like so:

    dt_force_plugin_active( 'akismet' ); or dt_force_plugin_active( 'wordpress-seo/wp-seo.php' );

    The only downside that I’ve seen so far is that you still get the Plugin deactivated. message in the admin notices.