3 namespace Drupal\contextual\Plugin\views\field;
5 use Drupal\Component\Serialization\Json;
6 use Drupal\Component\Utility\Html;
7 use Drupal\Component\Utility\UrlHelper;
8 use Drupal\Core\Form\FormStateInterface;
9 use Drupal\Core\Routing\RedirectDestinationTrait;
11 use Drupal\views\Plugin\views\field\FieldPluginBase;
12 use Drupal\views\ResultRow;
15 * Provides a handler that adds contextual links.
17 * @ingroup views_field_handlers
19 * @ViewsField("contextual_links")
21 class ContextualLinks extends FieldPluginBase {
23 use RedirectDestinationTrait;
28 public function usesGroupBy() {
35 protected function defineOptions() {
36 $options = parent::defineOptions();
38 $options['fields'] = ['default' => []];
39 $options['destination'] = ['default' => 1];
47 public function buildOptionsForm(&$form, FormStateInterface $form_state) {
48 $all_fields = $this->view->display_handler->getFieldLabels();
49 // Offer to include only those fields that follow this one.
50 $field_options = array_slice($all_fields, 0, array_search($this->options['id'], array_keys($all_fields)));
52 '#type' => 'checkboxes',
53 '#title' => $this->t('Fields'),
54 '#description' => $this->t('Fields to be included as contextual links.'),
55 '#options' => $field_options,
56 '#default_value' => $this->options['fields'],
58 $form['destination'] = [
60 '#title' => $this->t('Include destination'),
61 '#description' => $this->t('Include a "destination" parameter in the link to return the user to the original view upon completing the contextual action.'),
63 '0' => $this->t('No'),
64 '1' => $this->t('Yes'),
66 '#default_value' => $this->options['destination'],
73 public function preRender(&$values) {
74 // Add a row plugin css class for the contextual link.
75 $class = 'contextual-region';
76 if (!empty($this->view->style_plugin->options['row_class'])) {
77 $this->view->style_plugin->options['row_class'] .= " $class";
80 $this->view->style_plugin->options['row_class'] = $class;
85 * Overrides \Drupal\views\Plugin\views\field\FieldPluginBase::render().
87 * Renders the contextual fields.
89 * @param \Drupal\views\ResultRow $values
90 * The values retrieved from a single row of a view's query result.
92 * @see contextual_preprocess()
93 * @see contextual_contextual_links_view_alter()
95 public function render(ResultRow $values) {
97 foreach ($this->options['fields'] as $field) {
98 $rendered_field = $this->view->style_plugin->getField($values->index, $field);
99 if (empty($rendered_field)) {
102 $title = $this->view->field[$field]->last_render_text;
104 if (!empty($this->view->field[$field]->options['alter']['path'])) {
105 $path = $this->view->field[$field]->options['alter']['path'];
107 elseif (!empty($this->view->field[$field]->options['alter']['url']) && $this->view->field[$field]->options['alter']['url'] instanceof Url) {
108 $path = $this->view->field[$field]->options['alter']['url']->toString();
110 if (!empty($title) && !empty($path)) {
111 // Make sure that tokens are replaced for this paths as well.
112 $tokens = $this->getRenderTokens([]);
113 $path = strip_tags(Html::decodeEntities(strtr($path, $tokens)));
119 if (!empty($this->options['destination'])) {
120 $links[$field]['query'] = $this->getDestinationArray();
125 // Renders a contextual links placeholder.
126 if (!empty($links)) {
127 $contextual_links = [
132 'contextual-views-field-links' => UrlHelper::encodePath(Json::encode($links)),
138 '#type' => 'contextual_links_placeholder',
139 '#id' => _contextual_links_to_id($contextual_links),
141 return \Drupal::service('renderer')->render($element);
151 public function query() {}