View source
<?php
namespace Drupal\opigno_learning_path\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Url;
use Drupal\group\Entity\Group;
use Drupal\opigno_group_manager\Entity\OpignoGroupManagedContent;
use Drupal\opigno_group_manager\OpignoGroupContentTypesManager;
use Drupal\opigno_learning_path\Controller\LearningPathStepsController;
use Drupal\opigno_learning_path\Traits\LearningPathAchievementTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Security\TrustedCallbackInterface;
class StepsBlock extends BlockBase implements ContainerFactoryPluginInterface, TrustedCallbackInterface {
use LearningPathAchievementTrait;
protected $opignoGroupContentTypesManager;
public function __construct(array $configuration, $plugin_id, $plugin_definition, OpignoGroupContentTypesManager $opigno_group_content_types_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->opignoGroupContentTypesManager = $opigno_group_content_types_manager;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('opigno_group_manager.content_types.manager'));
}
public function getCacheContexts() {
return Cache::mergeContexts(parent::getCacheContexts(), [
'route',
'opigno_current:group_id',
'opigno_current:content_id',
'opigno_current:activity_id',
]);
}
public function getGroupByRouteOrContext() {
return Group::load($this
->getCurrentGroupId());
}
public function build() {
$group = $this
->getGroupByRouteOrContext();
$steps = $this
->getStepsByGroup($group);
$cid = $this
->getCurrentGroupContentId();
if (!$cid) {
return [];
}
if (!$steps) {
return [];
}
$steps = array_values($steps);
if (!$steps) {
return [];
}
foreach ($steps as $index => &$step) {
$step['step_previous'] = $steps[$index - 1] ?? FALSE;
$step['step_first'] = $index === 0;
$step['step_last'] = count($steps) - 1 === $index;
}
return [
'#type' => 'container',
[
'#theme' => 'opigno_lp_step_activity',
'title' => [
'#markup' => $group
->label(),
],
'steps' => $steps,
'#pre_render' => [
[
$this,
'processModuleList',
],
],
],
];
}
public function processModuleList($elements) {
foreach ($elements["steps"] as &$step) {
$link = $this
->getLinkToStart($step);
$step = [
'#theme' => sprintf('%s_%s', 'opigno_lp_step', strtolower($step["typology"])),
'step' => $step,
'#state' => $this
->getState($step),
'#current' => $this
->isModuleCurrent($step),
'#link' => FALSE,
'#locked' => !$link,
'#pre_render' => [
[
$this,
'processActivityList',
],
],
];
}
return $elements;
}
public function processActivityList($elements) {
$meta = CacheableMetadata::createFromRenderArray($elements);
if (in_array($elements["step"]['typology'], [
'Module',
])) {
[
$training,
$course,
$module,
] = $this
->getTrainingAndCourse($elements["step"]);
[
$activities,
$attempts,
] = $this
->getActivities($training, $course, $module);
$meta
->addCacheableDependency($attempts);
$activity_status = $this
->getActivityStatus($activities, $attempts, $module);
$activity_passed = array_filter($activity_status, static function ($status) {
return 'passed' === $status;
});
$next = FALSE;
$current_module = $this
->isModuleCurrent($elements["step"]);
foreach ($activities as &$activity) {
$meta
->addCacheableDependency($activity);
$state = $activity_status[$activity
->id()] ?? 'pending';
$current = $this
->getCurrentActivityId() === $activity
->id();
$is_link = in_array($state, [
'passed',
]);
$activity = [
'#theme' => 'opigno_lp_step_module_activity',
'#activity' => $activity,
"#state" => $state,
'#current' => $current,
'#link' => $current_module && ($current || $is_link || $next) ? Url::fromRoute('opigno_module.group.answer_form', [
'group' => $training
->id(),
'opigno_activity' => $activity
->id(),
'opigno_module' => $module
->id(),
])
->toString() : FALSE,
'#pre_render' => [
[
$this,
'processActivityStatus',
],
],
];
$next = $is_link && $current;
}
$elements['activity_counter'] = [
'#markup' => $this
->t('%passed/%total activities done', [
'%passed' => count($activity_passed),
'%total' => count($activity_status),
]),
];
$elements['activities'] = $activities;
}
$meta
->applyTo($elements);
return $elements;
}
public function processActivityStatus($elements) {
$elements['title'] = [
'#markup' => $elements['#activity']
->label(),
];
return $elements;
}
protected function isModuleCurrent(array $step) : bool {
return $this
->getCurrentGroupContentId() == $step['cid'];
}
protected function getState(array $step) : ?string {
return opigno_learning_path_get_step_status($step, $this
->currentUser()
->id(), TRUE);
}
protected function getLink($step) : Url {
$content_step = OpignoGroupManagedContent::load($step['cid']);
$content_type = $this->opignoGroupContentTypesManager
->createInstance($content_step
->getGroupContentTypeId());
$step_url = $content_type
->getStartContentUrl($content_step
->getEntityId(), $this
->getCurrentGroupId());
return Url::fromRoute($step_url
->getRouteName(), $step_url
->getRouteParameters());
}
public function getLinkToStart($step) : ?Url {
$link = NULL;
$controller = \Drupal::classResolver(LearningPathStepsController::class);
if ($step['step_first']) {
return $this
->getLink($step);
}
else {
$group_id = $this
->getCurrentGroupId();
$parent_content_id = $step["step_previous"]["cid"];
$group = Group::load($group_id);
$course_entity = OpignoGroupManagedContent::load($parent_content_id);
$resp = $controller
->getNextStep($group, $course_entity, FALSE);
if (($resp["#type"] ?? FALSE) != 'html_tag') {
return Url::fromRoute('opigno_learning_path.steps.next', [
'group' => $group_id,
'parent_content' => $parent_content_id,
]);
}
}
return $link;
}
protected function getTrainingAndCourse($step) : array {
$step_training = $this
->getStepTraining($step);
if (!$step_training) {
$step_training = [
'cid' => $step['cid'],
'id' => FALSE,
];
}
$content = $this
->entityTypeManager()
->getStorage('opigno_group_content')
->load($step_training["cid"]);
$training = $content instanceof OpignoGroupManagedContent ? $content
->getGroup() : NULL;
$course = $step_training["id"] ? $this
->entityTypeManager()
->getStorage('group')
->load($step_training["id"]) : FALSE ?: NULL;
$module = $this
->entityTypeManager()
->getStorage('opigno_module')
->load($step["id"]) ?: NULL;
return [
$training,
$course,
$module,
];
}
protected function getStepTraining(array $elements) {
return $elements["parent"] ?? FALSE;
}
public static function trustedCallbacks() {
return [
'processModuleList',
'processActivityList',
'processActivityStatus',
];
}
}