l10n_server-2.x-dev/l10n_community/src/Form/ExportForm.php
l10n_community/src/Form/ExportForm.php
<?php declare(strict_types=1); namespace Drupal\l10n_community\Form; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; /** * Translation export form. */ class ExportForm extends FormBase { /** * {@inheritdoc} */ public function getFormId() { return 'l10n_community_export'; } /** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, $uri = NULL, $langcode = NULL) { $project_storage = \Drupal::entityTypeManager() ->getStorage('l10n_server_project'); // When project was preset from path, disable the selector. $hide_projects = isset($uri); // Set initial form state, so we can consistently use that. if (!$form_state->getValues()) { /** @var \Drupal\l10n_server\Entity\L10nServerProjectInterface $project */ if ($uri && $project = $project_storage->loadByProperties(['uri' => $uri])) { $form_state->setValues([ 'project' => $project->id(), 'release' => isset($_GET['release']) ? $_GET['release'] : 'all', ]); } elseif (isset($_GET['project']) && $projects = $project_storage->loadByProperties(['uri' => $_GET['project']])) { /** @var \Drupal\l10n_server\Entity\L10nServerProjectInterface $project */ $project = reset($projects); $form_state->setValues([ 'project' => $project->id(), 'release' => isset($_GET['release']) ? $_GET['release'] : 'all', ]); } } $form = []; if ($hide_projects) { // This only happens if we have a project to export via $uri. // In this case, $uri is already verified via the menu system. $form['project'] = [ '#type' => 'value', '#value' => $form_state->getValue('project'), ]; } else { $form['project'] = [ '#title' => t('Project'), '#required' => TRUE, '#default_value' => $project ?? NULL, '#ajax' => [ // 'event' missing, Drupal will apply the per-#type defaults. 'callback' => '::ajaxReleases', 'event' => 'change', 'wrapper' => 'l10n-server-releases', 'effect' => 'fade', 'progress' => [ 'type' => 'throbber', 'message' => $this->t('Getting releases...'), ], ], ]; $project_count = $project_storage ->getQuery() ->condition('status', 1) ->count() ->execute(); 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'] = []; $projects = $project_storage->loadMultiple(); foreach ($projects as $project) { // Title used to conform to the autocomplete behavior. $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', ]; } } $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 releases merged')] + $release_options; $form['release'] = [ '#title' => $this->t('Release'), '#required' => TRUE, '#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>', ]; if (isset($langcode)) { $form['langcode'] = [ '#type' => 'value', '#value' => $langcode, ]; // Only include the type selector if we are not presenting a template // export page (which does not have a language). $language = \Drupal::languageManager()->getLanguage($langcode); $form['translations'] = [ '#title' => $this->t('Add @language translations', ['@language' => $language->getName()]), '#type' => 'checkbox', '#default_value' => 1, ]; $form['suggestions'] = [ '#title' => $this->t('Add @language suggestions', ['@language' => $language->getName()]), '#type' => 'checkbox', '#description' => t('For untranslated strings, the first suggestion will be exported as a fuzzy translation. All other suggestions are exported in comments.'), ]; $form['verbose'] = [ '#title' => $this->t('Verbose output'), '#type' => 'checkbox', '#description' => t('Verbose files are ideal for desktop editing, compact files are better for download size.'), '#default_value' => 1, ]; } $form['submit'] = [ '#type' => 'submit', '#value' => isset($langcode) ? t('Export Gettext file') : t('Export Gettext template'), ]; return $form; } /** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $project_storage = \Drupal::entityTypeManager() ->getStorage('l10n_server_project'); $release_storage = \Drupal::entityTypeManager() ->getStorage('l10n_server_release'); // This was validated to work in the validation code. /** @var \Drupal\l10n_server\Entity\L10nServerProjectInterface $project */ $project = $project_storage->load($form_state->getValue('project')); if (!$form_state->getValue('release')) { $form_state->setErrorByName('release', $this->t('Please choose a release or opt to export for all releases.')); $form_state['redirect'] = [$_GET['q'], ['project' => $project->getUri()]]; return; } elseif ($form_state->getValue('release') != 'all') { $releases = $release_storage->loadByProperties([ 'pid' => $project->id(), 'rid' => $form_state->getValue('release'), ]); if (!$releases) { $form_state->setErrorByName('release', $this->t('Invalid release chosen.')); return; } } $language = NULL; if ($langcode = $form_state->getValue('langcode')) { $language = \Drupal::languageManager() ->getLanguage($langcode); } // Generate tarball or PO file and get file name. /** @var \Drupal\l10n_community\L10nExporter $exporter */ $exporter = \Drupal::service('l10n_community.exporter'); $export_result = $exporter->export( $project->getUri(), ($form_state->getValue('release') == 'all' ? NULL : $form_state->getValue('release')), $language, empty($form_state->getValue('translations')), empty($form_state->getValue('verbose')), FALSE, empty($form_state->getValue('suggestions')) ); if (isset($export_result) && is_array($export_result)) { // If we got an array back from the export build, tear that into pieces. [$mime_type, $file_name, $serve_name, $sid_count] = $export_result; header('Content-Disposition: attachment; filename=' . $serve_name); header('Content-Type: ' . $mime_type); echo file_get_contents($file_name); unlink($file_name); die(); } else { // Messages should already be recorded about any build errors. } } /** * 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 releases merged')] + $release_options; $form['release']['#options'] = $release_options; return $form['release']; } }