Capabilities concept is the “heart” of the WordPress access management as it literally defines what user can or cannot do. The official WordPress documentation describes the capability as the permission to perform one or more type of tasks and every authenticated user may have at least one capability either directly assigned or inherited from a parent role(s).
List of all standard capabilities for the WordPress core can be found in the Roles and Capabilities article.
While most of capabilities are self-explanatory based on its name (edit_posts, manage_options, remove_users etc.), there are still a lot of confusion associated with what they actually are responsible for and why even when user has a certain capability assigned, he or she still is not allowed to perform anticipated tasks.
There is no good answer to this question as a lot of core WordPress capabilities have exceptions. For example, when the website is multisite setup and user is not a super admin, then even if create_users capability is granted, user still will not be able to create new user; or manage_links capability will be ignored if link_manager_enabled option is turned off.
Based on the WordPress 4.9 version there are at least 65 exceptions defined in the core so do not hesitate to contact me if you have difficulties with managing capabilities.
All role-based capabilities are stored in the wp_options table with option name wp_user_roles while user-based capabilities are stored in the wp_usermeta table with meta key name wp_capabilities. The wp_ prefix may vary based on the value in the global $table_prefix variable defined in the wp-config.php file.
The list of capabilities is the associated array where the element key is capability itself while element value is the rule that defines if capability is granted or denied (1 means that capability is granted while 0 – denied).
WordPress has the core current_user_can function that is used to check if currently logged in user has certain capability however the function triggers quite complex functionality that in some cases may return unexpected result. It all depends on how many active plugins or theme(s) hook into the current_user_can function.
As it was mentioned above, some capabilities have exceptions that are programmatically defined in the map_meta_cap function. Additionally any third-party solution can hook into the process with user_has_cap filter and overwrite the outcome.
The capability is considered as granted if the rule contains not empty value.
Please note! Since 2011 I’ve personally experience only few instances were other plugins incorrectly hooked into the current_user_can function. So if something is not working as expected it is less likely related to any plugins or themes but rather leak of knowledge in capability exceptions.
How does the capability actually work?
Capability itself is useless, unless, it is referenced in the code. Technically it means that in order for a capability to work, somewhere in the code, there should be a programmatic check if authenticated user has a specific capability or not. This is up to a developer to define what part of the website (of functionality) is protected with what capability.
Note! Not everything in the WordPress has associated capability. For example you will not find a capability that is responsible to show or hide post search above the list of posts on the Backend or even capability that restrict access to the backend.
To learn how to restrict access to the entire backend area for authenticated users, check How to lockdown WordPress backend article.
Fortunately a lot of customization can be accomplished with native WordPress hooks but this requires custom development. For more information about the WordPress hooks check What is the WordPress hook article.
Can you create a custom capability?
Various plugins or themes add custom capabilities to the WordPress core either by storing them into the database or registering them dynamically during the website load. It is hard to tell which way is correct, however it is much harder to manage access to a website with dynamically added capabilities because only certain plugin or theme knows about them and controls when they are registered.
Dynamically added capabilities typically are registered with init hook by modifying the get_current_user()->allcaps public property.
With AAM plugin you have all necessary set of tools to manage access to the WordPress website capabilities for roles or even individual users. For more information about this, please refer to the How to manage WordPress capabilities article.
Capability itself is useless unless it is supported in the code. So if you are not familiar with PHP coding, please consult with your developer or simply contact me before considering to create any custom capabilities.