0

Consider a complex system made in WordPress with multiple roles and capabilities. Let's take a University website, for instance.

A University website could have a capability to post news to the home, another capability to manage content from a specific course, etc.

What is the best practice to keep roles and capabilities organized in a complex scenario?

0

Answering my own question, if your system is not performance-critical, you can use a plugin for it, such as User Role Editor:

roles and capabilities best practices wordpress

It supports multi-site, multiple roles per user and a lot more.

Optionally, If I were to write it:

If I would like to have total control over it and write my custom code, I would handle roles management in a plugin, to keep it organized and logically separated from the rest of the code.

The main advantage of this structure right now is to give a dedicated folder to Roles, keeping it organized, and providing a basic OOP structure to work with. This could be extended with methods to help assigning custom post types capabilities for instance, etc.

plugins/custom-roles-manager/custom-roles-manager.php

<?php
/*
 * Plugin Name:  Custom Roles Manager
 * Description:  This plugin handles roles capabilities.
 * Requires PHP: 5.3
 */
defined('ABSPATH') OR exit;

/** Runs only when the plugin is activated */
register_activation_hook(__FILE__, 'custom_roles_manager_activate');
function custom_roles_manager_activate()
{
    require_once(__DIR__ . '/RoleInterface.php');

    // This is the folder we add roles on
    $roles_folder = __DIR__ . '/roles';

    // If it throws anything, WordPress will automatically disable the plugin and show the notice
    $roles = crm_get_roles_in_folder($roles_folder);

    // Give developer a chance to filter the roles for any reason
    $roles = apply_filters('crm_get_roles', $roles);

    foreach ($roles as $role) {
        // Filter might add $role that does not implement RoleInterface
        if ($role instanceof RoleInterface) {
            $role->add();
        } else {
            throw new Exception('All roles handled by Custom Roles Manager must implement RoleInterface interface.');
        }
    }
}

/**
 * Returns an array of concrete classes that implements RoleInterface
 * in a given directory
 * 
 * @param $dir
 *
 * @return array
 * @throws ReflectionException
 */
function crm_get_roles_in_folder($dir)
{
    $roles = array();

    $roles_files = new RegexIterator(
        new DirectoryIterator($dir),
        '/\.php$/',
        RegexIterator::MATCH
    );

    foreach ($roles_files as $role_file) {
        include_once($role_file->getPathname());
        $r = new ReflectionClass($role_file->getBasename('.php'));
        if ($r->implementsInterface(RoleInterface::class)) {
            $roles[] = $r->newInstance();
        }
    }

    return $roles;
}

plugins/custom-roles-manager/RoleInterface.php

<?php

interface RoleInterface
{
    /**
     * Function that has to be implemented for
     * each concrete class to actually add the role.
     */
    public function add();
}

plugins/custom-roles-manager/roles/PublicRelationsRole.php

<?php

class PublicRelationsRole implements RoleInterface
{
    public function add()
    {
        add_role(
            'public_relations',
            __('Public Relations'),
            [
                'read',
                'edit_post',
                'publish_post',
                'delete_post',
            ]
        );
    }
}

Example scenario: Creating "Some Other Role"

  1. Create file wp-content/plugins/custom-roles-manager/Roles/SomeOtherRole.php
  2. Make it implement RoleInterface and create add method in it, which calls add_role function from WordPress.
  3. Deactivate and activate plugin.

With time, your complex role system will have a dedicated folder for them, helping keep it organized, using OOP, which gives a few options on code re-use over time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.