Support for Block field

Created on 18 July 2024, 4 months ago
Updated 30 July 2024, 4 months ago

Using a Paragraphs type that's referencing a (Views) block with Block field.

There's no Transform available in the Paragraphs' Manage transform settings, keeping the field disabled. Makes sense really.

Can you add support for this or point me in the right direction to implement the required Transform?

Placing the block thru Block layout Transform settings works:

        "views_block__current_user_block_1": {
            "type": "view",
            "view_id": "current_user",
            "display_id": "block_1",
            "results": [
                {
                    "type": "entity",
                    "entity_type": "user",
                    "bundle": "user",
                    "id": "1",
                    "transform_mode": "default",
                    "langcode": "en",
                    "label": "admin"
                }
            ],
            "exposed_filters": [],
            "pager": []
        }
Feature request
Status

Active

Version

1.1

Component

Transform blocks

Created by

🇫🇮Finland irowboat

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

Comments & Activities

  • Issue created by @irowboat
  • 🇫🇮Finland irowboat

    Also field support for Views Transforms is definitely on the wishlist.

  • 🇩🇰Denmark erik_petra

    You can write your own Field Transform plugins and we're currently working on a guide for it.
    But a good example for it is to check out some existing ones, such as src/Plugin/Transform/Field/EntityTransform.php

    As for field support for Views Transforms, that's our next goal within Views integration.

  • 🇫🇮Finland irowboat

    Thanks, I got it working.

    Here's some proof-of-concept code for anyone interested - Block field support for Views and Webform blocks. (Not using content/custom blocks but understanding what's happening here, should be easy to implement.)

    
    namespace Drupal\transform_api_block_field\Plugin\Transform\Field;
    
    use Drupal\Core\Block\BlockManagerInterface;
    use Drupal\Core\Field\FieldDefinitionInterface;
    use Drupal\Core\Field\FieldItemListInterface;
    use Drupal\group\Context\GroupRouteContext;
    use Drupal\transform_api\FieldTransformBase;
    use Drupal\transform_api_views\Transform\ViewTransform;
    use Drupal\views\Plugin\Block\ViewsBlock;
    use Drupal\webform\Entity\Webform;
    use Drupal\webform\Plugin\Block\WebformBlock;
    use Drupal\webform\WebformTokenManagerInterface;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    
    /**
     * Transform field plugin for block field items.
     *
     * @FieldTransform(
     *  id = "block_field_transform",
     *  label = @Translation("Block field transform"),
     *  field_types = {
     *    "block_field"
     *  }
     * )
     */
    class BlockFieldTransform extends FieldTransformBase {
    
      /**
       * The block manager service.
       *
       * @var \Drupal\Core\Block\BlockManagerInterface
       */
      protected $blockManager;
    
      /**
       * The group content storage service.
       *
       * @var \Drupal\group\Entity\GroupRouteContext
       */
      protected $groupRouteContext;
    
      /**
       * The token manager service.
       *
       * @var \Drupal\webform\WebformTokenManagerInterface
       */
      protected $tokenManager;
    
      /**
       * Constructs a BlockFieldTransform object.
       *
       * @param string $plugin_id
       *   The plugin_id for the transform.
       * @param mixed $plugin_definition
       *   The plugin implementation definition.
       * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
       *   The definition of the field to which the transform is associated.
       * @param array $settings
       *   The transform settings.
       * @param string $label
       *   The transform label display setting.
       * @param string $transform_mode
       *   The transform mode.
       * @param array $third_party_settings
       *   Any third party settings.
       * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
       *   The block manager service.
       * @param \Drupal\group\Entity\GroupRouteContext $group_route_context
       *   The group route context to get the group entity.
       * @param \Drupal\webform\WebformTokenManagerInterface $token_manager
       *   The token manager service.
       */
      public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $transform_mode, array $third_party_settings, BlockManagerInterface $block_manager, GroupRouteContext $group_route_context, WebformTokenManagerInterface $token_manager) {
        parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $transform_mode, $third_party_settings);
        $this->blockManager = $block_manager;
        $this->groupRouteContext = $group_route_context;
        $this->tokenManager = $token_manager;
      }
    
      /**
       * {@inheritdoc}
       */
      public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
        return new static(
          $plugin_id,
          $plugin_definition,
          $configuration['field_definition'],
          $configuration['settings'],
          $configuration['label'],
          $configuration['transform_mode'],
          $configuration['third_party_settings'],
          $container->get('plugin.manager.block'),
          $container->get('group.group_route_context'),
          $container->get('webform.token_manager')
        );
      }
    
      /**
       * {@inheritdoc}
       */
      public function transformElements(FieldItemListInterface $items, $langcode) {
        $elements = [];
        if ($items->isEmpty()) {
          return $elements;
        }
    
        foreach ($items as $item) {
          // Assuming each $item contains the plugin_id and settings.
          $plugin_id = $item->get('plugin_id')->getValue();
          $settings = $item->get('settings')->getValue();
    
          // Create block plugin instance.
          $block_plugin = $this->blockManager->createInstance($plugin_id, $settings);
    
          // We currently only handle Views blocks and Webform blocks.
          // Views blocks leverage the ViewsTransform plugin, while Webform blocks
          // get the form elements and transform them as a simple field list.
          if ($block_plugin instanceof ViewsBlock) {
            $args = [];
    
            // If you need to pass contextual filter values, add them here.
            // You can get any other fields from the parent by loading the entity
            // with $items->getEntity(); - this is useful if you want to get a
            // category, or some other setting the View needs.
            //
            // Get the View id and display id, this is one way.
            $plugin_id_array = explode(':', $plugin_id);
            $view_name_array = explode('-', $plugin_id_array[1]);
    
            // Transform API Views submodule provides a ViewsTransform plugin.
            $elements[] = new ViewTransform($view_name_array[0], $view_name_array[1], [], $args);
          }
          elseif ($block_plugin instanceof WebformBlock) {
    
            // Get the Webform ID from the block settings.
            $webform_id = $settings['webform_id'];
            // Load the webform.
            $webform = Webform::load($webform_id);
            if ($webform) {
    
              // Return only the form elements.
              $webform_elements = $webform->getElementsInitialized();
              $webform_elements = $this->tokenManager->replace($webform_elements, $webform);
              $elements[] = [
                'type' => 'webform',
                'webform_id' => $webform_id,
                'fields' => $this->processWebformFields($webform_elements),
              ];
            }
          }
    
        }
    
        return $elements;
      }
    
      /**
       * Removes the hash from the keys of the given array for Transform API.
       *
       * Also turns the root level keys to numeric.
       */
      protected function processWebformFields(array $array, $level = 0) {
        $result = [];
        $index = 0;
    
        foreach ($array as $key => $value) {
          // Remove the leading '#' from the key.
          $newKey = ltrim($key, '#');
    
          // If the value is an array, process it recursively.
          if (is_array($value)) {
            $value = $this->processWebformFields($value, $level + 1);
          }
    
          // Add the new key-value pair to the result array.
          if ($level === 0) {
            // For the first level, use numeric keys.
            $result[$index] = $value;
            $index++;
          }
          else {
            // For deeper levels, retain associative keys.
            $result[$newKey] = $value;
          }
        }
    
        return $result;
      }
    
    }
    
    
Production build 0.71.5 2024