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() ->accessCheck(TRUE) -> count () ->accessCheck(FALSE) ->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.' , [ ]); } $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 * Return a render array with a list of groups a user is a member. * * @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 ), ]; } } } |