Een hart voor de Drupal Community

Bij make it fly geloven we sterk in Drupal en Open Source software in het algemeen. We maken dagelijks gebruik van vele open source componenten en de vele Drupal modules die beschikbaar zijn. We dragen actief ons steentje bij aan de community door zelf patches, modules en documentatie te voorzien, daarnaast zijn enkele teamleden ook actief in de Drupal User Group vzw.

Een overzicht van onze bijdragen aan de Drupal community vind je terug op onze Drupal.org pagina. Naast het actief meerwerken aan de Drupal community, zetten we ook andere ontwikkelaars op weg door vragen te beantwoorden op Drupal Answers.

  1. Document dependency on ui_skins to activate theme selection

    Sven Decabooter

    <code>

    Problem/Motivation

    I was creating a new starterkit theme for Daisy UI, following the instructions mentioned in https://git.drupalcode.org/project/ui_suite_daisyui/-/blob/5.0.x/starter..., under "Adding a new (random) theme".

    However, I got stuck on the last sentence: The new Random DaisyUI theme will be available under /admin/appearance/settings/my_daisyui_theme in the theme section.

    This "Theme" section was not available on my generated Daisy UI theme. It took me a few minutes to figure out that I hadn't yet enabled the "UI Skins" module, which I assumed would have been installed as a requirement to the theme, but is not.

    Although obvious in hindsight, it would be good to document this explicitly.

  2. Error attempting rollback

    Brecht Ceyssens

    We bumped into an issue when requesting translations for 22 languages. The batch operation crashed and the process was not finished correctly. Unfortunately Drupal didn't log the actual error because the rollback itself failed:

    Drupal\Core\Database\TransactionOutOfOrderException: Error attempting rollback of 691eee6a167188.49133015\drupal_transaction. Active stack: 691eee6a167188.49133015\drupal_transaction > 691eee6a26b399.04569357\savepoint_1 in Drupal\Core\Database\Transaction\TransactionManagerBase->rollback() (line 363 of /web/core/lib/Drupal/Core/Database/Transaction/TransactionManagerBase.php).
    
    #0 /web/core/lib/Drupal/Core/Database/Transaction.php(61): Drupal\Core\Database\Transaction\TransactionManagerBase->rollback()
    #1 /web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(812): Drupal\Core\Database\Transaction->rollBack()
    #2 /web/core/lib/Drupal/Core/Entity/EntityBase.php(370): Drupal\Core\Entity\Sql\SqlContentEntityStorage->save()
    #3 /web/modules/contrib/tmgmt/src/Entity/Job.php(559): Drupal\Core\Entity\EntityBase->save()
    #4 /web/modules/contrib/tmgmt/src/Entity/Job.php(694): Drupal\tmgmt\Entity\Job->setState()
    #5 /web/modules/contrib/tmgmt_smartling/src/Plugin/tmgmt/Translator/SmartlingTranslator.php(337): Drupal\tmgmt\Entity\Job->submitted()
    #6 /web/modules/contrib/tmgmt/src/Entity/Job.php(752): Drupal\tmgmt_smartling\Plugin\tmgmt\Translator\SmartlingTranslator->requestTranslation()
    #7 /web/modules/contrib/tmgmt/src/JobCheckoutManager.php(333): Drupal\tmgmt\Entity\Job->requestTranslation()
    #8 /web/modules/contrib/tmgmt/src/JobCheckoutManager.php(289): Drupal\tmgmt\JobCheckoutManager->requestTranslation()
    #9 /web/modules/contrib/tmgmt/src/JobCheckoutManager.php(237): Drupal\tmgmt\JobCheckoutManager->doBatchSubmit()
    #10 /web/core/includes/batch.inc(298): Drupal\tmgmt\JobCheckoutManager::batchSubmit()
    #11 /web/core/includes/batch.inc(139): _batch_process()
    #12 /web/core/includes/batch.inc(95): _batch_do()
    #13 /web/core/modules/system/src/Controller/BatchController.php(52): _batch_page()
    #14 [internal function]: Drupal\system\Controller\BatchController->batchPage()

    I'll attempt to patch core to log the actual error before rolling back to transaction. In the meanwhile I'm stuck with the isuse. Do you have an idea what could have caused this? If you want, we can provide additional information about the translation job/ID so you can search the logs on Smartling side?

  3. Swagger-PHP OpenAPI 3 documentation generator

    Sven Decabooter

    This module uses the zircote/swagger-php library to let you document your Drupal code, and generate an OpenAPI 3 specification and documentation UI, based on those PHP attributes.

    Installation

    • Install this module and its dependencies via Composer.
    • Install the swagger-api/swagger-ui library in your /libraries folder. See https://www.drupal.org/project/openapi_ui_swagger#installation-composer
    • Enable the swagger_php module
    • Use the zircote/swagger-php library PHP attributes to document your API, e.g. a custom RestResource plugin you have created.

    Example usage

    Say we have created a custom RestResource plugin, and want to document this API endpoint via the OpenAPI 3 specification.

    
    namespace Drupal\my_custom_api\Plugin\rest\resource;
    
    use Drupal\Core\StringTranslation\TranslatableMarkup;
    use Drupal\rest\Attribute\RestResource;
    use Drupal\rest\ModifiedResourceResponse;
    use Drupal\rest\Plugin\ResourceBase;
    use OpenApi\Attributes as OA;
    
    /**
     * My custom API endpoint.
     */
    #[OA\Info(
      version: "1.0.0",
      description: "API documentation for my custom API",
      title: "My Custom API"
    )]
    #[RestResource(
      id: 'my_custom_resource',
      label: new TranslatableMarkup('Custom API endpoint to send data to.'),
      uri_paths: [
        'create' => '/api/v1/custom/add',
      ],
    )]
    class MyCustomResource extends ResourceBase {
    
      /**
       * Responds to POST requests and saves the data.
       */
      #[OA\Post(path: '/api/v1/custom/add', operationId: 'my_custom_resource_add')]
      #[OA\Response(response: '200', description: 'The processed data')]
      public function post(array $data): ModifiedResourceResponse {}
    
    }
    

    This renders the following API documentation page + an OpenAPI 3 compatible JSON specification file:

    More information: https://zircote.github.io/swagger-php/

  4. The highlight js code runs on all code blocks

    Fons

    Just installed the update and altered my SDC component a little.

    Works perfectly now.

    You can see the code container and the inline code container in action on this page:

    https://webhaven.io/documentation/theming/theme-structure

    Thanks!

  5. Support other authentication providers

    Sven Decabooter

    Problem/Motivation

    In the API or Endpoint plugins, you can specify an "auth" parameter. I added "basic_auth" in there, expecting the basic auth security definition to be added to the OpenAPI spec (see https://swagger.io/docs/specification/v2_0/authentication/basic-authenti...). However, this does nothing.

    Looking into \Drupal\rest_easy\Plugin\APIBase::getSecurityDefinitions(), only `rest_easy_api_key` seems to be supported. I guess not all auth providers defined in Drupal can be added automatically to the OpenAPI spec, but basic_auth and maybe oauth2 could be added I think?

  6. in: "body" unexpected behaviour

    Sven Decabooter

    Problem/Motivation

    I am trying to set up a REST API endpoint, but run into some issues with defining body parameters.

    Installed modules: - openapi 2.3.0 - openapi_rest 2.0.0 - openapi_ui 1.0.0-rc5 - openapi_ui_redoc 1.0.0-rc5 - openapi_ui_swagger 1.1.0 - rest_easy 1.1.3-alpha1

    I have an endpoint that uses the POST method. I want the data to be entered via POST, like:

    {
      "registrationId": "some-id",
      "title": "Some title",
      ...
    }
    

    I have created a parameter class to achieve this:

    #[RESTEasyParameter(
      api: "my_api",
      id: "registrationId",
      type: "string",
      default: '',
      description: new TranslatableMarkup("The unique key for the registration."),
      in: "body",
      required: TRUE
    )]
    

    This seems to produce an unexpected schema. When I try to use the UI modules, it also seems to act up:

    Swagger Seems to treat this as a JSON value instead of a string?

    ReDoc Just crashes...

    If I enable the "rest_easy_example" module, and try to change the "pretty" parameter's "in" value to body, the same happens...

  7. Icon API field type

    Sven Decabooter

    Problem/Motivation

    Since Drupal 11.1, the Icon API was introduced in Drupal - https://www.drupal.org/docs/develop/drupal-apis/icon-api For a project I have used this API to define a set of icons that can be used within the project.

    In a custom field, I'd like to add an icon subfield. Currently I have implemented this by using the ui_icons module with a couple of its submodules. I create a new Media type "Icon" to reference the appropriate icon, and in the custom field I create an entity reference to the "Icon" media entities. This does get the job done.

    It feels like a workaround however, in that I always have to create an icon media entity instance, before it can be used within the custom field, so from an editorial point of view, it's not really user friendly.

    Not sure how technically complex it would be, but it would be nice if I could reference an icon from an icon pack directly within a custom field subfield.

    This probably would have to be added in a submodule, which is only installable on Drupal 11.1+, since the Icon API is not available on older Drupal versions, which might complicate things further.

  8. The highlight js code runs on all code blocks

    Fons

    Just had a look and looks like a good solution.

    Thank you for taking the time to come up with it.

    When it’s pushed to a release I’ll update my projects and the SDC components where needed to go with the new flow.

    Thank you, if anything would occur I’ll let you know. 🙏

  9. Afterburner

    Brecht Ceyssens

    Afterburner is a performance module for Drupal that brings true concurrency to background and queue processing. It integrates Spatie’s Async library to process tasks in parallel PHP workers, both during the Terminate event and within queue systems.

    Why Afterburner? Drupal’s native queue system and terminate hooks are sequential — they process one item at a time or run within a single PHP request. Afterburner adds a layer of asynchronous concurrency, enabling heavy post-response or queue workloads to execute in parallel, without blocking user-facing requests.

  10. Document pipelines and hosting automation

    Sven Decabooter

    Problem/Motivation

    The current workflow with the upstream la_eu repository, as well as our Dropsolid hosting-specific repository is a bit difficult to follow, at least in my head. So we should document the current state, to make sure everyone can understand how it's set up.

  11. Option "Groups in menu" renders error message

    Sven Decabooter

    Problem/Motivation

    When the option "Automatically show Groups in the admin menu" is selected, a menu item is added for each Group, linking to the Site Settings entity listing, with the "Group" exposed filter prefilled.

    The prefilled value is the Group ID, but the produces an error when clicked:

    Example:

    When the group name is used in the URL, instead of the ID, this works again: /admin/content/site-settings?group=Company+information

  12. Optionally use property text as details wrapper label

    Sven Decabooter

    Problem/Motivation

    Followup from issue #3541876: Allow collapsing / expanding of multivalue items:

    Furthermore it would be nice if we could optionally select a (text) property of the custom_field field that functions as the details label, instead of Item (1), Item (2), etc...

    Proposed resolution

    - In the form widget settings, add an optional setting to select the property whose value should be used as the details wrapper label - This setting is only shown when the "Details" wrapper is selected - The setting shows a select list of properties available on that custom_field field - probably only string values should be in that list - If selected, some Javascript code should be added to the widget form, which copies the text from the selected property and uses it as details label. When the text of the selected property changes in the form, the details label should be updated. The text should probably be sanitized and have a maximum length set (if too long, append "..." at the end?)

  13. Fatal error: Declaration of Drupal\webform\EntityStorage\WebformEntityStorageTrait::__get($name) must be compatible with Drupal\Core\Entity\ContentEntityStorageBase::__get(string $name): mixed

  14. Fatal error: Declaration of Drupal\webform\EntityStorage\WebformEntityStorageTrait::__get($name) must be compatible with Drupal\Core\Entity\ContentEntityStorageBase::__get(string $name): mixed

    Fons
    Fons added a comment on drupal.org: Fatal error: Declaration of Drupal\webform\EntityStorage\WebformEntityStorageTrait::__get($name) must be compatible with Drupal\Core\Entity\ContentEntityStorageBase::__get(string $name): mixed
  15. Fatal error: Declaration of Drupal\webform\EntityStorage\WebformEntityStorageTrait::__get($name) must be compatible with Drupal\Core\Entity\ContentEntityStorageBase::__get(string $name): mixed

    Fons

    Problem/Motivation

    I just upgraded to Drupal 11.2.6 and I get the following errog:

    Fatal error: Declaration of Drupal\webform\EntityStorage\WebformEntityStorageTrait::__get($name) must be compatible with Drupal\Core\Entity\ContentEntityStorageBase::__get(string $name): mixed

  16. HTMX Extras

    Randal

    The HTMX Extras module adds some lazy loading functionality to your website.

    Currently, these elements are implemented:

    • Lazy load entity: A template to lazily load an entity render
    • Lazy load route: A template to lazily load the contents of a given route
    • Search API lazy load row plugin: Renders your views lazily when they're revealed in the viewport (completely customizable, uses the "Lazy load entity"-template)

    More functionality will be added once the need arises, feel free to create a ticket if you have a use case that could fall under this module's scope.

    For replacing Drupal's AJAX API with HTMX, we gladly refer to the excellent HTMX-project

  17. The highlight js code runs on all code blocks

    Fons

    I have it running on 3 websites in production and all is well (it's also a minor change) so I've changed the status to reviewed & tested.

    Would love to get this change in so I can get rid of the patches.

    Thanks in advance!

  18. Drupal content export does not support Layout Builder inline blocks

    Sven Decabooter

    Problem/Motivation

    I tested the upcoming 11.3 functionality to export Drupal content to a directory. This with the purpose the import it again on other websites through recipes.

    While #3532951: Support exporting content and its dependencies to a folder structure on disk and https://www.drupal.org/project/default_content/issues/3160146#comment-16... seem to imply that Layout Builder content export will be possible, this seems to be only half the case.

    When I create a Layout Builder section that contains an inline block component, I would expect the block_content entity to be exported as well.

    For this to work previously with the Default Content contrib module, I needed to apply several patches, including https://www.drupal.org/project/default_content/issues/3160146. I assume the logic in that patch was not moved over to the Drupal core default content system yet.

    Since Layout Builder, inline blocks and default content export are all in core, it seems less acceptable to me that this wouldn't work out of the box.

    Steps to reproduce

    - Install Layout Builder and activate it for a content type - Create a new block type containing a field - Configure Layout Builder to allow adding that block type to a LB section on a test node - Export the test node (through php core/scripts/drupal content:export node [NID] --dir=../test_default_content --with-dependencies)

    Example simple node with an inline LB block:

    After exporting, I get the following file: test_default_content/node/4f651b20-2513-4a64-889d-1aa0e721f75b.yml

    _meta:
      version: '1.0'
      entity_type: node
      uuid: 4f651b20-2513-4a64-889d-1aa0e721f75b
      bundle: page
      default_langcode: nl
    default:
      revision_uid:
        -
          target_id: 1
      status:
        -
          value: true
      uid:
        -
          target_id: 1
      title:
        -
          value: 'Test page with an inline layout builder block'
      created:
        -
          value: 1760792440
      promote:
        -
          value: false
      sticky:
        -
          value: false
      path:
        -
          alias: /test-page-inline-layout-builder-block
          langcode: nl
      content_translation_source:
        -
          value: und
      content_translation_outdated:
        -
          value: false
      layout_builder__layout:
        -
          section:
            layout_id: layout_onecol
            layout_settings:
              label: ''
            components:
              558dca26-6728-4bb6-97e5-587cced0f198:
                uuid: 558dca26-6728-4bb6-97e5-587cced0f198
                region: content
                configuration:
                  id: 'inline_block:test_block_type'
                  label: 'Test block type'
                  label_display: false
                  provider: layout_builder
                  view_mode: full
                  block_id: '18'
                  block_revision_id: '18'
                  block_serialized: null
                  context_mapping: {  }
                weight: 0
                additional: {  }
            third_party_settings: {  }
    

    Note that the text "This text should be exported" is nowhere to be found. This would have to added to a test_default_content/block_content/558dca26-6728-4bb6-97e5-587cced0f198.yml file....

Sven Decabooter - Drupal Developer

"Onze teamleden bouwen zelf ook mee aan ons geliefde Drupal, en daar zijn we trots op"

Sven Decabooter
Drupal developer

Betrouwbare technologie, naadloze prestaties. Dat zijn onze Drupal-oplossingen.