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. User context switching not working

    Brecht Ceyssens

    Hi @loparev, we're running into the same issue.

    We've setup a new Drupal environment to isolate the issue: Drupal: 11.2.2 Tmgmt: 8.x-1.17 Tmgmt Smartling: 8.x-9.17

    We've used the context debug submodule which works as advertised. The issue however only occurs when trying to upload unpublished pages, in combination with the queue worker running from command line.

    It looks like the code, copied from masquerade, on its own (handled with curl afterwards) doesn't handle sessions completely. Masquerade does a redirect on which the Symfony frameworks handles the session correctly and sets the cookie in a response listener.

    To dive deeper into the issue, dumping the cookies from modules/contrib/tmgmt_smartling/src/Context/ContextUserAuth.php's getCookies() looks like SSESSc2b280e207aa821b24606f896b740d6d=. As you can see it lacks the session_id value.

    It's probably because the queue is handled via command line (cron)? Let me know if you need more information to reproduce on your end.

  2. Error when trying to create an ECA model via AI

    Sven Decabooter

    Problem/Motivation

    I tried clicking the "Ask AI" button, to have it generate an ECA model for me. I didn't save the exact prompt beforehand unfortunately, so I don't have that to reproduce.

    The general purpose was like this:

    Upon saving a node, create an SEO-friendly summary of the full node display, and fill it in in a designated field. The full node display context was provided via the [node:render:full] token (drupal/token_entity_render module).

    After this request, the batch process started, but crashed with the following error:

  3. Error when trying to trigger AI Automator

    Sven Decabooter

    Problem/Motivation

    I tried creating an ECA model that automatically fills in a textarea field on a page node (field_seo_description). It is supposed to take the whole node contents (full view mode), and use AI to create a summary out of that, and fill it in the aforementioned field.

    However, when trying to use the "AI automator" action trigger, I'm getting the following error: action "AI Automator Trigger" (eca_ai_automator_1fcddok): The submitted value in the Automator element is not allowed.

    Steps to reproduce

    Used module versions:

    • "drupal/ai": 1.2.0-alpha2
    • "drupal/ai_integration_eca": 1.0.0-rc2
    • "drupal/bpmn_io": 3.0.0
    • "drupal/eca": 3.0.2
    • "drupal/modeler_api": 1.0.x-dev
    • "drupal/token_entity_render": 2.0.0
    • "drupal/schemata": 1.0.0

    Configuration for my field_seo_description field:

    • “Enable AI Automator”: checked
    • Automator type: LLM Text
    • Input mode: Advanced
    • Prompt:
      Create an SEO-friendly summary of the page content, as provided within the context below.
      The description should be in the same language as the provided body text.
      If the context is not sufficient or empty, please just return an empty string.
      
      Context:
      Title: [node:title]
      Body: [node:render:full]
      

      Body token is provided by the token_entity_render module. It provides HTML output of the whole page. Not sure if this is the best approach, since I'd want only the text, not the HTML, but it's a start...

    • "Edit when changed": checked
    • “Automator worker”: ECA
    • "AI Provider": LLM Proxy (using lite_llm)
    • “Joiner”: Space

    I created an ECA model, and dragged a start event on it - selecting "Update content entity" (bundle: node page) The action is of type "AI Automator Trigger".

    Screenshot:

  4. Move TextExtractor service to AI core

    Sven Decabooter

    So for example:

    \Drupal\ai\AiFieldTextExtractor\TextFieldExtractor:

    #[AiFieldTextExtractor(
      id: "text",
      label: new TranslatableMarkup('Text'),
      field_types: [
        'title',
        'text',
        'text_long',
        'string',
        'string_long',
      ],
    )]
    class TextFieldExtractor {
    
      /**
       * {@inheritdoc}
       */
      public function getColumns(): array {
        return ['value'];
      }
    
      /**
       * {@inheritdoc}
       */
      public function extract(ContentEntityInterface $entity, string $fieldName): array {
        // IMPLEMENTATION.
      }
    
      /**
       * {@inheritdoc}
       */
      public function shouldExtract(ContentEntityInterface $entity, FieldConfigInterface $fieldDefinition): bool {
        return TRUE;
      }
    
    }
    

    (some of these methods would be in a base class obviously, but for illustration purposes I added them here)

    and

    \Drupal\ai_translate\FieldTextExtractor\TextFieldExtractor:

    #[FieldTextExtractor(
      id: "text",
      label: new TranslatableMarkup('Text'),
      field_types: [
        'title',
        'text',
        'text_long',
        'string',
        'string_long',
      ],
    )]
    class TextFieldExtractor extends \Drupal\ai\AiFieldTextExtractor\TextFieldExtractor: {
    
      /**
       * {@inheritdoc}
       */
      public function setValue(ContentEntityInterface $entity, string $fieldName, array $textMeta) : void {
        // IMPLEMENTATION.
      }
    
      /**
       * {@inheritdoc}
       */
      public function shouldExtract(ContentEntityInterface $entity, FieldConfigInterface $fieldDefinition): bool {
        return $fieldDefinition->isTranslatable();
      }
    
    }
    
  5. Move TextExtractor service to AI core

    Sven Decabooter

    I probably was a bit too enthusiastic with my MR.

    I identified multiple problems with just moving the FieldTextExtractor plugins from ai_translate to ai core:

    1. The logic in shouldExtract() for each plugin is tightly coupled to translation logic. In it's easiest form, it checks if a field is translatable. In more complex cases, e.g. for Entity References, it checks configuration settings to determine whether to extract a given entity reference.
    2. The logic in setValue() is also tightly coupled to translation logic. It assumes the plugin that extracted the field value, will store it again on the exact field same location (but on the translated version of an entity)

    The scenario's where text extraction could be useful outside of translation logic, seem to be:

    • For ai_content_suggestion: this just needs the extraction part, not the logic for setting the value again on the same field!
    • For ai_automators: might be useful to provide the extracted values as tokens to automators? There is already something in place like that, but using the extractor plugins might extend that logic? Haven't looked to deeply into this. But this would also only need the extraction logic I assume?
    • ... other places?

    Refactoring the FieldTextExtractor plugins to be more generic, while keeping backwards compatibility, seems rather challenging. I was thinking we could set it up as follows:

    New plugin type: AiFieldTextExtractor
    • Resides in the Drupal\ai namespace
    • Provides implementations for various field types, same as current ai_translate FieldTextExtractor plugins
    • Only implements the methods: extract(), shouldExtract() & getColumns() no value setting logic
    • Does it need to be limited to extracting text? If not, name it AiFieldExtractor? Haven't thought this through yet :)
    Existing plugin type: FieldTextExtractor
    • Resides in the Drupal\ai_translate namespace
    • Already has implementations for various field types: they will be refactored to extend their AiFieldTextExtractor equivalent
    • Only provides the setValue() method.
    • extract() and shouldExtract() could be overridden to provide translation-specific logic that is not in the parent AiFieldTextExtractor plugin counterpart
    • Could potentially be deprecated in 2.0.0 in favor of a better named AiTranslateFieldTextExtractor plugin / namespace, but that might be nitpicking on my part...

    ai_translate and contrib modules extending this module would keep on using the FieldTextExtractor plugins. Other AI modules could use just the extract logic from the AiFieldTextExtractor plugins, and run with it.

    Does that make sense, or is it overly complex and unnecessary? Thanks for giving it some thought.

  6. Move TextExtractor service to AI core

    Sven Decabooter

    TODO:

    - \Drupal\ai\TextExtractor::shouldExtract() still contains translation-specific logic. This should be moved to the module making use of the Text Extractor service, in this case ai_translate. Not sure how this should be set up.

  7. Move TextExtractor service to AI core

    Sven Decabooter

    Added a MR to refactor this. Marked the existing ai_translate classes / services deprecated, so contrib modules extending them, have time to update their dependencies.

  8. PageSpeed Insights - Accessibility (ARIA)

    Fons

    Problem/Motivation

    Hello, I'm using the FAQ field module on my websites and it's really nice.

    I render them with the JQuery accordion formatter.

    I've noticed that PageSpeed Insights has accessibility warnings based on the standard implementation.

    Steps to reproduce

    Setup a FAQ field with formatter JQuery accordion.

    Run the PageSpeed Insights tool (https://pagespeed.web.dev/).

    You'll see you get a 95 score (if your websites complies on all other points and a notice):

    "Elements with an ARIA [role] that require children to contain a specific [role] are missing some or all of those required children."

    I've already changed the h3 to a button to see if that helps and some other stuff but I keep getting the warning.

    Anyone else has any ideas? Would love to get this fixed.

  9. Translation batch process does not handle translation errors

    Sven Decabooter

    Setting back to 1.2.x as the correct branch to target.

    I tried reproducing this, as I had earlier experienced weird behavior when I had connection problems to my AI API endpoint. However, in my testing, I get into \Drupal\ai_translate\Plugin\AiProvider\ChatTranslationProvider::translateText(), and into the GuzzleException catching. This then logs the error, but proceeds to return an empty translated text output.

    This finally results into database errors trying to save the translation, and the display of the message "There was some issue with content translation.".

    So the scenario above might be a separate use case that could be taken into account for improving the error message output. The error message should be more clear, and a translation should not be attempted to be created I guess?

  10. The translation submodule does not respect the content translation module permissions

    Sven Decabooter

    Tested this MR.

    I removed all content_translation permissions from a given user. They could no longer see the "Translations" tab in that case.

    However, when given the "Create AI translation" permission, they could still access the translation URL directly, and a translation was added. Not sure if this is desired behaviour, or if it should be an AND operation: only create AI content translations when you have "create ai content translation" permission + the appropriate content_translation permission as well.

    So the original issue raised in this topic was not yet fixed, AFAIK.

    The improved logic to hide the AI Translation column when not relevant, seems to work and is definitely an improvement.

  11. AI Translate default configuration is not valid

    Sven Decabooter

    I also took the opportunity to add extra config validation to the schema. This is useful for when ai_translate settings get set via another means than the settings form, e.g. via a recipe.

    This also lays the groundwork for simplifying the settings form, by using #config_target for all / relevant form elements.

  12. AI Translate default configuration is not valid

    Sven Decabooter
    • Fixed the entity_reference_depth that was wrongly positioned in the default config
    • Added missing language_settings default value
    • Updated default reference_defaults values. Now it defaults to empty, since it was referencing entity types that might not even exist on a given site, making the configuration valid more of a challenge.

    The last change might be debatable...

  13. AI Translate default configuration is not valid

    Sven Decabooter

    Problem/Motivation

    The config schema for ai_translate module is defined in modules/ai_translate/config/schema/ai_translate.schema.yml.

    The default config upon installation of the module is defined in modules/ai_translate/config/install/ai_translate.settings.yml, but does not follow the exact schema.

    Noteably, the option `entity_reference_depth` is added within the reference_defaults array, instead of on its own.

  14. Pass AI token usage data to the events

    Sven Decabooter

    Deprecation warnings have been fixed in the new OpenAiBasedProviderClientBase class. Pipeline still gives a PHPUnit error in Drupal\Tests\ai\Kernel\Utility\TextChunkerTest Not sure how this is related to this issue...

  15. Provide service aliases for autowiring

    Sven Decabooter

    Thanks, that seems like a good addition.

    Could we also take the opportunity to set autowire: true in the services defined in externalauth.services.yml? Autowiring is supported since 9.3, and since our min. required version is 9.5, that should work.

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.