Bulk Image

Własna akcja w module Views Bulk Operations

Moduł Views Bulk Operations jest używany, gdy chcemy dodać możliwość wykonywania masowych operacji na wybranych encjach. Mimo wbudowanych akcji takich jak np. publikacja czy usuwanie wpisów, w prosty sposób można dodać własne, złożone akcje. W tym przykładzie pokazane będzie jak dodać akcję, która zmieni stan wpisu (Workflows).

Views bulk operations

Akcja wykonywana jest na wszystkich zaznaczonych wpisach i z automatu wykonuje się w kolejkach Batch tak, aby nie przeciążyć systemu i nie spowodować “wywalenia” się strony, gdy proces wykonuje się za długo. 

Jeżeli wiesz, co robisz i masz ku temu powody, to w konfiguracji pola możesz wyłączyć opcję kolejkowania.

Instalacja i konfiguracja VBO

Moduł Views Bulk Operations instaluje się poprzez ściągnięcie i rozpakowanie paczki w katalogu modules/contrib lub za pomocą komendy composer, która ściągnie najnowszą stabilną wersję modułu.

composer require drupal/views_bulk_operations

Po instalacji modułu nie trzeba w żaden sposób konfigurować, a wystarczy dodać odpowiednie pole do strony (lub bloku) utworzonego przez moduł Views.

  • Dodaj nowy widok z treściami (Content), który tworzy stronę.
  • Format wyświetlania ustaw na Tabela.
    Nie jest to konieczność, po prostu checkboxy na tabeli wyglądają naturalniej
  • Dodaj pole tytułu
  • Dodaj pole Views bulk operations
Views bulk operations

 

Konfiguracja akcji dla pola VBO

W konfiguracji pola można zaznaczyć, które masowe akcje będą mogły być wykonywane na wynikach. Jest tam kilkanaście predefiniowanych akcji, takich jak na przykład:

  • usuwanie wpisów
  • publikowanie 
  • przyklejanie
Views bulk operations

 

Powyższa lista jest zgodna, gdy widok wyświetla zawartość (Content). Jeżeli dodasz widok wyświetlający użytkowników (Users), to zauważysz, że lista ma inne akcje. 

Dodanie własnej akcji do VBO

Celem jest dodanie własnych akcji na wpisach (Content), które zmienią stan (Workflows) wybranych wpisów. 

Stany wpisów nie są dostępne od razu po instalacji Drupala. W tym celu trzeba włączyć dwa dodatkowe moduły, które znajdują się bezpośrednio w Drupalu. Nie trzeba ściągać nic dodatkowego.

Wejdź na stronę z modułami - admin/modules

Włącz moduły: Workflows i Content moderation

WorkflowsContent moderation

Konfiguracja Workflows

Dla celów tego wpisu wykorzystam automatycznie zdefiniowane stany dla typu Editorial, który dostępny jest od razu po włączeniu modułu Content moderation. 

Jedynie co trzeba zrobić, to włączyć dany typ przejścia stanów dla wybranych rodzajów zawartości.

  • Na stronie admin/config/workflow/workflows edytuj typ Editorial
  • Ustaw typ zawartości Artykuł (Article)
Workflows editorial

 

Ta operacja doda nowe pole do każdego formularza dodawania/edycji artykułu.

Workflows

Do widoku gdzie jest pole VBO dodaj: 

  • pole wyświetlające stan danego wpisu - Content: Moderation state
  • filtr, który ograniczy wyświetlanie wpisów z typu Artykuł

Jeżeli dodany jest filtr ograniczający wpisy jedynie do tych opublikowanych Content: Published (= Yes), to go usuń. Będzie blokował wyświetlanie wpisów, które mają stan np. Draft lub Archived, które z definicji są niepublikowane.

Kod własnej akcji

Stwórz własny moduł i włącz go. W moim przypadku moduł nazywa się d_workflows
W katalogu modułu stwórz strukturę katalogów src/Plugin/Action

Utwórz w nim nowy plik z klasą dla akcji zmiany stanu wpisu na Published.

Nazwa pliku: PublishNodeAction.php

/**
 * Content moderation publish node.
 *
 * @Action(
 *   id = "d_workflows_publish_node_action",
 *   label = @Translation("Publish node (moderation_state)"),
 *   type = "node",
 *   confirm = TRUE
 * )
 */

class PublishNodeAction extends ViewsBulkOperationsActionBase {

Ważna jest tutaj adnotacja klasy.

Ustalasz w niej id dla akcji, może być to dowolna unikalna wartość. Warto w jej nazwie zawrzeć nazwę modułu oraz to, co dana akcja robi.

Label to wartość, która pojawi się w konfiguracji pola VBO.

Type to typ encji, dla której będzie dostępna nowa akcja. W tym przypadku jest to node, ale może być na przykład user, taxonomy_term czy jakakolwiek inna.

Nasza klasa dziedziczy po ViewsBulkOperationsActionBase
Wymaga to zadeklarowania dwóch metod:

  • execute() - co ma zostać wykonane dla każdego rekordu
  • access() - kto może wykonać akcję

Przykładowy kod metody execute()

/**
 * {@inheritdoc}
 */
public function execute(ContentEntityInterface $entity = NULL) {
  if (!$state = $entity->get('moderation_state')->getString()) {
    return $this->t(':title  - can\'t change state',
      [
        ':title' => $entity->getTitle(),
      ]
    );
  }

  switch ($state) {
    case 'archived':
    case 'draft':
      $entity->set('moderation_state', 'published');
      $entity->save();
      break;
  }

  return $this->t(':title state changed to :state',
    [
      ':title' => $entity->getTitle(),
      ':state' => $entity->get('moderation_state')->getString(),
    ]
  );
}

Pierwszy warunek sprawdza, czy dana encja ma włączoną opcję ustalania stanów.

W naszym przypadku jest to jedynie Article. Gdy akcja będzie zainicjowana na wpisach bez włączonych stanów (puste $entity->get('moderation_state')->getString()), to zostanie przerwana i informacja o tym zostanie wyświetlona.

Warunek można łatwo rozszerzyć o np. sprawdzanie rodzaju zawartości dla encji.

$entity->bundle()

W dalszej części kodu sprawdzany jest aktualny stan wpisu i jeżeli warunek jest spełniony, to kod zmienia stan na Published.

$entity->set('moderation_state', 'published');

Przykładowy kod metody access()

  /**
   * {@inheritdoc}
   */
  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
    if ($object instanceof Node) {
      $can_update = $object->access('update', $account, TRUE);
      $can_edit = $object->access('edit', $account, TRUE);

      return $can_edit->andIf($can_update)->isAllowed();
    }

    return FALSE;
  }

W tym prostym warunku sprawdzane jest, czy operujemy na obiektach typu Node oraz czy użytkownik wykonujący akcję ma do niego uprawnienia edycji i update. W przeciwnym wypadku kod zwróci FALSE i akcja nie zostanie wykonana.

Cały plik PublishNodeAction.php wygląda tak:

<?php

namespace Drupal\d_workflows\Plugin\Action;

use Drupal\node\Entity\Node;
use Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Entity\ContentEntityInterface;

/**
 * Content moderation publish node.
 *
 * @Action(
 *   id = "d_workflows_publish_node_action",
 *   label = @Translation("Publish node (moderation_state)"),
 *   type = "node",
 *   confirm = TRUE
 * )
 */

class PublishNodeAction extends ViewsBulkOperationsActionBase {

  use StringTranslationTrait;

  /**
   * {@inheritdoc}
   */
  public function execute(ContentEntityInterface $entity = NULL) {
    if (!$state = $entity->get('moderation_state')->getString()) {
      return $this->t(':title  - can\'t change state',
        [
          ':title' => $entity->getTitle(),
        ]
      );
    }

    switch ($state) {
      case 'archived':
      case 'draft':
        $entity->set('moderation_state', 'published');
        $entity->save();
        break;
    }

    return $this->t(':title state changed to :state',
      [
        ':title' => $entity->getTitle(),
        ':state' => $entity->get('moderation_state')->getString(),
      ]
    );
  }

  /**
   * {@inheritdoc}
   */
  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
    if ($object instanceof Node) {
      $can_update = $object->access('update', $account, TRUE);
      $can_edit = $object->access('edit', $account, TRUE);

      return $can_edit->andIf($can_update)->isAllowed();
    }

    return FALSE;
  }
}


W edycji pola VBO będzie dostępna nowa akcja.

Views bulk operations

 

Podsumowanie

Doświadczeni programiści Drupala jak również konsultanci Drupala zapewniają, że dodanie nowych akcji do Views Bulk Operations jest proste i sprowadza się do stworzenia dodatkowej klasy z dwoma metodami. Na podstawie tego prostego przykładu możesz budować bardziej złożone akcje masowe na encjach różnego typu.

3. Najlepsze praktyki zespołów programistycznych