knowledge-8.x-1.x-dev/src/Service/CompetencyService.php

src/Service/CompetencyService.php
<?php

namespace Drupal\knowledge\Service;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\knowledge\KnowledgeCompetencyServiceInterface;
use Drupal\user\UserInterface;

/**
 * Service for the Competency entity.
 */
class CompetencyService implements KnowledgeCompetencyServiceInterface {
  use StringTranslationTrait;
  use MessengerTrait;

  /**
   * The settings.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  protected $settings;

  /**
   * The competency storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $competencyStorage;

  /**
   * The user role storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $userRoleStorage;

  /**
   * The current user.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $currentUser;

  /**
   * Constructs a new CompetencyService object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param mixed $string_translation
   *   The string translation service.
   * @param mixed $messenger
   *   The messenger service.
   * @param mixed $current_user
   *   The current user.
   */
  public function __construct(ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, $string_translation, $messenger, $current_user) {
    $this->settings = $config_factory->get('knowledge.competency.settings');
    $this->competencyStorage = $entity_type_manager->getStorage('knowledge_competency');
    $this->userRoleStorage = $entity_type_manager->getStorage('user_role');
    $this->setStringTranslation($string_translation);
    $this->setMessenger($messenger);
    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public function get() {
    $setting = $this->settings->get('roles') ?? [];
    usort($setting, [static::class, 'sort']);

    return $setting;
  }

  /**
   * {@inheritdoc}
   */
  public function getUserCompetency($user_id) {
    $query = $this->competencyStorage->getQuery();
    $result = $query
      ->condition('user_id', $user_id)
      ->accessCheck(FALSE)
      ->execute();
    $competency = NULL;
    if (count($result) == 1) {
      $competency = $this->competencyStorage->load(current($result));
    }
    if (count($result) == 0) {
      $competency = $this->competencyStorage->create([
        'user_id' => $user_id,
      ]);
    }

    return $competency;
  }

  /**
   * {@inheritdoc}
   */
  public function getRoleIds() {
    $roles = $this->get();
    $role_ids = [];
    foreach ($roles as $role) {
      $role_ids[] = $role['role'];
    }
    return $role_ids;
  }

  /**
   * {@inheritdoc}
   */
  public function hasRoleOrBetter($role, $user_roles) {
    if (in_array($role, $user_roles)) {
      return TRUE;
    }

    $roles = $this->getRoleIds();
    $role_index = array_search($role, $roles);
    if ($role_index === FALSE) {
      return FALSE;
    }

    foreach (range($role_index + 1, count($roles) - 1) as $i) {
      if (in_array($roles[$i] ?? NULL, $user_roles)) {
        return TRUE;
      }
    }

    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function doRoleRemoval(UserInterface &$user) {
    $user_roles = $user->getRoles(TRUE);
    $removable_roles = $this->getRemovableRoles($user_roles);
    foreach ($removable_roles as $role) {
      $user->removeRole($role);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function doPreSave(&$roles, $orginal_roles) {

    $role_settings = $this->get();
    $sorted_roles = $this->getRoleIds();
    $existing_completed = [];

    foreach ($orginal_roles as $role) {
      $completed = $role['total'] == $role['correct'] && $role['approved'] != NULL;
      if ($completed) {
        $existing_completed[] = $role['role'];
      }
    }
    $new_roles = [];
    foreach ($roles as $role) {
      $role_name = $role->role;
      $complete = $role->total == $role->correct;
      if (!$complete) {
        continue;
      }
      $existing = in_array($role_name, $existing_completed);
      if ($existing || $role->proposed != NULL) {
        continue;
      }
      $new_roles[] = $role_name;
    }

    $completed_roles = [];
    $settings = [];
    foreach ($role_settings as $setting) {
      $role = $setting['role'];
      $settings[$role] = $setting;
      $is_existing = in_array($role, $existing_completed);
      $is_new = in_array($role, $new_roles);
      $completed = !$is_existing && $is_new;
      if ($completed) {
        $completed_roles[] = $role;
      }
      elseif ($is_existing) {
        continue;
      }
      else {
        break;
      }
    }

    foreach ($roles as $role) {
      $role_name = $role->role;
      $completed = in_array($role_name, $completed_roles);
      if (!$completed) {
        continue;
      }
      $action = $settings[$role_name]['action'] ?? '_none';

      $now = time();
      $curren_user_id = $this->currentUser->id();

      switch ($action) {

        case 'auto':
          $role->proposed = $now;
          $role->proposer = $curren_user_id;
          $role->approved = $now;
          $role->approver = $curren_user_id;
          break;

        case 'leader':
          $role->proposed = $now;
          $role->proposer = $curren_user_id;
          break;

        case '_none':
        default:
          $role->proposed = $now;
          $role->approved = $now;
          break;
      }
    }

  }

  /**
   * {@inheritdoc}
   */
  public function doPostSave($user, $roles, $orginal_roles) {
    $approved_roles = [];
    foreach ($roles as $role) {
      if ($role['approved'] != NULL) {
        $approved_roles[] = $role['role'];
      }
    }
    $orginal_approved_roles = [];
    foreach ($orginal_roles as $role) {
      if ($role['approved'] != NULL) {
        $orginal_approved_roles[] = $role['role'];
      }
    }

    $new_approved_roles = array_diff($approved_roles, $orginal_approved_roles);
    $settings = $this->get();
    $role_ids = $this->getRoleIds();
    $save_user = FALSE;
    $user_roles = $user->getRoles(TRUE);
    foreach ($settings as $setting) {
      $role = $setting['role'];
      if (!in_array($role, $new_approved_roles)) {
        continue;
      }

      $promote = $setting['promote'] ?? '_none';
      $promote_role_id = NULL;
      switch ($promote) {
        case 'self':
          $needs_role = !$this->hasRoleOrBetter($role, $user_roles);
          if ($needs_role) {
            $user->addRole($role);
            $promote_role_id = $role;
            $save_user = TRUE;
          }
          break;

        case 'next':
          $next_role = $role_ids[array_search($role, $role_ids) + 1] ?? NULL;
          if (!is_null($next_role)) {
            $needs_role = !$this->hasRoleOrBetter($next_role, $user_roles);
            if ($needs_role) {
              $user->addRole($next_role);
              $promote_role_id = $next_role;
              $save_user = TRUE;
            }
          }
          break;

        case '_none':
        default:
          break;
      }

    }

    if ($save_user) {
      $user->save();
      $promote_role = $this->userRoleStorage->load($promote_role_id);
      $this->messenger()->addMessage($this->t('%user was promoted to %role.', [
        '%role' => $promote_role->label(),
        '%user' => $user->getDisplayName(),
      ]));
    }

  }

  /**
   * {@inheritdoc}
   */
  public function getPromotionRole($role_id) {
    $roles = $this->get();
    $role_ids = $this->getRoleIds();
    $role_index = array_search($role_id, $role_ids);
    if ($role_index === FALSE) {
      return NULL;
    }

    $next_role = $role_ids[$role_index + 1] ?? NULL;

    $settings = $this->get();
    $role_settings = [];
    foreach ($settings as $setting) {
      $role_settings[$setting['role']] = $setting;
    }

    $promote = $role_settings[$role_id]['promote'] ?? '_none';
    switch ($promote) {
      case 'self':
        return $role_id;

      case 'next':
        return $next_role;

      case '_none':
      default:
        return NULL;
    }

  }

  /**
   * Get the roles that can be removed.
   *
   * @param array $user_roles
   *   The user roles.
   *
   * @return array
   *   The roles that can be removed.
   */
  private function getRemovableRoles($user_roles) {

    $removable_roles = [];
    $best_role = NULL;
    $roles = $this->getRoleIds();
    foreach ($roles as $index => $role) {
      if (in_array($role, $user_roles)) {
        if (!is_null($best_role)) {
          $removable_roles[] = $best_role;
        }

        $best_role = $role;
      }
    }

    return $removable_roles;
  }

  /**
   * Callback for usort.
   */
  private static function sort($a, $b) {
    if ($a['weight'] == $b['weight']) {
      return 0;
    }
    return ($a['weight'] < $b['weight']) ? -1 : 1;
  }

}

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

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