2

I am trying to create a custom role in a wordpress multisite environment. This role is to have the same capabilities as an admin but also have the ability to commit unfiltered HTML like super admins. I have had success in creating the role and set unfiltered_html to true, but the text editor still strips Iframes and other html elements. Below is my PHP code for the new role which I have named 'developer'.

function add_developer()
{
//remove role if it already exists
if( get_role('developer') ){
      remove_role( 'developer' );
}
//custom user role for unfiltered_html
$result = add_role('developer', __('Developer' ),
                  array(
                  'read' => true,
                  'activate_plugins' => true,
                  'delete_others_pages' => true,
                  'delete_others_posts' => true,
                  'delete_pages' => true,
                  'delete_posts' => true,
                  'delete_private_pages' => true,
                  'delete_private_posts' => true,
                  'delete_published_pages' => true,
                  'delete_published_posts' => true,
                  'edit_dashboard' => true,
                  'edit_others_pages'  => true,
                  'edit_others_posts' => true,
                  'edit_pages' => true,
                  'edit_posts' => true,
                  'edit_private_pages' => true,
                  'edit_private_posts' => true,
                  'edit_published_pages' => true,
                  'edit_published_posts' => true,
                  'edit_theme_options' => true,
                  'export' => true,
                  'import' => true,
                  'list_users' => true,
                  'manage_categories' => true,
                  'manage_links' => true,
                  'manage_options' => true,
                  'manage_comments' => true,
                  'promote_users' => true,
                  'publish_pages' => true,
                  'publish_posts' => true,
                  'read_private_pages' => true,
                  'read_private_posts' => true,
                  'remove_users' => true,
                  'switch_themes' => true,
                  'upload_files' => true,
                  'unfiltered_html' => true
                  )
                  );
if ( null !== $result ) {
    echo 'Yay! New role created!';
}
else {
    echo 'Oh... the basic_contributor role already exists.';
}

}

I am working in a team to convert a huge website with thousands of pages and would like to avoid giving everyone super admin access. Is there anyway that I can avoid the html filter for only specific user roles? If not is there anyway to do this for specific users? I would like to avoid altering core and don't mind removing all filtering. I am currently testing this in my functions.php file of my theme but will eventually write a plugin to this.

I am aware of the security risks that will be present due to users being able to post javascript but my team is willing to live with this if we do not have to explicitly give the whole team superadmin access.

Any help is much appreciated!

3 Answers 3

1

This had me baffled for a while as well. Not exactly a solution for your problem, but this should get you on your way.

add_action( 'admin_init', 'my_kses_remove_filters' );
function my_kses_remove_filters() {
    $current_user = wp_get_current_user();
 
    if ( my_user_has_role( 'administrator', $current_user ) )
        kses_remove_filters();
}
 
function my_user_has_role( $role = '', $user = null ) {
    $user = $user ? new WP_User( $user ) : wp_get_current_user();
 
    if ( empty( $user->roles ) )
        return;
 
    if ( in_array( $role, $user->roles ) )
        return true;
 
    return;
}

This action removes the filters for administrators. First it gets the role of the current user and if the role is 'administrator', it removes the filters on editing content.

This solutions draws heavily from this page.

1
  • As per @brett's experience, the above is also no longer working for me. Currently on WP 5.4.2.
    – MastaBaba
    Jun 25, 2020 at 13:26
0

I found this code to work for me

function multisite_restore_unfiltered_html( $caps, $cap, $user_id, ...$args ) {
    if ( 'unfiltered_html' === $cap && (user_can( $user_id, 'editor' ) || user_can( $user_id, 'administrator' ) ) ) {
        $caps = array( 'unfiltered_html' );
    }

    return $caps;
}

add_filter( 'map_meta_cap', 'multisite_restore_unfiltered_html', 1, 4 );

https://gist.github.com/kellenmace/9e6a6fbb92ec75940f23d2a6f01c9b59

1
  • Working on version 5.9.3
    – keetbis
    Jun 16 at 17:19
-1

Adding an action which calls kses_remove_filters() didn't work for me. I actually had to hack WordPress to achieve this.

The problem is that WordPress has a global override in the method map_meta_cap() in wp-includes/capabilities.php, which ignores the unfiltered_html capability in a multisite install if the user is not a super admin.

Get rid of that override, and you’re sweet. Until you have to update WordPress, of course, and you’ll have to do it all over again.

        case 'unfiltered_html':
        // Disallow unfiltered_html for all users, even admins and super admins.
            if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) {
                $caps[] = 'do_not_allow';
//          } elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
//              $caps[] = 'do_not_allow';
            } else {
            $caps[] = 'unfiltered_html';
            }
        break;
3

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.