cefrl-1.0.0-beta1/src/CEFRLOptions.php
src/CEFRLOptions.php
<?php
namespace Drupal\cefrl;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
/**
* Provides option lists based on CEFRL levels.
*/
class CEFRLOptions implements CEFRLOptionsInterface {
use StringTranslationTrait;
const CEFRL_SETTINGS = 'cefrl.settings';
const CEFRL_DEFINITIONS = 'definitions';
const CEFRL_ID = 'id';
const CEFRL_LABEL = 'label';
const CEFRL_DESCRIPTION = 'description';
const CEFRL_ALLOW_GROUPS = 'allow_group_selection';
const CEFRL_INCLUDE_NATIVE = 'include_native_speaker';
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* The string translation service.
*
* @var \Drupal\Core\StringTranslation\TranslationInterface
*/
protected $stringTranslation;
/**
* The CEFRL Levels service.
*
* @var \Drupal\cefrl\CEFRLLevelsInterface
*/
protected $cefrlLevels;
/**
* Constructs a CEFRLOptions object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
* @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
* The string translation service.
* @param \Drupal\cefrl\CEFRLLevelsInterface $cefrl_levels
* The CEFRL Levels service.
*/
public function __construct(
ConfigFactoryInterface $config_factory,
TranslationInterface $string_translation,
CEFRLLevelsInterface $cefrl_levels
) {
$this->configFactory = $config_factory;
$this->stringTranslation = $string_translation;
$this->cefrlLevels = $cefrl_levels;
}
/**
* Provides the allowed values for the CEFRL level.
*
* @param bool $allow_groups
* Indicates whether level groups are allowed.
* @param bool $include_native
* Indicates whether the Native speaker pseudo-level is allowed.
*
* @return array
* The allowed values for the CEFRL level.
*/
public function allowedLevelValues(bool $allow_groups = FALSE, bool $include_native = FALSE): array {
$level_keys = \array_keys($this->cefrlLevels->getLevels());
if ($allow_groups) {
$group_keys = \array_keys($this->cefrlLevels->getGroups());
$allowed_values = \array_merge($level_keys, $group_keys);
}
else {
$allowed_values = $level_keys;
}
if ($include_native) {
$allowed_values[] = CEFRLLevels::CEFRL_NS;
}
sort($allowed_values);
return $allowed_values;
}
/**
* Provides the options for a field widget.
*
* @param bool $allow_groups
* Indicates whether level groups are allowed.
* @param bool $include_native
* Indicates whether the Native speaker pseudo-level is allowed.
*
* @return array
* The options for a field widget.
*/
public function getOptions(bool $allow_groups = FALSE, bool $include_native = FALSE): array {
$options = (!$allow_groups)
? $this->getNestedOptions()
: $this->getOptionsWithGroups();
if ($include_native) {
$options += $this->getNativeSpeakerOption();
}
return $options;
}
/**
* Provides the CEFRL levels as options, grouped by their CEFRL level groups.
*
* @return array
* The nested options.
*/
protected function getNestedOptions(): array {
$options = [];
$groups = $this->cefrlLevels->getGroups();
foreach ($groups as $group => $levels) {
$label = $this->getLabel($group);
$optgroup = (!empty($label)) ? implode(' - ', [$group, $label]) : $group;
foreach ($levels as $level) {
$label = $this->getLabel($level);
$option = (!empty($label)) ? implode(' - ', [$level, $label]) : $level;
$options[$optgroup][$level] = $option;
}
}
return $options;
}
/**
* Provides both CEFRL level groups and levels as options.
*
* @return array
* The options with groups.
*/
protected function getOptionsWithGroups(): array {
$options = [];
$groups = $this->cefrlLevels->getGroups();
foreach ($groups as $group => $levels) {
$label = $this->getLabel($group);
$option = (!empty($label)) ? implode(' - ', [$group, $label]) : $group;
$options[$group] = $this->t('Any @group', ['@group' => $option]);
foreach ($levels as $level) {
$label = $this->getLabel($level);
$option = (!empty($label)) ? implode(' - ', [$level, $label]) : $level;
$options[$level] = $this->t('└── @level', ['@level' => $option]);
}
}
return $options;
}
/**
* Provides the grouped CEFRL levels as options, indexed by weight.
*
* @return array
* The weight indexed options.
*/
public function getWeightOptions(): array {
$weight_options = [];
$nested = $this->getNestedOptions();
foreach ($nested as $optgroup => $options) {
foreach ($options as $key => $label) {
$weight = $this->cefrlLevels->getItemWeight($key);
$weight_options[$optgroup][$weight] = $label;
}
}
return $weight_options;
}
/**
* Provides the 'Native speaker' pseudo-level option.
*
* @return array
* The 'Native speaker' pseudo-level option.
*/
public function getNativeSpeakerOption(): array {
return [CEFRLLevels::CEFRL_NS => $this->t('Native speaker')];
}
/**
* Provides the label for a level or group as defined in configuration.
*
* If no label is defined in configuration, the original key is returned.
*
* If the key is not found in configuration, NULL is returned.
*
* @param string $key
* The key of the item (level or group).
*
* @return string|null
* The label for the item, or NULL.
*/
public function getLabel(string $key): ?string {
$definitions = $this->configFactory
->get(self::CEFRL_SETTINGS)
->get(self::CEFRL_DEFINITIONS);
foreach ($definitions as $definition) {
if ($definition[self::CEFRL_ID] === $key) {
return $definition[self::CEFRL_LABEL] ?? $key;
}
}
return NULL;
}
/**
* Provides the description for a level or group as defined in configuration.
*
* If no description is defined in configuration, an empty string is returned.
*
* If the key is not found in configuration, NULL is returned.
*
* @param string $key
* The key of the item (level or group).
*
* @return string|null
* The description for the item, or NULL.
*/
public function getDescription(string $key): ?string {
$definitions = $this->configFactory
->get(self::CEFRL_SETTINGS)
->get(self::CEFRL_DEFINITIONS);
foreach ($definitions as $definition) {
if ($definition[self::CEFRL_ID] === $key) {
return $definition[self::CEFRL_DESCRIPTION] ?? '';
}
}
return NULL;
}
}
