database = $database; $this->entityManager = $entity_manager; $this->moduleHandler = $module_handler; $this->currentUser = $current_user; $this->target_type = $plugin_definition['target_entity']; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { return new static( $configuration, $plugin_id, $plugin_definition, $container->get('database'), $container->get('entity.manager'), $container->get('module_handler'), $container->get('current_user') ); } /** * {@inheritdoc} */ public function getSummary() { $summery = parent::getSummary(); $entity_type = $this->entityManager->getDefinition($this->target_type); $result_description = $this->configuration['result_description']; if (!empty($result_description)) { $summery[] = $this->t('Result description: @result_description', [ '@result_description' => $result_description ]); } if ($entity_type->hasKey('bundle')) { $has_bundle_filter = !empty($this->configuration['bundles']); $bundles = []; if ($has_bundle_filter) { $bundles_info = $this->entityManager->getBundleInfo($this->target_type); foreach ($this->configuration['bundles'] as $bundle) { $bundles[] = $bundles_info[$bundle]['label']; } } $summery[] = $this->t('Bundle filter: @bundle_filter', [ '@bundle_filter' => $has_bundle_filter ? implode(', ', $bundles) : t('None'), ]); $summery[] = $this->t('Group by bundle: @bundle_grouping', [ '@bundle_grouping' => $this->configuration['group_by_bundle'] ? $this->t('Yes') : $this->t('No'), ]); } return $summery; } /** * {@inheritdoc} */ public function defaultConfiguration() { return parent::defaultConfiguration() + [ 'result_description' => '', 'bundles' => [], 'group_by_bundle' => FALSE, ]; } /** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $entity_type = $this->entityManager->getDefinition($this->target_type); $form['result_description'] = [ '#title' => $this->t('Result description'), '#type' => 'textfield', '#default_value' => $this->configuration['result_description'], '#size' => 120, '#maxlength' => 255, '#weight' => -100, ]; $this->insertTokenList($form, [$this->target_type]); // Filter the possible bundles to use if the entity has bundles. if ($entity_type->hasKey('bundle')) { $bundle_options = []; foreach ($this->entityManager->getBundleInfo($this->target_type) as $bundle_name => $bundle_info) { $bundle_options[$bundle_name] = $bundle_info['label']; } $form['bundles'] = [ '#type' => 'checkboxes', '#title' => $this->t('Restrict to the selected bundles'), '#options' => $bundle_options, '#default_value' => $this->configuration['bundles'], '#description' => $this->t('If none of the checkboxes is checked, allow all bundles.'), '#element_validate' => [[get_class($this), 'elementValidateFilter']], '#weight' => -50, ]; // Group the results by bundle. $form['group_by_bundle'] = [ '#type' => 'checkbox', '#title' => $this->t('Group by bundle'), '#default_value' => $this->configuration['group_by_bundle'], '#weight' => -50, ]; } return $form; } /** * {@inheritdoc} */ public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { } /** * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { $this->configuration['result_description'] = $form_state->getValue('result_description'); $this->configuration['bundles'] = $form_state->getValue('bundles'); $this->configuration['group_by_bundle'] = $form_state->getValue('group_by_bundle'); } /** * Form element validation handler; Filters the #value property of an element. */ public static function elementValidateFilter(&$element, FormStateInterface $form_state) { $element['#value'] = array_filter($element['#value']); $form_state->setValueForElement($element, $element['#value']); } /** * {@inheritdoc} */ public function getMatches($string) { $query = $this->buildEntityQuery($string); $result = $query->execute(); if (empty($result)) { return []; } $matches = []; $entities = $this->entityManager->getStorage($this->target_type)->loadMultiple($result); foreach ($entities as $entity_id => $entity) { // Check the access against the defined entity access handler. /** @var \Drupal\Core\Access\AccessResultInterface $access */ $access = $entity->access('view', $this->currentUser, TRUE); if (!$access->isAllowed()) { continue; } $matches[] = [ 'title' => $this->buildLabel($entity), 'description' => $this->buildDescription($entity), 'path' => $this->buildPath($entity), 'group' => $this->buildGroup($entity), ]; } return $matches; } /** * Builds an EntityQuery to get entities. * * @param $match * Text to match the label against. * * @return \Drupal\Core\Entity\Query\QueryInterface * The EntityQuery object with the basic conditions and sorting applied to * it. */ protected function buildEntityQuery($match) { $match = $this->database->escapeLike($match); $entity_type = $this->entityManager->getDefinition($this->target_type); $query = $this->entityManager->getStorage($this->target_type)->getQuery(); $label_key = $entity_type->getKey('label'); if ($label_key) { $query->condition($label_key, '%' . $match . '%', 'LIKE'); $query->sort($label_key, 'ASC'); } // Bundle check. if (!empty($this->configuration['bundles']) && $bundle_key = $entity_type->getKey('bundle')) { $query->condition($bundle_key, $this->configuration['bundles'], 'IN'); } // Add tags to let other modules alter the query. $query->addTag('linkit_entity_autocomplete'); $query->addTag('linkit_entity_' . $this->target_type . '_autocomplete'); // Add access tag for the query. $query->addTag('entity_access'); $query->addTag($this->target_type . '_access'); return $query; } /** * Builds the label string used in the match array. * * @param \Drupal\Core\Entity\EntityInterface $entity * The matched entity. * * @return string * The label for this entity. */ protected function buildLabel($entity) { return Html::escape($entity->label()); } /** * Builds the description string used in the match array. * * @param \Drupal\Core\Entity\EntityInterface $entity * The matched entity. * * @return string * The description for this entity. */ protected function buildDescription($entity) { $description = \Drupal::token()->replace($this->configuration['result_description'], [$this->target_type => $entity], []); return LinkitXss::descriptionFilter($description); } /** * Builds the path string used in the match array. * * @param \Drupal\Core\Entity\EntityInterface $entity * The matched entity. * * @return string * The URL for this entity. */ protected function buildPath($entity) { return $entity->toUrl()->toString(); } /** * Builds the group string used in the match array. * * @param \Drupal\Core\Entity\EntityInterface $entity * The matched entity. * * @return string * The match group for this entity. */ protected function buildGroup($entity) { $group = $entity->getEntityType()->getLabel(); // If the entities by this entity should be grouped by bundle, get the // name and append it to the group. if ($this->configuration['group_by_bundle']) { $bundles = $this->entityManager->getBundleInfo($entity->getEntityTypeId()); $bundle_label = $bundles[$entity->bundle()]['label']; $group .= ' - ' . $bundle_label; } return $group; } }