View source
<?php
namespace Drupal\straw\Plugin\EntityReferenceSelection;
use Drupal\Component\Utility\Html;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Plugin\EntityReferenceSelection\TermSelection;
use Drupal\Core\Cache\Cache;
class StrawSelection extends TermSelection {
public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
$options = [];
$bundles = $this->entityTypeBundleInfo
->getBundleInfo('taxonomy_term');
$handler_settings = $this->configuration['handler_settings'];
$bundle_names = !empty($handler_settings['target_bundles']) ? $handler_settings['target_bundles'] : array_keys($bundles);
foreach ($bundle_names as $bundle) {
if ($vocabulary = Vocabulary::load($bundle)) {
foreach ($this
->getSelectableTerms($vocabulary
->id()) as $term) {
$referenceable = TRUE;
if ($match && $match_operator == "CONTAINS") {
$referenceable = stripos($term['tree_path'], $match) !== FALSE;
}
if ($match && $match_operator == "STARTS_WITH") {
$referenceable = stripos($term['tree_path'], $match) === 0;
}
if ($match && $match_operator == "=") {
$referenceable = $term['tree_path'] == $match;
}
if ($referenceable) {
$options[$vocabulary
->id()][$term['tid']] = Html::escape($term['tree_path']);
if ($limit > 0 && count($options[$vocabulary
->id()]) == $limit) {
break;
}
}
}
}
}
return $options;
}
private function getSelectableTerms($bundle_name) {
$cache_context_keys = \Drupal::service('cache_contexts_manager')
->convertTokensToKeys([
'user.permissions',
])
->getKeys();
$cid = $bundle_name . ':' . implode(':', $cache_context_keys);
$straw_cache = \Drupal::cache('straw');
if ($cached_data = $straw_cache
->get($cid)) {
return $cached_data->data;
}
$all_terms = $this->entityTypeManager
->getStorage('taxonomy_term')
->loadTree($bundle_name);
$all_terms = array_reduce($all_terms, function ($carry, $item) {
$carry[$item->tid] = $item;
return $carry;
}, []);
$searchable_data = [];
foreach ($all_terms as $term) {
$tree_path = $term->name;
$current = $term;
while (($parent_id = $current->parents[0]) && ($parent = $all_terms[$parent_id])) {
$tree_path = $parent->name . ' >> ' . $tree_path;
$current = $parent;
}
$searchable_data[] = [
'tid' => $term->tid,
'tree_path' => $tree_path,
];
}
\Drupal::cache('straw')
->set($cid, $searchable_data, Cache::PERMANENT, [
'taxonomy_term_list',
]);
return $searchable_data;
}
public function createNewEntity($entity_type_id, $bundle, $label, $uid) {
$term_names = explode('>>', $label);
$new_term_storage = \Drupal::service('straw.new_term_storage');
$last_term = NULL;
$tree_path = '';
while ($term_name = array_shift($term_names)) {
$tree_path .= ($tree_path ? ' >> ' : '') . trim($term_name);
$matching_terms_by_vocabulary = $this
->getReferenceableEntities($tree_path, '=', 1);
if (empty($matching_terms_by_vocabulary[$bundle])) {
array_unshift($term_names, $term_name);
break;
}
$last_term = key($matching_terms_by_vocabulary[$bundle]);
}
while ($term_name = array_shift($term_names)) {
$tree_path .= ($tree_path ? ' >> ' : '') . trim($term_name);
if ($found_term = $new_term_storage
->get($bundle, $tree_path)) {
$last_term = $found_term;
}
else {
$last_term = Term::create([
'vid' => $bundle,
'name' => trim($term_name),
'parent' => $last_term,
]);
$new_term_storage
->set($bundle, $tree_path, $last_term);
}
}
return $last_term;
}
}