function TermDevelGenerate::generateTerms
Same name in other branches
- 4.x devel_generate/src/Plugin/DevelGenerate/TermDevelGenerate.php \Drupal\devel_generate\Plugin\DevelGenerate\TermDevelGenerate::generateTerms()
Generates taxonomy terms for a list of given vocabularies.
Parameters
array $parameters: The input parameters from the settings form or drush command.
Return value
array Information about the created terms.
1 call to TermDevelGenerate::generateTerms()
- TermDevelGenerate::generateElements in devel_generate/
src/ Plugin/ DevelGenerate/ TermDevelGenerate.php - Business logic relating with each DevelGenerate plugin.
File
-
devel_generate/
src/ Plugin/ DevelGenerate/ TermDevelGenerate.php, line 222
Class
- TermDevelGenerate
- Provides a TermDevelGenerate plugin.
Namespace
Drupal\devel_generate\Plugin\DevelGenerateCode
protected function generateTerms(array $parameters) : array {
$info = [
'terms' => 0,
'terms_translations' => 0,
];
$min_depth = $parameters['minimum_depth'];
$max_depth = $parameters['maximum_depth'];
// $parameters['vids'] from the UI has keys of the vocab ids. From drush
// the array is keyed 0,1,2. Therefore create $vocabs which has keys of the
// vocab ids, so it can be used with array_rand().
$vocabs = array_combine($parameters['vids'], $parameters['vids']);
// Delete terms from the vocabularies we are creating new terms in.
if ($parameters['kill']) {
$deleted = $this->deleteVocabularyTerms($vocabs);
$this->setMessage($this->formatPlural($deleted, 'Deleted 1 existing term', 'Deleted @count existing terms'));
if ($min_depth != 1) {
$this->setMessage($this->t('Minimum depth changed from @min_depth to 1 because all terms were deleted', [
'@min_depth' => $min_depth,
]));
$min_depth = 1;
}
}
// Build an array of potential parents for the new terms. These will be
// terms in the vocabularies we are creating in, which have a depth of one
// less than the minimum for new terms up to one less than the maximum.
$all_parents = [];
foreach ($parameters['vids'] as $vid) {
$info['vocabs'][$vid] = $this->vocabularyStorage
->load($vid)
->label();
// Initialise the nested array for this vocabulary.
$all_parents[$vid] = [
'top_level' => [],
'lower_levels' => [],
];
$ids = [];
for ($depth = 1; $depth < $max_depth; ++$depth) {
$query = $this->termStorage
->getQuery()
->accessCheck(FALSE)
->condition('vid', $vid);
if ($depth == 1) {
// For the top level the parent id must be zero.
$query->condition('parent', 0);
}
else {
// For lower levels use the $ids array obtained in the previous loop.
$query->condition('parent', $ids, 'IN');
}
$ids = $query->execute();
if (empty($ids)) {
// Reached the end, no more parents to be found.
break;
}
// Store these terms as parents if they are within the depth range for
// new terms.
if ($depth == $min_depth - 1) {
$all_parents[$vid]['top_level'] = array_fill_keys($ids, $depth);
}
elseif ($depth >= $min_depth) {
$all_parents[$vid]['lower_levels'] += array_fill_keys($ids, $depth);
}
}
// No top-level parents will have been found above when the minimum depth
// is 1 so add a record for that data here.
if ($min_depth == 1) {
$all_parents[$vid]['top_level'] = [
0 => 0,
];
}
elseif (empty($all_parents[$vid]['top_level'])) {
// No parents for required minimum level so cannot use this vocabulary.
unset($vocabs[$vid]);
}
}
if ($vocabs === []) {
// There are no available parents at the required depth in any vocabulary,
// so we cannot create any new terms.
throw new \Exception(sprintf('Invalid minimum depth %s because there are no terms in any vocabulary at depth %s', $min_depth, $min_depth - 1));
}
// Insert new data:
for ($i = 1; $i <= $parameters['num']; ++$i) {
// Select a vocabulary at random.
$vid = array_rand($vocabs);
// Set the group to use to select a random parent from. Using < 50 means
// on average half of the new terms will be top_level. Also if no terms
// exist yet in 'lower_levels' then we have to use 'top_level'.
$group = mt_rand(0, 100) < 50 || empty($all_parents[$vid]['lower_levels']) ? 'top_level' : 'lower_levels';
$parent = array_rand($all_parents[$vid][$group]);
$depth = $all_parents[$vid][$group][$parent] + 1;
$name = $this->getRandom()
->word(mt_rand(2, $parameters['title_length']));
$values = [
'name' => $name,
'description' => 'Description of ' . $name . ' (depth ' . $depth . ')',
'format' => filter_fallback_format(),
'weight' => mt_rand(0, 10),
'vid' => $vid,
'parent' => [
$parent,
],
// Give hook implementations access to the parameters used for generation.
'devel_generate' => $parameters,
];
if (isset($parameters['add_language'])) {
$values['langcode'] = $this->getLangcode($parameters['add_language']);
}
/** @var \Drupal\taxonomy\TermInterface $term */
$term = $this->termStorage
->create($values);
// Populate all fields with sample values.
$this->populateFields($term);
$term->save();
// Add translations.
if (isset($parameters['translate_language']) && !empty($parameters['translate_language'])) {
$info['terms_translations'] += $this->generateTermTranslation($parameters['translate_language'], $term);
}
// If the depth of the new term is less than the maximum depth then it can
// also be saved as a potential parent for the subsequent new terms.
if ($depth < $max_depth) {
$all_parents[$vid]['lower_levels'] += [
$term->id() => $depth,
];
}
// Store data about the newly generated term.
++$info['terms'];
@$info[$vid][$depth]['total']++;
// List only the first 10 new terms at each vocab/level.
if (!isset($info[$vid][$depth]['terms']) || count($info[$vid][$depth]['terms']) < 10) {
$info[$vid][$depth]['terms'][] = $term->label();
}
unset($term);
}
return $info;
}