Form controller for the job edit forms.
Expanded class hierarchy of JobForm
class JobForm extends TmgmtFormBase {
/**
* @var \Drupal\tmgmt\JobInterface
*/
protected $entity;
/**
* @var \Drupal\tmgmt\JobQueue
*/
protected $jobQueue;
/**
* @var \Drupal\tmgmt\JobCheckoutManager
*/
protected $jobCheckoutManager;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$form = parent::create($container);
$form->jobQueue = $container
->get('tmgmt.queue');
$form->jobCheckoutManager = $container
->get('tmgmt.job_checkout_manager');
return $form;
}
/**
* {@inheritdoc}
*/
public function form(array $form, FormStateInterface $form_state) {
// If the job is submittable and is in the queue, display the progress.
if ($this->entity
->isSubmittable() && $this->jobQueue
->isJobInQueue($this->entity) && $this->jobQueue
->count() + $this->jobQueue
->getProcessed() > 1) {
$total = $this->jobQueue
->getProcessed() + $this->jobQueue
->count();
$percent = $this->jobQueue
->getProcessed() ? round($this->jobQueue
->getProcessed() / $total * 100, 0) : 3;
$form['progress'] = [
'#theme' => 'progress_bar',
'#attached' => [
'library' => 'tmgmt/admin',
],
'#percent' => $percent,
'#weight' => -100,
];
$form['progress_details'] = [
'#type' => 'details',
'#title' => $this
->getStringTranslation()
->formatPlural($this->jobQueue
->count(), '@count job pending', '@count jobs pending'),
'#open' => FALSE,
'#weight' => -99,
];
$translation = $this
->getStringTranslation();
$item_labels = array_map(function (JobInterface $job) use ($translation) {
if (!$job
->getTargetLangcode() || $job
->getTargetLangcode() == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
$target = '?';
}
else {
$target = $job
->getTargetLanguage()
->getName();
}
return $translation
->translate('@label, @source to @target', [
'@label' => $job
->label(),
'@source' => $job
->getSourceLanguage()
->getName(),
'@target' => $target,
]);
}, $this->jobQueue
->getAllJobs());
$form['progress_details']['job_list'] = [
'#theme' => 'item_list',
'#items' => $item_labels,
];
}
$job = $this->entity;
// Handle source language.
$available['source_language'] = tmgmt_available_languages();
$job->source_language = $form_state
->getValue('source_language') ?: $job
->getSourceLangcode();
// Handle target language.
$available['target_language'] = tmgmt_available_languages();
$job->target_language = $form_state
->getValue('target_language') ?: $job
->getTargetLangcode();
// Remove impossible combinations so we don't end up with the same source and
// target language in the dropdowns.
foreach (array(
'source_language' => 'target_language',
'target_language' => 'source_language',
) as $field_name => $opposite) {
if (!empty($job
->get($field_name)->value)) {
unset($available[$opposite][$job
->get($field_name)->value]);
}
}
$target = '?';
$source = $job
->getSourceLanguage() ? $job
->getSourceLanguage()
->getName() : '?';
if (!$job
->getTargetLangcode() || $job
->getTargetLangcode() == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
$job->target_language = key($available['target_language']);
$target = '?';
}
elseif ($job
->getTargetLanguage()) {
$target = $job
->getTargetLanguage()
->getName();
}
$states = Job::getStates();
// Set the title of the page to the label and the current state of the job.
$form['#title'] = t('@title (@source to @target, @state)', array(
'@title' => $job
->label(),
'@source' => $source,
'@target' => $target,
'@state' => $states[$job
->getState()],
));
$form = parent::form($form, $form_state);
$form['info'] = array(
'#type' => 'container',
'#attributes' => array(
'class' => array(
'tmgmt-ui-job-info',
'clearfix',
),
),
'#weight' => 0,
);
// Check for label value and set for dynamically change.
if ($form_state
->getValue('label') && $form_state
->getValue('label') == $job
->label()) {
$job->label = NULL;
$job->label = $job
->label();
$form_state
->setValue('label', $job
->label());
}
$form['label']['widget'][0]['value']['#description'] = t('You can provide a label for this job in order to identify it easily later on. Or leave it empty to use the default one.');
$form['label']['#group'] = 'info';
$form['label']['#prefix'] = '<div id="tmgmt-ui-label">';
$form['label']['#suffix'] = '</div>';
// Make the source and target language flexible by showing either a select
// dropdown or the plain string (if preselected).
if ($job
->getSourceLangcode() || !$job
->isSubmittable()) {
$form['info']['source_language'] = array(
'#title' => t('Source language'),
'#type' => 'item',
'#markup' => isset($available['source_language'][$job
->getSourceLangcode()]) ? $available['source_language'][$job
->getSourceLangcode()] : '',
'#prefix' => '<div id="tmgmt-ui-source-language" class="tmgmt-ui-source-language tmgmt-ui-info-item">',
'#suffix' => '</div>',
'#value' => $job
->getSourceLangcode(),
);
}
else {
$form['info']['source_language'] = array(
'#title' => t('Source language'),
'#type' => 'select',
'#options' => $available['source_language'],
'#default_value' => $job
->getSourceLangcode(),
'#required' => TRUE,
'#prefix' => '<div id="tmgmt-ui-source-language" class="tmgmt-ui-source-language tmgmt-ui-info-item">',
'#suffix' => '</div>',
'#ajax' => array(
'callback' => array(
$this,
'ajaxLanguageSelect',
),
),
);
}
if (!$job
->isSubmittable()) {
$form['info']['target_language'] = array(
'#title' => t('Target language'),
'#type' => 'item',
'#markup' => isset($available['target_language'][$job
->getTargetLangcode()]) ? $available['target_language'][$job
->getTargetLangcode()] : '',
'#prefix' => '<div id="tmgmt-ui-target-language" class="tmgmt-ui-target-language tmgmt-ui-info-item">',
'#suffix' => '</div>',
'#value' => $job
->getTargetLangcode(),
);
}
else {
$form['info']['target_language'] = array(
'#title' => t('Target language'),
'#type' => 'select',
'#options' => $available['target_language'],
'#default_value' => $job
->getTargetLangcode(),
'#required' => TRUE,
'#prefix' => '<div id="tmgmt-ui-target-language" class="tmgmt-ui-target-language tmgmt-ui-info-item">',
'#suffix' => '</div>',
'#ajax' => array(
'callback' => array(
$this,
'ajaxLanguageSelect',
),
'wrapper' => 'tmgmt-ui-target-language',
),
);
}
// Display selected translator for already submitted jobs.
if (!$job
->isSubmittable() && !$job
->isContinuous()) {
$form['info']['translator'] = array(
'#type' => 'item',
'#title' => t('Provider'),
'#markup' => $job
->getTranslatorLabel(),
'#prefix' => '<div class="tmgmt-ui-translator tmgmt-ui-info-item">',
'#suffix' => '</div>',
'#value' => $job
->getTranslatorId(),
);
}
if (!$job
->isContinuous()) {
$form['info']['word_count'] = array(
'#type' => 'item',
'#title' => t('Total words'),
'#markup' => number_format($job
->getWordCount()),
'#prefix' => '<div class="tmgmt-ui-word-count tmgmt-ui-info-item">',
'#suffix' => '</div>',
);
$form['info']['tags_count'] = array(
'#type' => 'item',
'#title' => t('Total HTML tags'),
'#markup' => number_format($job
->getTagsCount()),
'#prefix' => '<div class="tmgmt-ui-tags-count tmgmt-ui-info-item">',
'#suffix' => '</div>',
);
if (\Drupal::service('plugin.manager.tmgmt.translator')
->supportsFiles()) {
$form['info']['file_count'] = array(
'#type' => 'item',
'#title' => t('Total files'),
'#markup' => number_format($job
->getFileCount()),
'#prefix' => '<div class="tmgmt-ui-file-count tmgmt-ui-info-item">',
'#suffix' => '</div>',
);
}
}
else {
$roles = array_filter(Role::loadMultiple(), function (RoleInterface $role) {
foreach ([
'administer tmgmt',
'create translation jobs',
'submit translation jobs',
'accept translataion jobs',
] as $permission) {
if ($role
->hasPermission($permission)) {
return TRUE;
}
}
return FALSE;
});
if (array_key_exists('authenticated', $roles)) {
$filter = [];
}
else {
$ids = array_keys($roles);
$roles = array_combine($ids, $ids);
$filter = [
'type' => 'role',
'role' => $roles,
];
}
$form['info']['uid'] = array(
'#title' => t('Owner'),
'#type' => 'entity_autocomplete',
'#target_type' => 'user',
'#selection_settings' => [
'include_anonymous' => FALSE,
'filter' => $filter,
'field' => 'uid',
],
'#process_default_value' => TRUE,
'#default_value' => $job
->getOwnerId() == 0 ? User::load(\Drupal::currentUser()
->id()) : $job
->getOwner(),
'#required' => TRUE,
'#prefix' => '<div id="tmgmt-ui-owner" class="tmgmt-ui-owner tmgmt-ui-info-item">',
'#suffix' => '</div>',
);
}
if (!$job
->isContinuous()) {
$message = $this
->getConflictingItemsMessage($job);
$form['message'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#prefix' => '<div class="messages existing-items messages--warning hidden">',
'#suffix' => '</div>',
];
if ($message) {
$form['message']['#value'] = $message;
$form['message']['#prefix'] = '<div class="messages existing-items messages--warning">';
}
}
// Display created time only for jobs that are not new anymore.
if (!$job
->isUnprocessed() && !$job
->isContinuousActive()) {
$form['info']['created'] = array(
'#type' => 'item',
'#title' => t('Created'),
'#markup' => $this->dateFormatter
->format($job
->getCreatedTime()),
'#prefix' => '<div class="tmgmt-ui-created tmgmt-ui-info-item">',
'#suffix' => '</div>',
'#value' => $job
->getCreatedTime(),
);
}
else {
// Indicate the state to the forms css classes.
$form['#attributes']['class'][] = 'state-unprocessed';
}
if (!$job
->isContinuous()) {
if ($view = Views::getView('tmgmt_job_items')) {
$form['job_items_wrapper'] = array(
'#type' => 'container',
'#weight' => 10,
'#prefix' => '<div id="tmgmt-ui-job-checkout-details">',
'#suffix' => '</div>',
);
$form['footer'] = tmgmt_color_job_item_legend();
$form['footer']['#weight'] = 100;
// Translation jobs.
$output = $view
->preview($job
->isSubmittable() ? 'checkout' : 'submitted', array(
$job
->id(),
));
$form['job_items_wrapper']['items'] = array(
'#type' => 'details',
'#title' => t('Job items'),
'#open' => in_array($job
->getState(), array(
Job::STATE_ACTIVE,
)),
'#prefix' => '<div class="' . 'tmgmt-ui-job-items ' . ($job
->isSubmittable() ? 'tmgmt-ui-job-submit' : 'tmgmt-ui-job-manage') . '">',
'view' => $output,
'#attributes' => array(
'class' => array(
'tmgmt-ui-job-items',
$job
->isSubmittable() ? 'tmgmt-ui-job-submit' : 'tmgmt-ui-job-manage',
),
),
'#suffix' => '</div>',
);
}
// Always show suggestions when the job has not yet been submitted.
if ($job
->isSubmittable()) {
// A Wrapper for a button and a table with all suggestions.
$form['job_items_wrapper']['suggestions'] = array(
'#type' => 'details',
'#title' => $this
->t('Suggestions'),
'#open' => TRUE,
'#access' => $job
->isSubmittable(),
);
$form['job_items_wrapper']['suggestions']['container'] = array(
'#type' => 'container',
'#prefix' => '<div id="tmgmt-ui-job-items-suggestions">',
'#suffix' => '</div>',
);
// Create the suggestions table.
$suggestions_table = array(
'#type' => 'tableselect',
'#header' => array(),
'#options' => array(),
'#multiple' => TRUE,
);
$this
->buildSuggestions($suggestions_table, $form_state);
// A save button on bottom of the table is needed.
$form['job_items_wrapper']['suggestions']['container']['suggestions_list'] = array(
'suggestions_table' => $suggestions_table,
'suggestions_add' => array(
'#type' => 'submit',
'#value' => t('Add suggestions'),
'#submit' => array(
'::addSuggestionsSubmit',
),
'#limit_validation_errors' => array(
array(
'suggestions_table',
),
),
'#attributes' => array(
'class' => array(
'tmgmt-ui-job-suggestions-add',
),
),
),
);
// Only show suggestions if there are any, in that case collapse
// the job items list by default.
$form['job_items_wrapper']['suggestions']['#access'] = !empty($suggestions_table['#options']);
$form['job_items_wrapper']['items']['#open'] = empty($suggestions_table['#options']);
}
}
if ($job
->isContinuous()) {
$form['continuous_settings'] = array(
'#type' => 'details',
'#title' => $this
->t('Continuous settings'),
'#description' => $this
->t('Configure the sources that should be enabled for this continuous job.'),
'#open' => TRUE,
'#weight' => 10,
'#tree' => TRUE,
);
$source_manager = \Drupal::service('plugin.manager.tmgmt.source');
$source_plugins = $source_manager
->getDefinitions();
foreach ($source_plugins as $type => $definition) {
$plugin_type = $source_manager
->createInstance($type);
if ($plugin_type instanceof ContinuousSourceInterface) {
$form['continuous_settings'][$type] = $plugin_type
->continuousSettingsForm($form, $form_state, $job);
}
}
}
// Display the checkout settings form if the job can be checked out.
if ($job
->isSubmittable() || $job
->isContinuous()) {
$form['translator_wrapper'] = array(
'#type' => 'details',
'#title' => t('Configure provider'),
'#weight' => 20,
'#prefix' => '<div id="tmgmt-ui-translator-wrapper">',
'#suffix' => '</div>',
'#open' => TRUE,
);
// Show a list of translators tagged by availability for the selected source
// and target language combination.
if (!($translators = tmgmt_translator_labels_flagged($job))) {
$this
->messenger()
->addWarning(t('There are no providers available. Before you can checkout you need to @configure at least one provider.', array(
'@configure' => Link::fromTextAndUrl(t('configure'), Url::fromRoute('entity.tmgmt_translator.collection'))
->toString(),
)));
}
$preselected_translator = $job
->getTranslatorId() && isset($translators[$job
->getTranslatorId()]) ? $job
->getTranslatorId() : key($translators);
$job->translator = $form_state
->getValue('translator') ?: $preselected_translator;
$form['translator_wrapper']['translator'] = array(
'#type' => 'select',
'#title' => t('Provider'),
'#description' => t('The configured provider that will process the translation.'),
'#options' => $translators,
'#access' => !empty($translators),
'#default_value' => $job
->getTranslatorId(),
'#required' => TRUE,
'#ajax' => array(
'callback' => array(
$this,
'ajaxTranslatorSelect',
),
'wrapper' => 'tmgmt-ui-translator-wrapper',
),
);
// Add the provider logo in the settings wrapper.
/** @var \Drupal\tmgmt\Entity\Translator $entity */
$definition = \Drupal::service('plugin.manager.tmgmt.translator')
->getDefinition($job
->getTranslatorPlugin()
->getPluginId());
$npath = \Drupal::service('extension.list.module')
->getPath($definition['provider']);
if (isset($definition['logo'])) {
$form['translator_wrapper']['logo'] = $logo_render_array = [
'#theme' => 'image',
'#uri' => \Drupal::service('file_url_generator')
->generateAbsoluteString($npath . '/' . $definition['logo']),
'#alt' => $definition['label'],
'#title' => $definition['label'],
'#attributes' => [
'class' => 'tmgmt-logo-settings',
],
'#suffix' => '<div class="clearfix"></div>',
];
}
$settings = $this
->checkoutSettingsForm($form_state, $job);
if (!is_array($settings)) {
$settings = array();
}
$form['translator_wrapper']['settings'] = array(
'#type' => 'details',
'#title' => t('Checkout settings'),
'#prefix' => '<div id="tmgmt-ui-translator-settings">',
'#suffix' => '</div>',
'#tree' => TRUE,
'#open' => TRUE,
) + $settings;
// If there are additional jobs in the queue, allow to submit them all.
$count = $this->jobQueue
->count();
if ($count > 1 && !$job
->isContinuous()) {
$form['translator_wrapper']['submit_all'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Submit all @count translation jobs with the same settings', [
'@count' => $count,
]),
'#description' => $this
->t('This will attempt to submit all @count pending translation jobs to the same provider with the configured settings. Jobs that can not be submitted successfully can be re-submitted with different settings.', [
'@count' => $count,
]),
];
}
}
elseif ($job
->getTranslatorId() && !$job
->isContinuous()) {
$form['translator_wrapper'] = array(
'#type' => 'details',
'#title' => t('Provider information'),
'#open' => TRUE,
'#weight' => 20,
);
$form['translator_wrapper']['checkout_info'] = $this
->checkoutInfo($job);
}
if (!$job
->isContinuous() && !$job
->isSubmittable() && empty($form['translator_wrapper']['checkout_info'])) {
$form['translator_wrapper']['checkout_info'] = array(
'#type' => 'markup',
'#markup' => t('The translator does not provide any information.'),
);
}
$form['clearfix'] = array(
'#markup' => '<div class="clearfix"></div>',
'#weight' => 45,
);
if (!$job
->isContinuous() && ($view = Views::getView('tmgmt_job_messages'))) {
$output = $view
->preview('embed', array(
$job
->id(),
));
if ($view->result) {
$form['messages'] = [
'#type' => 'details',
'#title' => $view->storage
->label(),
'#open' => TRUE,
'#weight' => 50,
];
$form['messages']['view'] = $output;
}
}
$form['#attached']['library'][] = 'tmgmt/admin';
return $form;
}
protected function actions(array $form, FormStateInterface $form_state) {
$job = $this->entity;
$actions['save'] = array(
'#type' => 'submit',
'#value' => t('Save job'),
'#submit' => array(
'::submitForm',
'::save',
),
'#weight' => 5,
);
if (!$job
->isUnprocessed()) {
$actions['save']['#button_type'] = 'primary';
}
if (!$job
->isContinuous() && $job
->access('submit')) {
$actions['submit'] = array(
'#type' => 'submit',
'#button_type' => 'primary',
'#value' => $this->jobQueue
->count() <= 1 ? t('Submit to provider') : t('Submit to provider and continue'),
'#access' => $job
->isSubmittable(),
'#disabled' => !$job
->getTranslatorId(),
'#submit' => array(
'::submitForm',
'::save',
),
'#weight' => 0,
);
$actions['resubmit_job'] = array(
'#type' => 'submit',
'#submit' => array(
'tmgmt_submit_redirect',
),
'#redirect' => 'admin/tmgmt/jobs/' . $job
->id() . '/resubmit',
'#value' => t('Resubmit'),
'#access' => $job
->isAborted(),
'#weight' => 10,
);
$actions['abort_job'] = array(
'#type' => 'submit',
'#value' => t('Abort job'),
'#redirect' => 'admin/tmgmt/jobs/' . $job
->id() . '/abort',
'#submit' => array(
'tmgmt_submit_redirect',
),
'#access' => $job
->isAbortable(),
'#weight' => 15,
);
}
else {
$actions['save']['#button_type'] = 'primary';
}
if (!$job
->isNew()) {
$actions['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
'#submit' => array(
'tmgmt_submit_redirect',
),
'#redirect' => 'admin/tmgmt/jobs/' . $job
->id() . '/delete',
// Don't run validations, so the user can always delete the job.
'#limit_validation_errors' => array(),
);
}
return $actions;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
/** @var \Drupal\tmgmt\JobInterface $job */
$job = parent::validateForm($form, $form_state);
if ($job
->hasTranslator()) {
$translator = $job
->getTranslator();
// Check translator availability.
$available_status = $translator
->checkAvailable();
$translatable_status = $translator
->checkTranslatable($job);
if (!$available_status
->getSuccess()) {
$form_state
->setErrorByName('translator', $available_status
->getReason());
}
elseif (!$translatable_status
->getSuccess()) {
$form_state
->setErrorByName('translator', $translatable_status
->getReason());
}
}
if (!$job
->isContinuous() && isset($form['actions']['submit']) && $form_state
->getTriggeringElement()['#value'] == $form['actions']['submit']['#value']) {
$existing_items_ids = $job
->getConflictingItemIds();
$form_state
->set('existing_item_ids', $existing_items_ids);
// If the amount of existing items is the same as the total job item count
// then the job can not be submitted.
if (count($job
->getItems()) == count($existing_items_ids)) {
$form_state
->setErrorByName('target_language', $this
->t('All job items are conflicting, the job can not be submitted.'));
}
}
}
/**
* {@inheritdoc}
*/
public function buildEntity(array $form, FormStateInterface $form_state) {
/** @var \Drupal\tmgmt\JobInterface $job */
$job = parent::buildEntity($form, $form_state);
if ($job
->hasTranslator()) {
$translator = $job
->getTranslator();
// If requested custom job settings handling, copy values from original job.
if ($translator
->hasCustomSettingsHandling()) {
$original_job = \Drupal::entityTypeManager()
->getStorage('tmgmt_job')
->loadUnchanged($job
->id());
$job->settings = $original_job->settings;
}
}
// Make sure that we always store a label as it can be a slow operation to
// generate the default label.
if (empty($job->label)) {
$job->label = $job
->label();
}
return $job;
}
/**
* Overrides Drupal\Core\Entity\EntityForm::save().
*/
public function save(array $form, FormStateInterface $form_state) {
parent::save($form, $form_state);
// Everything below this line is only invoked if the 'Submit to provider'
// button was clicked.
if (isset($form['actions']['submit']) && $form_state
->getTriggeringElement()['#value'] == $form['actions']['submit']['#value']) {
if ($this->entity
->get('label')
->isEmpty()) {
$this->entity
->set('label', $this->entity
->label());
}
// Delete conflicting items.
$storage = \Drupal::entityTypeManager()
->getStorage('tmgmt_job_item');
if ($existing_items_ids = $form_state
->get('existing_item_ids')) {
$storage
->delete($storage
->loadMultiple($existing_items_ids));
$num_of_items = count($existing_items_ids);
$this
->messenger()
->addWarning(\Drupal::translation()
->formatPlural($num_of_items, '1 conflicting item has been dropped.', '@count conflicting items have been dropped.'));
}
if ($form_state
->getValue('submit_all')) {
$this
->getRequest()->query
->remove('destination');
$translator_id = $form_state
->getValue('translator');
if ($translator = Translator::load($translator_id)) {
if ($translator
->getPlugin() instanceof MultipleCheckoutInterface) {
$this->jobCheckoutManager
->requestTranslationMultiple($this->jobQueue
->getAllJobs(), $translator);
if ($redirect = $this->jobQueue
->getNextUrl()) {
// Proceed to the next redirect queue item, if there is one.
$form_state
->setRedirectUrl($redirect);
}
elseif ($destination = $this->jobQueue
->getDestination()) {
// Proceed to the defined destination if there is one.
$form_state
->setRedirectUrl(Url::fromUri('base:' . $destination));
}
else {
// Per default we want to redirect the user to the overview.
$form_state
->setRedirectUrl(Url::fromRoute('view.tmgmt_job_overview.page_1'));
}
return;
}
}
$batch = array(
'title' => t('Submitting jobs'),
'operations' => [],
'finished' => [
JobCheckoutManager::class,
'batchSubmitFinished',
],
);
foreach ($this->jobQueue
->getAllJobs() as $job) {
$batch['operations'][] = [
[
JobCheckoutManager::class,
'batchSubmit',
],
[
$job
->id(),
$this->entity
->id(),
],
];
}
batch_set($batch);
return;
}
if (!$this->jobCheckoutManager
->requestTranslation($this->entity)) {
// Don't redirect the user if the translation request failed but retain
// existing destination parameters so we can redirect once the request
// finished successfully.
$this
->getRequest()->query
->remove('destination');
return;
}
else {
$this->jobQueue
->markJobAsProcessed($this->entity);
}
if ($redirect = $this->jobQueue
->getNextUrl()) {
// Proceed to the next redirect queue item, if there is one.
$form_state
->setRedirectUrl($redirect);
}
elseif ($destination = $this->jobQueue
->getDestination()) {
// Proceed to the defined destination if there is one.
$form_state
->setRedirectUrl(Url::fromUri('base:' . $destination));
}
else {
// Per default we want to redirect the user to the overview.
$form_state
->setRedirect('view.tmgmt_job_overview.page_1');
}
}
else {
// Per default we want to redirect the user to the overview.
$form_state
->setRedirect('view.tmgmt_job_overview.page_1');
}
}
/**
* Helper function for retrieving the job settings form.
*
* @todo Make use of the response object here.
*/
function checkoutSettingsForm(FormStateInterface $form_state, JobInterface $job) {
$form = array();
if (!$job
->hasTranslator()) {
return $form;
}
$translator = $job
->getTranslator();
$result = $translator
->checkAvailable();
if (!$result
->getSuccess()) {
$form['#description'] = $result
->getReason();
return $form;
}
// @todo: if the target language is not defined, the check will not work if the first language in the list is not available.
$result = $translator
->checkTranslatable($job);
if ($job
->getTargetLangcode() && !$result
->getSuccess()) {
$form['#description'] = $result
->getReason();
return $form;
}
$plugin_ui = $this->translatorManager
->createUIInstance($translator
->getPluginId());
$form = $plugin_ui
->checkoutSettingsForm($form, $form_state, $job);
return $form;
}
/**
* Helper function for retrieving the rendered job checkout information.
*/
function checkoutInfo(JobInterface $job) {
// The translator might have been disabled or removed.
if (!$job
->hasTranslator()) {
return array(
'#markup' => t('The job has no provider assigned.'),
);
}
$translator = $job
->getTranslator();
$plugin_ui = $this->translatorManager
->createUIInstance($translator
->getPluginId());
return $plugin_ui
->checkoutInfo($job);
}
/**
* {@inheritdoc}
*/
public function delete(array $form, FormStateInterface $form_state) {
$form_state
->setRedirectUrl($this->entity
->toUrl('delete-form'));
}
/**
* Ajax callback to fetch the supported translator services and rebuild the
* target / source language dropdowns.
*/
public function ajaxLanguageSelect(array $form, FormStateInterface $form_state) {
$message = $this
->getConflictingItemsMessage($this->entity);
$replace = $form_state
->getUserInput()['_triggering_element_name'] == 'source_language' ? 'target_language' : 'source_language';
$response = new AjaxResponse();
$response
->addCommand(new ReplaceCommand('#tmgmt-ui-translator-wrapper', $form['translator_wrapper']));
$response
->addCommand(new ReplaceCommand('#tmgmt-ui-' . str_replace('_', '-', $replace), $form['info'][$replace]));
if ($message) {
$response
->addCommand(new InvokeCommand('.existing-items', 'removeClass', array(
'hidden',
)));
$response
->addCommand(new ReplaceCommand('.existing-items > div', $message));
}
else {
$response
->addCommand(new InvokeCommand('.existing-items', 'addClass', array(
'hidden',
)));
$response
->addCommand(new ReplaceCommand('.existing-items > div', ''));
}
return $response;
}
/**
* Ajax callback to fetch the options provided by a translator.
*/
public function ajaxTranslatorSelect(array $form, FormStateInterface $form_state) {
return $form['translator_wrapper'];
}
/**
* Adds selected suggestions to the job.
*/
function addSuggestionsSubmit(array $form, FormStateInterface $form_state) {
// Save all selected suggestion items.
if (is_array($form_state
->getValue('suggestions_table'))) {
$job = $form_state
->getFormObject()
->getEntity();
foreach ($form_state
->getValue('suggestions_table') as $id) {
$key = (int) $id - 1;
// Because in the tableselect we need an idx > 0.
if (isset($form_state
->get('tmgmt_suggestions')[$key]['job_item'])) {
$item = $form_state
->get('tmgmt_suggestions')[$key]['job_item'];
$job
->addExistingItem($item);
}
}
}
// Force a rebuild of the form.
$form_state
->setRebuild();
$form_state
->set('tmgmt_suggestions', NULL);
}
/**
* Fills the tableselect with all translation suggestions.
*
* Calls hook_tmgmt_source_suggestions(Job) and creates the resulting list
* based on the results from all modules.
*
* @param array $suggestions_table
* Tableselect part for a $form array where the #options should be inserted.
* @param array $form_state
* The main form_state.
*/
function buildSuggestions(array &$suggestions_table, FormStateInterface $form_state) {
$options = array();
$job = $form_state
->getFormObject()
->getEntity();
if ($job instanceof Job) {
// Get all suggestions from all modules which implements
// 'hook_tmgmt_source_suggestions' and cache them in $form_state.
if (!$form_state
->get('tmgmt_suggestions')) {
$form_state
->set('tmgmt_suggestions', $job
->getSuggestions());
}
// Remove suggestions which are already processed, translated, ...
$job
->cleanSuggestionsList($form_state
->get('tmgmt_suggestions'));
// Process all valid entries.
foreach ($form_state
->get('tmgmt_suggestions') as $k => $result) {
if (is_array($result) && isset($result['job_item']) && $result['job_item'] instanceof JobItem) {
$options[$k + 1] = $this
->addSuggestionItem($result);
}
}
$suggestions_table['#options'] = $options;
$suggestions_table['#empty'] = t('No related suggestions available.');
$suggestions_table['#header'] = array(
'title' => t('Label'),
'type' => t('Type'),
'reason' => t('Reason'),
'words' => t('Word count'),
);
}
}
/**
* Create a Suggestion-Table entry based on a Job and a title.
*
* @param array $result
* Suggestion array with the keys job_item, reason and from_item.
*
* @return array
* Options-Entry for a tableselect array.
*/
function addSuggestionItem(array $result) {
$item = $result['job_item'];
$reason = isset($result['reason']) ? $result['reason'] : NULL;
$option = array(
'title' => $item
->label(),
'type' => $item
->getSourceType(),
'words' => $item
->getWordCount(),
'tags' => $item
->getTagsCount(),
'reason' => $reason,
);
if (!empty($result['from_item'])) {
$from_item = JobItem::load($result['from_item']);
if ($from_item) {
$option['reason'] = t('%reason in %job', array(
'%reason' => $option['reason'],
'%job' => $from_item
->label(),
));
}
}
return $option;
}
/**
* Handles submit call to rebuild a job.
*/
public function submitBuildJob(array $form, FormStateInterface $form_state) {
$this->entity = $this
->buildEntity($form, $form_state);
$form_state
->setRebuild();
}
/**
* Builds a message on conflicting job items.
*
* @param \Drupal\tmgmt\JobInterface $job
* The job to build the message for.
*
* @return \Drupal\Core\StringTranslation\TranslatableMarkup|null
* Either a message with the inforamtion about the conflicting items or
* null if there are none.
*/
protected function getConflictingItemsMessage(JobInterface $job) : ?TranslatableMarkup {
// Checkout whether given source already has items in translation.
$conflicting_items_by_item = $job
->getConflictingItems();
if (!$conflicting_items_by_item) {
return NULL;
}
// Make a list of links to the existing items causing the conflicts.
$conflicts = [];
$num_of_existing_items = 0;
foreach ($conflicting_items_by_item as $conflicting_items) {
$num_of_existing_items += count($conflicting_items);
foreach (JobItem::loadMultiple($conflicting_items) as $id => $conflicting_item) {
$conflicts[] = Link::createFromRoute($conflicting_item
->label(), 'entity.tmgmt_job_item.canonical', [
'tmgmt_job_item' => $id,
])
->toString();
}
}
// Make the links usable in formatPlural().
$conflict_list = Markup::create(implode(', ', $conflicts));
return \Drupal::translation()
->formatPlural($num_of_existing_items, '1 item conflicts with pending item and will be dropped on submission. Conflicting item: @items.', '@count items conflict with pending items and will be dropped on submission. Conflicting items: @items.', [
'@items' => $conflict_list,
]);
}
}
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
JobForm:: |
protected | property | 1 | |
JobForm:: |
protected | property | ||
JobForm:: |
protected | property | ||
JobForm:: |
protected | function | 1 | |
JobForm:: |
function | Create a Suggestion-Table entry based on a Job and a title. | ||
JobForm:: |
function | Adds selected suggestions to the job. | ||
JobForm:: |
public | function | Ajax callback to fetch the supported translator services and rebuild the target / source language dropdowns. | |
JobForm:: |
public | function | Ajax callback to fetch the options provided by a translator. | |
JobForm:: |
public | function | ||
JobForm:: |
function | Fills the tableselect with all translation suggestions. | ||
JobForm:: |
function | Helper function for retrieving the rendered job checkout information. | ||
JobForm:: |
function | Helper function for retrieving the job settings form. | ||
JobForm:: |
public static | function |
Overrides TmgmtFormBase:: |
|
JobForm:: |
public | function | ||
JobForm:: |
public | function | 1 | |
JobForm:: |
protected | function | Builds a message on conflicting job items. | |
JobForm:: |
public | function | Overrides Drupal\Core\Entity\EntityForm::save(). | 1 |
JobForm:: |
public | function | Handles submit call to rebuild a job. | |
JobForm:: |
public | function | ||
TmgmtFormBase:: |
protected | property | The date formatter. | |
TmgmtFormBase:: |
protected | property | Renderer. | |
TmgmtFormBase:: |
protected | property | Source plugin manager. | |
TmgmtFormBase:: |
protected | property | Translator plugin manager. |