l10n_server-2.x-dev/l10n_community/src/Form/PickGoForm.php
l10n_community/src/Form/PickGoForm.php
<?php declare(strict_types=1); namespace Drupal\l10n_community\Form; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; use Drupal\group\GroupMembershipLoaderInterface; use Drupal\language\Entity\ConfigurableLanguage; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a Localization community UI form. */ final class PickGoForm extends FormBase { /** * Constructor. * * @param \Drupal\Core\Database\Connection $connection * The database connection. * @param \Drupal\Core\Session\AccountInterface $current_user * The current user. * @param \Drupal\group\GroupMembershipLoaderInterface $group_membership_loader * The group membership loader. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * The language manager. * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager * The entity type manager. */ public function __construct( private readonly Connection $connection, private readonly AccountInterface $current_user, private readonly GroupMembershipLoaderInterface $group_membership_loader, private readonly ModuleHandlerInterface $module_handler, private readonly LanguageManagerInterface $language_manager, private readonly EntityTypeManagerInterface $entity_type_manager ) { } /** * {@inheritdoc} */ public static function create(ContainerInterface $container): self { return new PickGoForm( $container->get('database'), $container->get('current_user'), $container->get('group.membership_loader'), $container->get('module_handler'), $container->get('language_manager'), $container->get('entity_type.manager') ); } /** * {@inheritdoc} */ public function getFormId(): string { return 'l10n_community_pick_go'; } /** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state): array { $project_count = $this->entity_type_manager ->getStorage('l10n_server_project') ->getQuery() ->count() ->execute(); $language_list = []; foreach ($this->language_manager->getLanguages() as $langcode => $language) { // Need to load this again to get access to the third party settings :/. $language = ConfigurableLanguage::load($langcode); if ($language->getThirdPartySetting('l10n_pconfig', 'formula')) { $language_list[$langcode] = $this->t("@language", [ '@language' => $language->getName(), ]); } } if (!count($language_list) || !$project_count) { $plural_config_tip = ''; if (!$this->module_handler->moduleExists('l10n_pconfig')) { $plural_config_tip = ' ' . $this->t('The <a href="@plural_config">Plural formula configurator</a> module is recommended for plural formula setup.', [ '@plural_config' => 'https://drupal.org/project/l10n_pconfig', ]); } $form['dummy'] = [ '#markup' => $this->t('No languages with plural formulas defined or no projects scanned yet. Check the <a href="@languages">configuration of languages</a>, <a href="@connectors">list of connectors</a> and <a href="@projects">projects</a>.', [ '@languages' => Url::fromUri('internal:/admin/config/regional/language')->toString(), '@connectors' => Url::fromUri('internal:/admin/config/l10n-server/connectors')->toString(), '@projects' => Url::fromUri('internal:/admin/localization/projects')->toString(), ]) . $plural_config_tip, ]; return $form; } $default_language = ''; if ($this->module_handler->moduleExists('l10n_groups')) { // We are dealing with a groups based permission model. $form['groups'] = $this->pickGo(); if ( isset($form['groups']['#l10n_groups']) && is_array($form['groups']['#l10n_groups']) ) { // Pick the first language as default. Most people are only member of // one language, so this should be a safe default. $default_language = current($form['groups']['#l10n_groups']); } } if (count($language_list) > 1) { // If more than one language. $form['langcode'] = [ // For three or less languages, display radio buttons, select otherwise. '#type' => (count($language_list) <= 3) ? 'radios' : 'select', '#title' => $this->t('Pick a language'), '#options' => ['' => $this->t('All')] + $language_list, '#description' => $this->t('Alternatively you can <a href="@explore">explore languages</a>.', [ '@explore' => Url::fromUri('internal:/translate/languages')->toString(), ]), '#default_value' => $default_language, ]; } else { // Only one language, store as form value. $language_code = key($language_list); $language_name = $language_list[$language_code]; $form['langcode'] = [ '#type' => 'value', '#value' => $language_code, ]; } if (count($language_list) > 1) { $projects_title = $this->current_user->hasPermission('browse translations') ? $this->t('And/or pick a project') : $this->t('Or pick a project'); } else { $projects_title = $this->t('Pick a project for @language translation', [ '@language' => $language_name, ]); } $form['project'] = [ '#title' => $projects_title, '#description' => $this->t('Alternatively you can <a href="@explore">explore projects</a>.', [ '@explore' => Url::fromUri('internal:/translate/projects')->toString(), ]), '#default_value' => $form_state->getValue('project'), ]; if ($project_count <= 30) { // Radio box widget for as much as 5 projects, select widget for 5-30 // projects. $form['project']['#type'] = ($project_count <= 5 ? 'radios' : 'select'); $form['project']['#options'] = ['' => $this->t('All')]; $projects = \Drupal::entityTypeManager() ->getStorage('l10n_server_project') ->loadMultiple(); foreach ($projects as $project) { // Title used to conform to the autocomplete behavior. $form['project']['#options'][$project->id()] = $project->label(); } } else { // Autocomplete field for more than 30 projects. $form['project'] += [ '#type' => 'entity_autocomplete', '#target_type' => 'l10n_server_project', ]; } $form['actions'] = [ '#type' => 'actions', ]; $form['actions']['submit'] = [ '#type' => 'submit', '#value' => $this->t('Go there'), ]; return $form; } /** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state): void { if ( empty($form_state->getValue('project')) && empty($form_state->getValue('langcode')) ) { // We require at least one to be selected to be effective. $form_state->setErrorByName('langcode', $this->t('At least select a language or a project.')); } } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state): void { $langcode = $form_state->getValue('langcode'); $pid = $form_state->getValue('project'); $redirect_url = NULL; $uri = $this->connection ->query( "SELECT uri FROM {l10n_server_project} WHERE pid = :pid", [':pid' => $form_state->getValue('project')] )->fetchField(); if ( !empty($pid) && $uri ) { // Project surely selected, possibly with language too. if (!empty($langcode) && $this->current_user->hasPermission('browse translations')) { $redirect_url = Url::fromUri('internal:/translate/languages/' . $langcode . '/translate', ['query' => ['project' => $uri]]); } else { // Only project set or both language and project set, // no access to browse > go to project. $redirect_url = Url::fromUri('internal:/translate/projects/' . $uri); } } elseif (!empty($langcode)) { // Only language set. $redirect_url = Url::fromUri('internal:/translate/languages/' . $langcode); } if ($redirect_url) { $form_state->setRedirectUrl($redirect_url); } } /** * List groups a user is a member of to help jump there. * * @return array * * @throws \Drupal\Core\Entity\EntityMalformedException * @throws \Drupal\Core\TypedData\Exception\MissingDataException */ private function pickGo(): array { $group_memberships = $this->group_membership_loader->loadByUser($this->current_user->getAccount()); if (empty($group_memberships)) { return []; } $l10n_groups = []; foreach ($group_memberships as $group_membership) { $group = $group_membership->getGroup(); if ($group->getGroupType()->id() === 'translation') { $l10n_groups[$group->get('field_translation_language')->first()->getValue()['target_id']] = $this->t('<a href="@url">@name</a>', [ '@name' => $group->label(), '@url' => $group->toUrl()->toString(), ]); } } if (!empty($l10n_groups)) { return [ '#markup' => '<span>' . $this->formatPlural(count($l10n_groups), $this->t('Your group'), $this->t('Your groups')) . '</span><p>' . implode(', ', $l10n_groups) . '</p>', '#l10n_groups' => array_keys($l10n_groups), ]; } } }