private function isAllowedSingle($what, $user, $userRoles, $content = null, $contenttypeSlug = null, $contentId = null)
    {
        if ($content !== null) {
            $parts = [
                'contenttype',
                $contenttypeSlug,
                $what,
                $contentId,
            ];
        } else {
            $parts = explode(':', $what);
        }

        switch ($parts[0]) {
            case 'overview':
                $contenttype = null;
                if (isset($parts[1])) {
                    $contenttype = $parts[1];
                }
                if (empty($contenttype)) {
                    if (in_array(self::ROLE_EVERYONE, $userRoles)) {
                        $this->audit("Granting 'overview' for everyone (hard-coded override)");

                        return true;
                    }
                    $this->audit("Denying 'overview' for anonymous user (hard-coded override)");

                    return false;
                }
                $permission = 'view';

                break;

            case 'relatedto':
                $contenttype = isset($parts[1]) ? $parts[1] : '';
                if (empty($contenttype)) {
                    $this->audit("Granting 'relatedto' globally (hard-coded override)");

                    return true;
                }
                $permission = 'view';

                break;

            case 'contenttype':
                $contenttype = $parts[1];
                $permission = $contentId = null;
                if (isset($parts[2])) {
                    $permission = $parts[2];
                }
                if (isset($parts[3])) {
                    $contentId = $parts[3];
                }
                if (empty($permission)) {
                    $permission = 'view';
                }

                // Handle special case for owner.
                if (empty($contentId)) {
                    break;
                }

                // If content was not passed but our rule contains the content
                // we need, lets fetch the Content object @see #3909
                if (is_string($content) || ($contenttype && $contentId)) {
                    $content = $this->app['query']->getContent("$contenttype/$contentId", ['hydrate' => false]);
                }

                if ((int) ($content['ownerid']) && ((int) ($content['ownerid']) === (int) ($user['id']))) {
                    $userRoles[] = self::ROLE_OWNER;
                }
                break;

            case 'editcontent':
            case 'contentaction':
            case 'deletecontent':
                // editcontent is handled separately in Backend/editcontent()
                // This is because editing content is governed by two separate
                // permissions per content type, "create" and "edit".
                // Similarly, contentaction and deletecontent are handled
                // separately in Backend/contentaction() and
                // Backend/deletecontent(), respectively, because transitions
                // are governed by a set of separate permissions.
                $this->audit("Granting '{$parts[0]}' (hard-coded override)");

                return true;

            default:
                $permission = $what;
                $contenttype = null;
                break;
        }

        return $this->checkPermission($userRoles, $permission, $contenttype);
    }