l10n_server-2.x-dev/l10n_community/src/Form/FilterForm.php

l10n_community/src/Form/FilterForm.php
<?php

declare(strict_types=1);

namespace Drupal\l10n_community\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\l10n_community\Controller\L10nCommunityLanguagesController;

/**
 * Translation export form.
 */
final class FilterForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'l10n_community_filter';
  }

  /**
   * {@inheritdoc}
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form_state object.
   *
   * @return array|string[]
   *   The form array.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\TypedData\Exception\MissingDataException
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $user_storage = \Drupal::entityTypeManager()
      ->getStorage('user');
    $project_storage = \Drupal::entityTypeManager()
      ->getStorage('l10n_server_project');
    $release_storage = \Drupal::entityTypeManager()
      ->getStorage('l10n_server_release');
    $project_count = $project_storage
      ->getQuery()
      ->condition('status', 1)
      ->count()->execute();
    /** @var \Drupal\group\Entity\Group $group */
    $group = \Drupal::routeMatch()->getParameter('group');
    $language = \Drupal::languageManager()->getLanguage($group->get('field_translation_language')->first()->getValue()['target_id']);

    $translation_options = [
      L10N_STATUS_ALL => '<' . $this->t('Any') . '>',
      L10N_STATUS_UNTRANSLATED => $this->t('Untranslated'),
      L10N_STATUS_TRANSLATED => $this->t('Translated'),
      L10N_STATUS_IS_TRANSLATION => $this->t('Is translation'),
    ];
    $suggestion_options = [
      L10N_STATUS_ALL => '<' . $this->t('Any') . '>',
      L10N_STATUS_NO_SUGGESTION => $this->t('Has no suggestion'),
      L10N_STATUS_HAS_SUGGESTION => $this->t('Has suggestion'),
      L10N_STATUS_IS_SUGGESTION => $this->t('Is suggestion'),
    ];

    // This form can be submitted multiple times to support AJAX flows.
    // So we set an initial default value set for the form values, if there was
    // none submitted already. Otherwise, the submitted values will take on
    // being the defaults.
    if (empty($form_state->getValues())) {
      $filters = L10nCommunityLanguagesController::buildFilterValues($_GET);
      $form_state->setValues([
        'project' => isset($filters['project']) ? $filters['project'] : '',
        'release' => isset($filters['release']) ? $filters['release'] : 'all',
        'context' => isset($filters['context']) ? $filters['context'] : 'all',
        'status' => isset($filters['status']) ? $filters['status'] : L10N_STATUS_ALL,
        'author' => isset($filters['author']) ? $filters['author'] : '',
        'search' => isset($filters['search']) ? $filters['search'] : '',
        'limit' => isset($filters['limit']) ? $filters['limit'] : 10,
        'sid' => isset($filters['sid']) ? $filters['sid'] : 0,
      ]);
    }

    $form = [
      '#prefix' => '<div class="l10n-server-filter clear-block">',
      '#suffix' => '</div>',
    ];
    $class_is_default_project = empty($form_state->getValue('project')) ? 'is-default' : 'is-not-default';
    if ($pid = $form_state->getValue('project')) {
      $selected_project = $project_storage->load($pid);
    }

    $form['project'] = [
      '#title' => $this->t('Project'),
      '#default_value' => $selected_project ?? NULL,
      '#ajax' => [
        'callback' => '::ajaxReleases',
        'event' => 'change',
        'wrapper' => 'l10n-server-releases',
        'effect' => 'fade',
        'progress' => [
          'type' => 'throbber',
          'message' => $this->t('Getting releases...'),
        ],
      ],
      '#attributes' => ['class' => [$class_is_default_project]],
      '#prefix' => '<div class="filter-widget">',
      '#suffix' => '</div>',
    ];
    if ($project_count <= 30) {
      // Select widget for 1-30 projects.
      $form['project']['#type'] = 'select';
      $form['project']['#options'] = ['all' => $this->t('All')];
      $projects = $project_storage->loadMultiple();
      /** @var \Drupal\l10n_server\Entity\L10nServerProjectInterface $project */
      foreach ($projects as $project) {
        // URI used to shorten the lookup cycle in filter sanitization.
        $form['project']['#options'][$project->getUri()] = $project->label();
      }
    }
    else {
      // Autocomplete field for more than 30 projects.
      $form['project'] += [
        '#type' => 'entity_autocomplete',
        '#target_type' => 'l10n_server_project',
        '#size' => 20,
      ];
    }

    // Always add releases option, so we can update it when
    // needed as the project changes with AJAX.
    $release_options = ['all' => $this->t('All')];
    /** @var \Drupal\l10n_server\Entity\L10nServerProjectInterface $selected_project */
    if (isset($selected_project)) {
      $releases = $release_storage->loadByProperties(['pid' => $selected_project->id()]);
      foreach ($releases as $release) {
        $release_options[$release->id()] = $release->label();
      }
    }

    $class_is_default_release = $form_state->getValue('release') == 'all' ? 'is-default' : 'is-not-default';
    $form['release'] = [
      '#title' => $this->t('Release'),
      '#type' => 'select',
      '#options' => $release_options,
      '#default_value' => $form_state->getValue('release') ?? 'all',
      // Wrapper used to replace release options via AJAX.
      '#prefix' => '<div id="l10n-server-releases">',
      '#suffix' => '</div>',
      '#attributes' => ['class' => [$class_is_default_release]],
    ];

    if (isset($selected_project)
      && $form_state->getValue('release') != 'all') {
      $form['release']['#field_suffix'] = '<div class="start-over-link"><a href="' . Url::fromUri('internal:/group/' . $group->id() . '/reset/' . $selected_project->getUri() . '/' . $form_state->getValue('release'))->toString() . '">' . t('Missing strings?') . '</a></div>';
    }

    if (count($contexts = $this->getContexts()) > 1) {
      $class_is_default_context = $form_state->getValue('context') == 'all' ? 'is-default' : 'is-not-default';
      $form['context'] = [
        '#title' => $this->t('Context'),
        '#type' => 'select',
        '#options' => ['all' => $this->t('All')] + $contexts,
        '#default_value' => $form_state->getValue('context'),
        '#attributes' => ['class' => [$class_is_default_context]],
        '#prefix' => '<div class="break"></div><div class="filter-widget">',
        '#suffix' => '</div><div class="break"></div>',
      ];
    }

    $form['reveal_more_filter'] = [
      '#title' => $this->t('Reveal more filters'),
      '#type' => 'radio',
      '#states' => [
        'visible' => [
          ':input[name="reveal_more_filter"]' => [
            'checked' => FALSE,
          ],
        ],
      ],
    ];

    $form['status'] = [
      '#type' => 'container',
      '#tree' => TRUE,
      '#prefix' => '<div class="' . ($form_state->getValue('status') == L10N_STATUS_ALL ? 'is-default' : 'is-not-default') . '">',
      '#suffix' => '</div>',
      '#attributes' => ['class' => ['status-wrapper']],
      '#states' => [
        'visible' => [
          ':input[name="reveal_more_filter"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];
    
    $form['status']['translation'] = [
      '#title' => $this->t('Status'),
      '#type' => 'select',
      '#options' => $translation_options,
      '#default_value' => $form_state->getValue('status') || (L10N_STATUS_TRANSLATED | L10N_STATUS_UNTRANSLATED | L10N_STATUS_IS_TRANSLATION),
      '#prefix' => '<div class="filter-widget">',
    ];

    $form['status']['suggestion'] = [
      '#type' => 'select',
      '#options' => $suggestion_options,
      '#default_value' => $form_state->getValue('status') || (L10N_STATUS_HAS_SUGGESTION | L10N_STATUS_NO_SUGGESTION | L10N_STATUS_IS_SUGGESTION),
      '#suffix' => '</div>',
    ];

    $class_is_default_author = empty($form_state->getValue('author')) ? 'is-default' : 'is-not-default';

    if ($uid = $form_state->getValue('author')) {
      $selected_author = $user_storage->load($uid);
    }

    $form['author'] = [
      '#type' => 'entity_autocomplete',
      '#title' => $this->t('Submitted by'),
      '#maxlength' => 60,
      '#target_type' => 'user',
      '#default_value' => $selected_author ?? NULL,
      '#size' => 15,
      '#attributes' => ['class' => [$class_is_default_author]],
      '#prefix' => '<div class="filter-widget">',
      '#suffix' => '</div>',
      '#states' => [
        'visible' => [
          ':input[name="reveal_more_filter"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];

    $class_is_default_search = empty($form_state->getValue('search')) ? 'is-default' : 'is-not-default';
    $form['search'] = [
      '#title' => $this->t('Contains'),
      '#type' => 'textfield',
      '#default_value' => $form_state->getValue('search'),
      '#size' => 20,
      '#attributes' => ['class' => [$class_is_default_search]],
      '#prefix' => '<div class="filter-widget">',
      '#suffix' => '</div><div class="break"></div>',
      '#states' => [
        'visible' => [
          ':input[name="reveal_more_filter"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];

    $class_is_default_sid = empty($form_state->getValue('sid')) ? 'is-default' : 'is-not-default';
    $form['sid'] = [
      '#title' => t('String ID'),
      '#type' => 'textfield',
      '#default_value' => empty($form_state->getValue('sid')) ? '' : $form_state->getValue('sid'),
      '#size' => 10,
      '#attributes' => ['class' => [$class_is_default_sid]],
      '#prefix' => '<div class="filter-widget">',
      '#suffix' => '</div>',
      '#states' => [
        'visible' => [
          ':input[name="reveal_more_filter"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];

    $class_is_default_limit = $form_state->getValue('limit') == 10 ? 'is-default' : 'is-not-default';
    $form['limit'] = [
      '#type' => 'select',
      '#title' => t('Limit'),
      '#options' => [5 => 5, 10 => 10, 20 => 20, 30 => 30, 50 => 50],
      '#default_value' => $form_state->getValue('limit'),
      '#attributes' => ['class' => [$class_is_default_limit]],
      '#display_none' => $form_state->getValue('limit') == 10,
      '#prefix' => '<div class="filter-widget">',
      '#suffix' => '</div>',
      '#states' => [
        'visible' => [
          ':input[name="reveal_more_filter"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];

    $form['actions'] = [
      '#type' => 'actions',
      '#prefix' => '<div class="filter-submit">',
      '#suffix' => '</div>',
    ];

    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#name' => 'submit',
      '#value' => $this->t('Filter'),
      '#button_type' => 'primary',
    ];

    $form['actions']['reset'] = [
      '#type' => 'markup',
      '#markup' => '<div class="reset-link"><a href="' . Url::fromUri('internal:/group/' . $group->id() . '/translate')->toString() . '" class="filter-exclude">' . $this->t('Clear all filters') . '</a></div>',
    ];

    $form['#attached']['library'][] = 'l10n_community/forms';
    $form['#attached']['library'][] = 'l10n_community/editor';

    if ($language->getDirection() == LanguageInterface::DIRECTION_RTL) {
      $form['#attached']['library'][] = 'l10n_community/editor-rtl';
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $trigger = $form_state->getTriggeringElement();
    if ($trigger['#name'] === 'reset') {
      // Redirect clearing the filters.
      $route_name = \Drupal::routeMatch()->getRouteName();
      $route_parameters = [
        'group' => \Drupal::routeMatch()->getParameter('group')->id(),
      ];
      $form_state->setRedirect($route_name, $route_parameters);
    }

    if ($trigger['#name'] === 'submit') {
      // Redirect keeping the relevant filters intact in the URL.
      $route_name = \Drupal::routeMatch()->getRouteName();
      $route_parameters = [
        'group' => \Drupal::routeMatch()->getParameter('group')->id(),
      ];
      $options = [
        'query' => L10nCommunityLanguagesController::buildFilterValues([
          'project' => $form_state->getValue('project'),
          'status' => $form_state->getValue('status'),
          'release' => $form_state->getValue('release'),
          'search' => $form_state->getValue('search'),
          'author' => $form_state->getValue('author'),
          'context' => $form_state->getValue('context'),
          'limit' => $form_state->getValue('limit'),
          'sid' => $form_state->getValue('sid'),
        ]),
      ];
      $form_state->setRedirect($route_name, $route_parameters, $options);
    }
  }

  /**
   * Get all contexts from the database.
   *
   * @return array
   *   Array of context values.
   */
  private function getContexts() {
    $contexts = [];
    $result = \Drupal::database()
      ->query("SELECT DISTINCT context FROM {l10n_server_string} ORDER BY context");
    foreach ($result as $context) {
      $contexts[empty($context->context) ? 'none' : $context->context] = empty($context->context) ? $this->t('No context') : $context->context;
    }
    return $contexts;
  }

  /**
   * Ajax callback.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form_state object.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public static function ajaxReleases(array &$form, FormStateInterface $form_state) {
    $release_options = [];
    if ($pid = $form_state->getValue('project')) {
      $releases = \Drupal::entityTypeManager()
        ->getStorage('l10n_server_release')
        ->loadByProperties(['pid' => $pid]);
      foreach ($releases as $release) {
        $release_options[$release->id()] = t('@version only', [
          '@version' => $release->getVersion(),
        ]);
      }
      krsort($release_options);
    }
    $release_options = ['all' => t('All')] + $release_options;
    $form['release']['#options'] = $release_options;
    return $form['release'];
  }

}

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

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