Chris@0: 'entity.manager']; Chris@0: Chris@0: /** Chris@0: * The loaded View object. Chris@0: * Chris@17: * @var \Drupal\views\ViewExecutable Chris@0: */ Chris@0: protected $view; Chris@0: Chris@0: /** Chris@18: * The entity type manager service. Chris@18: * Chris@18: * @var \Drupal\Core\Entity\EntityManagerInterface Chris@18: */ Chris@18: protected $entityTypeManager; Chris@18: Chris@18: /** Chris@18: * The module handler service. Chris@18: * Chris@18: * @var \Drupal\Core\Extension\ModuleHandlerInterface Chris@18: */ Chris@18: protected $moduleHandler; Chris@18: Chris@18: /** Chris@18: * The current user. Chris@18: * Chris@18: * @var \Drupal\Core\Session\AccountInterface Chris@18: */ Chris@18: protected $currentUser; Chris@18: Chris@18: /** Chris@18: * Constructs a new ViewsSelection object. Chris@18: * Chris@18: * @param array $configuration Chris@18: * A configuration array containing information about the plugin instance. Chris@18: * @param string $plugin_id Chris@18: * The plugin_id for the plugin instance. Chris@18: * @param mixed $plugin_definition Chris@18: * The plugin implementation definition. Chris@18: * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager Chris@18: * The entity type manager service. Chris@18: * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler Chris@18: * The module handler service. Chris@18: * @param \Drupal\Core\Session\AccountInterface $current_user Chris@18: * The current user. Chris@18: */ Chris@18: public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user) { Chris@18: parent::__construct($configuration, $plugin_id, $plugin_definition); Chris@18: Chris@18: $this->entityTypeManager = $entity_type_manager; Chris@18: $this->moduleHandler = $module_handler; Chris@18: $this->currentUser = $current_user; Chris@18: } Chris@18: Chris@18: /** Chris@18: * {@inheritdoc} Chris@18: */ Chris@18: public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { Chris@18: return new static( Chris@18: $configuration, Chris@18: $plugin_id, Chris@18: $plugin_definition, Chris@18: $container->get('entity_type.manager'), Chris@18: $container->get('module_handler'), Chris@18: $container->get('current_user') Chris@18: ); Chris@18: } Chris@18: Chris@18: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function defaultConfiguration() { Chris@0: return [ Chris@0: 'view' => [ Chris@0: 'view_name' => NULL, Chris@0: 'display_name' => NULL, Chris@0: 'arguments' => [], Chris@0: ], Chris@0: ] + parent::defaultConfiguration(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function buildConfigurationForm(array $form, FormStateInterface $form_state) { Chris@0: $form = parent::buildConfigurationForm($form, $form_state); Chris@0: Chris@0: $view_settings = $this->getConfiguration()['view']; Chris@0: $displays = Views::getApplicableViews('entity_reference_display'); Chris@0: // Filter views that list the entity type we want, and group the separate Chris@0: // displays by view. Chris@18: $entity_type = $this->entityTypeManager->getDefinition($this->configuration['target_type']); Chris@18: $view_storage = $this->entityTypeManager->getStorage('view'); Chris@0: Chris@0: $options = []; Chris@0: foreach ($displays as $data) { Chris@0: list($view_id, $display_id) = $data; Chris@0: $view = $view_storage->load($view_id); Chris@0: if (in_array($view->get('base_table'), [$entity_type->getBaseTable(), $entity_type->getDataTable()])) { Chris@0: $display = $view->get('display'); Chris@0: $options[$view_id . ':' . $display_id] = $view_id . ' - ' . $display[$display_id]['display_title']; Chris@0: } Chris@0: } Chris@0: Chris@0: // The value of the 'view_and_display' select below will need to be split Chris@0: // into 'view_name' and 'view_display' in the final submitted values, so Chris@0: // we massage the data at validate time on the wrapping element (not Chris@0: // ideal). Chris@0: $form['view']['#element_validate'] = [[get_called_class(), 'settingsFormValidate']]; Chris@0: Chris@0: if ($options) { Chris@0: $default = !empty($view_settings['view_name']) ? $view_settings['view_name'] . ':' . $view_settings['display_name'] : NULL; Chris@0: $form['view']['view_and_display'] = [ Chris@0: '#type' => 'select', Chris@0: '#title' => $this->t('View used to select the entities'), Chris@0: '#required' => TRUE, Chris@0: '#options' => $options, Chris@0: '#default_value' => $default, Chris@0: '#description' => '
' . $this->t('Choose the view and display that select the entities that can be referenced.
Only views with a display of type "Entity Reference" are eligible.') . '
' . $this->t('No eligible views were found. Create a view with an Entity Reference display, or add such a display to an existing view.', [ Chris@0: ':create' => Url::fromRoute('views_ui.add')->toString(), Chris@0: ':existing' => Url::fromRoute('entity.view.collection')->toString(), Chris@0: ]) . '
', Chris@0: ]; Chris@0: } Chris@0: else { Chris@0: $form['view']['no_view_help']['#markup'] = '' . $this->t('No eligible views were found.') . '
'; Chris@0: } Chris@0: } Chris@0: return $form; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Initializes a view. Chris@0: * Chris@0: * @param string|null $match Chris@0: * (Optional) Text to match the label against. Defaults to NULL. Chris@0: * @param string $match_operator Chris@0: * (Optional) The operation the matching should be done with. Defaults Chris@0: * to "CONTAINS". Chris@0: * @param int $limit Chris@0: * Limit the query to a given number of items. Defaults to 0, which Chris@0: * indicates no limiting. Chris@0: * @param array|null $ids Chris@0: * Array of entity IDs. Defaults to NULL. Chris@0: * Chris@0: * @return bool Chris@0: * Return TRUE if the view was initialized, FALSE otherwise. Chris@0: */ Chris@0: protected function initializeView($match = NULL, $match_operator = 'CONTAINS', $limit = 0, $ids = NULL) { Chris@0: $view_name = $this->getConfiguration()['view']['view_name']; Chris@0: $display_name = $this->getConfiguration()['view']['display_name']; Chris@0: Chris@0: // Check that the view is valid and the display still exists. Chris@0: $this->view = Views::getView($view_name); Chris@0: if (!$this->view || !$this->view->access($display_name)) { Chris@17: \Drupal::messenger()->addWarning(t('The reference view %view_name cannot be found.', ['%view_name' => $view_name])); Chris@0: return FALSE; Chris@0: } Chris@0: $this->view->setDisplay($display_name); Chris@0: Chris@0: // Pass options to the display handler to make them available later. Chris@0: $entity_reference_options = [ Chris@0: 'match' => $match, Chris@0: 'match_operator' => $match_operator, Chris@0: 'limit' => $limit, Chris@0: 'ids' => $ids, Chris@0: ]; Chris@0: $this->view->displayHandlers->get($display_name)->setOption('entity_reference_options', $entity_reference_options); Chris@0: return TRUE; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) { Chris@0: $display_name = $this->getConfiguration()['view']['display_name']; Chris@0: $arguments = $this->getConfiguration()['view']['arguments']; Chris@0: $result = []; Chris@0: if ($this->initializeView($match, $match_operator, $limit)) { Chris@0: // Get the results. Chris@0: $result = $this->view->executeDisplay($display_name, $arguments); Chris@0: } Chris@0: Chris@0: $return = []; Chris@0: if ($result) { Chris@0: foreach ($this->view->result as $row) { Chris@0: $entity = $row->_entity; Chris@0: $return[$entity->bundle()][$entity->id()] = $entity->label(); Chris@0: } Chris@0: } Chris@0: return $return; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function countReferenceableEntities($match = NULL, $match_operator = 'CONTAINS') { Chris@0: $this->getReferenceableEntities($match, $match_operator); Chris@0: return $this->view->pager->getTotalItems(); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function validateReferenceableEntities(array $ids) { Chris@0: $display_name = $this->getConfiguration()['view']['display_name']; Chris@0: $arguments = $this->getConfiguration()['view']['arguments']; Chris@0: $result = []; Chris@0: if ($this->initializeView(NULL, 'CONTAINS', 0, $ids)) { Chris@0: // Get the results. Chris@0: $entities = $this->view->executeDisplay($display_name, $arguments); Chris@0: $result = array_keys($entities); Chris@0: } Chris@0: return $result; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Element validate; Check View is valid. Chris@0: */ Chris@0: public static function settingsFormValidate($element, FormStateInterface $form_state, $form) { Chris@0: // Split view name and display name from the 'view_and_display' value. Chris@0: if (!empty($element['view_and_display']['#value'])) { Chris@0: list($view, $display) = explode(':', $element['view_and_display']['#value']); Chris@0: } Chris@0: else { Chris@0: $form_state->setError($element, t('The views entity selection mode requires a view.')); Chris@0: return; Chris@0: } Chris@0: Chris@0: // Explode the 'arguments' string into an actual array. Beware, explode() Chris@0: // turns an empty string into an array with one empty string. We'll need an Chris@0: // empty array instead. Chris@0: $arguments_string = trim($element['arguments']['#value']); Chris@0: if ($arguments_string === '') { Chris@0: $arguments = []; Chris@0: } Chris@0: else { Chris@0: // array_map() is called to trim whitespaces from the arguments. Chris@0: $arguments = array_map('trim', explode(',', $arguments_string)); Chris@0: } Chris@0: Chris@0: $value = ['view_name' => $view, 'display_name' => $display, 'arguments' => $arguments]; Chris@0: $form_state->setValueForElement($element, $value); Chris@0: } Chris@0: Chris@0: }