Commit df204de1 authored by Oleksandr Horbatiuk's avatar Oleksandr Horbatiuk 🧩
Browse files

Issue #3256927 by chmez: Restore the possibility of joining to course directly by an anonymous user

parent dfdcc035
Loading
Loading
Loading
Loading
+60 −43
Original line number Diff line number Diff line
@@ -30,7 +30,8 @@ use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\search_api\Query\QueryInterface;
use Drupal\social_course\Entity\CourseEnrollmentInterface;
use Drupal\social_course\Plugin\Join\SocialCourseJoin;
use Drupal\social_course\Plugin\Join\SocialCourseDirectJoin;
use Drupal\social_course\Plugin\Join\SocialCourseInviteJoin;
use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\views\ViewExecutable;

@@ -809,9 +810,16 @@ function social_course_change_form_field_texts(array &$form): void {
 * Implements hook_social_group_join_info_alter().
 */
function social_course_social_group_join_info_alter(array &$info): void {
  foreach (['course_basic', 'course_advanced'] as $type) {
  if (isset($info['social_group_direct_join'])) {
    $info['social_group_direct_join']['class'] = SocialCourseDirectJoin::class;
  }

  /** @var \Drupal\social_course\CourseWrapperInterface $wrapper */
  $wrapper = \Drupal::service('social_course.course_wrapper');

  foreach ($wrapper->getAvailableBundles() as $type) {
    if (\Drupal::moduleHandler()->moduleExists("social_{$type}_invite")) {
      $info['social_group_invite_join']['class'] = SocialCourseJoin::class;
      $info['social_group_invite_join']['class'] = SocialCourseInviteJoin::class;

      break;
    }
@@ -825,10 +833,12 @@ function social_course_social_group_join_method_info_alter(
  array &$items,
  ?FieldableEntityInterface $entity
): void {
  if ($entity !== NULL && $entity->getEntityTypeId() === 'group') {
    /** @var \Drupal\social_course\CourseWrapperInterface $wrapper */
    $wrapper = \Drupal::service('social_course.course_wrapper');

    if (
    $entity !== NULL &&
    $entity->getEntityTypeId() === 'group' &&
    in_array($type = $entity->bundle(), ['course_basic', 'course_advanced']) &&
      in_array($type = $entity->bundle(), $wrapper->getAvailableBundles()) &&
      \Drupal::moduleHandler()->moduleExists("social_{$type}_request")
    ) {
      $weight = $items['added']['weight'];
@@ -836,18 +846,22 @@ function social_course_social_group_join_method_info_alter(
      $items['request']['weight'] = $weight;
    }
  }
}

/**
 * Implements hook_social_group_join_method_usage().
 */
function social_course_social_group_join_method_usage(): array {
  $items = $types = [];
  $items = [];

  foreach (['course_basic', 'course_advanced'] as $type) {
    if (\Drupal::moduleHandler()->moduleExists("social_{$type}_request")) {
      $types[] = $type;
    }
  }
  /** @var \Drupal\social_course\CourseWrapperInterface $wrapper */
  $wrapper = \Drupal::service('social_course.course_wrapper');

  $types = array_filter(
    $wrapper->getAvailableBundles(),
    fn (string $type): bool =>
      \Drupal::moduleHandler()->moduleExists("social_{$type}_request"),
  );

  if (!empty($types)) {
    $items[] = [
@@ -864,23 +878,30 @@ function social_course_social_group_join_method_usage(): array {
 * Implements hook_social_group_types_alter().
 */
function social_course_social_group_types_alter(array &$social_group_types): void {
  $social_group_types[] = 'course_basic';
  $social_group_types[] = 'course_advanced';
  /** @var \Drupal\social_course\CourseWrapperInterface $wrapper */
  $wrapper = \Drupal::service('social_course.course_wrapper');

  $social_group_types = array_merge(
    $social_group_types,
    $wrapper->getAvailableBundles(),
  );
}

/**
 * Implements hook_social_group_hide_types_alter().
 */
function social_course_social_group_hide_types_alter(array &$hidden_types): void {
  $hidden_types[] = 'course_basic';
  $hidden_types[] = 'course_advanced';
  /** @var \Drupal\social_course\CourseWrapperInterface $wrapper */
  $wrapper = \Drupal::service('social_course.course_wrapper');

  $hidden_types = array_merge($hidden_types, $wrapper->getAvailableBundles());
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function social_course_form_views_exposed_form_alter(array &$form, FormStateInterface $form_state): void {
  if ($form_state->get('view')->id() == 'search_content') {
  if ($form_state->get('view')->id() === 'search_content') {
    foreach (['course_article', 'course_section', 'course_video'] as $type) {
      unset($form['type']['#options'][$type]);
    }
@@ -977,11 +998,11 @@ function social_course_preprocess_fieldset(array &$variables): void {
 */
function social_course_preprocess_group(array &$variables): void {
  $group = $variables['group'];
  /** @var \Drupal\social_course\CourseWrapper $course_wrapper */

  /** @var \Drupal\social_course\CourseWrapperInterface $course_wrapper */
  $course_wrapper = \Drupal::service('social_course.course_wrapper');
  $bundles = $course_wrapper->getAvailableBundles();

  if (in_array($group->bundle(), $bundles)) {
  if (in_array($group->bundle(), $course_wrapper->getAvailableBundles())) {
    $course_wrapper->setCourse($group);
    $account = \Drupal::currentUser();

@@ -993,8 +1014,10 @@ function social_course_preprocess_group(array &$variables): void {
    $variables['course_sections'] = count($sections);

    $variables['finished_sections'] = 0;

    foreach ($sections as $section) {
      $status = $course_wrapper->getSectionStatus($section, $account);

      if ($status === CourseEnrollmentInterface::FINISHED) {
        $variables['finished_sections'] += 1;
      }
@@ -1010,6 +1033,7 @@ function social_course_preprocess_group(array &$variables): void {

    if ($group->getMember($account)) {
      $course_wrapper->setCourse($group);

      switch ($course_wrapper->getCourseStatus($account)) {
        case CourseEnrollmentInterface::NOT_STARTED:
          $variables['course_status'] = 'enrolled';
@@ -1024,6 +1048,7 @@ function social_course_preprocess_group(array &$variables): void {
          break;
      }
    }

    // Add teaser tag variable.
    if (in_array($variables['view_mode'], ['teaser', 'featured'])) {
      $variables['title_prefix']['teaser_tag'] = [
@@ -1031,24 +1056,16 @@ function social_course_preprocess_group(array &$variables): void {
      ];
    }

    if (
      $group->hasField('field_flexible_group_visibility') &&
      $group->hasField('field_group_allowed_join_method')
    ) {
      $visibility_values = $group->getFieldValue('field_flexible_group_visibility', 'value');
      $allowed_options = $group->getFieldValue('field_group_allowed_join_method', 'value');

      if ($visibility_values === 'public' && $allowed_options === 'direct' && $account->isAnonymous()) {
        $variables['anonymous_join'] = TRUE;
        $variables['group_operations_url'] = Url::fromRoute('social_course.join.anonymous', ['group' => $group->id()]);
        $variables['#attached']['library'][] = 'core/drupal.dialog.ajax';
        $variables['#attached']['library'][] = 'social_group_request/social_group_popup';
      }
    }

    if (isset($variables['group_settings_help'])) {
      $help_text_markup = &$variables['group_settings_help'];
      $help_text_markup = t(str_replace([t('Group')->render(), t('group')->render()], [t('Course')->render(), t('course')->render()], $help_text_markup));

      $help_text_markup = t(
        str_replace(
          [t('Group')->render(), t('group')->render()],
          [t('Course')->render(), t('course')->render()],
          $help_text_markup,
        ),
      );
    }
  }
}
+4 −3
Original line number Diff line number Diff line
@@ -31,12 +31,13 @@ social_course.next_material:
        type: entity:group
      node:
        type: entity:node
social_course.join.anonymous:
  path: '/course/{group}/join-anonymous'

social_course.join:
  path: '/course/{group}/join'
  defaults:
    _controller: '\Drupal\social_course\Controller\CourseJoinController::anonymousRequestMembership'
  requirements:
    _access: 'TRUE'
    _user_is_logged_in: 'FALSE'
  options:
    parameters:
      group:
+17 −34
Original line number Diff line number Diff line
@@ -5,8 +5,6 @@ namespace Drupal\social_course\Controller;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityFormBuilderInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\group\Entity\GroupInterface;
use Drupal\social_course\Form\CourseJoinAnonymousForm;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -16,55 +14,40 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
 */
class CourseJoinController extends ControllerBase {

  /**
   * GroupRequestController constructor.
   *
   * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
   *   The form builder.
   * @param \Drupal\Core\Entity\EntityFormBuilderInterface $entity_form_builder
   *   The entity form builder.
   */
  public function __construct(
    FormBuilderInterface $form_builder,
    EntityFormBuilderInterface $entity_form_builder
  ) {
    $this->formBuilder = $form_builder;
    $this->entityFormBuilder = $entity_form_builder;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): self {
    return new static(
      $container->get('form_builder'),
      $container->get('entity.form_builder')
    );
    $instance = parent::create($container);

    $instance->formBuilder = $container->get('form_builder');

    return $instance;
  }

  /**
   * Callback to request membership for anonymous.
   *
   * @param \Drupal\group\Entity\GroupInterface $group
   *   The group entity object.
   */
  public function anonymousRequestMembership(GroupInterface $group): AjaxResponse {
    $request_form = $this->formBuilder()->getForm(CourseJoinAnonymousForm::class, $group);

    $response = new AjaxResponse();
    $response->addCommand(new OpenModalDialogCommand(
    return (new AjaxResponse())
      ->addCommand(new OpenModalDialogCommand(
        $this->t(
          'Join a "@group_title" course',
          [
            '@group_title' => $group->label(),
          ]
          ['@group_title' => $group->label()],
        ),
        $this->formBuilder()->getForm(
          CourseJoinAnonymousForm::class,
          $group,
        ),
        $request_form,
        [
          'width' => '337px',
          'dialogClass' => 'social_group-popup social_group-popup--anonymous',
        ]
      )
        ],
      ),
    );

    return $response;
  }

}
+49 −26
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

namespace Drupal\social_course\Form;

use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
@@ -17,30 +18,35 @@ use Symfony\Component\HttpFoundation\RequestStack;
class CourseJoinAnonymousForm extends FormBase {

  /**
   * Group entity.
   *
   * @var \Drupal\group\Entity\GroupInterface
   * The group entity object.
   */
  protected $group;
  protected ?GroupInterface $group;

  /**
   * Request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   * The module handler.
   */
  protected $requestStack;
  private ModuleHandlerInterface $moduleHandler;

  /**
   * GroupRequestMembershipRejectForm constructor.
   * CourseJoinAnonymousForm constructor.
   *
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
   */
  public function __construct(TranslationInterface $string_translation, RequestStack $request_stack) {
    $this->setStringTranslation($string_translation);
    $this->requestStack = $request_stack;
  public function __construct(
    TranslationInterface $string_translation,
    RequestStack $request_stack,
    ModuleHandlerInterface $module_handler
  ) {
    $this
      ->setStringTranslation($string_translation)
      ->setRequestStack($request_stack);

    $this->moduleHandler = $module_handler;
  }

  /**
@@ -49,7 +55,8 @@ class CourseJoinAnonymousForm extends FormBase {
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('string_translation'),
      $container->get('request_stack')
      $container->get('request_stack'),
      $container->get('module_handler'),
    );
  }

@@ -63,20 +70,34 @@ class CourseJoinAnonymousForm extends FormBase {
  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, GroupInterface $group = NULL) {
    $this->group = $group;

  public function buildForm(
    array $form,
    FormStateInterface $form_state,
    GroupInterface $group = NULL
  ) {
    $form['description'] = [
      '#type' => 'html_tag',
      '#tag' => 'p',
      '#value' => $this->t('In order to join a course, please first sign up or log in.'),
    ];

    $previous_url = $this->requestStack->getCurrentRequest()->headers->get('referer');
    $form['actions']['#type'] = 'actions';

    if (($this->group = $group) !== NULL) {
      $previous_url = $this->getRequest()->headers->get('referer');
      $request = Request::create($previous_url);
      $referer_path = $request->getRequestUri();
    $dest = Url::fromRoute('social_group_quickjoin.quickjoin_group', ['group' => $group->id()])->toString();
    $form['actions']['#type'] = 'actions';

      if ($this->moduleHandler->moduleExists('social_group_quickjoin')) {
        $destination = Url::fromRoute(
          'social_group_quickjoin.quickjoin_group',
          ['group' => $group->id()],
        )->toString();

        $referer_path .= '?' . $destination;
      }
    }

    $form['actions']['sign_up'] = [
      '#type' => 'link',
      '#title' => $this->t('Sign up'),
@@ -88,9 +109,10 @@ class CourseJoinAnonymousForm extends FormBase {
          'waves-btn',
        ],
      ],
      '#url' => Url::fromRoute('user.register', [
        'destination' => $referer_path . '?' . $dest,
      ]),
      '#url' => Url::fromRoute(
        'user.register',
        isset($referer_path) ? ['destination' => $referer_path] : [],
      ),
    ];

    $form['actions']['log_in'] = [
@@ -104,9 +126,10 @@ class CourseJoinAnonymousForm extends FormBase {
          'waves-btn',
        ],
      ],
      '#url' => Url::fromRoute('user.login', [
        'destination' => $dest,
      ]),
      '#url' => Url::fromRoute(
        'user.login',
        isset($destination) ? ['destination' => $destination] : [],
      ),
    ];

    return $form;
+87 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\social_course\Plugin\Join;

use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Url;
use Drupal\social_course\CourseWrapperInterface;
use Drupal\social_group\EntityMemberInterface;
use Drupal\social_group\Plugin\Join\SocialGroupDirectJoin;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a join plugin instance for joining directly.
 */
class SocialCourseDirectJoin extends SocialGroupDirectJoin {

  /**
   * The course wrapper.
   */
  private CourseWrapperInterface $wrapper;

  /**
   * The module handler.
   */
  private ModuleHandlerInterface $moduleHandler;

  /**
   * {@inheritdoc}
   */
  public static function create(
    ContainerInterface $container,
    array $configuration,
    $plugin_id,
    $plugin_definition
  ): self {
    /** @var self $instance */
    $instance = parent::create(
      $container,
      $configuration,
      $plugin_id,
      $plugin_definition,
    );

    $instance->wrapper = $container->get('social_course.course_wrapper');
    $instance->moduleHandler = $container->get('module_handler');

    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function actions(EntityMemberInterface $entity, array &$variables): array {
    $items = parent::actions($entity, $variables);

    if (
      !$items &&
      $this->currentUser->isAnonymous() &&
      $entity->getEntityTypeId() === 'group' &&
      in_array($entity->bundle(), $this->wrapper->getAvailableBundles()) &&
      $entity->hasField('field_flexible_group_visibility') &&
      $entity->hasField('field_group_allowed_join_method') &&
      $entity->getFieldValue('field_flexible_group_visibility', 'value') === 'public'
    ) {
      $url = Url::fromRoute('social_course.join', ['group' => $entity->id()]);

      if ($url->access()) {
        $items[] = [
          'label' => $this->t('Join'),
          'url' => $url,
          'attributes' => [
            'class' => ['btn-accent', 'use-ajax'],
          ],
        ];

        $variables['#attached']['library'][] = 'core/drupal.dialog.ajax';

        if ($this->moduleHandler->moduleExists('social_group_request')) {
          $variables['#attached']['library'][] = 'social_group_request/social_group_popup';
        }
      }
    }

    return $items;
  }

}
Loading