# Question
Title: Is it possible to disable taxonomy hierarchy?
The site I am building uses fields (plus a custom module) to provide a richer set of relationships between taxonomy terms than the built-in hierarchy allows.

I want to remove/disable the built-in hierarchy. What I mean is that when a user is creating or editing a term, I do not want them to see the "Relations" section, and when they are viewing a list of terms in a taxonomy, I want the drag-and-drop functionality to only work for ordering, not indenting.

I know I can do this with another module using `hook_form_alter()` or the like, but is there an easier and quicker way to "turn off" this functionality in Drupal 8? I have a vague memory of (maybe in an earlier Drupal, or somewhere else) being able to specify, when you create a taxonomy, if you want it to be hierarchical or not, but I cannot find such a thing here.

# Answer
If the Relation input is not exposed in the Form Display, then you are going to need to use a `hook_form_alter` to hide the Relation input.

Also, note, that the drag and reorganize on the vocabulary overview will still support hierarchy. You'll need to alter that form as well to disable it.
> 0 votes

# Answer
**UPDATE**

You can also use Flat Taxonomy module, this will get rid off both the parent and the drag-n-drop. Also if you enable it for an existing vocabulary with terms with hierarchy, it will flatten the tree for you. Bare in mind that the panel "Relations" keeps showing since contains the "Weight" field. If you plan using this module check the opened issues #3115794 and #3012578 since you need does patches in order to work.

**Original answer**

You can use Taxonomy Max Depth module, even though it does not get rid off the "Relations" panel validates the input, and also prevents the drag-n-drop on the terms overview. For a better results in terms of UX you can also hide the panel using the `hook_form_alter` as mentioned (I don't know how to achieve the same for the drag-n-drop other than replacing the view).
> 0 votes

# Answer
Or you can add something like that in your custom module:

```
Implements hook_form_BASE_FORM_ID_alter() for the taxonomy term form.

function MY_CUSTOM_MODULE_form_taxonomy_term_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form['relations']['parent']['#options'] = [0 => '<root>'];

  if (\Drupal::state()->get('taxonomy_test.disable_parent_form_element', FALSE)) {
    $form['relations']['parent']['#disabled'] = TRUE;
  }
}

```

If you have a huge vocabulary, now it should load a bit faster!

Though! the backend is still running a taxonomy load::tree() which using lot of RAM!

You will need to patch it to prevent loading the tree and reduce your RAM usage for very large vocabularies!
> 0 votes

---
Tags: 8, taxonomy-terms
---


# Question
Title: Add fields to content-type when Theme is enabled
Is there any way we can change configuration items when we switch to a specific theme?

Our (simplified) situation:

* Using Drupal 10.2
* Our customers can choose between different themes
* Every theme uses content-type 'Page'
* One theme has a background-picture, differing from page to page, uploaded by the editors. So if this theme is chosen, 'Page' needs to have a field 'background-image' (media).

How can I add a field to a content-type when setting this theme as default theme without manual changes in the admin-backend?

What I already tried:

* Using `hook_install()` =\> This hook only works on modules and not on themes. (https://www.drupal.org/node/2652542). And even if: It would be executed on theme installation and not when it is set as default.
* Using `config/install` (as mentioned in Is there a theme equivalent of hook\_install()?) =\> This allows me to install `field.storage.node.field_background_picture` and `field.field.node.page.field_background_picture`, but not to add the `field_background_picture` to the already existing `core.entity_form_display.node.page.default` and similar configs - I now have the field, but neither in the form nor in the display.
* Using `config/optional` =\> The same as above. Additions or changes to existing config do not lead to errors, but the changes to the form and view are silently ignored. And even if: It would be executed on theme installation and not when it is set as default.

Thanks in advance and greetings from Switzerland mullzk

# Answer
> 0 votes
Thanks a lot both @Clive & @unusedspoon, this makes sense.

hook\_form\_alter has its problem as well though: We use the administration theme when editing or creating content - so hook\_form\_alter is not called on our theme, but on claro.

I now created hooks in the module, where we define our page-content-type:

```
function pagemodule_form_alter(array &$form) {
  $theme_name = \Drupal::config('system.theme')?->get('default');
  if ($theme_name != 'background_image_theme') {
    $form['field_background_image']['#access']=false;
  }
}
function pagemodule_preprocess_node__page(array &$variables) {
  if (isset($variables['elements']['field_background_image'])) {
    $theme_name = \Drupal::config('system.theme')?->get('default');
    if ($theme_name != 'background_image_theme') {
      hide($variables['content']['field_background_image']);
    }
  }
}

```

I understand the approach that themes are presentation only.
But I also think that putting this logic outside the themes can get a bit messy, if we have have \>10 themes with different fields each.

Perhaps, I will add the theme-specific fields in a list in the theme.info.yml and then query this list (via theme.manager-service) in the module-hooks above...

---
Tags: theming, configuration
---


# Question
Title: How can I set eager loading for a Entity Reference field for Media (Image)?
I see this is done for an image field in the Manage Display options, but can't find this option for Entity Reference fields for Media (Image) with Rendered entity as the format. This affects Largest Contentful Paint, so I would love to be able to set this per Entity Reference field in a content type just like it's done with image fields. I can recreate the image tag through template files and preproccess hooks, but it seems like this should be possible through the UI.

entity reference field for media (image):  vs. regular image field showing loading option

# Answer
I found the answer. If you select Thumbnail as the Format under Manage Display, you can then select the gear to the right and any image style you have. Underneath that is the loading eager/lazy preference options. This does not mean that Hudri is incorrect. I didn't want to create multiple media display modes, so this was what I was looking for as described https://www.youtube.com/watch?v=3kx3BLDCd2Y
> 0 votes

---
Tags: media
---


# Question
Title: Getting fatal error when trying to install Umami test site
I'm using Windows 10. I have installed composer and PHP.

I run the command `composer create-project drupal/recommended-project mysite` to create a recommended project. That works with no errors. Then I try to run the command `php web/core/scripts/drupal quick-start demo_umami` to install a sample Drupal site using the Umami Maganize demo:

```
C:\drupal\mysite>php web/core/scripts/drupal quick-start demo_umami
 9/17 [==============>-------------]
Install site
PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480
bytes) in C:\drupal\mysite\web\core\lib\Drupal\Core\TypedData\Plugin\DataType\ItemList.php on
line 274

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)
in C:\drupal\mysite\web\core\lib\Drupal\Core\TypedData\Plugin\DataType\ItemList.php on line
274

C:\drupal\mysite>

```

It makes no sense that I'm trying to allocate only 20480 bytes and that's causing it to throw a FatalError. How do I fix this?

# Answer
In php.ini, increase the memory\_limit from 128MB to 2G:

```
; Maximum amount of memory a script may consume
; https://php.net/memory-limit
;memory_limit = 128M
memory_limit = 2G

```
> -3 votes

---
Tags: 10
---


# Question
Title: How do I limit the allowed taxonomy terms basing on the content type?
I have two different content types, *Computer* and *Chemistry*, and taxonomy terms for all articles (content types) which store the methodology of the article. The taxonomy hierarchy is the following.

* Articles
    + Computer
        - Arithmetic (Term ID: 1)
        - DMA (Term ID: 2) // abbreviation for "Direct Memory Access"
    + Chemistry
        - NGE (Term ID: 3) // abbreviation for "Noble Gas Elements"
        - DMA (Term ID: 4) // abbreviation for "Dynamic Mechanical Analysis"

When users are creating or editing a node of type *Chemistry*, just *NGE* and *DMA* (whose ID is 4) should be allowed to select.

I only need one taxonomy vocabulary, since there are too many content types, and if I want to add a vocabulary for each of them, then it leads too many vocabularies; more importantly it removes the ability of freely navigating in different types using taxonomy hierarchy.

How do I limit the allowed taxonomy terms basing on the content type?

# Answer
According to my choice you should use hook\_form\_alter to bind taxonomy list based on article type.

```
function MY_MODULE_NAME_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'my_form_id') {
    $default_value = 0;
    $options = getArticles('Computer','Articles');
    $form['your_taxonomy_field_name'] = array(
      '#title' => t('Articlas'),
      '#type' => 'select',
      '#options' => $options,
      '#access' => 1,
      '#default_value' => $default_value,
      '#weight' => 1,
    );
  }
}
function getArticles($articleType,$vocabularyName) {
  //get the vocabulary
  $vocabulary = taxonomy_get_vocabularies();
  $vid = -1;
  foreach ($vocabulary as $item) {
    if ($item->name == $vocabularyName) {
      $vid = $item->vid;
    }
  }
  if ($vid != -1) {
    //get the parrent Term
    $query = new EntityFieldQuery;
    $result = $query
      ->entityCondition('entity_type', 'taxonomy_term')
      ->propertyCondition('name', $articleType)
      ->propertyCondition('vid', $vid)
      ->execute();
    $parrent_tid = array_shift($result['taxonomy_term'])->tid;
    //return children
    return taxonomy_get_children($parrent_tid);
  }
  return NULL;
}

```
> 3 votes

# Answer
The Term Reference Tree module might help. This module provides an expandable tree widget for the Taxonomy Term Reference field in Drupal 7.

**Term Reference Tree:**

> This module provides an expandable tree widget for the Taxonomy Term Reference field in Drupal 7. This widget is intended to serve as a replacement for Drupal's core Taxonomy Term Reference widget, which is a flat list of radio buttons or checkboxes and not necessarily fit for medium to large taxonomy trees.

**How to use this module**

1) Enable the Term Reference Tree module.
2) Go to the Manage Fields tab of any fieldable entity (such as a content type, taxonomy term, or user.
3) Add a new field with a type of Term Reference.
4) In the widget select box, select Term reference tree.

5) Last step is important onc, as shown in the below image you have to give the taxonomy term id of which vocabulary you want to show for specific content type.
> 2 votes

# Answer
According to this answer on the main Stackoverflow site, a submodule of Content Taxonomy called "Content Taxonomy Options"would be perfect for this:

> You can do this with Content Taxonomy's Content Taxonomy Options module. Add a new Content Taxonomy field, and use the Select widget. In the field settings, under the Advanced settings for hierarchical vocabularies field group, select the Parent Term you want to use for that field.
> 2 votes

# Answer
Mobile and Laptop should be separate Vocabularies.

Then for mobile content type, when you add a tax term field, select mobile as your vocabulary.
> 1 votes

# Answer
I would suggest avoding taxonomy altogether and define your own content types. I go into this in depth in another post. When you scroll down my post, you will find that you can do ***exactly*** what you are looking to do.

I am not a big fan of the "there's a module for that" philosophy because every time you add another module, you increase the footprint of your Drupal site; you load that module for ever page in ever session whether you need it or not.

By using Views, Entity, Entity-Reference, Entity-Connect (stuff you should be using) you can turn off taxonomy completely and get a better ***indexed*** alternative to taxonomy.

Say no to taxonomy
> 1 votes

# Answer
For Drupal 9.2-10 this module allowed me to select a parent term within a taxonomy, and display only the children of that parent.

Client-side Hierarchical Select

Also came across this nice demo video of the CSHS module
> 0 votes

---
Tags: 7, taxonomy-terms
---


# Question
Title: Custom Flag not appearing in "Configure Relationship: Flags"
I am building a community site to link former co-workers. I have used the Flags module to allow users to tag locations/teams. I am trying to use views to now list all the users who have flagged a location/team. When I try to add my flag to "Configure Relationship: Flags" it is not an option. Can anyone explain this?

*EDIT* I started with a list of users, those users have flagged the node with a custom flag marking it as a work location. My intention is to connect people who tagged the location in the same way. I wish to add a block to each page with a list of those people who worked together.

# Answer
I was adding bookmarks for commerce products and saw this issue.

How I solved this was I created a new view and selected my custom flag:

I then went ahead to configure the view.

Using Drupal 10.2.3.
> 0 votes

---
Tags: views, flags
---


title: hook_cron(): PHP output does not appear

text:
# Question
Title: hook_cron(): PHP output does not appear
I am (finally) migrating our Drupal 7 sites to Drupal 10.

The one problem I have not been able to resolve is output from the `hook_cron()`.

Everything appears to execute, whether running on the browser using the special link, clicking on the 'Run cron' button, or as a crontab job. (This is verified by the logger messages, or informational messages which will subsequently appear on the site.)

However, none of the PHP output (for example, `echo` or `print_r()`) which worked under Drupal 7 appear on the browser or as an external crontab task. The web page doesn't even refresh. This is problematic because our cronjobs output a lot of debug information that allow us to verify that the tasks ran correctly, and this output is redirected into an email which can be reviewed without accessing the Drupal site. So it is not practical to use the logger or other Drupal mechanisms.

Interestingly, there are scenarios where the output does appear, which might provide a clue as to what the problem is:

* if I include a call to phpinfo()
* on certain (but not all) PHP errors, which causes all preceding output to appear

Note that this issue also occurs with the example cron code (cron\_example.module) if I try to add echo statements; I have found one other user (on the drupal forum) who also ran into this as part of other questions, but there was no any information on how to resolve it.

I tried flush() in case it's some sort of buffering issue, but to no avail.

```
function cron_daily_cron() {
  // This output is not shown.
  echo "cron_daily_cron started...";

  // The messenger message is shown.
  \Drupal::logger('cron_daily')->notice('cron_daily_cron started');
  \Drupal::messenger()->addMessage('cron_daily_cron started...', 'info');
  \Drupal::logger('cron_daily')->notice('cron_daily_cron exited');

  // The error output caused by the following line is shown.
  inexistentfunctioncall();

  // This message is not shown.
  echo "cron_daily_cron exited";
}

```

thank you!

# Answer
The cron controller returns an empty string with a HTTP status 204 (No Content) by design. Otherwise, they could buffer the output and put it in the response.

However, you can try to run cron via drush

```
drush cron

```

This does produce PHP output on the command line when I test it.
> 0 votes

---
Tags: hooks, cron
---


# Question
Title: How to get last_comment_timestamp for a node
Can someone tell me what table to look for to get the node's last\_comment\_timestamp?

# Answer
It's in the `node_comment_statistics` table.
> 1 votes

# Answer
```
if( $node->hasField('comment') ) { $last_comment_timestamp = $node->comment->last_comment_timestamp; }

```
> 0 votes

---
Tags: nodes, comments
---


# Question
Title: How can I return a different number of results per page for a view if a user is accessing the site with a mobile device?
I have a large number of views that show member profiles. Right now, I only show 8 members per page, because on a mobile device it takes a very long time to scroll.

However, for the desktop, I could easily show 20 members per page.

Since there are a large number of views, I don't want to do this if I have to duplicate all of them and change the pager settings. Is there another way to return a different number of results per page if the user is on a mobile device?

# Answer
> 3 votes
Personally, I would use something like Views Infinite Scroll instead of messing with the pager. This would be better for most users in all cases.

However, you can use the Mobile Detect module inside a `hook_views_pre_build()`. Something like this (untested)

```
function mymodule_views_pre_build (&$view) {
  $detect = mobile_detect_get_object();
  $is_mobile = $detect->isMobile();
  $is_tablet = $detect->isTablet();

  if ($is_mobile && !$is_tablet) {
    $view->pager["items_per_page"] = 8;
  }
  else {
    $view->pager["items_per_page"] = 20;
  }
}

```

This would affect all views. `dpm()` the `$view` object to see how you would use it to add logic to limit to particular views and/or displays.

However, adding logic like this really complicates the cachability of pages using the normal methods. The Mobile Detect module has a submodule that adds some ctools selection and access rules. Using this, you could have view panes for device types, and then leverage Page Manager for caching.

*Disclosure: I am the author of the Mobile Detect module.*

# Answer
> 3 votes
You could use Browscap module along with Browscap Block which would add the visibility of blocks depending on device. Next you could add two blocks one for Normal screen and one for mobile devices.

> **Browscap Block**
>
> Browscap Block adds visibility options to block configuration settings to allow you hide or show blocks in mobile devices.

If you do not want to create multiple views then you could use the browscap function in your template file to detect the browser and then restrict the number of items displayed. The function would be `browscap_get_browser()`

This could either be done in `hook_views_pre_build` function or with in the `Style output` template file where it loops through the $rows array. you could restrict it the number to 8 depending on the device by exiting the loop once you reach the required count.

# Answer
> 1 votes
For those that find this like i did, I am running drupal 10, look into Responsive Views Pager It is simple with all the settings in the pager part of the view.

---
Tags: views
---


# Question
Title: Webforms Warning message: Update the Input Mask Library
I've been looking at the Warning message to download and update the Input Mask library to version 5.0.x for some time now.

I've tried all the suggestions at https://www.drupal.org/docs/contributed-modules/webform/webform-libraries. None of them makes the message go away on my local ddev installation.

/admin/reports/status says `JQuery:input Mask 5.0.8 (Installed)` when jquery.inputmask is in docroot/libraries, or `jQuery: Input Mask 5.0.8 (CDN)` when the library is being loaded via a CDN.

If I add an exit(); after webform\_requirements is called in webform.install.requirements.inc or if I comment out webform\_requirements completely, the message still prints.

Does anyone have a new suggestion? I'd like this message to go away.

# Answer
> 0 votes
Ultimately the answer was to click the X in the upper right corner of the warning message one time to make it go away forever.

From what I can tell, the persistence of this message may have been because of `$help_manager->addNotification()` or perhaps `hook_webform_message_custom()`. I found no record of webform\_update\_8187() in the database.

---
Tags: webforms, 10
---


title: How to delete duplicate path aliases?

text:
# Question
Title: How to delete duplicate path aliases?
Duplicate path aliases are seen as rows in the `path_alias` table with identical `path` and `alias` columns.

Due to old bugs in pathauto and other reasons, like buggy custom code, it is possible to have duplicate rows in the `path_alias` table. This can make the `path_alias` enormous for large sites.

Duplicate path aliases serve no purpose whatsoever. You only need one of each.

# Answer
> 5 votes
If there are many duplicates, use the queue system to delete them gradually. Start by enqueuing identified duplicates in an update hook:

```
// file: my_module.install
/**
 * Enqueue duplicate path aliases for cleanup.
 */
function my_module_update_10001() {
  $query = \Drupal::database()->select('path_alias', 'pa')
    ->fields('pa', ['alias']);
  $query->addExpression('count(alias)');
  $query->groupBy('alias');
  $query->having('COUNT(alias) >= :matches', [':matches' => 2]);
  $results = $query->execute()->fetchAll(\PDO::FETCH_COLUMN);
  \Drupal::logger('my_module')->notice('Enqueuing duplicate path aliases for cleanup');
  foreach ($results as $alias) {
    $queue = \Drupal::queue('my_module_delete_duplicate_path_aliases');
    $queue->createItem($alias);
  }
  return t('Update 10001 completed successfully.');
}

```

Add the `my_module_delete_duplicate_path_aliases` queue runner to do the work:

```
<?php
// file: src/Plugin/QueueWorker/DeleteDuplicatePathAliases.php

namespace Drupal\my_module\Plugin\QueueWorker;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Queue\QueueWorkerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Deletes duplicate path aliases.
 *
 * @QueueWorker(
 *   id = "my_module_delete_duplicate_path_aliases",
 *   title = @Translation("Delete duplicate path aliases"),
 *   cron = {"time" = 30}
 * )
 */
class DeleteDuplicatePathAliases extends QueueWorkerBase implements ContainerFactoryPluginInterface {

  /**
   * {@inheritDoc}
   */
  final public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    private LoggerChannelFactoryInterface $logger,
    private EntityTypeManagerInterface $entityTypeManager,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * {@inheritDoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('logger.factory'),
      $container->get('entity_type.manager'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function processItem($data) {
    $alias = (string) $data;
    $query = $this->entityTypeManager->getStorage('path_alias')->getQuery();
    $entity_ids = $query
      ->accessCheck(FALSE)
      ->condition('alias', $alias)
      ->sort('id', 'DESC')
      ->execute();

    /** @var \Drupal\path_alias\Entity\PathAlias[] $entities */
    $entities = $this->entityTypeManager->getStorage('path_alias')->loadMultiple($entity_ids);

    $count = 0;
    // Keep the newest unique aliases by language and path, and delete the rest.
    $seen = [];
    foreach ($entities as $entity) {
      if (isset($seen[$entity->language()->getId()][$entity->getPath()])) {
        $entity->delete();
        $count++;
      }
      $seen[$entity->language()->getId()][$entity->getPath()] = TRUE;
    }
    $this->logger->get('my_module')->notice('Deleted ' . $count . ' duplicate path aliases for ' . $alias);
  }

}

```

---
Tags: database, path-aliases
---


# Question
Title: Why is the db connection to migrate silently failing?
I'm using D10, drush 12, ddev. In settings.local.php I have:

```
$databases['migrate']['default'] = array (
  'database'  => 'd7',
  'username'  => 'db',
  'password'  => 'db',
  'host'      => 'db',
  'port'      => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver'    => 'mysql',
);

```

In the code when I do:

```
$db = Database::getAllConnectionInfo();

```

the var\_dump shows 'migrate' being part of the array:

```
array(2) {
  ["default"]=>
  array(1) {
    ["default"]=>
    array(11) {
      ["database"]=>
      string(2) "db"
      ["username"]=>
      string(2) "db"
      ["password"]=>
      string(2) "db"
      ["host"]=>
      string(2) "db"
      ["port"]=>
      int(3306)
      ["driver"]=>
      string(5) "mysql"
      ["prefix"]=>
      string(0) ""
      ["namespace"]=>
      string(34) "Drupal\mysql\Driver\Database\mysql"
      ["autoload"]=>
      string(45) "core/modules/mysql/src/Driver/Database/mysql/"
      ["pdo"]=>
      array(6) {
        [3]=>
        int(2)
        [1000]=>
        bool(true)
        [1005]=>
        bool(true)
        [20]=>
        bool(true)
        [1013]=>
        bool(false)
        [17]=>
        bool(true)
      }
      ["init_commands"]=>
      array(1) {
        ["sql_mode"]=>
        string(33) "SET sql_mode = 'ANSI,TRADITIONAL'"
      }
    }
  }
  ["migrate"]=>
  array(1) {
    ["default"]=>
    array(9) {
      ["database"]=>
      string(2) "d7"
      ["username"]=>
      string(2) "db"
      ["password"]=>
      string(2) "db"
      ["host"]=>
      string(2) "db"
      ["port"]=>
      string(4) "3306"
      ["driver"]=>
      string(5) "mysql"
      ["prefix"]=>
      string(0) ""
      ["namespace"]=>
      string(34) "Drupal\mysql\Driver\Database\mysql"
      ["autoload"]=>
      string(45) "core/modules/mysql/src/Driver/Database/mysql/"
    }
  }
}

```

but when I try to create a connection, with

```
return Database::getConnection('migrate');

```

I receive:

```
In ExceptionHandler.php line 46:

  SQLSTATE[42S02]: Base table or view not found: 1146 Table 'db.node_type' doesn't exist: SELECT `name`,`type`,`description` from node_type ORDER BY `name`; Array
  (
  )

In StatementWrapperIterator.php line 110:

  SQLSTATE[42S02]: Base table or view not found: 1146 Table 'db.node_type' doesn't exist

```

and dumping the connection variable shows a connection to the default db but not to the migrate db.

Let me add context and more code. I began with a working module for D10 providing a drush 12 custom command. At that point, the command made no use of a database. I simply wanted to add an option to the command that makes use of a database. I mention this for two reasons: to point out that the structure of using a drush custom command had already bene in place and working, and to point out that this is a drush command, in case it could be how drush interacts with the database(s) that makes a difference.

I had been bootstrapping drush to the configuration level. In adding the new feature I upped that to the database level:

```
  #[CLI\Bootstrap(level: DrupalBootLevels::DATABASE)]

```

I added the following *use* entries:

```
  use Drupal\Core\Database\Connection;
  use Drupal\Core\Database\Database;

```

Once I have determined that the drush command has been entered with the option request to use the database, I call the method to establish the connection and do a simple query (I prefer to added new functionality in steps...easier to test).

```
if ($options['db']) {
  $db = $this->getD7DbConnection();
  if (!$db) {
    $this->logger()->error(dt("There is no migrate database configured in the site settings."));
    return NULL;
  }
  $file = Drupal::service('extension.path.resolver')->getPath('module', 'mymodule') . '/data/items.db.yml';
  return $this->scanDb($db, $file);
}

```

This method succeeds. It contains the db connection info showing two db's, default and migrate, shown above in the var\_dump:

private function getD7DbConnection() { $db = Database::getAllConnectionInfo(); if (isset($db\['migrate'\])) { return Database::getConnection('migrate'); }

```
return FALSE;

```

}

This method then fails. I threw a simple query into it for now just to prove or disprove a connection:

private function scanDb(Connection $db, $file) { $results = $db-\>query('SELECT * from node\_type ORDER BY `name`;');

```
return $results;

```

}

And that's all there is. At this point I'm simply attempting to connect to the db, as a result of the request via drush option, and do a simple query.

# Answer
> 0 votes
It turns out that getConnection parameters are (target, key), so ('default', 'migrate') rather than ('migrate', 'default').

---
Tags: database, 10
---


title: Modifying a custom form on submit

text:
# Question
Title: Modifying a custom form on submit
I have a custom module with a custom form, Drupal 10, and when the form is submitted I want to either 1. add some markup to the submitted page or 2. change a value on the form. I have failed on the former, so I am trying the latter.

Here's my code, without the chaffe:

```
public function buildForm(array $form, FormStateInterface $form_state): array {
    $form['plate'] = [
        '#type' => 'textfield',
        '#title' => $this->t('Plate'),
    ];

    $form['actions'] = [
        '#type' => 'action',
        'submit' => [
            '#type' => 'submit',
            '#value' => $this->t('Search'),
        ],
    ];
}

public function submitForm(array &$form, FormStateInterface $form_state): void {
    $this->messenger()->addStatus($this->t('The form has changed'));
    $form_state->setValue('plate', 'Changed Value');
    $form_state->plate = [
        '#type' => 'textfield',
        '#title' => $this->t('Plate wjiijowqoiwefewiofjewfio'),
        '#value' => 'Changed Value',
        '#default_value' => 'Changed Value',
    ];
    $form_state->plate['#value'] = "Changed Value";
    $form_state->setRebuild();
}

```

Can you see where I am going wrong?

# Answer
> 3 votes
The form elements should be manipulated in the build method. You can use the current state of the form there too.

To override the user input, you can't use `setValue` on the form state. The form system is built to maintain user input on rebuild, so you have to manipulate that directly:

```
public function submitForm(array &$form, FormStateInterface $form_state): void {
  $this->messenger()->addStatus($this->t('The form has changed'));

  $input = $form_state->getUserInput();
  $input['plate'] = 'Changed Value';
  $form_state->setUserInput($input);

  $form_state->setRebuild();
}

```

Then in the build method you can change things based on whether the form has been submitted:

```
public function buildForm(array $form, FormStateInterface $form_state): array {
  $submitted = $form_state->isSubmitted();

  $form['plate'] = [
    '#type' => 'textfield',
    '#title' => $submitted ? $this->t('Plate submitted') : $this->t('Plate'),
  ];

  if ($submitted) {
    $form['html'] = [
      '#markup' => '<p>Something</p>',
    ];
  }

  $form['actions'] = [
    '#type' => 'action',
    'submit' => [
      '#type' => 'submit',
      '#value' => $this->t('Search'),
    ],
  ];

  return $form;
}

```

As an aside, there's almost never a need to set `#value` on a form element directly - it will stop that element from accepting any new user input. You can use `#default_value` to set the initial value, and then the form state methods to manipulate it during a form lifecycle.

---
Tags: 10
---


# Question
Title: How do I set the PHP version for a contrib module with GitLab CI?
I'm trying to set up testing using the GitLab template for contrib modules.

In the module's `composer.json`, PHP 8.2 is required, and since the CI is currently defaulting to 8.1, the install fails.

So, based on the variables documentation, I tried adding the following to `.gitlab-ci.yml`:

```
variables:
  _TARGET_PHP: "8.3"

```

When I pushed and the pipeline ran, it was still at PHP 8.1.

So then I tried:

```
variables:
  _TARGET_PHP: "CORE_PHP_MAX"

```

Which according to the docs linked above is currently 8.3.

However, that failed too-- still stuck at 8.1.

How do I set the PHP version for GitLab CI for a contrib module?

# Answer
> 1 votes
This should work.

```
variables:
  CORE_PHP_MIN: "8.2"

```

You can use `_TARGET_PHP: "8.3"` on a job like composer and PHPUnit. There are a few ways you can do this. Which project are you working on? I want to look at your pipeline.

---
Tags: testing
---


# Question
Title: Contrib module phpstan on Gitlab CI: How to make dependency modules available?
I have a module Decoupled Passkeys that adds JSON-RPC module endpoints, so it depends on JSON-RPC.

When I run tests with a custom `phpstan.neon`, I'm getting a lot of errors because phpstan cannot find the JSON-RPC module:

```
  130    Call to static method internalError() on an unknown class
         Drupal\jsonrpc\Object\Error.
          Learn more at https://phpstan.org/user-guide/discovering-symbols

```

Here's a failed pipeline.

The JSON-RPC module is required in `composer.json`:

```
{
  "name": "drupal/decoupled_passkeys",
  "description": "Enables passkey login/registration via JSON:RPC and Webauthn.",
  "type": "drupal-module",
  "require": {
    "php": ">=8.2",
    "ext-json":  "*",
    "drupal/jsonrpc": "^2",
    "drupal/public_key_credential_source": "^1.0@alpha"
  },

```

The `phpstan.neon` looks like this:

```
parameters:
        checkGenericClassInNonGenericObjectType: false
        # Sometimes Drupal gets it wrong.
        treatPhpDocTypesAsCertain: false
        level: 9
        ignoreErrors:
          # Drupal does not define its own arrays.
          - '#no value type specified in iterable type array#'
          - '#no value type specified in iterable type Drupal\\Core\\Field\\FieldItemListInterface#'
          # Level 9 has lots of annoying offset errors.
          - '#Cannot access offset#'

```

When running phpstan from Gitlab CI via Drupal.org, how do I tell phpstan where the dependent modules are installed? I don't want to check the dependencies for errors with phpstan, but I need phpstan to be able to access the classes in the dependencies to see what is being extended.

# Answer
The composer file is correct; drupal/jsonrpc

The info.yml file is not correct. Only modules provided by core are prefixed with drupal, e.g. `drupal:comment`. All other modules are prefixed with the project name, e.g. `jsonrpc:jsonrpc`
> 1 votes

---
Tags: testing
---


# Question
Title: Composer installing Tripal module only above v4 and if continuing with v4, getting error with Chado module
As part of college course work, I am required to make a genomic database with a local website with basic features. I have installed Drupal 10.2.3 with PostgreSQL 14.11 and PHP 8.3.4.

My primary question is, should I continue with Tripal version 4 even though it is still in development? If no, how do I downgrade to stable v3.10 when facing this error?

When trying to install (or downgrade to) Tripal v3.10 using

> sudo -u www-data composer require 'drupal/tripal:^3.10'

I am getting following error

```

  Problem 1
    - Root composer.json requires drupal/tripal ^3.10, found drupal/tripal[dev-4.x, 4.0.0-alpha1, 4.0.0-alpha2, 4.x-dev (alias of dev-4.x)] but it does not match the constraint.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.

```

My composer.json only contains the below

```
{
    "require": {
        "drush/drush": "^12.4",
        "drupal/core": "^10.2"
    }
}

```

I am new to Drupal as well as website development in general, and figured I would face less issues with v3 than v4 (which is still in development).

As a side note, I tried continuing with drupal/tripal:4.0.0-alpha2, and was able to proceed until I got error in Chado installation via *Home \> Administration \> Tripal \> Data Storage \> Chado \> Install Chado*. From my limited understanding, it has something to do with missing "drupal\_chado\_installations" table but it seems to exist when I give command

> SELECT * FROM information\_schema.tables WHERE table\_name = 'drupal\_chado\_installations'

I am also adding the Chado installation error if someone feels it is better to continue with Tripal v4 @ http://localhost/admin/tripal/storage/chado/install

> The website encountered an unexpected error. Try again later.
>
> Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE\[42P01\]: Undefined table: 7 ERROR: relation "drupal\_chado\_installations" does not exist LINE 3: "drupal\_chado\_installations" "i" ^: SELECT "i"."install\_id" AS "install\_id", "i"."schema\_name" AS "schema\_name", "i"."version" AS "version", "i"."created" AS "created", "i"."updated" AS "updated" FROM "drupal\_chado\_installations" "i"; Array ( ) in Drupal\tripal\_chado\Database\ChadoConnection-\>getAvailableInstances() (line 279 of modules/contrib/tripal/tripal\_chado/src/Database/ChadoConnection.php).
>
> Drupal\Core\Database\StatementWrapperIterator-\>execute() (Line: 851) Drupal\Core\Database\Connection-\>query() (Line: 239) Drupal\pgsql\Driver\Database\pgsql\Connection-\>query() (Line: 525) Drupal\Core\Database\Query\Select-\>execute() (Line: 155) Drupal\pgsql\Driver\Database\pgsql\Select-\>execute() (Line: 279) Drupal\tripal\_chado\Database\ChadoConnection-\>getAvailableInstances() (Line: 47) Drupal\tripal\_chado\Form\ChadoInstallForm-\>buildForm() call\_user\_func\_array() (Line: 536) Drupal\Core\Form\FormBuilder-\>retrieveForm() (Line: 283) Drupal\Core\Form\FormBuilder-\>buildForm() (Line: 73) Drupal\Core\Controller\FormController-\>getContentResult() call\_user\_func\_array() (Line: 123) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() (Line: 627) Drupal\Core\Render\Renderer-\>executeInRenderContext() (Line: 121) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>wrapControllerExecutionInRenderContext() (Line: 97) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() (Line: 181) Symfony\Component\HttpKernel\HttpKernel-\>handleRaw() (Line: 76) Symfony\Component\HttpKernel\HttpKernel-\>handle() (Line: 58) Drupal\Core\StackMiddleware\Session-\>handle() (Line: 48) Drupal\Core\StackMiddleware\KernelPreHandle-\>handle() (Line: 28) Drupal\Core\StackMiddleware\ContentLength-\>handle() (Line: 32) Drupal\big\_pipe\StackMiddleware\ContentLength-\>handle() (Line: 106) Drupal\page\_cache\StackMiddleware\PageCache-\>pass() (Line: 85) Drupal\page\_cache\StackMiddleware\PageCache-\>handle() (Line: 50) Drupal\ban\BanMiddleware-\>handle() (Line: 48) Drupal\Core\StackMiddleware\ReverseProxyMiddleware-\>handle() (Line: 51) Drupal\Core\StackMiddleware\NegotiationMiddleware-\>handle() (Line: 36) Drupal\Core\StackMiddleware\AjaxPageState-\>handle() (Line: 51) Drupal\Core\StackMiddleware\StackedHttpKernel-\>handle() (Line: 704) Drupal\Core\DrupalKernel-\>handle() (Line: 19)

My settings.php file already contains the database connection detail so many solutions mentioning that are not working

```
$databases['default']['default'] = array (
  'database' => 'teak_wood_genes_db',
  'username' => 'postgres_molecular',
  'password' => '**********',
  'prefix' => 'drupal_',
  'host' => 'localhost',
  'port' => '5432',
  'driver' => 'pgsql',
  'namespace' => 'Drupal\\pgsql\\Driver\\Database\\pgsql',
  'autoload' => 'core/modules/pgsql/src/Driver/Database/pgsql/',
);

```

# Answer
> 0 votes
Version 3.10 does not exist for that version of Drupal. Composer is telling you all the available versions.

---
Tags: database, composer, version-control
---


# Question
Title: How to add at least one CSS class to a twig region?
I am trying to add CSS classes to a new region `{{ page.example }}` in page.html.twig

In the start of page.html.twig, I have added a set of CSS classes:

```
{%
set classes = [
  'region--content',
  'grid-full',
  'layout--pass--content-medium',
]
%}

```

When I try to apply them to an element as follows, this element just disappears from my node.

```
{{ page.example.addClass(classes) }}

```

What have I done wrong?

# Answer
I didn't find a simple way to add at least one class with Twig so I have added classes with HTML this way:

```
<div class="region--content grid-full layout--pass--content-medium">
  {{ page.example }}
</div>

```

I have flushed all caches of Drupal with Drush and flushed all caches of the web browser to test the webpage appearance and indeed found this change to work.
> 0 votes

---
Tags: theming, 10
---


title: Get block_content from block

text:
# Question
Title: Get block_content from block
What is the correct way to check if a block has an associated block\_content instance, and if so, get the block\_content object? What I have does not feel particularly intuitive or efficient:

```
/** @var \Drupal\block\Entity\Block $block */
$block;
$block_plugin = $block->getPlugin();
if ($block_plugin->getBaseId() == 'block_content') {
  /** @var \Drupal\block_content\Entity\BlockContent $block_content */
  $block_content = $block->getPlugin()->build()['#block_content'];
}

```

It feels weird to build the render array for the `$block_plugin` just to get access to the block content, but there doesn't seem to be a more helpful method on `$block` or `$block_plugin`.

For context: I'm conditionally updating block configuration in a deploy hook based on the block\_content bundle, so I'm not rendering anything. Given that, it feels like I shouldn't be using the render array.

# Answer
> 2 votes
@4uk4's comment on the original problem pointed me to a better answer:

```
$block_plugin = $block->getPlugin();

$uuid = $block_plugin->getDerivativeId() ? $block_plugin->getDerivativeId() : '';

$block_content = \Drupal::service('entity.repository')->loadEntityByUuid('block_content', $uuid);

if ($block_content) {...}

```

Thanks for pointing me in the right direction!

---
Tags: blocks
---


# Question
Title: How to allow users to log in by multiple email addresses?
I'm trying to find a way to allow users to log in by email address when they have multiple email addresses registered on my site.

I'm using the Email Registration module to allow users to register with an email address.

Then I can use the Alternative User Emails module to save all the old email addresses when users change their email addresses. These old email addresses are stored in a separate database table.

The email registration module uses `user_load_by_mail()` to get the user account when logging in. I think that overriding this is probably the simplest way, but there is no `hook_user_load_by_mail()` as far as I can tell.

So it looks like my options are:

* Hacking core to override `user_load_by_mail()`
* Patching the *Email Registration* module to check the table added by the *Alternative User Emails* module

Is there a way to glue these together in a custom module without hacking any module?
Ideally, I'd be able to write my own custom module that builds on top of core and contributed modules.

# Answer
> 0 votes
Actually, the Alternative User Emails module supports this functionality out of the box-- it modifies core's email queries to return alternative emails as well.

There was a bug in the module that prevented this from working in all cases, but that has now been fixed.

So the solution here is as simple as "install both Email Registration and Alternative User Emails, and they will work together seamlessly."

---
Tags: authentication-authorization, 10
---


title: How to rerun hook_post_update_NAME()

text:
# Question
Title: How to rerun hook_post_update_NAME()
Drupal 8 introduced `hook_post_update_NAME()` which has some benefits over `hook_update_n`, for updating modules.

Each `hook_post_update_NAME()` should only run once, but sometimes I want to rerun it, like when I'm debugging the update hook during development. With `hook_update_n`, you can reset the schema version in the database.

How do you rerun `hook_post_update_NAME()`?

# Answer
> 15 votes
"post\_update" hooks that have been run are stored in the database, in the `key_value` table, `post_update` collection, but the data is serialized and awkward to update directly.

I used some of the details from @kiamlaluno's answer to create a drush script which you can use to reset a single hook. Here's a basic version (longer version is here):

```
#!/usr/bin/env drush

$key_value = \Drupal::keyValue('post_update');
$update_list = $key_value->get('existing_updates');

$choice = drush_choice($update_list, dt('Which post_update hook do you want to reset?'));

if ($choice) {
  $removed_el = $update_list[$choice];
  unset($update_list[$choice]);
  $key_value->set('existing_updates', $update_list);
  drush_print("$removed_el was reset");
} else {
  drush_print("Reset was cancelled");
}

```

And here's an example of what it looks like when you run it from the command line:

```
./scripts/reset_hook_post_update_NAME.drush

Which post_update hook do you want to reset?
 [0]   :  Cancel
 [1]   :  system_post_update_add_region_to_entity_displays
 [2]   :  system_post_update_hashes_clear_cache
 [3]   :  system_post_update_recalculate_configuration_entity_dependencies
 [4]   :  system_post_update_timestamp_plugins
 [5]   :  my_module_post_update_example_hook

# The script pauses for user input.
5

my_module_post_update_example_hook was reset

```

# Answer
> 7 votes
Here is an example you can use from the command line with drush php-eval:

```
drush php:eval '$update_hook_name = "<my_hook_post_update_name>";
$key_value = \Drupal::keyValue("post_update");
$existing_updates = $key_value->get("existing_updates");
$index = array_search($update_hook_name, $existing_updates);
unset($existing_updates[$index]);
$key_value->set("existing_updates", $existing_updates);'

```

When you re-run drush updatedb you will see your post\_update\_hook waiting to be run.

# Answer
> 2 votes
Here's the solution I worked up for rolling back updates. In my case, all the updates I wanted to remove and run again all start with 'MY\_MODULE\_post\_update', so I'm filtering them out based on that string being present; adjust your filter condition in this command as appropriate:

```
drush ev '$updates = \Drupal::keyValue("post_update")->get("existing_updates"); \Drupal::keyValue("post_update")->set("existing_updates", array_diff_key($updates, array_filter($updates, function($v){return FALSE !== strstr($v,"MY_MODULE_post_update");})));'

```

# Answer
> 1 votes
`UpdateRegistry::getPendingUpdateFunctions()` contains the following code. See what the comment says.

```
  // First figure out which hook_{$this->updateType}_NAME got executed
  // already.
  $existing_update_functions = $this->keyValue->get('existing_updates', []);

```

UpdateRegistry::$updateType is set to `'post_update'`.
`$this->keyValue` is set from `UpdateRegistryFactory::create()` with the value of `$this->container->get('keyvalue')->get('post_update')`.

The equivalent procedural code to get that keyvalue collection is the following one.

```
$key_value = \Drupal::keyValue('post_update');

```

Set *existing\_updates* to an empty array, and Drupal will think none of the post update callbacks have been called.

```
$key_value = \Drupal::keyValue('post_update');
$key_value->set('existing_updates', []);

```

Remove the callback name from the *existing\_updates* key of that keyvalue, and Drupal will think that post update callback has not yet been invoked.

# Answer
> 1 votes
This is an updated script to use for Drupal 9.x Drush 10.x - it corrects the edge case of selecting the '1' as a choice (which returns 0) and allows the user to filter choices by a PREFIX.

https://gist.github.com/wayne-weibel/01e7f00b32dbcb96eb2785817693483f

```
<?php

use Drush\Commands\DrushCommands;

/**
 * @file
 * Reset module hook_post_update_NAME
 *
 * A tool for developing and debugging post_update hooks.
 *
 * This script will ONLY reset the hook to be run again ...
 *
 * If data is being changed, backup the database and restore as needed
 *
 * Usage:
 * drush php:script reset_hook_post_update.php [-- PREFIX]
 *
 * @see https://www.drush.org/latest/commands/php_script/
 *
 * https://gist.github.com/bryanbraun/852646078ef6b33d2dc2ecacc96c9865
 * https://www.drush.org/latest/api/Drush/Commands/DrushCommands.html
 */

$key_value = \Drupal::keyValue('post_update');
$update_list = $key_value->get('existing_updates');

$indexes = array_flip($update_list);
$choices = array_reverse($update_list);
if ($extra) {
    $prefix = array_shift($extra);
    $choices = array_filter(
        $choices,
        fn($c) => str_starts_with($c, $prefix)
    );
}

$io = DrushCommands::io();
$reset = $io->choice("Which post_update hook do you want to reset?", $choices, 0);
if ($reset !== FALSE) {
    $remove = $choices[$reset];
    $index = $indexes[$remove];
    if ($remove === $update_list[$index]) {
        unset($update_list[$index]);
        $key_value->set("existing_updates", $update_list);
        $io->success("$remove has been reset.");
    }
    else {
        // Really should not even get here!
        $io->error("Unable to match selection!");
    }
}
// Cancelled message is handled in `choice`.

```

# Answer
> 0 votes
If it is a one-time thing and you're okay with a quick fix rather than a nice fix that runs with `drush updb`, then you can do this to save time:

```
drush eval "require 'modules/custom/FOO/FOO.post_update.php'; FOO_post_update_NAME();"

```

Here, replace `FOO` with your module's name and replace `NAME` based on the name of your post-update hook.

Don't forget to test it on your local dev env and run it on all the environments that require this post-update.

# Answer
> 0 votes
There is a quick and dirty way that is fine for local development.

Temporarily append a suffix to the post-update function:

```
function mymodule_post_update_ABC_001(): {
  [..]
}

```

Here, `_001` is a temporary suffix that you can count up during development, whereas `ABC` is the actual name of the update that you want to keep.

This method will pollute the key-value table, but this is ok, if you regularly destroy your local database with a new db import from production.

Of course you want to remove the temporary suffix when you commit to version control.

# Answer
> -1 votes
Call it from within `hook_update_n()` and then do what you were doing before.

---
Tags: 8, updating
---


# Question
Title: How to render formatted text field from paragraphs as is in twig?
I need to render a text (formatted long) field using twig. At this time i am doing the following below. However, i am finding that if i were to add a line break in the text field or apply adding spacing or a horizontal line, the twig filter "raw" removes those attributes. I need assistance to see what I am missing.

I have already set the view mode for field on the content type to default

Twig template (filter used)

```
{% for item in items %}
    {{ item.field_body.value|raw }}
{% endfor %}

```

Expecting

Actual result

# Answer
This is the code I'm using inside one of my field templates to output a text field, which is used as an HTML/JS widget input box

```
{% for item in items %}
  <div{{ item.attributes }}>{{ item.content['#context'].value|raw }}</div>
{% endfor %}

```

Should work for you, I guess you'll have to remove the `|raw` filter for your case. (But usually it is not the recommended way to output fields this way.)
> 3 votes

# Answer
Never use raw, it **will** hurt you, use this instead

```
{{ {
    '#type': 'processed_text',
    '#text':  item.content['#context'].value,
    '#format': 'rich_text',
} }}

```
> 0 votes

---
Tags: views, theming, 8, nodes
---


title: Error with Chado module installation

text:
# Question
Title: Error with Chado module installation
As part of college course work, I am required to make a genomic database with a local website with basic features. I have installed Drupal 10.2.3 with PostgreSQL 14.11, PHP 8.3.4 and Tripal 4.0.0-alpha2.

I am facing error during Chado module installation via Home \> Administration \> Tripal \> Data Storage \> Chado \> Install Chado. I have already enabled it from the 'Extend' tab. I am new to Drupal as well as website development in general. From my limited understanding, it has something to do with missing "drupal\_chado\_installations" table but it seems to exist when I give command

```
SELECT * FROM information_schema.tables WHERE table_name = 'drupal_chado_installations'

```

Below is the Chado installation error when I try installing through my local server's website @http://localhost/admin/tripal/storage/chado/install

> The website encountered an unexpected error. Try again later.
>
> ```
> Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "drupal_chado_installations" does not exist
>
> ```
>
> LINE 3: "drupal\_chado\_installations" "i" ^: SELECT "i"."install\_id" AS "install\_id", "i"."schema\_name" AS "schema\_name", "i"."version" AS "version", "i"."created" AS "created", "i"."updated" AS "updated" FROM "drupal\_chado\_installations" "i"; Array ( ) in Drupal\tripal\_chado\Database\ChadoConnection-\>getAvailableInstances() (line 279 of modules/contrib/tripal/tripal\_chado/src/Database/ChadoConnection.php).
>
> ```
> Drupal\Core\Database\StatementWrapperIterator->execute() (Line: 851) Drupal\Core\Database\Connection->query() (Line: 239)
>
> ```
>
> Drupal\pgsql\Driver\Database\pgsql\Connection-\>query() (Line: 525) Drupal\Core\Database\Query\Select-\>execute() (Line: 155) Drupal\pgsql\Driver\Database\pgsql\Select-\>execute() (Line: 279) Drupal\tripal\_chado\Database\ChadoConnection-\>getAvailableInstances() (Line: 47) Drupal\tripal\_chado\Form\ChadoInstallForm-\>buildForm() call\_user\_func\_array() (Line: 536) Drupal\Core\Form\FormBuilder-\>retrieveForm() (Line: 283) Drupal\Core\Form\FormBuilder-\>buildForm() (Line: 73) Drupal\Core\Controller\FormController-\>getContentResult() call\_user\_func\_array() (Line: 123) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() (Line: 627) Drupal\Core\Render\Renderer-\>executeInRenderContext() (Line: 121) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>wrapControllerExecutionInRenderContext() (Line: 97) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() (Line: 181) Symfony\Component\HttpKernel\HttpKernel-\>handleRaw() (Line: 76) Symfony\Component\HttpKernel\HttpKernel-\>handle() (Line: 58) Drupal\Core\StackMiddleware\Session-\>handle() (Line: 48) Drupal\Core\StackMiddleware\KernelPreHandle-\>handle() (Line: 28) Drupal\Core\StackMiddleware\ContentLength-\>handle() (Line: 32) Drupal\big\_pipe\StackMiddleware\ContentLength-\>handle() (Line: 106) Drupal\page\_cache\StackMiddleware\PageCache-\>pass() (Line: 85) Drupal\page\_cache\StackMiddleware\PageCache-\>handle() (Line: 50) Drupal\ban\BanMiddleware-\>handle() (Line: 48) Drupal\Core\StackMiddleware\ReverseProxyMiddleware-\>handle() (Line: 51) Drupal\Core\StackMiddleware\NegotiationMiddleware-\>handle() (Line: 36) Drupal\Core\StackMiddleware\AjaxPageState-\>handle() (Line: 51) Drupal\Core\StackMiddleware\StackedHttpKernel-\>handle() (Line: 704) Drupal\Core\DrupalKernel-\>handle() (Line: 19)

My settings.php file already contains the database connection details so online solutions mentioning that are not working

```
$databases['default']['default'] = array (
  'database' => 'teak_wood_genes_db',
  'username' => 'postgres_molecular',
  'password' => '**********',
  'prefix' => 'drupal_',
  'host' => 'localhost',
  'port' => '5432',
  'driver' => 'pgsql',
  'namespace' => 'Drupal\\pgsql\\Driver\\Database\\pgsql',
  'autoload' => 'core/modules/pgsql/src/Driver/Database/pgsql/',
);

```

# Answer
Turns out the error is due to table prefix. Table prefix is depreciated in latest versions and threw errors. Solved by removing the entire database (after backup) and creating a new one without prefix, also removing the prefix in settings.php file.
> 1 votes

---
Tags: database, debugging, 10
---


# Question
Title: Getting error from entity.eval.inc - null given in array_values() - upon login after upgrading to 7.100 and php to 8.1.2
We recently spun up a new server with newer php. Tested the new server, converted dns records to now point to the new server, etc. I was about to take it out of maintenance and noticed drupal had an update. We were running 7.99. I figured not much risk, never had a problem updating drupal. Still, upgraded in test and it seemed fine, upgraded prod and took it out of maintenance. Now if you log out and log back in you get "The website encountered an error" page. Reloading the page will get you to the after login screen.

The log showed this error message: TypeError: array\_values(): Argument #1 ($array) must be of type array, null given in array\_values() (line 60 of /usr/share/nginx/oursite/sites/all/modules/rules/modules/entity.eval.inc)

I did the same upgrade to 7.100 on the old server and it doesn't have the problem. It's running php 7.2.24. Of course, with spinning up a new server there are lots of other things that are updated.

I hack the file and fixed it with this:

`return array('entity_fetched' => is_array($return)? array_values($return): array());`

original code

`return array('entity_fetched' => array_values($return);`

I find it hard to believe there is bug in the code. I'm guessing we're missing some entity.

Any thoughts on how to fix this properly?

# Answer
To properly fix this you should file a bug report, with detailed steps to reproduce. Drupal project pages have in the right-hand column a place to report issues, such a bugs.
> -1 votes

---
Tags: log-messages
---


# Question
Title: How to safely output user input HTML in a twig theme
Very basic question:

I have a twig template were I want to output the HTML content of a CkEditor managed field within a node.

```
<div class="wrap-user-html">
  {{ node.field_myfield.0.value }}
</div>

```

This does not work, as it prints the html code with html entities. I'm getting e. g.

```
<div class="wrap-user-html">
  <p>foo</p>
</div>

```

I could use |raw and it would work, but I read this is unsafe. Also when using raw, text format filters from the ckeditor settings seem to not get applied.

How do I do this right?

# Answer
> 2 votes
Thanx to the comment of user cilefen I finally got it:

instead of

```
<div class="wrap-user-html">
  {{ node.field_myfield.0.value|raw }}
</div>

```

it would be

```
  {% set wysiwgcontent = {
    '#type': 'processed_text',
    '#text': node.field_myfield.0.value,
    '#format': node.field_myfield.0.format,
  } %}
  {{ wysiwgcontent }}

```

---
Tags: 10
---


# Question
Title: Can I put taxonomy tags in a block and if I can, how to prevent them from appearing in a field of a node?
Having the taxonomy tags in **a field of a node** in the main content block of the **Content region**, is a problem for me, as I would prefer having them inside a block so to better choose where they appear.

Can I put taxonomy tags in a block and if I can, how to prevent them from appearing in a field of a node?

# Answer
You can move them around "like a block" with Layout Builder, which is included in core. The positioning will still be within the content region, but it can be anywhere in the content region, and you can customize the design however you like. I would try this first.

But, if you really want a block, you can make one with Views. Create a view of type taxonomy and then create a block display for that view. To get the taxonomy terms for the current node, you will have to configure the arguments (contextual filters) correctly, which can be a little tricky. However, when you finish, you will have a block you can position wherever you like.

To stop the terms from appearing on the node once you have the block, go to Manage Display for the content type and set the terms field not to display.
> 0 votes

---
Tags: theming, nodes, taxonomy-terms, blocks, 10
---


# Question
Title: How to replace "default" with website domain name during drush user-login
When I run `drush user-login username`, drush prints a url like `http://default/user/reset/1/32323933...`. How do I replace *default* with the actual website name?

# Answer
> 15 votes
You can use option `--url`:

> `-l <http://example.com:8888>, URI of the drupal site to use (only needed in multisite environments or when running on an alternate port).`
> `--uri=<http://example.com:8888>`

```
$  drush uli -l yoursite.dev

```

Or create a record in your aliases.drushrc.php file:

```
$aliases['yoursite-dev'] = array(
  'root' => '/vhosts/yoursite.dev',
  'uri' => 'yoursite.dev',
);

```

Now you have an alias `@yoursite-dev` and can use it:

```
$ drush use @yoursite-dev
$ drush uli

```

## Update:

Now I prefer to create `sites/default/drushrc.php` file for each Drupal folder:

```
<?php
$options['l'] = 'http://yoursite.dev';
$options['r'] = '/vhosts/yoursite.dev';

```

More info about `drushrc.php`: https://raw.githubusercontent.com/drush-ops/drush/8.x/examples/example.drushrc.php

# Answer
> 2 votes
I used this command for login into my local site:

```
drush uli --uri=http://your_local_url

```

# Answer
> 0 votes
You can set the uri in a drush site alias file to avoid getting http://default at the beginning of your password reset links.

ie. **drush/sites/example.sites.yml**

```
live:
   host: server.example.com
   user: user
   ssh: '-p 22'
   root: /home/user/public_html/docroot
   uri: 'http://example.com'
test:
   host: server2.example.net
   user: user2
   ssh: '-p 22'
   root: /home/user2/public_html/docroot
   uri: 'http://test.example.net'
dev:
   host: localhost
   user: docker
   root: /var/www/docroot
   uri: 'http://example.dev.example.com'

```

Then use the Drush site alias in the command for the password reset link:

```
drush @example.dev uli

```

The **example** after the @ symbol in the Drush site alias comes from the first part of the Drush site alias filename. The second part comes from the site entry in the file.

# Answer
> 0 votes
You could also export the environment variable DRUSH\_OPTIONS\_URI.

`export DRUSH_OPTIONS_URI=http://example.com`

# Answer
> 0 votes
I work with lando and I threw together the following function:

```
duli() {
    sitename=$(lando info|grep -E https|tail -n1|cut -d \' -f2)
    lando drush uli -l $sitename;
}

```

---
Tags: drush
---


# Question
Title: Error creating a status transition programmatically - Missing bundle for entity type workflow_transition
I'm currently working on a migration project from D7 to D10. I have a form that needs to go through several steps from creation to completion, here are some of them:

* New Request
* Under Analysis
* Manager Approval

The status transition is done through a button called "Save and Submit" which, when clicked, the form should go directly from the "Creation" status to the "Under Analysis" status.

For this, I'm using the "Workflow" contrib module - https://www.drupal.org/project/workflow \- and created a status transition programmatically. But when requesting the transition I am getting an error.

Can anyone help me with this problem, please?

Here is my code and the error received:

```
public static function createNodeStatusTransition($node_id, $workflow_id, $transition_id, $field_name, $to_state_id, $user_id = NULL) {

$node = Node::load($node_id);

if (!$node instanceof EntityInterface) {
  throw new \InvalidArgumentException("Node with ID $node_id does not exist.");
}

$workflow = Workflow::load($workflow_id);

if (!$workflow) {
  throw new \InvalidArgumentException("Workflow with ID $workflow_id does not exist.");
}

$current_state = $node->get($field_name)->value;

$to_state = WorkflowState::load($to_state_id);
if (!$to_state) {
  throw new \InvalidArgumentException("Workflow state with ID $to_state_id does not exist.");
}

if ($to_state->getWorkflowId() !== $workflow_id) {
  throw new \InvalidArgumentException("The 'to' state does not belong to the workflow with ID $workflow_id.");
}

$transition = WorkflowTransition::create([
  'entity_type' => $node->getEntityTypeId(),
  'entity_id' => $node_id,
  'field_name' => $field_name,
  'from_sid' => $current_state,
  'to_sid' => $to_state_id,
  'uid' => $user_id ?: \Drupal::currentUser()->id(),
  'timestamp' => \Drupal::time()->getRequestTime(),
]);

$transition->save();

\Drupal::messenger()->addMessage(t('The transition was successfully created for the node %node_title.', ['%node_title' => $node->label()]));

```

}

# Answer
I managed to solve the problem. Now it's working fine. Here's what the code looked like after the changes.

```
public static function createNodeStatusTransition($node_id, $workflow_id, $field_name, $to_state_id, $user_id = NULL) {

$node = Node::load($node_id);

if (!$node instanceof EntityInterface) {
  throw new \InvalidArgumentException("Node with ID $node_id does not exist.");
}

$workflow = Workflow::load($workflow_id);

if (!$workflow) {
  throw new \InvalidArgumentException("Workflow with ID $workflow_id does not exist.");
}

$current_state = $node->get($field_name)->value;

$to_state = WorkflowState::load($to_state_id);
if (!$to_state) {
  throw new \InvalidArgumentException("Workflow state with ID $to_state_id does not exist.");
}

if ($to_state->getWorkflowId() !== $workflow_id) {
  throw new \InvalidArgumentException("The 'to' state does not belong to the workflow with ID $workflow_id.");
}

// Create Workflow Transition
$transition = WorkflowTransition::create([$current_state]);
$transition->setValues($to_state, \Drupal::currentUser()->id(), \Drupal::time()->getRequestTime(), '', TRUE);
$transition->setTargetEntity($node);

// Updates the field relating to the entity's workflow state
$entity = $transition->getTargetEntity();
$entity->{$field_name}->value = $transition->getToSid();
if ($transition->getWorkflow()->getSetting('always_update_entity')) {
  $entity->changed = $transition->getTimestamp();
}
$entity->save();

$transition->save();

\Drupal::messenger()->addMessage(t('The transition was successfully created for the node %node_title.', ['%node_title' => $node->label()]));

```

}
> 1 votes

---
Tags: 10, workflows
---


# Question
Title: I have 2 commerce feeds imports, one must run before the other
I have a drupal 7 commerce site, each day our client uploads a .csv with updates to approx. 4000 products, including published status.

2 imports have been configured, 1 to update the product information and the other to update the product references (node/display) - both read the same .csv.

The importers must run 3 times a day, in order to avoid errors, the product importer must execute before the reference importer. If we use Drupal cron, both will start at the same scheduled time, which leads to errors.

What we really want is to run the product importer until it is completed (multiple times if necessary), and only then to run the reference importer. All of the above 3 times a day.

I imagine there is a hook allowing execution of a specific importer, so I can run it via bash cron, but I don't know where to begin looking, any pointers would be appreciated.

# Answer
> 2 votes
There are multiple solutions to this problem:

1. **Cron manager**

One is indeed to use a cron manager module. I think you would need Feeds Ultimate Cron for this. This solution would require you though to guess when the first import is completed.
2. **Rules**

Using the Rules action 'Execute feeds importer' (requires latest dev of Feeds 7.x-2.x or the patch from https://www.drupal.org/node/2446307). In this case you would create a Rules component of type 'Action set' and then add two times the action for executing a feeds importer (one for each importer). Perhaps it possible with Rules Scheduler to run this action set on a regular basis? Note that you should configure the importers to *not* run in background, else both imports may still run simultaneously. Also note that Feeds would try in this case to perform the whole import in one go, so it could perhaps cause max runtime issues.
3. **Drush**

Feeds has a drush command called `feeds-import` with which you can perform an import in one go. So you could create a shell script that runs both imports after eachother and then run that script on a regular basis. For details about this command, see https://drushcommands.com/drush-7x/feeds/feeds-import/
4. **Implement hook\_feeds\_after\_import()**

Feeds has a hook called `hook_feeds_after_import()` that you could use to initiate an other import programmatically:

```
/**
 * Implements hook_feeds_after_import().
 */
function mymodule_feeds_after_import(FeedsSource $source) {
  // Run product display importer after product importer.
  if ($source->importer->id == 'product_importer') {
    $product_display_source = feeds_source('product_display_importer');
    $product_display_source->existing()->startImport();

    // Execute batch, if there is any. Set 'progressive' to false to prevent
    // batch from triggering a drupal_goto().
    // (note: this code is not needed when using the 'process in background' option.)
    $batch =& batch_get();
    if (!empty($batch)) {
      $batch['progressive'] = FALSE;
      batch_process();
    }
  }
}

```

# Answer
> 0 votes
Use this module and it will do the work for you: https://www.drupal.org/project/feeds\_dependency

---
Tags: 7, commerce, feeds
---


title: Looking for support

text:
# Question
Title: Looking for support
After a long illness and hospitalization, I have resumed the maintenance of the D7 website of a small patient association. Migration to D10 was partially successful. Article content has been transferred, but photos are still missing. Where can I place a call for someone who can help me specifically? The aim is to be back online quickly and then take the time to keep up with the developments of Drupal of recent years.

Sorry if this is not the place for this question.

# Answer
Drupal is a software maintained by a diverse community rather than a company with a support telephone number.

All sources of Drupal support are categorized.

You may post a request for paid services in this forum, and stipulate the telephone requirement.
> 1 votes

---
Tags: 7
---


title: Taxonomy cache invalidate

text:
# Question
Title: Taxonomy cache invalidate
Drupal cache Drupal 10.

I'm trying to invalidate the cache, when there's a new taxonomy term is added.

Here's my code:

```
$build = [
  '#cache' => [
    'contexts' => ['taxonomy_list:city'],
    ]
];

return (new ResourceResponse($data, 200))->addCacheableDependency(CacheableMetadata::createFromRenderArray($build));

```

When I added a new city, the Cache is still HIT. I want to refresh the cache when a new city is added to the taxonomy list.

# Answer
> 1 votes
This is a list cache tag, see https://www.drupal.org/docs/drupal-apis/cache-api/cache-tags#syntax. And the entity machine name is `taxonomy_term`.

So the correct cache metadata could look like this:

```
$build = [
  '#cache' => [
    'tags' => ['taxonomy_term_list:city'],
  ],
];

```

However, you still might need to add a cache context, in case the taxonomy query has dependencies like parts of the URL or the current user. See https://www.drupal.org/docs/drupal-apis/cache-api/cache-contexts

---
Tags: 10
---