social_course-8.x-2.11/src/Plugin/Block/CourseNavigationBlock.php

src/Plugin/Block/CourseNavigationBlock.php
<?php

namespace Drupal\social_course\Plugin\Block;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Template\Attribute;
use Drupal\group\Entity\GroupInterface;
use Drupal\node\NodeInterface;
use Drupal\social_course\CourseWrapperInterface;
use Drupal\social_course\Entity\CourseEnrollmentInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a 'CourseNavigationBlock' block.
 *
 * @Block(
 *   id = "course_navigation",
 *   admin_label = @Translation("Course navigation block"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", required = FALSE)
 *   }
 * )
 */
class CourseNavigationBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * The entity repository.
   *
   * @var \Drupal\Core\Entity\EntityRepositoryInterface
   */
  protected $entityRepository;

  /**
   * The course wrapper.
   *
   * @var \Drupal\social_course\CourseWrapperInterface
   */
  protected $courseWrapper;

  /**
   * The current active user.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Creates a CourseNavigationBlock instance.
   *
   * @param array $configuration
   *   The plugin configuration, i.e. an array with configuration values keyed
   *   by configuration option name. The special key 'context' may be used to
   *   initialize the defined contexts by setting it to an array of context
   *   values keyed by context names.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository.
   * @param \Drupal\social_course\CourseWrapperInterface $course_wrapper
   *   The course wrapper.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   The current active user.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    EntityRepositoryInterface $entity_repository,
    CourseWrapperInterface $course_wrapper,
    AccountProxyInterface $current_user,
    EntityTypeManagerInterface $entity_type_manager,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);

    $this->entityRepository = $entity_repository;
    $this->courseWrapper = $course_wrapper;
    $this->currentUser = $current_user;
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity.repository'),
      $container->get('social_course.course_wrapper'),
      $container->get('current_user'),
      $container->get('entity_type.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    $node = $this->getContextValue('node');
    $account = $this->currentUser;

    if ($node instanceof NodeInterface && $node->id()) {
      // Get node translation if exists.
      $node = $this->entityRepository->getTranslationFromContext($node);
      $this->courseWrapper->setCourseFromMaterial($node);
      $parent_section = $this->courseWrapper->getSectionFromMaterial($node);

      // Prepares variable with the course sections.
      $course_sections = [];
      /** @var \Drupal\node\NodeInterface $section */
      foreach ($this->courseWrapper->getSections() as $section) {
        $section_item = [
          'attributes' => new Attribute(),
          'parent' => FALSE,
          'number' => $this->courseWrapper->getSectionNumber($section) + 1,
          'parts_count' => 0,
          'parts_finished' => 0,
        ];

        // Set the values for progress indicator.
        $section_item['parts_count'] = count($this->courseWrapper->getMaterials($section));
        $section_item['parts_finished'] = count($this->courseWrapper->getFinishedMaterials($section, $account));

        $entities = $this->getCourseEnrollmentEntities($this->courseWrapper, $section);

        $this->addStatusLabelForSections($entities, $this->courseWrapper, $section, $section_item);
        $this->addAccessLabelForSections($section, $section_item, $parent_section);

        $course_sections[] = $section_item;
      }

      // Prepares variable with the material items of the active section.
      $items = [];
      $course_enrollments = $this->getCourseEnrollmentEntities($this->courseWrapper, $parent_section);

      foreach ($course_enrollments as $key => $course_enrollment) {
        unset($course_enrollments[$key]);
        $course_enrollments[$course_enrollment->get('mid')->target_id] = $course_enrollment;
      }

      /** @var \Drupal\node\NodeInterface $material */
      foreach ($this->courseWrapper->getMaterials($parent_section) as $material) {
        $item = [
          'label' => $material->label(),
          'url' => FALSE,
          'type' => $material->bundle(),
          'number' => $this->courseWrapper->getMaterialNumber($material) + 1,
          'active' => FALSE,
          'finished' => FALSE,
        ];

        if ($material->id() === $node->id()) {
          $item['active'] = TRUE;
        }

        if (isset($course_enrollments[$material->id()]) && $course_enrollments[$material->id()]->getStatus() === CourseEnrollmentInterface::FINISHED) {
          $item['finished'] = TRUE;
        }

        if ($this->courseWrapper->materialAccess($material, $this->currentUser, 'view')->isAllowed()) {
          $item['url'] = $material->toUrl();
        }

        $items[] = $item;
      }

      $build = [
        '#theme' => 'course_navigation',
        '#items' => $items,
        '#course_sections' => $course_sections,
        '#parent_course' => [
          'label' => $this->courseWrapper->getCourse()->label(),
          'url' => $this->courseWrapper->getCourse()->toUrl(),
        ],
        '#parent_section' => [
          'label' => $section->label(),
          'url' => $section->toUrl(),
        ],
      ];
    }

    return $build ?? [];
  }

  /**
   * Add status label for functions.
   *
   * @param \Drupal\social_course\CourseWrapperInterface $course_wrapper
   *   The course wrapper.
   * @param \Drupal\node\NodeInterface $section
   *   The node entity.
   *
   * @return array|\Drupal\Core\Entity\EntityInterface[]
   *   An array of course enrollments.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function getCourseEnrollmentEntities(CourseWrapperInterface $course_wrapper, NodeInterface $section) {
    $storage = $this->entityTypeManager->getStorage('course_enrollment');
    $entities = $storage->loadByProperties([
      'uid' => $this->currentUser->id(),
      'gid' => $course_wrapper->getCourse()->id(),
      'sid' => $section->id(),
    ]);

    return $entities;
  }

  /**
   * Add status label for sections.
   *
   * @param mixed $entities
   *   An array of course enrollments.
   * @param \Drupal\social_course\CourseWrapperInterface $course_wrapper
   *   The course wrapper.
   * @param \Drupal\node\NodeInterface $section
   *   The node entity.
   * @param array $section_item
   *   An array of section items.
   */
  protected function addStatusLabelForSections($entities, CourseWrapperInterface $course_wrapper, NodeInterface $section, array &$section_item) {
    if (!$entities) {
      $section_item['section_status'] = 'not-started';
      $section_item['allowed_start'] = $course_wrapper->sectionAccess($section, $this->currentUser, 'start')->isAllowed();
    }
    else {
      foreach ($entities as $entity) {
        if ($entity->getStatus() === CourseEnrollmentInterface::IN_PROGRESS) {
          $section_item['section_status'] = 'in-progress';
          $section_item['section_current'] = $entity->get('mid')->target_id;
          break;
        }
        elseif ($entity->getStatus() === CourseEnrollmentInterface::FINISHED) {
          $section_item['section_status'] = 'finished';
          $materials = $course_wrapper->getMaterials($section);
          $section_item['section_current'] = current($materials)->id();
        }
      }
    }
  }

  /**
   * Add access label for sections.
   *
   * @param \Drupal\node\NodeInterface $section
   *   The node entity.
   * @param array $section_item
   *   An array of section items.
   * @param object $parent_section
   *   The parent section.
   *
   * @throws \Drupal\Core\Entity\EntityMalformedException
   */
  protected function addAccessLabelForSections(NodeInterface $section, array &$section_item, $parent_section) {
    $access = $this->courseWrapper->sectionAccess($section, $this->currentUser, 'view');
    if ($access->isAllowed()) {
      $section_item['label'] = $section->toLink()->toRenderable();
      // Mark the current section link as active.
      if ($section->id() === $parent_section->id()) {
        $section_item['attributes']->addClass('active');
        $section_item['parent'] = TRUE;
      }
    }
    else {
      $section_item['label'] = $section->label();
      $section_item['attributes']->addClass('not-allowed');
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheTags() {
    $tags = parent::getCacheTags();
    $node = $this->getContextValue('node');

    if ($node instanceof NodeInterface && $node->id()) {
      $this->courseWrapper->setCourseFromMaterial($node);
      $tags = Cache::mergeTags($tags, $this->courseWrapper->getCourse()->getCacheTags());
      $tags = Cache::mergeTags($tags, $this->courseWrapper->getSectionFromMaterial($node)->getCacheTags());
    }

    return $tags;
  }

  /**
   * {@inheritdoc}
   */
  protected function blockAccess(AccountInterface $account) {
    $node = $this->getContextValue('node');

    if ($node instanceof NodeInterface && $node->id()) {
      $this->courseWrapper->setCourseFromMaterial($node);

      if ($this->courseWrapper->getSections()) {
        $group = $this->courseWrapper->getCourse();

        return AccessResult::allowedIf($group instanceof GroupInterface);
      }
    }

    return AccessResult::forbidden();
  }

}

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

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