Views bulk operations support

Created on 3 May 2024, about 2 months ago
Updated 14 May 2024, about 1 month ago

Problem/Motivation

I would like to use Views bulk operations on a Views database connector view. I actually do not need to manipulate the database, I am looking to execute custom actions on an external site using the fetched values. Currently adding the VBO field to a VDC view gives the message:

Views Bulk Operations will work only with normal entity views and contrib module views that are integrated. See \Drupal\views_bulk_operations\EventSubscriber\ViewsBulkOperationsEventSubscriber class for integration best practice.

Steps to reproduce

Create a VDC view as normal and add the VBO field. This produces the message above and does not render the field in the view.

Proposed resolution

Integrate VDC with VBO as per https://www.drupal.org/docs/contributed-modules/views-bulk-operations-vb... β†’
I am not sure but I think we need to expose VDC data as entities before adding the event subscriber. Does anyone have any tips on how to get started?

✨ Feature request
Status

Active

Version

2.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States j.young

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @j.young
  • πŸ‡ΊπŸ‡ΈUnited States andileco

    Have you looked at https://www.drupal.org/project/external_entities β†’ and decided that definitely does not work for your use-case?

  • πŸ‡ΊπŸ‡ΈUnited States j.young

    I have looked at that a bit, but it seems to only support PostgreSQL and MySQL databases. I'm using an Oracle db, which I hacked VDC to pull in. I'll play with it some more but at this point it seems like the easiest thing will be to have VDC directly define the entities (or even maybe in a separate module), and then add the event subscriber stuff. Hopefully I am on the right track.

  • πŸ‡ΊπŸ‡ΈUnited States j.young

    So I have tried several other modules/approaches to get the functionality I need but VDC comes the closest. I am currently stuck at getting the entities passed through to my custom action. VBO is recognizing my entities in the view but when I make a selection and execute the action, I get errors as noted below.

    I have installed the entity_test module from core, and am creating an EntityTest entity for each row in StandardVDC.php. I took this idea from Views Remote Data β†’ as it seems to be a good way to define entities without saving them to the database. I don't think saving the entities helps anyway as I have tried that as well.

    I added this code to the beginning of the render() function. There is probably a better place to do this but I have tried moving it to other files and this is the only way I can get it to work.

        if ($this->options['label'] == 'COLUMN_NAME') {
            $values->_entity = EntityTest::create([
              'name' => $values->column_name,
            ]);
        }

    Also need this use statement at the top of file

    use Drupal\entity_test\Entity\EntityTest;

    I created src/Service/VdcVboViewsData.php

    <?php
    
    namespace Drupal\views_database_connector;
    
    use Drupal\views\ResultRow;
    use Drupal\views\ViewExecutable;
    
    /**
     * Contains entity getter method.
     */
    class VdcVboViewsData {
      
      /**
       * The entity getter method.
       *
       * @param \Drupal\views\ResultRow $row
       *   Views result row.
       * @param string $relationship_id
       *   Id of the view relationship.
       * @param \Drupal\views\ViewExecutable $view
       *   The current view object.
       */
      public static function getEntityFromRow(ResultRow $row, $relationship_id, ViewExecutable $view) {
        $entity = $row->_entity;
        return $entity;
      }
    
    }
    

    src/EventSubscriber/ViewsDatabaseConnectorEventSubscriber.php

    <?php
    
    namespace Drupal\views_database_connector\EventSubscriber;
    
    use Drupal\views_bulk_operations\Service\ViewsBulkOperationsViewDataInterface;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Drupal\views_bulk_operations\ViewsBulkOperationsEvent;
    
    /**
     * Event subscriber class.
     */
    class ViewsDatabaseConnectorEventSubscriber implements EventSubscriberInterface {
    
      // Subscribe to the VBO event with high priority
      // to prepopulate the event data.
      private const PRIORITY = 999;
    
      /**
       * {@inheritdoc}
       */
      public static function getSubscribedEvents() {
        $events = [];
        // The next line prevents hard dependency on VBO module.
        if (class_exists(ViewsBulkOperationsEvent::class)) {
          $events['views_bulk_operations.view_data'][] = ['provideViewData', 0];
          self::PRIORITY;
        }
        return $events;
      }
    
      /**
       * Provide entity type data and entity getter to VBO.
       *
       * @param \Drupal\views_bulk_operations\ViewsBulkOperationsEvent $event
       *   The event object.
       */
      public function provideViewData(ViewsBulkOperationsEvent $event) {
        if ($event->getProvider() === 'views_database_connector') {
          $event->setEntityTypeIds(['entity_test']);
          $event->setEntityGetter([
             'file' => \Drupal::service('extension.list.module')->getPath('views_database_connector') . '/src/Service/VdcVboViewsData.php',
             'callable' => '\Drupal\views_database_connector\VdcVboViewsData::getEntityFromRow',
          ]);
        }
      }
    
    }
    

    And in views_database_connector.views.inc, added this to the table definition.

            $data[$table[0]]['table']['entity type'] = 'entity_test';
            $data[$table[0]]['table']['entity revision'] = FALSE;

    Here are the errors I am getting. I think the entities are not being loaded correctly by the VBO action processor.

    Error: Call to a member function language() on null in Drupal\views_bulk_operations\Service\ViewsBulkOperationsActionProcessor->populateQueue() (line 372 of /var/www/(drupal location)/modules/contrib/views_bulk_operations/src/Service/ViewsBulkOperationsActionProcessor.php)

    Got error 'PHP message: Uncaught PHP Exception Error: "Call to a member function language() on null" at /var/www/(drupal location)/modules/contrib/views_bulk_operations/src/Service/ViewsBulkOperationsActionProcessor.php line 372'

    Any help would be greatly appreciated. I tried doing a var_dump of $form_data that is being passed to the VBO action processor, and all my expected entity data is there except for $form_data['entity_labels']. If I define this manually then the action configuration form loads but of course it doesn't get the counts right. I suspect my entities aren't getting "labels" defined, I'm still trying to figure out how to do that.

  • πŸ‡ΊπŸ‡ΈUnited States j.young

    I think I got this working, I am recreating the virtual entities in VBO's action processor (views_bulk_operations/src/Service/ViewsBulkOperationsActionProcessor.php). I still need to create the entities in VDC so the view is aware of them and creates the VBO checkboxes.

    Added this code to the mentioned file inside the populateQueue function, right before $entity is set.

            $row->_entity = EntityTest::create([
              'name' => $row->column_name,
            ]);

    At first it was creating extra entities so the counts displayed on the configuration form were wrong. I'm not sure if I changed something but it started working as expected, and the counts/selection info are correct. Also only one entity is created per row now. I guess these are not duplicated since I'm not saving anything to the database. I think the second instance of EntityTest::create is just overwriting the first one that must be stored in cache.

    I will continue testing to make sure everything works how I need it to. I would love to help get the functionality added to the module so I am able to upgrade in the future. I am not familiar with the process but am willing to help with guidance. However if adding this is not desirable, feel free to close this issue. Thanks.

Production build 0.69.0 2024