# Question
Title: How do you install or turn on CKEditor 5 paste from word plugin
According to a conversation with CKEditor this feature is included in the Drupal 10 version. They do not support it and point you to Documentation for paste from Word

We cannot find where to turn this on so we get a clean paste nor are there instructions for installing the plugin to Drupal 10.

Can anyone assist in how to accomplish this task. Many thanks.

# Answer
CKEditor 5 \> paste from word plugin (maintaining html formatting) inbuilt in Drupal 10 core by default : there is n**o need to any additional configuration**

While **pasting the code in text editor field** make sure select **"full html" format** otherwise the html tags 'll be stripped & it gives illusion "paste from word plugin (along with maintaining html formatting)" functionality not working in Drupal 10.

Note: check off "Limit HTML" to remove the unnecessary Word formatting
> 1 votes

---
Tags: wysiwyg, installation, plugins
---


title: How to add a link to table row?

text:
# Question
Title: How to add a link to table row?
There is a field 'field\_upload\_artwork' that contains files. I am using them to build links to files and want to insert links after Apparel Printing in the last step of the form.

Now the markup in devtools of the browser looks like this:

```
<tbody>
<tr>
   <td>Apparel Printing</td>
   <td></td>
   <td #type="container" file_link="Array"></td>
   <td #type="container" file_link="Array"></td>
</tr>
</tbody>

```

Although it should be something like this (as I see):

```
<tbody>
<tr>
  <td>Apparel Printing</td>
  <td>
    <a href="".....>name_of_file.png</a>
  </td>
  <td>
    <a href="".....>name_of_file.png</a>
  </td>
</tr>
</tbody>

```

and this is how I build the table:

```
$files = [];
foreach ($quote_design->get('field_upload_artwork')->getValue() as $file) {
   if ($file = File::load($file['target_id'])) {
     $file_uri = $file->getFileUri();
     $file_link = [
       'title' => [
         '#type' => 'link',
         '#title' => $file->getFilename(),
         '#url' => $file_uri,
       ],
     ];
     $files[] = [
       '#type' => 'container',
       'file_link' => $file_link,
     ];
   }
}

$services_header = [
   'col0' => $this->t('Services'),
];
       // foreach ($files as $key => $file) {
       // $services_header['col' . $key] = '';
       // }

$services_row = [
   array_merge([$quote_design->get('field_service')->value, ''], $files),
];

$form['confirm_quote'][$key]['services_table'] = [
   '#type' => 'table',
   '#header' => $services_header,
   '#rows' => $services_row,
];

```

What am I doing wrong here? According to the idea, we need foreach, which I commented out. But if I uncomment it, then everything breaks down.

# Answer
you should try this structure:

```
$rows[] = [
  'data' => [
    'label' => [
      'data' => [
        'link' => [
          '#type' => 'link',
          '#title' => 'link text',
          '#url' => Url::fromRoute('custom_module.route'),
        ],
      ],
    ],
  ],
];

```

which in my case looks like this:

```
      $services_header = [
        'col0' => $this->t('Services'),
      ];

      $services_rows = [
        [$quote_design->get('field_service')->value],
      ];

      foreach ($quote_design->get('field_upload_artwork')->getValue() as $file_key => $file_item) {
        if ($file_id = $file_item['target_id']) {
          $file = File::load($file_id);
          $file_url = $file->createFileUrl(FALSE);

          $services_header['col' . ($file_key + 1)] = '';

          $services_rows['data' . ($file_key + 1)] = [
            'label' => [
              'data' => [
                'link' => [
                  '#type' => 'link',
                  '#title' => 'Art Link',
                  '#url' => Url::fromUri($file_url),
                  '#attributes' => [
                    'class' => ['entity-quote-confirm-quote-services-table-link'],
                  ],
                ],
              ],
            ],
          ];
        }

      }

```

Also, I found this example (but I didn't use it):

```
use Drupal\Component\Render\FormattableMarkup;
  $rows[] = array(

      array('data' => new FormattableMarkup('<a href=":link">@name</a>',
        [':link' => $entry['link_url'],
        '@name' => $entry['name']])
      ),

```
> 1 votes

# Answer
If using the `table` theme, the `#rows` array contents must follow some guidelines. `#rows` must be:

> An array of the rows to be displayed. Each row is either an array of cell contents or an array of properties as described in table.html.twig Alternatively specify the data for the table as child elements of the table element. Table elements would contain rows elements that would in turn contain column elements. - https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21Table.php/class/Table/10

So if `#rows` contains render arrays, they must be named child elements.
> 0 votes

---
Tags: forms, 9
---


# Question
Title: How to get views machine name in `block--views-block-html.twig` file?
I've create views as block. Then i tried to theme my views block by altering `block--views-block-html.twig` file. I've struggled to get views machine name in this file. I need views machine name for some reason. So any other solutions to get views machine name?

# Answer
Views machine name would be: /admin/structure/views/view/**frontpage**.

You can edit/change the view name on right corner: *Edit view name / description*.

You can override the template name using below.

* `[base template name]--[view machine name]--[view display id].html.twig`
* `[base template name]--[view machine name]--[view display type].html.twig`

So this would be:

* `views-view--frontpage--page.html.twig`

or:

* `views-view--frontpage--block.html.twig`

There is no theme information is displayed with D8 views as D7 views was having the those information.

Please refer the reference page.
> 1 votes

# Answer
You should be able to access the ID with:

```
$variables['view']->id();

```

...but to do that, you need to preprocess the block/view; in my case, I needed to grab the machine name of a view that I was preprocessing using `template_chn_preprocess_views_view()`.

See the other options/methods you can access inside `ViewExecutable`.
> 0 votes

# Answer
This would help someone still looking for adding a block template suggestion with View's machine name.

You should be able to get the View ID with `$variables['elements']['content']['#view_id]` if exists.

```
/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function my_theme_name_theme_suggestions_block_alter(array &$suggestions, array $variables) {
  $content = $variables['elements']['content'];

  // Add a common template suggestion for `View ID` view.
  if (isset($content['#view_id']) && $content['#view_id'] === 'view_id') {
    $suggestions[] = 'block__' . $content['#view_id'];
  }
}

```
> 0 votes

---
Tags: views, theming, 8, blocks
---


# Question
Title: Cannot upgrade guzzlehttp/guzzle (6.5.8 => 7.7.1) when passing from 9.5.11 to 10.1.5
I am trying to upgrade from Drupal 9.5.11 to 10.1.5. I am also running PHP 8.1.14.

\[root@ip-172-31-13-94 demo9\]# **composer require 'drupal/core-recommended:^10' 'drupal/core-composer-scaffold:^10' 'drupal/core-project-message:^10' --update-with-dependencies --no-update**

./composer.json has been updated

\[root@ip-172-31-13-94 demo9\]# **composer require 'drush/drush:^12' --no-update**

./composer.json has been updated

\[root@ip-172-31-13-94 demo9\]# **composer update**

```
Gathering patches for root package.
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - drupal/core-recommended[10.0.0-beta1, ..., 10.0.11] require guzzlehttp/guzzle ~7.5.0 -> found guzzlehttp/guzzle[7.5.0, 7.5.1, 7.5.2, 7.5.3] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core-recommended 10.1.0-beta1 requires guzzlehttp/guzzle ~7.5.1 -> found guzzlehttp/guzzle[7.5.1, 7.5.2, 7.5.3] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core 8.0.0-beta6 requires doctrine/common dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5 -> found doctrine/common[dev-remove-int-cast, 2.1.3, ..., 2.13.x-dev, 3.0.0, ..., 3.5.x-dev] but it does not match the constraint.
    - drupal/core[8.0.0-beta7, ..., 8.0.0-beta12] require guzzlehttp/guzzle ~5.0 -> found guzzlehttp/guzzle[5.0.0, ..., 5.3.4] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core[8.0.0-beta13, ..., 8.0.0-beta15] require guzzlehttp/guzzle dev-master#1879fbe853b0c64d109e369c7aeff09849e62d1e -> found guzzlehttp/guzzle[dev-improve-checks-for-http-2, dev-test, v1.0.3, v1.0.4, v2.0.0, ..., v2.8.8, v3.0.0, ..., v3.8.1, 4.0.0-rc.1, ..., 4.x-dev, 5.0.0, ..., 5.3.x-dev, 6.0.0, ..., 6.5.x-dev, 7.0.0-beta.1, ..., 7.9.x-dev] but it does not match the constraint.
    - drupal/core[8.0.0-beta16, ..., 8.1.6] require guzzlehttp/guzzle ~6.1 -> found guzzlehttp/guzzle[6.1.0, ..., 6.5.8] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core 8.1.7 requires guzzlehttp/guzzle ~6.2 -> found guzzlehttp/guzzle[6.2.0, ..., 6.5.8] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core[8.1.8, ..., 8.7.14] require guzzlehttp/guzzle ^6.2.1 -> found guzzlehttp/guzzle[6.2.1, ..., 6.5.8] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core[8.8.0-beta1, ..., 8.9.10] require guzzlehttp/guzzle ^6.3 -> found guzzlehttp/guzzle[6.3.0, ..., 6.5.8] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core[8.9.11, ..., 8.9.20] require php ^7.0.8 -> your php version (8.1.14) does not satisfy that requirement.
    - drupal/core[9.0.0-beta1, ..., 9.3.13] require guzzlehttp/guzzle ^6.5.2 -> found guzzlehttp/guzzle[6.5.2, ..., 6.5.8] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core[9.0.10, ..., 9.0.14] require php ^7.3 -> your php version (8.1.14) does not satisfy that requirement.
    - drupal/core[9.2.20, ..., 9.3.15] require guzzlehttp/guzzle ^6.5.6 -> found guzzlehttp/guzzle[6.5.6, 6.5.7, 6.5.8] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core[9.2.21, ..., 9.3.16] require guzzlehttp/guzzle ^6.5.7 -> found guzzlehttp/guzzle[6.5.7, 6.5.8] but it conflicts with your root composer.json require (~7.7.0).
    - drupal/core[9.3.17, ..., 9.3.22] require guzzlehttp/guzzle ^6.5.8 -> found guzzlehttp/guzzle[6.5.8] but it conflicts with your root composer.json require (~7.7.0).
    - Root composer.json requires drupal/vefl ^3.0 -> satisfiable by drupal/vefl[3.0.0].
    - drupal/core-recommended 10.1.1 requires drupal/core 10.1.1 -> satisfiable by drupal/core[10.1.1].
    - Conclusion: don't install drupal/core 10.1.1 (conflict analysis result)
    - drupal/core-recommended 10.1.2 requires drupal/core 10.1.2 -> satisfiable by drupal/core[10.1.2].
    - Conclusion: don't install drupal/core 10.1.2 (conflict analysis result)
    - drupal/core-recommended 10.1.3 requires drupal/core 10.1.3 -> satisfiable by drupal/core[10.1.3].
    - Conclusion: don't install drupal/core 10.1.3 (conflict analysis result)
    - drupal/core-recommended 10.1.4 requires drupal/core 10.1.4 -> satisfiable by drupal/core[10.1.4].
    - Conclusion: don't install drupal/core 10.1.4 (conflict analysis result)
    - drupal/core-recommended 10.1.5 requires drupal/core 10.1.5 -> satisfiable by drupal/core[10.1.5].
    - Conclusion: don't install drupal/core 10.1.5 (conflict analysis result)
    - drupal/core-recommended 10.1.0 requires drupal/core 10.1.0 -> satisfiable by drupal/core[10.1.0].
    - Conclusion: don't install drupal/core 10.1.0 (conflict analysis result)
    - drupal/vefl 3.0.0 requires drupal/core ^8 || ^9 -> satisfiable by drupal/core[8.0.0-beta6, ..., 8.9.20, 9.0.0-beta1, ..., 9.5.11].
    - You can only install one version of a package, so only one of these can be installed: drupal/core[8.0.0-beta6, ..., 8.9.20, 9.0.0-beta1, ..., 9.5.11, 10.0.0-beta1, ..., 10.1.5].
    - You can only install one version of a package, so only one of these can be installed: drupal/core[8.7.0-beta1, ..., 8.9.20, 9.0.0-beta1, ..., 9.5.11, 10.0.0-beta1, ..., 10.1.5].
    - drupal/core-recommended 10.1.0-rc1 requires drupal/core 10.1.0-rc1 -> satisfiable by drupal/core[10.1.0-rc1].
    - Root composer.json requires drupal/core-recommended ^10 -> satisfiable by drupal/core-recommended[10.0.0-beta1, ..., 10.1.5].

    Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.

I intentionally set the require for guzzle to ~7.7.0 but as you can see, it fails.  When I set it back to 6.5:

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - drupal/core-recommended[10.0.0-beta1, ..., 10.0.11] require guzzlehttp/guzzle ~7.5.0 -> found guzzlehttp/guzzle[7.5.0, 7.5.1, 7.5.2, 7.5.3] but it conflicts with your root composer.json require (^6.5).
    - drupal/core-recommended 10.1.0-beta1 requires guzzlehttp/guzzle ~7.5.1 -> found guzzlehttp/guzzle[7.5.1, 7.5.2, 7.5.3] but it conflicts with your root composer.json require (^6.5).
    - drupal/core-recommended[10.1.0-rc1, ..., 10.1.5] require guzzlehttp/guzzle ~7.7.0 -> found guzzlehttp/guzzle[7.7.0, 7.7.1] but it conflicts with your root composer.json require (^6.5).
    - Root composer.json requires drupal/core-recommended ^10 -> satisfiable by drupal/core-recommended[10.0.0-beta1, ..., 10.1.5].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.

```

\[root@ip-172-31-13-94 demo9\]# **composer update -W**

```
Gathering patches for root package.
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - drupal/core-recommended[10.0.0-beta1, ..., 10.0.11] require guzzlehttp/guzzle ~7.5.0 -> found guzzlehttp/guzzle[7.5.0, 7.5.1, 7.5.2, 7.5.3] but it conflicts with your root composer.json require (^6.5).
    - drupal/core-recommended 10.1.0-beta1 requires guzzlehttp/guzzle ~7.5.1 -> found guzzlehttp/guzzle[7.5.1, 7.5.2, 7.5.3] but it conflicts with your root composer.json require (^6.5).
    - drupal/core-recommended[10.1.0-rc1, ..., 10.1.5] require guzzlehttp/guzzle ~7.7.0 -> found guzzlehttp/guzzle[7.7.0, 7.7.1] but it conflicts with your root composer.json require (^6.5).
    - Root composer.json requires drupal/core-recommended ^10 -> satisfiable by drupal/core-recommended[10.0.0-beta1, ..., 10.1.5].

```

How in the world do I get past this?

I just completed the upgrade of an almost identical site in which the commands above worked fine.

```
- Upgrading guzzlehttp/guzzle (6.5.8 => 7.7.1)

  - Upgrading guzzlehttp/promises (1.5.3 => 2.0.1)

  - Upgrading guzzlehttp/psr7 (1.9.1 => 2.5.1)

```

How do I get around these Catch-22s? In following the guidelines here, here appears to be no way to upgrade guzzle to the version I need to upgrade: https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-or-later/upgrading-a-composer-based-site

These are my composer.json requires:

```
"require": {
    "aws/aws-sdk-php": "^3.279",
    "ckeditor/liststyle": "4.8.0",
    "composer/installers": "^1.9",
    "cweagans/composer-patches": "^1.7",
    "drupal/admin_toolbar": "^3.0",
    "drupal/adva": "^1.0@RC",
    "drupal/advancedqueue": "^1.0@RC",
    "drupal/backup_migrate": "^5.0@RC",
    "drupal/better_exposed_filters": "^6.0",
    "drupal/book_blocks": "^1.6",
    "drupal/ckeditor5_font": "^1.1@beta",
    "drupal/ckeditor5_paste_filter": "^1.0@alpha",
    "drupal/ckeditor_config": "^3.0",
    "drupal/ckeditor_find": "^2.0@beta",
    "drupal/ckeditor_font": "^1.2",
    "drupal/ckeditor_indentblock": "1.x-dev@dev",
    "drupal/ckeditor_liststyle": "1.x-dev@dev",
    "drupal/colorbutton": "^1.2",
    "drupal/core-composer-scaffold": "^9",
    "drupal/core-project-message": "^9",
    "drupal/core-recommended": "^9",
    "drupal/custom_book_block": "^1.0@RC",
    "drupal/d8w3css": "^2.0",
    "drupal/devel": "^5.1",
    "drupal/devel_kint_extras": "^1.1",
    "drupal/devel_php": "^1.3",
    "drupal/disable_messages": "^2.1",
    "drupal/editor_advanced_link": "^2.2",
    "drupal/editor_file": "^1.5",
    "drupal/email_confirmer": "^1.0@beta",
    "drupal/entity": "^1.2",
    "drupal/entity_browser": "^2.5",
    "drupal/entity_print": "^2.11",
    "drupal/entity_reference_facet_link": "^2.0",
    "drupal/entity_reference_revisions": "^1.9",
    "drupal/eva": "^3.0",
    "drupal/extlink": "^1.6",
    "drupal/facets": "^3.0@beta",
    "drupal/field_permissions": "^1.1",
    "drupal/flag": "^4.0@beta",
    "drupal/flexible_permissions": "^1.1",
    "drupal/group": "^2.2",
    "drupal/highlight": "^1.0",
    "drupal/jquery_ui": "^1.6",
    "drupal/jquery_ui_accordion": "^2.0",
    "drupal/key_auth": "^2.1",
    "drupal/libraries": "^4.0",
    "drupal/mailsystem": "^4.3",
    "drupal/media_migration": "^1.0@alpha",
    "drupal/menu_link_attributes": "^1.2",
    "drupal/message": "^1.2",
    "drupal/message_notify": "^1.2",
    "drupal/message_subscribe": "^1.1",
    "drupal/migrate_conditions": "^2.0@beta",
    "drupal/migrate_devel": "^2.0@alpha",
    "drupal/migrate_plus": "^6.0",
    "drupal/migrate_tools": "^6.0",
    "drupal/migrate_upgrade": "^4.0",
    "drupal/mimemail": "^1.0@alpha",
    "drupal/nbsp": "^2.0@alpha",
    "drupal/override_node_options": "^2.6",
    "drupal/panelbutton": "^1.3",
    "drupal/paragraphs": "1.x-dev@dev",
    "drupal/paragraphs_access": "^2.0@RC",
    "drupal/paragraphs_collapsible": "^1.2",
    "drupal/paragraphs_jquery_ui_accordion": "^1.6",
    "drupal/pdf_api": "2.x-dev@dev",
    "drupal/phpmailer_smtp": "^2.0",
    "drupal/printable": "^3.0",
    "drupal/queue_ui": "^3.1",
    "drupal/quick_node_clone": "^1.14",
    "drupal/redirect": "^1.7",
    "drupal/restrict_ip": "^4.0@beta",
    "drupal/restui": "^1.21",
    "drupal/s3fs": "^3.1",
    "drupal/scheduled_publish": "^3.9",
    "drupal/scheduler": "^1.3",
    "drupal/search_api": "^1.19",
    "drupal/search_api_attachments": "^9.0",
    "drupal/search_api_location": "^1.0@alpha",
    "drupal/search_api_solr": "^4.1",
    "drupal/search_api_spellcheck": "^4.0",
    "drupal/simple_popup_blocks": "^3.1",
    "drupal/simplenews": "^3.0@alpha",
    "drupal/site_settings": "^1.19",
    "drupal/smtp": "^1.0",
    "drupal/token": "^1.9",
    "drupal/token_filter": "^2.0",
    "drupal/typed_data": "^1.0@alpha",
    "drupal/upgrade_rector": "^2.0@alpha",
    "drupal/upgrade_status": "^4.0",
    "drupal/user_permission_condition": "^1.1",
    "drupal/userprotect": "^1.1",
    "drupal/variationcache": "^1.0",
    "drupal/vefl": "^3.0",
    "drupal/views_accordion": "^2.0.1",
    "drupal/views_block_filter_block": "^2.0",
    "drupal/views_conditional": "^1.3",
    "drupal/views_data_export": "^1.3",
    "drush/drush": "^10",
    "giggsey/libphonenumber-for-php": "^8.13",
    "guzzlehttp/guzzle": "^6.5",
    "h4cc/wkhtmltopdf-amd64": "^0.12.4",
    "h4cc/wkhtmltopdf-i386": "^0.12.4",
    "mikehaertl/phpwkhtmltopdf": "^2.5",
    "phpmailer/phpmailer": "^6.5",
    "tecnickcom/tcpdf": "~6"
},
"conflict": {
    "drupal/drupal": "*"
},

```

**Update:**

I added guzzle to the composer command and removed vefl and highlight:

```
 Problem 1
    - Conclusion: don't install drupal/core-recommended 10.0.0-beta2 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.1.0-beta1 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.0-rc1 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.0-rc2 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.0-rc3 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.1.0-rc1 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.0 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.1 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.2 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.3 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.4 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.5 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.6 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.7 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.8 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.9 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.10 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.0.11 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.1.0 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.1.1 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.1.2 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.1.3 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.1.4 (conflict analysis result)
    - Conclusion: don't install drupal/core-recommended 10.1.5 (conflict analysis result)
    - drupal/core-dev[9.2.0-beta3, ..., 9.2.21] require fabpot/goutte ^3.3 -> satisfiable by fabpot/goutte[v3.3.0, v3.3.1].
    - symfony/browser-kit[v4.4.0-BETA1, ..., v4.4.8] require php ^7.1.3 -> your php version (8.1.14) does not satisfy that requirement.
    - fabpot/goutte v3.3.0 require php ^7.1.3 -> your php version (8.1.14) does not satisfy that requirement.
    - fabpot/goutte v3.3.1 requires guzzlehttp/guzzle ^6.0 -> found guzzlehttp/guzzle[6.0.0, ..., 6.5.8] but it conflicts with your root composer.json require (^7.5).
    - drupal/core-dev[9.0.0-beta1, ..., 9.0.14] require symfony/browser-kit ^4.4 -> satisfiable by symfony/browser-kit[v4.4.0-BETA1, ..., v4.4.44].
    - drupal/core-dev[9.3.0-beta2, ..., 9.5.11] require symfony/var-dumper ^5.4 -> satisfiable by symfony/var-dumper[v5.4.0-BETA1, ..., v5.4.29].
    - drupal/core-dev 9.3.0-beta1 requires symfony/var-dumper ^5.3.0 -> satisfiable by symfony/var-dumper[v5.3.0-BETA1, ..., v5.4.29].
    - drupal/core-dev[9.1.0-beta1, ..., 9.2.0-beta2] require symfony/var-dumper ^5.1.2 -> satisfiable by symfony/var-dumper[v5.1.2, ..., v5.4.29].
    - symfony/http-kernel[v6.1.0-BETA1, ..., v6.1.12] conflict with symfony/browser-kit v4.4.44.
    - symfony/http-kernel[v6.1.0-BETA1, ..., v6.1.12] conflict with symfony/browser-kit v4.4.25.
    - You can only install one version of a package, so only one of these can be installed: symfony/var-dumper[v3.4.0-BETA1, ..., v3.4.47, v4.0.0-BETA1, ..., v4.4.47, v5.0.0-BETA1, ..., v5.4.29, v6.0.0-BETA1, ..., v6.4.0-BETA2, v7.0.0-BETA1, v7.0.0-BETA2].
    - drupal/core-recommended 10.0.0-beta1 requires symfony/http-kernel ~v6.1.4 -> satisfiable by symfony/http-kernel[v6.1.4, ..., v6.1.12].
    - drupal/core-recommended 10.0.0-beta1 requires symfony/var-dumper ~v6.1.3 -> satisfiable by symfony/var-dumper[v6.1.3, ..., v6.1.11].
    - Root composer.json requires drupal/core-recommended ^10 -> satisfiable by drupal/core-recommended[10.0.0-beta1, ..., 10.1.5].
    - Root composer.json requires drupal/core-dev ^9 -> satisfiable by drupal/core-dev[9.0.0-beta1, ..., 9.5.11].

```

These two lines are confusing:

```
    - Root composer.json requires drupal/core-recommended ^10 -> satisfiable by drupal/core-recommended[10.0.0-beta1, ..., 10.1.5].
    - Root composer.json requires drupal/core-dev ^9 -> satisfiable by drupal/core-dev[9.0.0-beta1, ..., 9.5.11].

```

# Answer
> 1 votes
This is how I finally got the site to upgrade:

Removed these patched modules:

"drupal/highlight": "^1.0",

"drupal/vefl": "^3.0",

"drupal/vefl": { "Drupal 10 support": "https://www.drupal.org/files/issues/2023-03-17/vefl-drupal10-compatibility.patch" },

"drupal/highlight": { "Automated Drupal 10 compatibility fixes": "https://www.drupal.org/files/issues/2022-06-15/highlight.1.x-dev.rector.patch" }

Added DEV into the mix:

**composer require 'drupal/core-dev:^10' 'guzzlehttp/guzzle:^7.5' 'drupal/core-recommended:^10' 'drupal/core-composer-scaffold:^10' 'drupal/core-project-message:^10' --update-with-dependencies --no-update --dev**

**composer require 'drush/drush:^12' --no-update**

**composer update -W**

Those modules were patched using cweagans/composer-patches and had ^10 in their info.yml files. Anyway, made it to 10.1.5.

---
Tags: composer, upgrading, 10
---


# Question
Title: Can create directories but can't upload files
When I try to upload a file with a file field, Drupal creates a sites/default/files/2023-10 directory, but can't upload the file. I see this validation error in the UI: "File upload error. Could not move uploaded file." And I see a similar notice in the Drupal log: "Upload error. Could not move uploaded file test.txt to destination public://2023-10/test.txt."

In admin/config/media/file-system, my public file system path is set to sites/default/files. There are no errors on the status page indicating a permissions problem.

If I delete the files directory altogether, and then save the form at admin/config/media/file-system, Drupal creates sites/default/files and sites/default/files/php.

What are the possible reasons Drupal can create directories inside of sites/default/files, but can't upload files?

```
Drupal version: 9.5.11
Web server: IIS 10
PHP 8.1.21

```

# Answer
> 0 votes
I needed to set the upload\_tmp\_dir in PHP.ini. This is what worked for me:

upload\_tmp\_dir = c:\PHP\tmp

I also gave full permissions to the IUSR user for that directory.

---
Tags: files, 9, iis
---


# Question
Title: How do I get the last available hook_update_N() for a module?
I'm having trouble getting a custom module to install and update successfully. I'd like to examine the database for the modules update\_N numbers. Is that possible? If it is, where do I look for it?

# Answer
They're in key/value storage, which in the database would be the `key_value` table. Look for entries with a `collection` of *system.schema*, and a `name` matching the machine name of the module you're interested in.

Through the API, it's a bit easier:

```
$current_version = drupal_get_installed_schema_version('name_of_module');

```
> 8 votes

# Answer
There is another possibility as pointed in the documentation

You could use drush and run the following command:

```
drush php-eval "echo drupal_get_installed_schema_version('module_name');"

```

to find the last applied update hook for a specific module.
> 2 votes

# Answer
For Drupal 10 would be:

```
drush php-eval  "echo \Drupal::service('update.update_hook_registry')->getInstalledVersion('MODULE_NAME');"

```
> 2 votes

---
Tags: 8, updating
---


# Question
Title: User error: "funding_source" is an invalid render array key
This seems to be related to Commerce orders and the Symfony Mailer module. I intermittently see this error when a user attempts to complete the checkout process using Commerce PayPal:

> Blockquote User error: "funding\_source" is an invalid render array key in Drupal\Core\Render\Element::children() (line 98 of /var/www/site/web/core/lib/Drupal/Core/Render/Element.php) #0 /var/www/site/web/core/includes/bootstrap.inc(347): \_drupal\_error\_handler\_real() #1 \[internal function\]: \_drupal\_error\_handler() #2 /var/www/site/web/core/lib/Drupal/Core/Render/Element.php(98): trigger\_error() #3 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(404): Drupal\Core\Render\Element::children() #4 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(204): Drupal\Core\Render\Renderer-\>doRender() #5 /var/www/site/web/core/lib/Drupal/Core/Template/TwigExtension.php(479): Drupal\Core\Render\Renderer-\>render() #6 /var/www/site/web/sites/default/files/php/twig/6529302194f2f\_commerce-order.html.twig\_2p-K4ggEbyH1Y08LLASzZvkUF/lEl50\_59oVkz1bTgwQDbm4t-UDXyh-LQi70GrCZvt-Y.php(44): Drupal\Core\Template\TwigExtension-\>escapeFilter() #7 /var/www/site/vendor/twig/twig/src/Template.php(405): \__TwigTemplate\_a737a4a270bc020c6c35483b73b12bb8-\>doDisplay() #8 /var/www/site/vendor/twig/twig/src/Template.php(378): Twig\Template-\>displayWithErrorHandling() #9 /var/www/site/vendor/twig/twig/src/Template.php(390): Twig\Template-\>display() #10 /var/www/site/web/core/themes/engines/twig/twig.engine(55): Twig\Template-\>render() #11 /var/www/site/web/core/lib/Drupal/Core/Theme/ThemeManager.php(384): twig\_render\_template() #12 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(433): Drupal\Core\Theme\ThemeManager-\>render() #13 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(204): Drupal\Core\Render\Renderer-\>doRender() #14 /var/www/site/web/core/lib/Drupal/Core/Template/TwigExtension.php(479): Drupal\Core\Render\Renderer-\>render() #15 /var/www/site/web/sites/default/files/php/twig/6529302194f2f\___string\_template\__c0e1ea\_CN1J\_WKEj7CUghI835RNG-N3T/QGF5E63NnWsxeN7rwaH9gK3ZBMZdwdU\_71Pac\_bLOP8.php(52): Drupal\Core\Template\TwigExtension-\>escapeFilter() #16 /var/www/site/vendor/twig/twig/src/Template.php(405): \__TwigTemplate\_4798832cb62276a94273997f6ae59d7e-\>doDisplay() #17 /var/www/site/vendor/twig/twig/src/Template.php(378): Twig\Template-\>displayWithErrorHandling() #18 /var/www/site/vendor/twig/twig/src/Template.php(390): Twig\Template-\>display() #19 /var/www/site/vendor/twig/twig/src/TemplateWrapper.php(45): Twig\Template-\>render() #20 /var/www/site/web/core/lib/Drupal/Core/Template/TwigEnvironment.php(234): Twig\TemplateWrapper-\>render() #21 /var/www/site/web/modules/contrib/symfony\_mailer/src/Plugin/EmailAdjuster/BodyEmailAdjuster.php(75): Drupal\Core\Template\TwigEnvironment-\>renderInline() #22 \[internal function\]: Drupal\symfony\_mailer\Plugin\EmailAdjuster\BodyEmailAdjuster-\>preRenderVariables() #23 /var/www/site/web/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php(101): call\_user\_func\_array() #24 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(788): Drupal\Core\Render\Renderer-\>doTrustedCallback() #25 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(374): Drupal\Core\Render\Renderer-\>doCallback() #26 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(204): Drupal\Core\Render\Renderer-\>doRender() #27 /var/www/site/web/core/lib/Drupal/Core/Template/TwigExtension.php(479): Drupal\Core\Render\Renderer-\>render() #28 /var/www/site/web/sites/default/files/php/twig/6529302194f2f\_email.html.twig\_Be65fSN2NURPnSHvFrCJkJ-VJ/J8ORnB2UzlbntcueOpSzbuv92fcZzaqOq2p2BZO7rJo.php(42): Drupal\Core\Template\TwigExtension-\>escapeFilter() #29 /var/www/site/vendor/twig/twig/src/Template.php(405): \__TwigTemplate\_25218f115be83ddbfa265487c92c8563-\>doDisplay() #30 /var/www/site/vendor/twig/twig/src/Template.php(378): Twig\Template-\>displayWithErrorHandling() #31 /var/www/site/vendor/twig/twig/src/Template.php(390): Twig\Template-\>display() #32 /var/www/site/web/core/themes/engines/twig/twig.engine(55): Twig\Template-\>render() #33 /var/www/site/web/core/lib/Drupal/Core/Theme/ThemeManager.php(384): twig\_render\_template() #34 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(433): Drupal\Core\Theme\ThemeManager-\>render() #35 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(204): Drupal\Core\Render\Renderer-\>doRender() #36 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(160): Drupal\Core\Render\Renderer-\>render() #37 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(580): Drupal\Core\Render\Renderer-\>Drupal\Core\Render{closure}() #38 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(161): Drupal\Core\Render\Renderer-\>executeInRenderContext() #39 /var/www/site/web/modules/contrib/symfony\_mailer/src/Email.php(538): Drupal\Core\Render\Renderer-\>renderPlain() #40 /var/www/site/web/modules/contrib/symfony\_mailer/src/Mailer.php(233): Drupal\symfony\_mailer\Email-\>render() #41 /var/www/site/web/modules/contrib/symfony\_mailer/src/Mailer.php(149): Drupal\symfony\_mailer\Mailer-\>doSend() #42 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(580): Drupal\symfony\_mailer\Mailer-\>Drupal\symfony\_mailer{closure}() #43 /var/www/site/web/modules/contrib/symfony\_mailer/src/Mailer.php(158): Drupal\Core\Render\Renderer-\>executeInRenderContext() #44 /var/www/site/web/modules/contrib/symfony\_mailer/src/Email.php(292): Drupal\symfony\_mailer\Mailer-\>send() #45 /var/www/site/web/modules/contrib/symfony\_mailer/src/MailManagerReplacement.php(92): Drupal\symfony\_mailer\Email-\>send() #46 /var/www/site/web/modules/contrib/commerce/src/MailHandler.php(105): Drupal\symfony\_mailer\MailManagerReplacement-\>mail() #47 /var/www/site/web/modules/contrib/commerce/modules/order/src/Mail/OrderReceiptMail.php(76): Drupal\commerce\MailHandler-\>sendMail() #48 /var/www/site/web/modules/contrib/commerce/modules/order/src/EventSubscriber/OrderReceiptSubscriber.php(63): Drupal\commerce\_order\Mail\OrderReceiptMail-\>send() #49 \[internal function\]: Drupal\commerce\_order\EventSubscriber\OrderReceiptSubscriber-\>sendOrderReceipt() #50 /var/www/site/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(142): call\_user\_func() #51 /var/www/site/web/modules/contrib/state\_machine/src/Plugin/Field/FieldType/StateItem.php(422): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher-\>dispatch() #52 /var/www/site/web/modules/contrib/state\_machine/src/Plugin/Field/FieldType/StateItem.php(389): Drupal\state\_machine\Plugin\Field\FieldType\StateItem-\>dispatchTransitionEvent() #53 \[internal function\]: Drupal\state\_machine\Plugin\Field\FieldType\StateItem-\>postSave() #54 /var/www/site/web/core/lib/Drupal/Core/Field/FieldItemList.php(233): call\_user\_func\_array() #55 /var/www/site/web/core/lib/Drupal/Core/Field/FieldItemList.php(198): Drupal\Core\Field\FieldItemList-\>delegateMethod() #56 \[internal function\]: Drupal\Core\Field\FieldItemList-\>postSave() #57 /var/www/site/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(938): call\_user\_func\_array() #58 /var/www/site/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(970): Drupal\Core\Entity\ContentEntityStorageBase-\>invokeFieldMethod() #59 /var/www/site/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(896): Drupal\Core\Entity\ContentEntityStorageBase-\>invokeFieldPostSave() #60 /var/www/site/web/modules/contrib/commerce/src/CommerceContentEntityStorage.php(56): Drupal\Core\Entity\ContentEntityStorageBase-\>invokeHook() #61 /var/www/site/web/modules/contrib/commerce/modules/order/src/OrderStorage.php(81): Drupal\commerce\CommerceContentEntityStorage-\>invokeHook() #62 /var/www/site/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(598): Drupal\commerce\_order\OrderStorage-\>invokeHook() #63 /var/www/site/web/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(781): Drupal\Core\Entity\EntityStorageBase-\>doPostSave() #64 /var/www/site/web/core/lib/Drupal/Core/Entity/EntityStorageBase.php(523): Drupal\Core\Entity\ContentEntityStorageBase-\>doPostSave() #65 /var/www/site/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(804): Drupal\Core\Entity\EntityStorageBase-\>save() #66 /var/www/site/web/modules/contrib/commerce/modules/order/src/OrderStorage.php(159): Drupal\Core\Entity\Sql\SqlContentEntityStorage-\>save() #67 /var/www/site/web/core/lib/Drupal/Core/Entity/EntityBase.php(339): Drupal\commerce\_order\OrderStorage-\>save() #68 /var/www/site/web/modules/contrib/commerce/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowBase.php(220): Drupal\Core\Entity\EntityBase-\>save() #69 /var/www/site/web/modules/contrib/commerce/modules/payment/src/Plugin/Commerce/CheckoutPane/PaymentProcess.php(180): Drupal\commerce\_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowBase-\>redirectToStep() #70 /var/www/site/web/modules/contrib/commerce/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowWithPanesBase.php(546): Drupal\commerce\_payment\Plugin\Commerce\CheckoutPane\PaymentProcess-\>buildPaneForm() #71 \[internal function\]: Drupal\commerce\_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowWithPanesBase-\>buildForm() #72 /var/www/site/web/core/lib/Drupal/Core/Form/FormBuilder.php(536): call\_user\_func\_array() #73 /var/www/site/web/core/lib/Drupal/Core/Form/FormBuilder.php(283): Drupal\Core\Form\FormBuilder-\>retrieveForm() #74 /var/www/site/web/core/lib/Drupal/Core/Form/FormBuilder.php(224): Drupal\Core\Form\FormBuilder-\>buildForm() #75 /var/www/site/web/modules/contrib/commerce/modules/checkout/src/Controller/CheckoutController.php(143): Drupal\Core\Form\FormBuilder-\>getForm() #76 \[internal function\]: Drupal\commerce\_checkout\Controller\CheckoutController-\>formPage() #77 /var/www/site/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call\_user\_func\_array() #78 /var/www/site/web/core/lib/Drupal/Core/Render/Renderer.php(580): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() #79 /var/www/site/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer-\>executeInRenderContext() #80 /var/www/site/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>wrapControllerExecutionInRenderContext() #81 /var/www/site/vendor/symfony/http-kernel/HttpKernel.php(169): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() #82 /var/www/site/vendor/symfony/http-kernel/HttpKernel.php(81): Symfony\Component\HttpKernel\HttpKernel-\>handleRaw() #83 /var/www/site/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel-\>handle() #84 /var/www/site/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session-\>handle() #85 /var/www/site/web/core/modules/page\_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle-\>handle() #86 /var/www/site/web/core/modules/page\_cache/src/StackMiddleware/PageCache.php(85): Drupal\page\_cache\StackMiddleware\PageCache-\>pass() #87 /var/www/site/web/modules/contrib/cleantalk/src/EventSubscriber/BootSubscriber.php(193): Drupal\page\_cache\StackMiddleware\PageCache-\>handle() #88 /var/www/site/web/core/modules/ban/src/BanMiddleware.php(50): Drupal\cleantalk\EventSubscriber\BootSubscriber-\>handle() #89 /var/www/site/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\ban\BanMiddleware-\>handle() #90 /var/www/site/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware-\>handle() #91 /var/www/site/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware-\>handle() #92 /var/www/site/web/core/lib/Drupal/Core/DrupalKernel.php(718): Stack\StackedHttpKernel-\>handle() #93 /var/www/site/web/index.php(19): Drupal\Core\DrupalKernel-\>handle() #94 {main}

Is this an order email twig template issue, or something else?

# Answer
To create a valid render array, put the string the function returns in a markup render element:

```
$variables['order']['funding_source'] = ['#markup' => commerce_paypal_funding_source_label($data['funding_source'])];

```
> 0 votes

---
Tags: commerce
---


# Question
Title: Drupal unable to login and logout several accounts in a single functional test
I am trying to run some functional tests in DDEV that check functions of protected routes. I can log in the first couple of users fine, but after that drupaLogin() fails to generate a logged in session.

Example:

```
$this->drupalGet(Url::fromRoute('mymodule.secondary_login'));
$this->submitForm([
  'name' => 'good@mymodule.com',
  'pass' => 'test',
], 'Log in');

// Try to go to /user.
$this->drupalGet('/user');
$this->assertSession()->addressEquals('member');

// More navigation and assertion checks here

// Make the cookie stale and test the redirect.
$this->getSession()->setCookie('session', NULL);
$this->drupalGet('/');
$this->assertSession()->addressEquals('member/login');
$this->drupalGet(Url::fromRoute('mymodule.secondary_logout'));
$this->assertFalse($this->loggedInUser);

// User is anon and session should be clear at this point, but drupalLogin fails
$authenticated_user = $this->drupalCreateUser([], 'Authenticated User', FALSE);
$this->drupalLogin($authenticated_user);
$this->drupalGet('/member');
$this->drupalGet(Url::fromRoute('mos_ticketure.logout'));
$this->assertSession()->statusCodeEquals(403);

```

`Url::fromRoute('mymodule.secondary_login')` is a login form that handles setting a cookie and registering a new user with ExternalAuth. secondary\_logout handles destroying the user session (copied from Drupal core logout()) as well as cleaning up custom cookies.

By the time it gets down to log in the Authenticated User, drupalLogin fails an assert check with:

```
User <em class="placeholder">Authenticated User</em> successfully logged in.
Failed asserting that false is true.

```

If I move it to a brand new test method, this simple test works fine:

```
$this->drupalGet(Url::fromRoute('mymodule.login'));
$this->submitForm([
  'name' => 'good@mymodule.com',
  'pass' => 'test',
], 'Log in');
$this->drupalGet(Url::fromRoute('mymodule.logout'));

$authenticated_user = $this->drupalCreateUser([], 'Authenticated User', FALSE);
$this->drupalLogin($authenticated_user);
$this->drupalGet('/member');
$this->drupalGet(Url::fromRoute('mymodule.logout'));
$this->assertSession()->statusCodeEquals(403);

```

If I click through these scenarios manually, the custom functionality does indeed appear to do what it should. Is this some sort of weird behavior with PHPUnit Functional tests with Mink unable to properly track cookies and session data in larger tests?

# Answer
> 0 votes
I was able to narrow it down to this block of code in an EventSubscriber:

```
if ($this->currentUser->isAnonymous() && $this->requestStack->getCurrentRequest()->cookies->has('session')) {
  $options = $this->sessionConfiguration->getOptions($event->getRequest());
  $cookie_domain = $options['cookie_domain'];

  $response = new RedirectResponse('/member/login', 302);
  $response->headers->clearCookie('session', '/', $cookie_domain);
  $response->headers->clearCookie('session_expires', '/', $cookie_domain);
  $event->setResponse($response);
}

```

Under test, Mink does not seem to be entirely eradicating cookies even though I have a logout hook and request event that sets them (and does erase them) in that certain condition. However, for anonymous users without that cookie this keeps being triggered, so I think functional tests may have some issue with custom cookies or clearing them properly in this regard with the Mink driver. Even calling `->drupalLogout()` had no further effect.

I wound up having to do `$this->getSession()->reset();` then I could do this in tests that do various types of user logins (custom or core):

```
$this->getSession()->reset();
    $authenticated_user = $this->drupalCreateUser([], 'Authenticated User', FALSE);
    $this->drupalLogin($authenticated_user);

```

It does seem to be an issue with Mink, based on some findings:

https://github.com/ariya/phantomjs/issues/11768

there are similar reported issues in various libraries... the tests will only work in this regard with a reset. Unsure of where the deeper issue lies, actual usage works (real person, real browser).

Added it here for tracking: https://www.drupal.org/project/drupal/issues/3398145

---
Tags: testing, sessions, cookies, 10
---


title: Getting rid of orphan role permissions

text:
# Question
Title: Getting rid of orphan role permissions
In the course of trying to uprade from D9.5 to D10 I face the following annoying problem: When I uninstalled the guestbook modules some time ago under D8 or D9, it didn't remove its permissions. D10 won't accept this. The module cannot be re-installed either at my Drupal level. Neither can I use drush cex or the UI, because both crash. The directory and module for guestbook don't exist anymore.

Is there a way to get rid of the permissions within the MySQL database?

# Answer
> 1 votes
If you are using config sync, you can edit the yml files for your permissions (one file per role) and remove the offending permissions. Then perform a config import.

Edit: Just saw that you can't use drush cex, you are going to need that, so best to work that out before trying to move forward on this issue. If you are already on 10, you are going to have to roll back to 9, remove the permissions and then upgrade again. D10 will throw a fatal error for orphaned permissions so no way around that. I assume you made backups?

You can use a module like upgrade status to track your readiness level.

---
Tags: upgrading, 10
---


# Question
Title: How do I replace hook_field_widget_WIDGET_TYPE_form_alter() with hook_field_widget_complete_WIDGET_TYPE_form_alter()?
I've been using `hook_field_widget_WIDGET_TYPE_form_alter()` for years. And, of course, in Drupal 10, it has been deprecated.

I am trying to add a hook to the file attachments widget. I just want to add a text box to each file that is attached. Each time a file is added to the form, a new text box is added for that file. This is the code I am using.

```
function solrai_field_widget_file_generic_form_alter(&$element, FormStateInterface $form_state, $context) {
  // Do not add the text field if the file has not been uploaded.
  if (empty($element['#default_value']['fids'])) {
    return;
  }

  // Check if the field is either field_public_files or field_private_files.
  if (in_array($element['#field_name'], ['field_public_files', 'field_private_files'])) {
    // Add the source URL text field.
    $element['source_url'] = [
      '#type' => 'textfield',
      '#title' => t('Source URL'),
      '#size' => 90,
      '#weight' => 0.006,
    ];
  }
}

```

How do I duplicate this behavior using `hook_field_widget_complete_WIDGET_TYPE_form_alter()`?

I've been trying for hours to get this done with AI, and just can't get there. The closest I get is getting the text box added when the form first comes up, but when I add a file to the form, the box disappears. The expected behavior is for a new box for the new file to be added to the form. This the code I was working with.

```
function solrai_field_widget_complete_file_generic_form_alter(&$field_widget_complete_form, FormStateInterface $form_state, $context) {
  $logger = \Drupal::service('logger.factory')->get('solrai');
  if (isset($field_widget_complete_form['widget']) && is_array($field_widget_complete_form['widget'])) {
    foreach ($field_widget_complete_form['widget'] as $key => &$file_widget) {
      if (is_array($file_widget) && isset($file_widget['#type']) && $file_widget['#type'] === 'managed_file') {
        if (isset($file_widget['#default_value']['target_id']) && !empty($file_widget['#default_value']['target_id'])) {
          $file_widget['source_url'] = [
            '#type' => 'textfield',
            '#title' => t('Source URL'),
            '#size' => 90,
          ];
        }
      }
    }
  }
  else {
    $logger->warning("The 'widget' key is not set or not an array.");
  }
}

```

>

>

# Answer
`hook_field_widget_WIDGET_TYPE_form_alter()` is replaced by `hook_field_widget_single_element_WIDGET_TYPE_form_alter()`.

See the change record Streamline Field Widget Hooks.

It's not replaced by `hook_field_widget_complete_WIDGET_TYPE_form_alter()`. However, it's possible to use it to alter single items but then you need to walk through the form array of the entire widget. It's easier to use the direct replacement.
> 3 votes

# Answer
It took hours to figure out because the extent to which your code needs to change is not documented anywhere I could find. I had to painstakingly parse through the data and cobble together the solution through trial and error. I don't know if this is the best way, but this is the only way I could get it to work.

Here is another, more simple example of the original deprecated hook.

```
function sbn_field_widget_file_generic_form_alter(&$element, FormStateInterface $form_state, $context) {
  $node = $form_state->getFormObject()->getEntity();

  if (empty($element['#default_value']['fids'])) {
    return;
  }

  if ($element['#field_name'] === 'field_public_files') {
    $element['switch_to_private'] = [
      '#type' => 'checkbox',
      '#title' => t('Switch to private'),
      '#weight' => 0.007,
    ];
  }
  elseif ($element['#field_name'] === 'field_private_files') {
    $element['switch_to_public'] = [
      '#type' => 'checkbox',
      '#title' => t('Switch to public'),
      '#weight' => 0.007,
    ];
  }
}

```

This is what it took to replace the functionality.

```
function sbn_field_widget_complete_file_generic_form_alter(&$element, FormStateInterface $form_state, $context) {
  $logger = \Drupal::service('logger.factory')->get('sbn');

  if (isset($element['widget']) && is_array($element['widget'])) {
    foreach ($element['widget'] as $key => &$file_widget) {
      if (is_array($file_widget) && isset($file_widget['#type']) && $file_widget['#type'] === 'managed_file') {
        if (isset($file_widget['#default_value']['fids']) && !empty($file_widget['#default_value']['fids'])) {
          if ($file_widget['#field_name'] === 'field_public_files') {
            $file_widget['switch_to_private'] = [
              '#type' => 'checkbox',
              '#title' => t('Switch to private'),
              '#weight' => 0.007,
            ];
          }
          elseif ($file_widget['#field_name'] === 'field_private_files') {
            $file_widget['switch_to_public'] = [
              '#type' => 'checkbox',
              '#title' => t('Switch to public'),
              '#weight' => 0.007,
            ];
          }
        }
      }
    }
  }
  else {
    $logger->warning("The 'widget' key is not set or not an array.");
  }
}

```
> 0 votes

---
Tags: hooks, 10
---


# Question
Title: How to format a view to show content but without a teaser?
I want to format a View to show content but without a teaser.

I can choose `fields` instead `content` but then I don't get all the CSS sytling I get with `content`.

I can hide the teaser in the View page with CSS as follows but I don't think that's good SEOwise.

```
.node--view-mode-teaser .node__content {
    display: none;
}

```

How to format a view to show content but without a teaser?

## Update after Patrick's comment

# Answer
> 3 votes
I advise you to use `content` rather than `fields`.

In view `content`, you can choose a `view mode`. Choose the view mode that suits you (full, teaser) or you can create one for your needs. In this example, the view mode is called "accroche" :

Go to to your content type / manage display. In this view mode you put the fields that you want to display in your view :

This way, you keep your css and it’s easier to manage if you modify your templates.

---
Tags: views, 10
---


# Question
Title: How to make existing public files private?
Let's say I have a node type "Article" which has a field "File" which is set to handle public files. A lot of articles and files get added.

Now the specs suddenly change and the "Article" will move behind a login and therefore also the attached files must be changed to be not publicly accessible anymore.

I already found out how to change the file system for the file field from public to private pretty easily by reimporting the manually updated `field.storage.node.field_file.yml` config. But: this only affects new files that will be added after the switch. It doesn't work for existing files. They still are accessible publicly. Many thousand existing files would need to be manually reuploaded to also make them private.

Does anybody of you have solved that in D8 before? If so, then how?

As all I can think of right now is to programmatically query all "Article" nodes, then foreach through all nodes, get the files, temporarily store them somewhere else, empty the field out, then try to reupload the files programmatically (probably my next question) and then resave each node.

Does that sound reasonable? Or can you think of any other approach that might work here (in D8)?

# Answer
Thanks a lot for the answers! FileField Paths definitely is the way to go.

1. Update the file field's field storage to handle private files.
2. Run FileField Paths' **Retroactive update** on your content type's file field.

---

**Step 1.** can be accomplished from within `hook_update_N` (if you use configuration management do that locally and then export the updated configuration and deploy the resulting `*.yml`):

```
$field_type = 'file';
$field_name = 'field_file';

if (!$field_storage_configs = \Drupal::entityManager()
  ->getStorage('field_storage_config')
  ->loadByProperties(['type' => $field_type])) {
  return;
}

foreach ($field_storage_configs as $field_storage) {
  // Note: These settings apply to the field_file field everywhere it is
  // used.
  if ($field_storage->getName() == $field_name) {
    $field_storage->setSetting('uri_scheme', 'private');
    $field_storage->enforceIsNew(FALSE);
    $field_storage->save();
  }
}

```

Alternatively, follow the manual config update and reimport as suggested in the question.

---

**Step 2.** is to go to your file field's edit screen and fire the **Retroactive update** upon saving the form:
> 9 votes

# Answer
It's quite simple, I tested this myself and it works.

1) With PHPMyAdmin or some DB managing application, you'll need to look at `node__field_NAME` that has your files. Record all the field\_NAME\_target\_id numbers that belong to your content type.

2) Go to to `file_managed` table.

3) Export table as .sql file

4) Open .sql file with some text editing app. Rename all `public://` to `private://` for the ones that have the fid number that you recorded.

5) Import .sql and override table `file_managed`. OR you could clear the table and then import.

6) Move the files to the private folder.

* **Important:** make sure that it has the same parent folder structure. If it was previously under `/files/2018-06/some.jpg`, in private it needs to be `/private/2018-06/some.jpg`

+ Also, no need to move image style image files, these will get auto created. Thus, you only need to grab the original.

7) Flush all caches.

---

I'm sure you could use SQL query to do 1 to 5. Basically all you gotta do is update the specific values of the `uri` column in the `field_managed` table.
> 4 votes

# Answer
I did this for Drupal 7, but haven't tried it in Drupal 8.

I believe that it should work similarly since there is already a D8 release for the required module: FileField Paths. I first installed and enabled the module before following the steps below:

> just in case someone is looking to do this, here are the steps:
>
> 1. backup your site and db
> 2. copy the table for your field to make a backup (in my case i copied: field\_data\_field\_attachments to field\_data\_field\_attachments\_bk)
> 3. empty table field\_data\_field\_attachments
> 4. go to drupal and the option to change the file system should be available, so change it
> 5. copy all data from field\_data\_field\_attachments\_bk back to field\_data\_field\_attachments
> 6. go to drupal, select your content type, select your file field, in file path settings select retroactive update
> 7. click save and it will move all your files to the right place in file system and update your db to the new path
>
> A Romka

Full thread
> 3 votes

# Answer
With my Drupal 8.6.3 the retro-active update doesn't work.

You still need to achieve step 1, to update the field storage of your field.

Then you need to update all existing files via the database with:

```
UPDATE file_managed SET uri = REPLACE(
    uri,
    'public://',
    'private://'
)
WHERE filemime like 'application%';

```

In my case I'm updating only the files, that's why I'm using this where clause.

Don't forget to clear the cache after this SQL query.
> 2 votes

# Answer
I was able to resolve this without using contrib. @leymannx's answer using FileField Paths is great, but I didn't want to install a contrib module for a one-time script. If you're familiar with batch processing items in hook\_post\_update\_NAME(), it's a piece of cake.

**Step 1:** Update your field to use private files. (See step 1 of @leymannx's answer)

**Step 2:** Make sure the new private files directory (or directories) exists (the subdirectory where you want to move your files)

Here's my example:

```
/**
 * Make sure the private files directory exists.
 */
function mymodule_update_9001(&$sandbox) {
  $directory = 'private://MY-SUBDIRECTORY';

  /** @var \Drupal\Core\File\FileSystemInterface $file_system */
  $file_system = \Drupal::service('file_system');

  $success = $file_system
    ->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY);

  if (!$success) {
    throw new UpdateException('The required directory does not exist (or exists and is not writable) or could not be created.');
  }
}

```

**Step 3:** Move existing files to the new directory.

The code to do this is straightforward for a single file:

```
use Drupal\file\FileInterface;

// Move file to the private files directory.
$file = loadMyFileEntitySomehow();
if ($file instanceof FileInterface) {
  // Note: $destination must be the full file uri, including file name.
  // Additionally, the directory must exist and be writable.
  $destination = 'private://MY-SUBDIRECTORY/' . $file->getFilename();
  \Drupal::service('file.repository')
    ->move($file, $destination);
}

```

Example post\_update to update all files in a specific field on a specific node type:

```
use Drupal\file\FileInterface;

/**
 * Move files to the private files directory.
 */
function mymodule_post_update_make_files_private(&$sandbox) {
  $batch_size = 25;
  $entity_type = 'node';
  $bundle = 'MY_BUNDLE';

  if (!isset($sandbox['num_processed'])) {
    $sandbox['num_processed'] = 0;
  }

  if (empty($sandbox['entity_ids'])) {
    $sandbox['entity_ids'] = \Drupal::entityTypeManager()
      ->getStorage($entity_type)
      ->getQuery()
      ->condition('type', $bundle)
      ->exists('field_MY_FILE_FIELD')
      ->execute();

    if (is_array($sandbox['entity_ids'])) {
      $sandbox['total'] = count($sandbox['entity_ids']);
    }
  }

  if (!empty($sandbox['entity_ids'])) {
    $current_batch_ids = array_slice($sandbox['entity_ids'], $sandbox['num_processed'], $batch_size);
    $current_batch_entities = \Drupal::entityTypeManager()
      ->getStorage($entity_type)
      ->loadMultiple($current_batch_ids);

    foreach ($current_batch_entities as $entity) {
      // Move files to the private files directory.
      $files = $entity->field_MY_FILE_FIELD->referencedEntities();
      foreach ($files as $file) {
        if ($file instanceof FileInterface) {
          \Drupal::service('file.repository')
            ->move($file, 'private://MY-SUBDIRECTORY/' . $file->getFilename());
        }
      }

      $sandbox['num_processed']++;
    }
  }

  if (!empty($sandbox['total'])) {
    $sandbox['#finished'] = $sandbox['num_processed'] / $sandbox['total'];
  }
  else {
    $sandbox['#finished'] = 1;
  }

}

```
> 2 votes

# Answer
Thank you everybody. I combined the previous answers into two update hooks that you can mostly copy and paste. Only use this if you want to move ALL files that are currently public into private.

The only change you need to make is to the function/hook implementation names, and to the `$field_names` array in the first hook.

The first hook will cause config changes if you have not already set your fields to use the private directory. I would recommend making that change and exporting config locally, but including this update hook as well so that when deploying to another environment the fields are set to use the private directory before the second hook is run, which will be *before* config is imported (if your deploy script is in the correct order).

```
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Utility\UpdateException;
use Drupal\file\FileInterface;

/**
 * Set file fields to use private files directory.
 */
function my_module_update_9007(&$sandbox) {
  $field_types = [
    'file',
    'image',
  ];
  $field_names = [
    'field_document',
    'field_media_image',
  ];

  foreach ($field_types as $field_type) {
    if (!$field_storage_configs = \Drupal::entityTypeManager()
      ->getStorage('field_storage_config')
      ->loadByProperties(['type' => $field_type])) {
      continue;
    }

    foreach ($field_storage_configs as $field_storage) {
      if (in_array($field_storage->getName(), $field_names)) {
        $field_storage->setSetting('uri_scheme', 'private');
        $field_storage->enforceIsNew(FALSE);
        $field_storage->save();
      }
    }
  }
}

/**
 * Move files from public directory to private.
 */
function my_module_update_9008(&$sandbox) {
  $batch_size = 25;

  if (!isset($sandbox['num_processed'])) {
    $sandbox['num_processed'] = 0;
  }

  if (empty($sandbox['entity_ids'])) {
    // Get an array of all file ids.
    $sandbox['entity_ids'] = \Drupal::entityQuery('file')
      ->execute();

    if (is_array($sandbox['entity_ids'])) {
      $sandbox['total'] = count($sandbox['entity_ids']);
    }
  }

  if (!empty($sandbox['entity_ids'])) {
    $current_batch_ids = array_slice($sandbox['entity_ids'], $sandbox['num_processed'], $batch_size);
    $current_batch_entities = \Drupal::entityTypeManager()
      ->getStorage('file')
      ->loadMultiple($current_batch_ids);

    foreach ($current_batch_entities as $file) {
      if ($file instanceof FileInterface) {
        $uri = $file->get('uri')->getValue()[0]['value'];
        // Only proceed if file is in public directory.
        if (str_contains($uri, 'public://')) {
          // Check that file actually exists.
          // If it doesn't there's nothing we can do.
          if (file_exists($uri)) {
            // Get the current subdirectory and recreate
            // it within the private files directory.
            $uri = str_replace('public://', '', $uri);
            $subdirectory = str_replace('/' . $file->get('filename')->getValue()[0]['value'], '', $uri);
            $subdirectory_path = 'private://' . $subdirectory;
            /** @var \Drupal\Core\File\FileSystemInterface $file_system */
            $file_system = \Drupal::service('file_system');
            $success = $file_system
              ->prepareDirectory($subdirectory_path, FileSystemInterface::CREATE_DIRECTORY);

            if (!$success) {
              throw new UpdateException('The required directory does not exist (or exists and is not writable) or could not be created.');
            }
            else {
              // Move file from public to private.
              // Note: $destination must be the full file uri,
              // including file name.
              // Additionally, the directory must exist and be writable.
              $destination = $subdirectory_path . '/' . $file->getFilename();
              \Drupal::service('file.repository')
                ->move($file, $destination);
            }
          }
        }
      }

      $sandbox['num_processed']++;
    }
  }

  if (!empty($sandbox['total'])) {
    $sandbox['#finished'] = $sandbox['num_processed'] / $sandbox['total'];
  }
  else {
    $sandbox['#finished'] = 1;
  }
}

```
> 0 votes

---
Tags: 8, files
---


# Question
Title: Updating Drupal 9.5 to Drupal 10 fails with php errors: what should php include path be?
I am attempting to update a Drupal 9.5 site to Drupal 10. Upgrade status says 100% ready PHP is 8.1.25 Webserver is nginx 1.18 MYSQL is 8.0.35-0ubuntu0.22.04.1 - (Ubuntu)

Following instructions here: https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-or-later/upgrading-a-composer-based-site

The composer update step completes, then php errors.

Details. Composer gets this far...

```
68/68 [============================] 100%
In FilesystemRepository.php line 163:

  file_get_contents(/srv/sid2/vendor/composer/composer/src/Composer/Repository/../InstalledVersions.php): Failed to open stream: No such file or
   directory

```

After that, any Composer or Drush command I try to execute does this...(srv/sid2/web is the document root for the site)

```
PHP Warning:

    require(/srv/sid2/vendor/composer/../guzzlehttp/promises/src/functions_include.php): Failed to open stream: No such file or directory in /srv/sid2/vendor/composer/autoload_real.php on line 82
    PHP Fatal error:  Uncaught Error: Failed opening required '/srv/sid2/vendor/composer/../guzzlehttp/promises/src/functions_include.php' (include_path='/srv/sid2/vendor/pear/archive_tar:/srv/sid2/vendor/pear/console_getopt:/srv/sid2/vendor/pear/pear-core-minimal/src:/srv/sid2/vendor/pear/pear_exception:.:/usr/share/php') in /srv/sid2/vendor/composer/autoload_real.php:82
    Stack trace:
    #0 /srv/sid2/vendor/composer/autoload_real.php(65): composerRequireadb589663ee65f2462c8612df87cae83()
    #1 /srv/sid2/vendor/autoload.php(7): ComposerAutoloaderInitadb589663ee65f2462c8612df87cae83::getLoader()
    #2 /srv/sid2/vendor/drush/drush/drush.php(58): include_once('...')
    #3 /srv/sid2/vendor/drush/drush/drush(4): require('...')
    #4 /srv/sid2/vendor/bin/drush(120): include('...')
    #5 {main}
      thrown in /srv/sid2/vendor/composer/autoload_real.php on line 82

```

The site does not load of course.

What has me thinking I have a php include\_path problem is this part: `(include_path='/srv/sid2/vendor/pear/archive_tar:/srv/sid2/vendor/pear/console_getopt:/srv/sid2/vendor/pear/pear-core-minimal/src:/srv/sid2/vendor/pear/pear_exception:.:/usr/share/php')`

But I don't understand php and/or Composer well enough to know what's gone wrong here or what the include\_path needs to be to allow PHP to find all the stuff it's looking for.

But maybe I'm on the wrong track?

The first error, failing to find InstalledVersions.php: The file exists, but it's in /vendor/composer/composer/src/Composer not /vendor/composer/composer/src/Composer/Repository/../ (By the way, what does "/../" mean?)

**Composer info:**

`which composer`, outside any Drupal projects, returns: `/usr/local/bin/composer`

`which composer` inside one of my other projects (not yet upgraded) returns `./vendor/bin/composer`

`composer why composer/composer` inside other projects returns `drupal/core-dev 9.5.0 requires composer/composer (^2.2.12)`

Inside a working project, `composer -V` indicates version 2.2.22. Globally, I get 2.5.4

Inside the failed upgrade project, all composer commands (so far) result in the errors already noted above.

# Answer
> 1 votes
This is a composer issue. Normally composer is installed globally

```
which composer

```

should return /usr/local/bin/composer. This is a global path for Drupal even if Linux considers it as local. If it doesn't return a path outside of the Drupal project then follow the install instructions https://getcomposer.org/download/

If you have a composer dependency locally

```
composer why composer/composer

```

then composer is part of your project, probably because of the dev package. If you don't need it remove the dev package. Otherwise, update the local composer in an extra step before updating Drupal:

```
composer update composer/composer

```

Also, when running into composer problems first try to update the global composer:

```
composer self-update

```

---
Tags: composer, 10
---


# Question
Title: Can't edit settings.php in Drupal 7 - Premission Denied - Can't Write to File via Cpanel File Manager
Trying to edit settings.php via Cpanel File Manager

I can CHMOD the file to anything I want and back but can't write to it.

I get the following message:

> Could not write /home/testing/public\_html/sites/default/settings.php: Permission denied

Do you think Apache suEXEC has anything to do with this?

# Answer
As others have mentioned, you must set the permissions on the `/sites/default` folder. The default permissions are set to `0555`, set them to `0755` for editing. Don't forget to restore the default values afterwards!
> 13 votes

# Answer
I will recommend to download the file on your local system if you can. Right click on the **settings.php** file and select **Properties** from the list. Uncheck the **Read-only** from **Attributes**. Click apply button and click OK. Make changes and upload the file back to the server.

NOTE: After editing the file Check the **Read-only** attribute before uploading.
> 2 votes

# Answer
You can edit the **permissions** of the folder it self. The folder "**default**" set to 0555, set them to 0755 for editing. Don't forget to restore the default values afterwards!
> 0 votes

# Answer
To prevent this issue in the future, add the following line to your `settings.php` file:

```
$settings['skip_permissions_hardening'] = TRUE;

```

This will prevent Drupal from re-enabling the read-only status of the `/sites/default` directory and the `settings.php` within. Drupal will no longer configure the permissions itself.
> 0 votes

---
Tags: files, configuration
---


title: I don't see Bartik as theme to enable

text:
# Question
Title: I don't see Bartik as theme to enable
I have reached a "screeching halt" trying to upgrade D9.5 to D10. So, I thought it might be better to "simply" start afresh with "vanilla" D10 and migrate stuff manually. Now I have a problem: Under D8/9 I have been using a subtheme of Bartik with an involved coloring scheme. I see that Bartik is still availabe as a contributed project. But - can it be used by simply installing it under a "vanilla" D10, without first installing it under D9 and then upgrading to D10. I downloaded Bartik in D10 using composer require drupal/bartik:^1.0. But, going to "Design" under D10, I don't now see Bartik as a choice to activate. Any help? Thanks in advance

# Answer
> 0 votes
I had to install both Bartik **and** Classy using composer and to add `dependency: classy` in my composer.json.

# Answer
> -1 votes
The Bartik theme is available here : https://www.drupal.org/project/bartik

---
Tags: 10
---


# Question
Title: Create a new Menu in Drupal 8 programmatically
Is it possible to create a new Menu in Drupal 8 programmatically using a custom module?

I am creating a custom module, and one of the requirements of the module is that it creates a new menu under `Structure > Menus`.

Most of the tutorials teach how to add a menu link to an existing menu. For example, Creating menu links, Add a menu link, etc.

In short, I need a way so that the end result is a menu below `"User Account Menu"` in the image, and then I can add my menu links to it, using above tutorials.

Thanks.

# Answer
> 8 votes
Menus are configuration; you can include one in your module by adding a file named `<module_root>/config/install/system.menu.foo.yml` to your codebase (replacing `foo` with the desired menu ID).

The contents of the file will be something similar to one of the same configs installed by the core system module, e.g.

```
langcode: en
status: true
dependencies: {  }
id: foo
label: 'Foo menu'
description: 'Links related to foo'
locked: true

```

When the module is (re)installed, the menu will be created.

You could also technically use the API in a `hook_install` or similar:

```
$menu = \Drupal::entityTypeManager()->getStorage('menu')
  ->create([
    'langcode' => 'en',
    'status' => TRUE,
    ...
  ]);

```

but the yml method is a bit cleaner, and I think recommended (can't find a source right now though).

As an aside, the menus are listed in alphabetical order. I don't think it would be straightforward to change that, menus have no concept of weight in relation to one another so you'd have to wedge that in somehow if you really need your menu at the bottom of the list.

# Answer
> 0 votes
Instead of re-installing the module you can import the newly created configuration via drush command.

```
drush config:import --source="modules/custom/[MODULE_NAME]/config/install/" --partial

```

---
Tags: 8, entities, navigation
---


title: Respond to "dialog:afterclose" once

text:
# Question
Title: Respond to "dialog:afterclose" once
I'm trying to figure out how to respond to `dialog:afterclose` only once, and I'm not having any luck getting the syntax right (and I'm having trouble finding resources because most search results refer to jquery.once, which has been removed). Here's my best guess:

```
(function ($, Drupal) {
  Drupal.behaviors.MyCustomModule = {
    attach(context) {
      const $window = $(once('MyCustomModule', window, context));
      $window.on('dialog:afterclose', (e) => {
        console.log('closed');
      });
    }
  }
})(jQuery, Drupal);

```

That never fires. If I change `$window` to `$(window)` it fires, but eight times. Can anyone point me in the right direction? Thanks in advance.

# Answer
> 0 votes
Drupal behaviors are triggered once after `DOMContentLoaded` with `document` context, but AFAIK never in the `window` context. Also, in a global use-case like this, you do not want to limit your once-function with a `context`, because if your behavior is loaded later and not with the initial load, the `document` will never again be part of the `context` again and therefore will never match again.

So the solution should be simply changing your once element from window to document, without context:

```
(function ($, Drupal) {
  Drupal.behaviors.MyCustomModule = {
    attach(context) {
      const elements = once('MyCustomModule', document);
      elements.forEach( () => {
        $(window).doSomething();
      });
    }
  }
})(jQuery, Drupal);

```

---
Tags: javascript
---


# Question
Title: How can I render only a region in a controller?
I'm looking to have a page on /templates/header which only renders what there is in the *header* region of the theme. I am using the following code for a custom controller.

```
namespace Drupal\wco_drupal_module\Controller;

use Drupal\Core\Controller\ControllerBase;

/**
 * Templates controller.
**/
class TemplatesController extends ControllerBase {

  public function header() {
    return [
      '#theme' => 'wco_templates_header',
    ];
  }

}

```

In the *wco\_drupal\_module.module* file, I am using the following code.

```
function wco_drupal_module_theme($existing, $type, $theme, $path) {
  return [
    'wco_templates_header' => [
      'render element' => 'requirements',
      'template' => 'region--header',
      'path' => $theme . '/templates/layout',
    ],
  ];
}

```

The *region-header.html.twig* template file contains the following code.

```
<h1>tasty test</h1>
{% if content %}
  <div class='flex-column region-headerW' >
    <div class='region region-header maxwidth' >
      {{ content }}
    </div>
  </div>
{% endif %}

```

This renders *something*, but there are two problems:

* The content is missing, so I only see *tasty test*.
* This is all rendered inside the generic layout; rather than just showing the header, I'm showing a whole page with header, footer, and all the regions.

I want to avoid that, and only display a single region (*header*) on a path. How can I achieve that?

# Answer
Display a single region, header, on a path:

1. create path : for this either can add node page with specific path or add custom controller
2. View the path let say /header
3. Then override the page template with specific path as displayed in the inspect provided by theme suggestion for eg override file name: page--testing--abc.html.twig Reference link for enable theme suggestion
4. Then open the override file in editor & keep the required region: like in my scenario: {{ page.header }}

Note: Make sure in the backend if you added additional block in the same region(header) then that 'll start appearing so hide other blocks for this particular page or either add new region and add that region in override template , add header block of site from backend in newly added region
> 2 votes

---
Tags: theming
---


# Question
Title: How can I render a Paragraph field in the views unformatted template?
I'm simply trying to render a Paragraph field from my content type in a view template. It's insanely difficult! I have the field setup to display the rendered entity, but how do I set it up in my template? Below 'field\_question' works fine but 'field\_faq\_answer', which is the Paragraph field, doesn't render anything.

```
{% for row in rows %}
  {% set question = row.content['#row']._entity.field_question.value %}
  {% set answer = row.content['#row']._entity.field_faq_answer %}

  {% include 'component--accordion-item.html.twig' with {
    'title': question,
    'uid': random(),
    'content': answer
  }
%}
{% endfor %}

```

# Answer
To render an entity field use the View filter of the module Twig Tweak:

```
{{ row.content['#row']._entity.field_faq_answer|view }}

```
> 0 votes

---
Tags: views, paragraphs
---


# Question
Title: Upgrade to Drupal 10.1.6, Theme Doesn't Load Outside Maintenance Mode
I'm working to upgrade a site from 9.5.11 to 10.1.6. I followed the instructions provided here:

https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-or-later/upgrading-a-composer-based-site

The upgrade went fine using composer, but when I visit the site after the upgrade I noticed that the site's theme isn't being loaded. The site is displayed as a long series of menus with content at the bottom of my browser window. I flushed all caches, still no luck. On a whim, I put the site back into maintenance mode, and suddenly everything looks fine again. The problem reappears if I bring the site out of maintenance mode.

I have full access to all menus while viewing the theme-less site, and I've tried switching themes, including trying to use the default Olivero theme, to see if that made a difference. It doesn't. Did I miss something with the upgrade? Can anyone help identify the problem?

# Answer
Drupal 10.1.x introduced CSS and JavaScript aggregation performance improvements in that there is change to `.htaccess` file as well.

Sites using nginx/php-fpm may need to update their nginx.conf file to pass through the css/js path to Drupal.

Before

```
# Passes style generation to PHP.
location ~ ^/sites/.*/files/styles/ {
  try_files $uri @rewrite;
}

```

After

```
# Passes image style and asset generation to PHP.
location ~ ^/sites/.*/files/(css|js|styles)/ {
  try_files $uri @rewrite;
}

```

Refer Change Record for more details.
> 5 votes

---
Tags: theming, upgrading
---


# Question
Title: Why is my message not showing for anonymous user?
In a custom form, I have this Ajax submit:

```
  public function ajaxSubmit(array &$form, FormStateInterface $form_state) {

    $response = new AjaxResponse();
    if ($form_state->hasAnyErrors()) {
      $messages = Drupal::messenger()->deleteAll();
      $messages = [
        '#theme' => 'status_messages',
        '#message_list' => $messages,
      ];
      $response->addCommand(new ReplaceCommand('#messages', ''));
      $response->addCommand(new AppendCommand('.region-highlighted', $messages));
    }
    else {

      some code...

      // Completion message -----------------------------------------------------
      if ($this->currentUser()->isAnonymous()) {
        $str = $this->t('membership request');
        $sMessage = $this->t('Your @str has been registered.<BR>It will be effective after reception of your payment.', ['@str' => $str]);
        Drupal::messenger()->addMessage($sMessage);
        $sMessage = $this->t('A confimation email has been sent.');
        Drupal::messenger()->addMessage($sMessage);
      }
      else {
        switch ($form_state->getStorage()['status']) {
          case 1:
            $sMessage = $this->t('Your wish has been recorded.');
            break;
          case 3:
            $str = $this->t('membership renewal request');
            $sMessage = $this->t('Your @str has been registered.<BR>It will be effective after reception of your payment.', ['@str' => $str]);
            break;
          default:
            $sMessage = $this->t('Renew membership: Unexpected case.');
        }
        Drupal::messenger()->addMessage($sMessage);
      }

      $response->addCommand(new \Drupal\Core\Ajax\RedirectCommand(Url::fromRoute('<front>')
        ->toString()));
    }
    return $response;
  }

}

```

When the code is executed by a logged in user, it works fine: user is redirected to front page and the message (for example 'Your wish has been recorded.') is displayed.
When the user is anonymous, redirection works but no message!
What is wrong with my code?

Update: Adding `$form['#attached']['library'][] = 'core/drupal.ajax';` at the beginning of `buildForm()` didn't work. So I tried to add it at the end of `buildForm()` and I realized that I already have `$form['#attached']['library'][] = 'association/membership';` for some javascript.
So I updated my library to:

```
LoM:
  version: 1.x
  header: true
  css:
    theme:
      css/ahover.css: {}
      css/datatable.css: {}
  js:
    js/LoM.js: {}
  dependencies:
    - core/jquery
    - shared/shared

LoP:
  version: 1.x
  header: true
  css:
    theme:
      css/ahover.css: {}
      css/datatable.css: {}
  js:
    js/LoP.js: {}
  dependencies:
    - core/jquery
    - shared/shared

membership:
  version: 1.x
  js:
    js/membership.js: {}
  dependencies:
    - core/drupal.ajax

```

But it still doesn't work! Any idea what I am doing wrong?

# Answer
> 0 votes
It was `drupal_flush_all_caches()` that was the reason of message not showing. Once removed, everything works as expected.

---
Tags: forms, ajax, 9, status-messages
---


# Question
Title: Expose View of Visitors information via JSON:API
I've enabled the JSON:API Views module to expose View data via the JSON:API. I've created a page view of Visitors data. Preview data suggests that there is data available. The view is set to be exposed via JSON:API. However, navigating to the jsonapi path (/jsonapi/views/visitors/page\_1) consistently results in a 404 "Page Not Found" error.

Other views of different data types are exposed via the JSON:API just fine.

Why would Visitors info not be accessible via the JSON:API?

# Answer
> 0 votes
Follow these steps to expose visitor data by json API:

Create view of "vistior" **entity type** of **rest export**

Then add required path/url like: jsonapi/views/visitors in path setting

Select **"json"** format by click on setting link \> that next to serializer format

you can select field or entity as per requirement

In the access you can select any option as per requirement or can keep unrestricted as well (testing purpose)

Save the view & try to hit the view page, result 'll start appear

**Note:There is no need to configure any additional permission.**

**if you try to check in this file here is routes() function Try to get **entity\_type** value it is empty due to which code return & getting 404 page not found error. so JSON:API Views" module not support/extend to "visitor" module functionality**

**There are some approaches that you can follow:**

* either extend "json api view" module functionality so that it supports vistor entity it requires custom workaround
* create custom json api which is also custom workaround
* Create REST export view as mentioned in answer

---
Tags: views
---


title: Drush unable to find settings.php

text:
# Question
Title: Drush unable to find settings.php
I have a unique problem, for which I am unable to find the reason and thus not an inch closer to solution since 4 days.

Drush is taking a separate settings.php file instead of the correct one.

**Check only the settings files link found on the link marked \[2\] in both the settings.**

So in dev environment, drush takes the following config:

```
[vagrant@frontier www]$ php ../bin/drush.php core-config
Enter a number to choose which file to edit.
 [0]  :  Cancel
         -- PHP ini files --
 [1]  :  /etc/php.ini
         -- Drupal --
 [2]  :  /var/www/sites/$DRUPAL_ROOT/cnf/settings.php
 [3]  :  /var/www/sites/$DRUPAL_ROOT/www/.htaccess

```

But on the deployment server, drush takes up the following config:

```
/var/www/frontier/www
devtools(pabetadfsp01p):php ../bin/drush.php core-config
Enter a number to choose which file to edit.
 [0]  :  Cancel
         -- PHP ini files --
 [1]  :  /etc/php.ini
         -- Drupal --
 [2]  :  /var/www/$DRUPAL_ROOT/www/sites/www/settings.php
 [3]  :  /var/www/$DRUPAL_ROOT/www/.htaccess

```

Now, I create a symlink at `$DRUPAL_ROOT/www/sites/default/settings.php` which refers to `$DRUPAL_ROOT/cnf/settings.php`. So drupal picks up the correct settings while drush doesn't.

I really don't have any idea as to what could cause this mis-configuration. Please let me know any remedy.

Also I don't create a `www` folder in the sites folder at `$DRUPAL_ROOT/www/sites/` which is displayed on drush settings on deployment server.

# Answer
First off, you should not call drush.php directly; use the `drush` script instead.

Regarding site selection, Drupal looks up the site to use based on the domain name in the http request, which is passed in via the HTTP headers. When you are using Drush, there is no web browser involved, so Drush needs to generate equivalent HTTP headers and select the appropriate site based on information that is provided either explicitly (via commandline options) or implicitly (via the current working directory).

If your cwd is inside your Drupal root, then Drush will, by default, look for the settings.php file inside the 'default' folder. You can change this default by setting your cwd to the folder that contains the settings.php file that you want, or by passing in `--uri=mydrupalsite.com` as a commandline option (or `-l mydrupalsite.com`). You might also want to read up on Drupal site aliases, which are an even more convenient way to tell Drush which Drupal site you'd like to use with your command.
> 1 votes

# Answer
This error means that Drupal couldn't find the database connection so make sure it's not overridden by another setting file like 'settings.local.php' and then ensure that the database connection is set correctly.
> 0 votes

---
Tags: drush, deployment
---


title: Check if empty region failed

text:
# Question
Title: Check if empty region failed
I try to check if my sidebar second if empty. If it is not empty, I add a class `col-md-8` on my `section-main`. To check if the sidebar is empty I use this code in the page.html.twig template of my custon theme:

```
{% if page.sidebar_second and page.sidebar_second is not empty and
page.sidebar_second|render|striptags|trim is not empty %}

```

My problem is that sometimes the sidebar second if considered as empty but it is not. In the sidebar second, I have a views block that the content depends on the current node taxonomy or book id. The query to get the content of this views block if altered in `my_custom_module_views_query_alter(ViewExecutable $view, QueryPluginBase $query)` function. When I checked for sidebar\_second in page.html.twig, the content of this block is always empty, but if I have another block in sidebar\_second (so the column is displayed), this block has actually some content and is displayed.

So to check if my sidebar is really empty or not, I tried to check that in the `my_custom_theme_preprocess_page()` function in my\_custom\_theme.theme, like this :

```
  $rendered_sidebar_second = \Drupal::service('renderer')->renderRoot($variables['page']['sidebar_second']);
  $with_sidebar_second = !empty(trim(strip_tags($rendered_sidebar_second)));
  $variables['with_sidebar_second'] = $with_sidebar_second;

```

Then , in my page.html.twig, I check the variable `with_sidebar_second` to know if sidebar\_second is empty o not. This gives the right results, but induces a problem for assets : *PHP Exception LogicException: 'A stray renderRoot() invocation is causing bubbling of attached assets to break.*. Using `renderPlain()` gives the same result. Using `render($variables['page']['sidebar_second'], false)` does not give the good result.

Is there a solution to have the good result for the sidebar\_second and have all assets too ?

# Answer
In theming the use of render() is correct, you can't use a different render method. The problem is that many blocks are placeholdered and you can't determine at the point the page template is rendered in which context the placeholdered block might be rendered in future. Probably then with a different user logged in because blocks cached per user are placeholdered by default.

The code in your question thinks the region is empty because `striptags` removes placeholders which usually are formatted as HTML tag.

You can change this at the expense of cache performance by adjusting the cacheablity of the blocks involved or customizing the auto-placerholder condition site-wide.

See https://www.drupal.org/docs/8/api/render-api/auto-placeholdering
> 1 votes

# Answer
In twig you can test if any content exists in a region in the following way:

```
{% if page.sidebar_second|render|striptags|trim|length %}
   <div class="section-main col-md-8">
{% else %}
   <div class="section-main">
{% endif %}

```
> 0 votes

---
Tags: 8, theming
---


title: Get pure SQL from Drupal::entityQuery

text:
# Question
Title: Get pure SQL from Drupal::entityQuery
Given the following code, how can I print the SQL that is generated?

```
$bundle='my_bundle_type';
$query = \Drupal::entityQuery('node');
$query->condition('status', 1);
$query->condition('type', $bundle);
$entity_ids = $query->execute();

```

What I have tried:

* `__toString()` doesn't work
* `dpq($query)` throws an error

# Answer
With debug tag (**devel module is mandatory**) we can print the raw sql.

```
$query = \Drupal::entityQuery('foo')->condition('bar', 'xyz')->addTag('debug');
$ids = $query->execute();

```
> 13 votes

# Answer
**UPDATE**

My original answer is not valid anymore, now there's a good solution for this, see Sukhjinder Singh answer. In short: use Devel module and add tag 'debug', execute it and query will be printed.

```
$entityQueryObject->addTag('debug')->execute();

```

**ORIGINAL ANSWER**

As @kiamlaluno says, the problem is \Drupal::entityQuery() implements QueryInterface, not SelectInterface. dpq needs its first argument to implements that SelectInterface.

The object returned by \Drupal::entityQuery() is a Drupal\Core\Entity\Query\Sql\Query. This object has a protected property that implements the SelectInterface:

```
  /**
   * The build sql select query.
   *
   * @var \Drupal\Core\Database\Query\SelectInterface
   */
  protected $sqlQuery;

```

Unfortunately, the Query objects don't allow to access the $sqlQuery or print the SQL string.

As a very **quick and dirty** hack you can edit the Query class file in *core/lib/Drupal/Core/Entity/Query/Sql/Query.php*, change the $sqlQuery property to be public, and access it directly.

In Query.php, `protected $sqlQuery` should be `public $sqlQuery;`.

Then you can use the dpq function from devel module with the internal property. Make sure the devel module is installed (so it's enabled).

> Prints a SQL string from a DBTNG Select object. Includes quoted arguments.

So in your case:

```
$sql_string = dpq($query->sqlQuery, TRUE));

```

Or just:

```
kint(dpq($query->sqlQuery, TRUE));

```

# dpq() Parameters

* **object $query**: An object that implements the SelectInterface interface.
* **boolean $return**: Whether to return the string. Default is FALSE, meaning to print it and return $query instead.
* **string $name**: Optional name for identifying the output.

# IMPORTANT!!

This is a dirty trick, you should revert the Query.php file when you are done. Hacking Drupal core is a very bad practice and kittens, ponies and other puppies are suffering when you do that. Maybe even some unicorns are - better think twice about it.

# Final thoughts

This a dirty workaround. Another better approach may exist but I'm not aware of it. If there is not a better way Drupal core may add some functionality to get the SQL string as sometimes is needed when debugging, and frankly, this hack is not a good way to do it.
> 12 votes

# Answer
With installed `Devel` module you can get the string with raw SQL query from EntityQuery class via:

```
$rawSqlQuery = (string) dpq($entityQuery);
echo $rawSqlQuery;

```
> 2 votes

# Answer
Here's another approach:

How can I debug entity queries in Drupal 8?

See the question in this link. This is a solution that has worked for me, if you add those two functions to a custom module, all you have to do is tag an entity query with "debug" to output the string version of the sql query.
> 1 votes

# Answer
You can simply use the \__toString() option as below and look at the SQL in the $query variable.

```
 $query = \Drupal::entityQuery('node')
->condition('status', 1)
->condition('type', 'basic_page')
->condition('changed', $utc_start, '>=')
->__toString();

```
> 1 votes

# Answer
You can use ReflectionClass in this case.

```
$reflection = new ReflectionClass(get_class($query));
$property = $reflection->getProperty('sqlQuery');
$entity_ids = $query->execute(); // this is required
$sql = (string)$property->getValue($queryObject);
echo $sql;

```
> 0 votes

# Answer
Enable Devel and Devel Kint modules then just try

```
 kint ($query);

```
> -2 votes

---
Tags: 8, database
---


# Question
Title: Caching of entity UUID in a frontend form
I have a form which is displayed in the frontend, through which anonymous users can create nodes. For guest users, the pages are cached and with them apparently some part of the form. We recently noticed that when a guest user opens the form and a second guest user also opens the form before the first user has submitted the form, then the second form can no longer be submitted. It's not a race condition, it doesn't matter when the second form is submitted or even who of the two users submits first. The second user gets a "duplicate entry" error for the UUID field of the node.

I dug around a bit in the code creating the form, and there is a part where a new node of the correct bundle is created, before the form and form\_state objects are created. It seems this new node or the whole form\_state are then cached. The problem goes away if I add a pre\_save hook for the node and set a new UUID there.

Now this doesn't seem like an unusual scenario, so my question is: Is this an expected behavior or should frontend node forms be cacheable and we somehow brought this on ourselves with some kind of mis-configuration?

The reason I'm not sure is that there are a lot of people asking how to disable the caching for pages with a form. I didn't see much info on whether forms like this should be cacheable, though. I did find this question where Berdir answered that frontend forms should be cacheable. The old bug for the user registration sounds exactly like what is happening for us. The answer is six years old, though, so is this still the correct answer in 2023?

We are on Drupal 9.5.11 (going to upgrade to 10 soon). I can post code examples tomorrow, if it seems that this is some kind of misconfiguration. I mean, we could simply go with resetting the UUID, but it seems hacky to me. Something like this shouldn't really be necessary, and I'm a bit afraid that this might have other, harder to spot side-effects.

Update: The code base is some years old and more complex than that, but boiled down to a simple example it looks like this. We have a block that we place on pages via the Layout Builder:

```
namespace Drupal\jf_test\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\jf_test\Form\TestContentForm;

/**
 * A test block.
 *
 * @Block(
 *    id = "test_content_form_block",
 *    label = @Translation("Test content form block"),
 *    admin_label = @Translation("Embed a content form for creating articles"),
 *  )
 */
class TestContentFormBlock extends BlockBase {

  public function build(): array {
    return TestContentForm::make();
  }

  public static function create(): array {
    return \Drupal::service('plugin.manager.block')
      ->createInstance('test_content_form_block')
      ->build();
  }

  public function getCacheMaxAge(): int {
    return 0;
  }

}

```

And the form class:

```
namespace Drupal\jf_test\Form;

use Drupal\Core\Form\FormState;

class TestContentForm {

  public static function make(): array {
    return (new TestContentForm())->build();
  }

  public function build(): array {
    // Create a new node entity of the correct bundle.
    $node = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->create(['type' => 'article']);

    // Build the form.
    $form = \Drupal::entityTypeManager()
      ->getFormObject($node->getEntityTypeId(), 'default')
      ->setEntity($node);
    $form_state = new FormState();
    $form_state->setValue('is_embedded', TRUE);
    // Workaround for "The same form twice on one page with different arguments
    // may process the wrong form when submitted"
    // @see https://www.drupal.org/project/drupal/issues/2821852
    $form_state->setRequestMethod('POST');
    $form_state->setCached(FALSE);

    return \Drupal::formBuilder()->buildForm($form, $form_state);
  }

}

```

I just ran this in a fresh Drupal 10.1 installation, and of course it worked without a problem. I also ran it in our Drupal 9.5.11 instalation, and it also worked there. So I guess I have to find out what's different about our specific node types we are trying to create.

# Answer
"Actually, TRUE is the default value ..." No, I meant the default value of FormState::$cache is FALSE in the $form\_state object. It should not be set to TRUE, which calling setCached() does without argument (as commented by @JohannesFreudendahl because of the default in the method).

The caching behavior of the form object is calculated automatically depending on the state of the form and Drupal does the necessary steps to connect a unique ID to cached form objects. For entity forms this includes the entity instance which is stored in $form\_state. Every new entity instance has a unique UUID.
> 0 votes

---
Tags: caching
---