moodle_rest-1.0.1/modules/moodle_rest_user/src/UserEventHelper.php

modules/moodle_rest_user/src/UserEventHelper.php
<?php

namespace Drupal\moodle_rest_user;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\migrate\Row;
use Drupal\moodle_rest\Services\MoodleRestException;
use Drupal\moodle_rest\Services\RestFunctions;
use Drupal\moodle_rest_user\Event\MoodleUserAssociate;
use Drupal\moodle_rest_user\Event\MoodleUserMap;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * Helper class for User CRUD hooks.
 */
class UserEventHelper implements ContainerInjectionInterface {

  /**
   * The event dispatcher.
   *
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
   */
  protected $eventDispatcher;

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

  /**
   * Moodle Rest Functions connector.
   *
   * @var \Drupal\moodle_rest\Services\RestFunctions
   */
  protected $moodle;

  /**
   * User Event Helper constructor.
   *
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
   *   Event dispatcher.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The factory for configuration objects.
   * @param \Drupal\moodle_rest\Services\RestFunctions $moodle
   *   The Moodle REST Functions connector.
   */
  public function __construct(EventDispatcherInterface $event_dispatcher, ConfigFactoryInterface $config_factory, RestFunctions $moodle) {
    $this->eventDispatcher = $event_dispatcher;
    $this->settings = $config_factory->get('moodle_rest_user.settings');
    $this->moodle = $moodle;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('event_dispatcher'),
      $container->get('config.factory'),
      $container->get('moodle_rest.rest_functions')
    );
  }

  /**
   * Operate on hook_user_login().
   *
   * @see moodle_rest_user_user_login()
   */
  public function userLogin(UserInterface $account) {
    if (
      $this->isUpdating($account) ||
      ($moodle_id = $this->getMoodleId($account)) === FALSE
    ) {
      return;
    }
    $updated = FALSE;
    if (!$moodle_id && $moodle_id = $this->settings->get('associate')) {
      if ($moodle_id = $this->associateAccount($account)) {
        $account->get($this->settings->get('moodle_id_field'))->setValue($moodle_id);
        $updated = TRUE;
      }
    }

    if ($moodle_id && $this->settings->get('pull')['login']) {
      $pulled_account = $this->pullUser($account, $moodle_id);
      if ($pulled_account && $pulled_account !== $account) {
        $account = $pulled_account;
        $updated = TRUE;
      }
    }

    if ($updated) {
      $account->moodle_rest_update = TRUE;
      $account->save();
    }
  }

  /**
   * Operate on hook_user_presave().
   *
   * @see moodle_rest_user_user_presave()
   */
  public function userPresave(UserInterface $account) {
    if (
      $this->isUpdating($account) ||
      ($moodle_id = $this->getMoodleId($account)) === FALSE
    ) {
      return;
    }

    if (!$moodle_id && $this->settings->get('associate')) {
      if ($moodle_id = $this->associateAccount($account)) {
        $account->get($this->settings->get('moodle_id_field'))->setValue($moodle_id);
      }
    }
  }

  /**
   * Operate on hook_user_insert().
   *
   * @see moodle_rest_user_user_insert()
   */
  public function userInsert(UserInterface $account) {
    if (
      $this->isUpdating($account) ||
      ($moodle_id = $this->getMoodleId($account)) === FALSE
    ) {
      return;
    }

    if (!$moodle_id && $this->settings->get('create')) {
      if ($moodle_id = $this->createMoodleUser($account)) {
        $account->get($this->settings->get('moodle_id_field'))->setValue($moodle_id);
        $account->moodle_rest_update = TRUE;
        $account->save();
      }
    }
  }

  /**
   * Operate on hook_user_update().
   *
   * @see moodle_rest_user_user_update()
   */
  public function userUpdate(UserInterface $account) {
    if (
      $this->isUpdating($account) ||
      ($moodle_id = $this->getMoodleId($account)) === FALSE
    ) {
      return;
    }

    if ($moodle_id && $this->settings->get('update')) {
      $moodle_id = $this->pushUser($account, $moodle_id);
    }
  }

  /**
   * Operate on hook_user_prepare_form().
   *
   * @see moodle_rest_user_user_prepare_form()
   */
  public function userEdit(UserInterface $account, FormStateInterface $form_state) {
    if (
      !$this->settings->get('pull')['edit'] ||
      $this->isUpdating($account) ||
      ($moodle_id = $this->getMoodleId($account)) === FALSE
    ) {
      return;
    }

    if (!$moodle_id && $this->settings->get('associate')) {
      if ($moodle_id = $this->associateAccount($account)) {
        $account->get($this->settings->get('moodle_id_field'))->setValue($moodle_id);
      }
    }

    if ($moodle_id) {
      $pulled_account = $this->pullUser($account, $moodle_id);
      // @todo rebuild form with $pulled_account.
    }
  }

  /**
   * Operate on hook_user_view().
   *
   * @see moodle_rest_user_user_view()
   */
  public function userView(UserInterface $account, array $build) {
    if (
      !$this->settings->get('pull')['view'] ||
      ($moodle_id = $this->getMoodleId($account)) === FALSE
    ) {
      return;
    }

    $updated = FALSE;
    if (!$moodle_id && $this->settings->get('associate')) {
      if ($moodle_id = $this->associateAccount($account)) {
        $account->get($this->settings->get('moodle_id_field'))->setValue($moodle_id);
        $updated = TRUE;
      }
    }

    if ($moodle_id && $this->settings->get('pull')['edit']) {
      $pulled_account = $this->pullUser($account, $moodle_id);
      if ($pulled_account && $pulled_account !== $account) {
        $account = $pulled_account;
        $updated = TRUE;
      }
      // @todo update $build with $pulled_account.
    }

    if ($updated) {
      $account->moodle_rest_update = TRUE;
      $account->save();
    }
  }

  /**
   * User entity is saved for a moodle update.
   *
   * @return bool
   */
  private function isUpdating(UserInterface $account) {
    return !empty($account->moodle_rest_update);
  }

  /**
   * Get Moodle ID.
   *
   * @return int|bool
   */
  public function getMoodleId(UserInterface $account) {
    $moodle_field = $account->get($this->settings->get('moodle_id_field'));
    if (!$moodle_field) {
      return FALSE;
    }
    return (int) $moodle_field->isEmpty() ? 0 : $moodle_field->first()->getValue()['value'];
  }

  /**
   * Try to associate user with existing moodle account.
   */
  public function associateAccount(UserInterface $account): int {
    $event = new MoodleUserAssociate($account);
    $this->eventDispatcher->dispatch($event, MoodleUserAssociate::EVENT_NAME);
    return $event->moodleId;
  }

  /**
   * Push a new user into Moodle.
   *
   * @param \Drupal\user\UserInterface $account
   *   The user to be added to Moodle.
   */
  protected function createMoodleUser(UserInterface $account) {
    $mapping = $this->settings->get('push_fields');
    $source = $this->userSourceFromMapping($account, $mapping);
    $row = new Row($source, array_flip(array_column($mapping, 'drupal')));
    // @todo Map can throw an exception for missing fields?
    $event = new MoodleUserMap($row, $mapping);
    $this->eventDispatcher->dispatch($event, MoodleUserMap::PUSH_EVENT);
    try {
      $result = $this->moodle->createUsers([$event->row->getDestination()]);
      $result = reset($result);
      if ($moodle_id = $result['id']) {
        return $moodle_id;
      }
    }
    catch (MoodleRestException $e) {
      // @todo Notify user? Log?
    }
  }

  /**
   * Pull user fields from Moodle to a user.
   *
   * @param \Drupal\user\UserInterface $account
   *   The user account to be pulled.
   * @param int $moodle_id
   *   Moodle ID of account.
   */
  protected function pullUser(UserInterface $account, $moodle_id) {
    try {
      $result = $this->moodle->getUsers(['id' => $moodle_id]);
    }
    catch (MoodleRestException $e) {
      // @todo Notify user? Log?
      return;
    }

    $update_account = clone $account;
    if ($moodle_user = reset($result)) {
      $mapping = $this->settings->get('pull_fields');
      $row = new Row($moodle_user, array_flip(array_column($mapping, 'moodle')));
      $event = new MoodleUserMap($row, $mapping);
      $this->eventDispatcher->dispatch($event, MoodleUserMap::PULL_EVENT);
      foreach ($row->getDestination() as $field_name => $values) {
        $field = $update_account->$field_name;
        if ($field instanceof TypedDataInterface) {
          $field->setValue($values);
        }
      }
    }

    return $update_account;
  }

  /**
   * Push user fields to a Moodle user.
   *
   * @param \Drupal\user\UserInterface $account
   *   The user accout to push.
   * @param int $moodle_id
   *   Moodle ID of account.
   */
  protected function pushUser(UserInterface $account, $moodle_id) {
    $mapping = $this->settings->get('push_fields');
    $source = $this->userSourceFromMapping($account, $mapping);
    $row = new Row($source, array_flip(array_column($mapping, 'drupal')));
    // @todo Map can throw an exception for missing fields?
    $event = new MoodleUserMap($row, $mapping);
    $this->eventDispatcher->dispatch($event, MoodleUserMap::PUSH_EVENT);
    try {
      $mapped_fields = $event->row->getDestination();
      $mapped_fields['id'] = $moodle_id;
      $result = $this->moodle->updateUsers([$mapped_fields]);
    }
    catch (MoodleRestException $e) {
      // @todo Notify user? Log?
    }
  }

  protected function userSourceFromMapping(UserInterface $user, array $mapping) {
    $fields = array_map(function ($value) {
      return strstr($value['drupal'] . '/', '/', TRUE);
    }, $mapping);

    $source = [];
    foreach ($fields as $field_name) {
      $field = $user->{$field_name};
      if ($field instanceof TypedDataInterface) {
        if ($field->getDataDefinition()->isList()) {
          $source[$field_name] = $field->getValue();
        }
        else {
          $source[$field_name] = $field->value;
        }
      }
    }

    return $source;
  }

}

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

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