permission_group-1.0.x-dev/src/Entity/PermissionGroup.php

src/Entity/PermissionGroup.php
<?php

namespace Drupal\permission_group\Entity;

use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\user\Entity\Role;

/**
 * Defines the permission group entity type.
 *
 * @ConfigEntityType(
 *   id = "permission_group",
 *   label = @Translation("Permission Group"),
 *   label_collection = @Translation("Permission Groups"),
 *   label_singular = @Translation("permission group"),
 *   label_plural = @Translation("permission groups"),
 *   label_count = @PluralTranslation(
 *     singular = "@count permission group",
 *     plural = "@count permission groups",
 *   ),
 *   handlers = {
 *     "list_builder" = "Drupal\permission_group\PermissionGroupListBuilder",
 *     "form" = {
 *       "add" = "Drupal\permission_group\Form\PermissionGroupForm",
 *       "edit" = "Drupal\permission_group\Form\PermissionGroupForm",
 *       "delete" = "Drupal\permission_group\Form\PermissionGroupDeleteForm"
 *     }
 *   },
 *   config_prefix = "group",
 *   admin_permission = "administer permissions",
 *   links = {
 *     "collection" = "/admin/structure/group",
 *     "add-form" = "/admin/structure/group/add",
 *     "edit-form" = "/admin/structure/group/{permission_group}",
 *     "edit-permissions-form" =
 *   "/admin/people/permission_groups/permissions/{permission_group}",
 *     "delete-form" = "/admin/structure/group/{permission_group}/delete"
 *   },
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label",
 *     "uuid" = "uuid"
 *   },
 *   config_export = {
 *     "id",
 *     "label",
 *     "description",
 *     "permissions",
 *     "permission_groups"
 *   }
 * )
 */
class PermissionGroup extends ConfigEntityBase {

  /**
   * The permission group ID.
   *
   * @var string
   */
  protected $id;

  /**
   * The permission group label. Maps to the permission title.
   *
   * @var string
   */
  protected $label = '';

  /**
   * The permission group status.
   *
   * @var bool
   */
  protected $status;

  /**
   * The group description.
   *
   * @var string
   */
  protected $description = '';

  /**
   * The permissions belonging to this permission group.
   *
   * @var array
   */
  protected $permissions = [];

  /**
   * Linked permission groups.
   *
   * @var array
   */
  protected $permission_groups = [];

  /**
   * Returns a list of permissions assigned to the group.
   *
   * @param bool $resolve_groups
   *   This will resolve permission groups using recursion so a group can
   *   contain other groups.
   *
   * @return string[]
   *   The permissions assigned to the group.
   */
  public function permissions($resolve_groups = FALSE) : array {
    static $resolved_groups = [];
    if (!$resolve_groups) {
      return $this->permissions;
    }

    // Determine if this is the top level call.
    $top_level_call = empty($resolved_groups);

    $permissions = $this->permissions;
    foreach ($this->permission_groups as $group_id) {
      if (!in_array($group_id, $resolved_groups, TRUE) && ($group = PermissionGroup::load($group_id))) {
        array_push($resolved_groups, $group_id);
        $permissions = array_merge($permissions, $group->permissions(TRUE));
      }
    }

    if ($top_level_call) {
      // Reset the static.
      $resolved_groups = [];
      // Only need to manipulate the array once.
      $permissions = array_unique($permissions);
      sort($permissions);
    }
    return $permissions;
  }

  /**
   * Gets the description.
   *
   * @return string
   *   The description.
   */
  public function description() : string {
    return $this->description;
  }

  /**
   * Sets the list of permissions assigned to the group.
   *
   * @param string[] $permissions
   *   A list of permissions to assign to the group.
   *
   * @return $this
   */
  public function setPermissions(array $permissions) : PermissionGroup {
    $this->permissions = $permissions;
    return $this;
  }

  /**
   * Returns a list of linked permission groups..
   *
   * @return string[]
   *   The permission group IDs linked to the group.
   */
  public function getPermissionGroups() : array {
    return $this->permission_groups;
  }

  /**
   * Sets the list of linked permission groups.
   *
   * @param string[] $permission_groups
   *   A list of permission group IDs.
   *
   * @return $this
   */
  public function setPermissionGroups(array $permission_groups) : PermissionGroup {
    $this->permission_groups = $permission_groups;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
    parent::postSave($storage, $update);
    $original_permissions = isset($this->original) ? $this->original->permissions(TRUE) : [];

    if ($original_permissions !== $this->permissions(TRUE)) {
      /** @var \Drupal\user\Entity\Role $role */
      foreach (Role::loadMultiple() as $role) {
        if ($this->isGroupInList($role->getThirdPartySetting('permission_group', 'groups', []))) {
          // Clean the slate of any permissions that are assigned originally by
          // this group so the permissions can be correctly rebuilt in
          // permission_group_user_role_presave().
          foreach ($original_permissions as $original_permission) {
            $role->revokePermission($original_permission);
          }
          $role->save();
        }
      }
    }
  }

  /**
   * Determines if a group is in a list of groups or their linked groups.
   *
   * @param string[] $groups
   *   The list of groups to check.
   *
   * @return bool
   *   TRUE is the group is in the list of groups.
   */
  private function isGroupInList(array $groups) {
    if (in_array($this->id(), $groups, TRUE)) {
      return TRUE;
    }
    if (!empty($groups)) {
      foreach (PermissionGroup::loadMultiple($groups) as $permissionGroup) {
        if ($this->isGroupInList($permissionGroup->getPermissionGroups())) {
          return TRUE;
        }
      }
    }
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public static function preDelete(EntityStorageInterface $storage, array $entities) {
    /** @var \Drupal\permission_group\Entity\PermissionGroup[] $entities */
    $ids_to_delete = array_keys($entities);
    // Empty the permissions so roles will be correctly updated in
    // PermissionGroup::postSave() and permission_group_user_role_presave().
    foreach ($entities as $permission_group) {
      $permission_group->setPermissions([])->save();
    }
    // Fix any roles that have a direct usage of permission groups that will be
    // deleted.
    foreach (Role::loadMultiple() as $role) {
      $linked_groups = $role->getThirdPartySetting('permission_group', 'groups', []);
      $new_linked_groups = array_diff($linked_groups, $ids_to_delete);
      if ($linked_groups !== $new_linked_groups) {
        $role
          ->setThirdPartySetting('permission_group', 'groups', $new_linked_groups)
          ->save();
      }
    }
    // Fix any permission groups that have a direct usage of the permission
    // groups that will be deleted.
    foreach (PermissionGroup::loadMultiple() as $permission_group) {
      if (!in_array($permission_group->id(), $ids_to_delete, TRUE)) {
        $linked_groups = $permission_group->getPermissionGroups();
        $new_linked_groups = array_diff($linked_groups, $ids_to_delete);
        if ($linked_groups !== $new_linked_groups) {
          $permission_group
            ->setPermissionGroups($new_linked_groups)
            ->save();
        }
      }
    }
    parent::preDelete($storage, $entities);
  }

  /**
   * Determines whether this group has any restricted access permissions.
   *
   * @param array|null $permission_handler_result
   *   For form building it is often useful to generate the current permission
   *   list outside of calling this method.
   *
   * @return bool
   *   TRUE if the permission group contains a restricted access permission.
   */
  public function restrictAccess(array $permission_handler_result = NULL) : bool {
    if (!$permission_handler_result) {
      $permission_handler_result = \Drupal::service('user.permissions')->getPermissions();
    }
    $restricted_access_permissions = array_keys(array_filter($permission_handler_result, function ($permission) {
      return isset($permission['restrict access']) && $permission['restrict access'];
    }));
    return (bool) array_intersect($this->permissions(TRUE), $restricted_access_permissions);
  }

  /**
   * Updates the permission groups on a role, if necessary.
   *
   * @param \Drupal\user\Entity\Role $role
   *   The role to update, if necessary.
   * @param array $group_ids
   *   The permission group IDs to link to the role.
   */
  public static function roleSave(Role $role, array $group_ids) {
    // Only save a role when something has changed.
    if ($group_ids === $role->getThirdPartySetting('permission_group', 'groups', [])) {
      return;
    }
    if (count($group_ids) > 0) {
      $role->setThirdPartySetting('permission_group', 'groups', $group_ids);
    }
    else {
      $role->unsetThirdPartySetting('permission_group', 'groups');
    }
    $role->save();
  }

  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    parent::calculateDependencies();
    // Load all permission definitions.
    $permission_definitions = \Drupal::service('user.permissions')->getPermissions();
    $valid_permissions = array_intersect($this->permissions, array_keys($permission_definitions));
    $invalid_permissions = array_diff($this->permissions, $valid_permissions);
    if (!empty($invalid_permissions) && !$this->get('skip_missing_permission_deprecation')) {
      @trigger_error('Adding non-existent permissions to a permission group is deprecated in drupal:9.3.0 and triggers a runtime exception before drupal:10.0.0. The incorrect permissions are "' . implode('", "', $invalid_permissions) . '". Permissions should be defined in a permissions.yml file or a permission callback. See https://www.drupal.org/node/3193348', E_USER_DEPRECATED);
    }
    foreach ($valid_permissions as $permission) {
      // Depend on the module that is providing this permissions.
      $this->addDependency('module', $permission_definitions[$permission]['provider']);
      // Depend on any other dependencies defined by permissions granted to
      // this role.
      if (!empty($permission_definitions[$permission]['dependencies'])) {
        $this->addDependencies($permission_definitions[$permission]['dependencies']);
      }
    }
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function onDependencyRemoval(array $dependencies) {
    $changed = parent::onDependencyRemoval($dependencies);
    // Load all permission definitions.
    $permission_definitions = \Drupal::service('user.permissions')->getPermissions();

    // Convert config and content entity dependencies to a list of names to make
    // it easier to check.
    foreach (['content', 'config'] as $type) {
      $dependencies[$type] = array_keys($dependencies[$type]);
    }

    // Remove any permissions from the permission group that are dependent on
    // anything being deleted or uninstalled.
    foreach ($this->permissions as $key => $permission) {
      if (!isset($permission_definitions[$permission])) {
        // If the permission is not defined then there's nothing we can do.
        continue;
      }

      if (in_array($permission_definitions[$permission]['provider'], $dependencies['module'], TRUE)) {
        unset($this->permissions[$key]);
        $changed = TRUE;
        // Process the next permission.
        continue;
      }

      if (isset($permission_definitions[$permission]['dependencies'])) {
        foreach ($permission_definitions[$permission]['dependencies'] as $type => $list) {
          if (array_intersect($list, $dependencies[$type])) {
            unset($this->permissions[$key]);
            $changed = TRUE;
            // Process the next permission.
            continue 2;
          }
        }
      }
    }

    return $changed;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc