translators-8.x-1.x-dev/src/Services/TranslatorSkills.php
src/Services/TranslatorSkills.php
<?php
namespace Drupal\translators\Services;
use Drupal\Component\Utility\Html;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Class TranslatorSkills.
*
* Translator skills helper class.
*
* @package Drupal\translators\Services
*/
class TranslatorSkills {
use StringTranslationTrait;
/**
* The content translation manager.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* Entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Current request.
*
* @var \Symfony\Component\HttpFoundation\Request|null
*/
protected $request;
/**
* Messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* Entity field.
*
* @var \Drupal\Core\Field\FieldItemList|null
*/
protected $entityField;
/**
* Constructs a TranslatorSkills service.
*
* @param \Drupal\Core\Session\AccountInterface $current_user
* Current user.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* Config factory.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* Entity type manager.
* @param \Symfony\Component\HttpFoundation\RequestStack $stack
* Request stack.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* Messenger.
*/
public function __construct(
AccountInterface $current_user,
ConfigFactoryInterface $config_factory,
EntityTypeManagerInterface $entity_type_manager,
RequestStack $stack,
MessengerInterface $messenger
) {
$this->currentUser = $current_user;
$this->configFactory = $config_factory;
$this->entityTypeManager = $entity_type_manager;
$this->request = $stack->getCurrentRequest();
$this->messenger = $messenger;
}
/**
* Get array with translation skills langcodes.
*
* @return array
* Multi-level array of all the translation skill langcodes.
*/
public function getTranslationSkills() {
$this->loadTranslationSkills();
return $this->entityField ? $this->entityField->getValue() : [];
}
/**
* Get source langcodes.
*
* @return array
* Array of all the source langcodes.
*/
public function getSourceLangcodes() {
$this->loadTranslationSkills();
return $this->entityField ? $this->entityField->getValueSourceLangcodes() : [];
}
/**
* Get target langcodes.
*
* @return array
* Array of all the source langcodes.
*/
public function getTargetLangcodes() {
$this->loadTranslationSkills();
return $this->entityField ? $this->entityField->getValueTargetLangcodes() : [];
}
/**
* Get all langcodes.
*
* @return array
* Array of all the source langcodes.
*/
public function getAllLangcodes() {
$this->loadTranslationSkills();
return $this->entityField ? $this->entityField->getValueAllLangcodes() : [];
}
/**
* Check if user has a specified language skill.
*
* @param string $langcode
* Language ID.
*
* @return bool
* TRUE - if a specified language exists in users skills list,
* FALSE otherwise.
*/
public function hasLangcode($langcode) {
return in_array($langcode, $this->getAllLangcodes());
}
/**
* Show empty message.
*/
public function showMissingTranslationSkillsWarning() {
$enabled = $this->configFactory
->get('translators.settings')
->get('enable_missing_skills_warning');
// Prevent showing warning message
// if the appropriate feature is not enabled.
if (empty($enabled)) {
return;
}
$user_id = $this->currentUser->id();
$options = $this->getEditTranslationSkillLinkWithRedirect();
$edit_url = Url::fromRoute('entity.user.edit_form', ['user' => $user_id], $options);
$link = Link::fromTextAndUrl('here', $edit_url)->toString();
$message = $this->t("Please register your translation skills @here", ['@here' => $link]);
// Prevent duplicated warning messages on a page.
$messages = $this->messenger->messagesByType('warning');
if (empty($messages) || !in_array($message, $messages)) {
$this->messenger->addWarning($message);
}
}
/**
* Check if user has skills with source/target langcodes.
*
* @param string $source
* Source langcode.
* @param string $target
* Target langcode.
*
* @return bool
* TRUE - if a specified translation skill exists in users skills list,
* FALSE otherwise.
*/
public function hasTranslationSkills($source, $target) {
$skills = $this->getTranslationSkills();
foreach ($skills as $skill) {
if ($skill['language_source'] == $source && $skill['language_target'] == $target) {
return TRUE;
}
}
return FALSE;
}
/**
* Build edit link options.
*
* @return array
* Edit link options array.
*/
protected function getEditTranslationSkillLinkWithRedirect() {
$options = [];
// Add fragment option to get user
// automatically scrolled down to the needed field.
$field_name = $this->configFactory
->get('translators.settings')
->get('translation_skills_field_name');
$options['fragment'] = 'edit-' . Html::getId($field_name) . '-wrapper';
// Add destination URL to get user being redirected back
// to the correct page after saving the user's edit form.
$options['query'] = [
'destination' => $this->request->getRequestUri(),
];
return $options;
}
/**
* Load translation skills for current user.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
protected function loadTranslationSkills() {
$user_id = $this->currentUser->id();
$this->entityTypeManager->getStorage('user')->resetCache([$user_id]);
$entity = $this->entityTypeManager->getStorage('user')->load($user_id);
$field_name = $this->configFactory
->get('translators.settings')
->get('translation_skills_field_name');
if (isset($entity->{$field_name})) {
$this->entityField = $entity->{$field_name};
}
}
/**
* Get users prefered translation source langcode for entity.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* Entity object.
* @param string $target
* Target langcode.
*
* @return string
* Processed language ID.
*/
public function getTranslationSourceLangcode(ContentEntityInterface $entity, $target = NULL) {
$original_langcode = $entity->getUntranslated()->language()->getId();
$config = $this->configFactory->get('translators.settings');
if (empty($config->get('enable_auto_preset_source_language_by_skills'))) {
return $original_langcode;
}
elseif ($config->get('enable_strict_translation_skill_pairing')) {
// Check strict translatil skills pairing if enabled.
foreach ($this->getSourceLangcodes() as $source_langcode) {
if (!$entity->hasTranslation($source_langcode)
|| !$this->hasTranslationSkills($source_langcode, $target)) {
continue;
}
return $source_langcode;
}
}
else {
// Check source langcodes first.
foreach ($this->getSourceLangcodes() as $source_langcode) {
if (!$entity->hasTranslation($source_langcode)) {
continue;
}
return $source_langcode;
}
// Then check target langcodes.
foreach ($this->getTargetLangcodes() as $target_langcode) {
if (!$entity->hasTranslation($target_langcode)) {
continue;
}
return $target_langcode;
}
}
return $original_langcode;
}
}
