# Question
Title: Some results in a view appear twice or more
On a multilingual site I have **a view of all nodes** with the following configuration:

* **View type:** Page
* **Format:** Table
* **Fields:** Content (title)
* **Filter criteria:** Published nodes
* **Sort criteria:** Publishing date (descending)
* **Paging:** Show all content
* **Pager link:** No
* **Advanced settings:** No
* **Rendering language:** Default language of the website

## My problem

My problem is that some results in the view (some links to nodes) appear twice or more, with some results appearing even five or six times.

The website is otherwise working fine with no errors.

---

## What I have tried to solve this problem

### 1. Adding a view language criteria

If I try to add a filter criteria based on language, I get four options:

1. Original language (content)
2. Translation language (content)
3. Original language (content revision)
4. Translation language (content revision)

Thus:

* I have tried to add the filter criteria `Original language (content)` were I chose the default (Hebrew) language of the site.
* I have tried to add the filter criteria `Translation language (content)` were I chose "Which is not one of (everything)" so there won't be any translation.

None of these approaches helped.

### 2. Detecting possible SQL table joins

I don't recall ever joining any table with any table but anyway in my website under `/admin/structure/views/settings` I chose to show a SQL query above previews of a views.

I got the following output above the preview of the discussed view when no language filter criterias existed:

```
SELECT "taxonomy_index"."created" AS "taxonomy_index_created", "node_field_data"."nid" AS "nid"
FROM
{node_field_data} "node_field_data"
LEFT JOIN {taxonomy_index} "taxonomy_index" ON node_field_data.nid = taxonomy_index.nid
WHERE "node_field_data"."status" = '1'
ORDER BY "taxonomy_index_created" DESC

```

---

## My question

How to solve my problem?

# Answer
For a multilingual site you need to add a filter for the language. There are different strategies, filter the `Translation language (content)` by the current language (= Content language selected for page), or filter the `Default translation (content)` (a flag indicating whether this is the default translation) (= True) and then translate when rendering the view row (in the middle section of the View). The second method is for displaying all nodes one time even if not translated into the current language.

Since you've answered my question in a now deleted comment that your site is multilingual you need this filter to get only one hit per node for nodes with multiple translations (I don't know if you have any). As commented by @cilefen, the other source for duplicate entries are JOINs to other entity tables, for example taxonomy. Enable the display of SQL queries at /admin/structure/views/settings and check for JOINs.
> 1 votes

# Answer
I wrote in the question:

* **Sort criteria: Publishing date (descending)**

But I was wrong and it was actually:

* **Sort criteria: Taxonomy term publishing date (descending)**

So, the problem was caused due to me mistakenly choosing the sort criteria "Publishing date" (Taxonomy term") instead just "Publishing date".

Choosing a sort criteria based on **a date in which the content was related to a term** caused the number of duplications in the view was corresponding to the number of taxonomy terms in the each node.

Replacing Sort criteria: Taxonomy term publishing date (descending) with Sort criteria: Publishing date (descending) solved my problem.
> 0 votes

---
Tags: views, 10
---


# Question
Title: How do I implement email dispatch with Drupal Symfony Mailer from scratch?
I'm implementing a cron job that should send a notification email to all users that meet a certain criterion. I created a Service implementing the `CronInterface` and `hook_cron` calls this service's `run()` method. This queries for the users that need notification. I want to loop over these user and send emails to them. These emails should contain a default message and they should be greeted with their name.

The system already uses the "Drupal Symfony Mailer". Everything in the documentation seems to migrate configurations from other implmentations.

I tried implementing a Plugin extending `EmailBuilderBase` with:

```
@EmailBuilder(
  id = "notification",
  sub_types = { "update" = @Translation("Update") },
  common_adjusters = {"email_subject", "email_body"},
)

```

My expectation was that I will be able to

* add a new policy on the configuration page that belongs to this class
* provide my notification text, using a token for the user name
* send the email via `Drupal::service('email_factory')->sendTypedEmail('notification', 'update', $user);`

This doesn't work. I can't create a policy matching my Builder. The dropdown menus on policy creation don't offer options for "notification" and "update" for the type and sub-type selection.

How do I create the policy that allows me to send my email via the method call above without writing a deprecated version that gets migrated?

# Answer
I created a specific type and subtype for a custom module, like this: In src/Plugin/Emailbuilder create a class MyModuleEmailBuilder extends EmailBuilderBase. Make an annotation there:

```
/**
 * Email Builder plug-in for the custom_email_example module.
 *
 * @EmailBuilder(
 *   id = "my_module",
 *   sub_types = {
 *     "update" = @Translation("Update"),
 *   },
 *   common_adjusters = {"email_subject", "email_body"},
 * )
 */

```

Then (re-)install the module. Hopes this helps!
> 1 votes

---
Tags: emails, symfony-services
---


# Question
Title: Why is my body field trimming well under the character limit (94 characters instead of 600)?
I have a view that is supposed to display a body field and trim it to under 600 characters. Most of the time it does that just fine, however sometimes it will trim down to under 100 characters for no apparent reason. Usually it is more likely if the text has more html tags than just simple p/ul/li etc (so strong, em, h4, etc). However I don't see why that should shrink how much it trims by that much. As an example, the following example text (obscured and shown as the source html so you can see everything that is happening) will only show the first p tag text at 600 characters, but will show everything if the character limit is increased to 611.

```
<p>
    <strong>Finding Connection in the Midst of Holiday Loneliness</strong><br>
    <strong>Dtr Hjkkdj Ertlkj ani Kjiyny Wiyhnn & OLI</strong>
</p>
<p>
    As the holidays roll in, for many it can be a time of laughter and joy, with family reunions, clinking of glasses, traditional foods, twinkling lights, and festive decorations; but it’s not as joyous for everyone at all times. The holiday season can also be a reminder of what, or who, is missing. It's hard when the world seems to be celebrating, and you're trying to find your footing in a state of loneliness that the holiday cheer often can’t quite reach.
</p>

```

Can anyone explain to me why this would trim to only the first paragraph tag at 600 trim limit, but display all of it at 611 trim limit? and how I can fix it so that the trim works as I would expect it to?

# Answer
> 6 votes
This is the expected behaviour, insofar as it's what the `text_summary()` function does to the HTML. From the function comments:

> \[...\] we generate the summary automatically, trying to end it at a sensible place such as the end of a paragraph, a line break, or the end of a sentence (in that order of preference).

It first truncates the input to the maximum length, then breaks it into HTML paragraphs; if it finds a complete paragraph within the limit, and the next paragraph is incomplete or above the limit, it delivers the first paragraph only, regardless of the remaining number of valid characters.

The Smart Trim module has an option to strip HTML, that might get you better results.

---
Tags: views
---


# Question
Title: How to make use of Devel debugging functions on large or complex objects
I am having trouble making real use of Devel's debugging functions `kint()` and `dpm()` in my modules and twig templates. They work fine for primitive variables, flat arrays and such, but if I want to inspect into some object like an `EntityRerefenceFieldItemList` they either cause the site to crash (white page) or generate so much data such that the scripts for expanding the list no longer work.

How do I circumvent these problems?

# Answer
When working with entities and fields, you want to see the *values*, not the objects.

For an entity, use `$entity->toArray()`, for a field object, use `$field->getValue()`. You can transform that almost 1:1 to accessing those values on an object, e.g. $entity-\>field\_name-\>property.

A few things are not shown there, for example computed properties like -\>entity on an entity reference field. See https://wizzlern.nl/drupal/drupal-8-entity-cheat-sheet for an overall introduction.

That said, I'd also strongly recommend an IDE + xdebug over any debugging functions, I only use that and sometimes a simple debug(), which works just fine on the value arrays returned by the methods mentioned above.
> 8 votes

# Answer
The first problem can temporarily get fixed by changing the max array/object levels Kint will go deep. Currently this still has to be done by changing one line of code in the module. Though there already is an issue https://www.drupal.org/node/2405179 to make this a configurable setting.

In `devel/kint/kint/config.default.php` change `7` to any number you are fine with. I usually set it to `4`.

```
/** @var int max array/object levels to go deep, if zero no limits are applied */
$_kintSettings['maxLevels'] = 7;

```

Remember that this number will get reset as soon as you update the Devel module.

---

Update: Now I found this beautiful snippet to simply be placed in your settings(.local).php. No hacking or patches needed.

```
// Change kint maxLevels setting:
include_once(DRUPAL_ROOT . '/modules/contrib/devel/kint/kint/Kint.class.php');
if (class_exists('Kint')) {
  // Set the maxlevels to prevent out-of-memory.
  Kint::$maxLevels = 4;
}

```
> 9 votes

# Answer
The Devel module is a great tool, however it does not work for every situation. There actually a module for debugging twig known as Twig XDebug(which i have not implemented yet).

**Or**

Get xdebuger manually installed with your IDE.

**Freely Available IDE's:**

* Netbeans
* Eclipse
* Aptana Studio (Eclipse derivative)

**Paid IDE's:**

* phpDesigner
* Jetbrains PHPStorm
* Komodo IDE (has some free/flexible pricing scenarios).

**Next Steps to be followed after choosing an IDE.**

1. Install Xdebug
2. Modify your php.ini config to enable xdebug
3. Install your IDE, configure to use xdebug and a browser.
4. Possibly a browser plugin for xdebug. Ex- Xdebug helper for Chrome
> 4 votes

# Answer
Be careful with mouse clicks, don't click on the `+` icon! This expands all levels, which can take a long time. If you click on the title bar, you only expand the top level.

Drupal 8 Debugging: Kareful Klicking in Kint
> 4 votes

# Answer
Add to settings.local.php or to settings.php

**Kint V3**

```
if (class_exists('Kint')) {
  // Change the maximum depth to prevent out-of-memory errors.
  \Kint::$max_depth = 4;
}

```

**Kint V4** (Might also work with V5, untested).

```
if (class_exists('Kint')) {
  // Change the maximum depth to prevent out-of-memory errors.
  \Kint::$depth_limit= 4;
}

```
> 1 votes

---
Tags: 8, debugging
---


# Question
Title: How to correctly create and edit left to right pages in a right to left website?
I have a website in Hebrew, a language written from right to left (RTL).

Hebrew is used for the administration interface and for the general interface; generally pages are in Hebrew for all users.

I don't have translated nodes, and I also don't want to have any translated node; either a node is in Hebrew or in another language.

My problem is that I need to add some nodes which are in English, written from left to right (LTR) but I am not sure how to do that correctly.

I want that in an English node, both the `H1` and the `article body` will appear LTR, **also while I create or edit it**.

How can I correctly create, edit and combine English nodes in a RTL website, especially when no translations are being used at all?

## What I do for now

For now I use this CSS and JavaScript.

### CSS

```
.page-node-type-dp-ltr {
    direction: ltr;
}

.page-node-type-dp-ltr .feed-icon {
    display: none; /* fix feed-icon flowing above text */
}

```

### JavaScript

```
// ==UserScript==
// @name         Drupal ltr
// @match        https://example.com/node/1/*

// ==/UserScript==

window.setInterval( ()=>{
    document.querySelector('*').style.direction = "ltr";
}, 1);

window.setInterval( ()=>{
    document.querySelector('.text-align-left').style.direction = "ltr";
}, 1);

window.setInterval( ()=>{
    document.querySelector('.ck-editor__editable').style.direction = "ltr";
}, 1);

```

It's not backend but it's the only thing I know to do that brings me closest to a backend solution.

# Answer
> 2 votes
I would suggest you to add a Boolean field to your *article* bundle. For each LTR node you can check this field; then, in your theme, check it and set the direction basing on it.

```
{% set direction = article.field_ltr.value ? 'ltr' : 'rtl' %}

<div dir="{{direction}}">
  {{ content }}
</div>

```

---
Tags: theming, 10
---


# Question
Title: Is there a way to test instantiating a service in an isolated unit test?
I have the a service definition in a custom Drupal 8 module which I would like to test. I've managed to test everything else in my module with unit tests, so my whole suite runs in a fraction of a second, and I'd like to avoid introducing anything Simpletest-based. (My CI infrastructure wouldn't support it anyway.) **Is there any way to test my service definition in an isolated unit test?** Here's my service definition:

### my\_module.services.yml

services:
  my_module.client:
    class: Drupal\my_module\Client
    factory: Drupal\my_module\Client::create
    arguments: ['@state', '@config.factory']```
</code></pre>

The manual test I've been performing is to run this Drush command.

```
drush ev 'var_dump(\Drupal::service("my_module.client")->_serviceId == "my_module.client" ? "PASS" : "FAIL");'

```

That's a sufficient smoke test while I'm developing. For a regression test, I'd also like to assert that the class returned is an instance of the correct type.

# Answer
> 0 votes
Great question, i was wondering this myself, too.

But first: Does this make sense at all? Yes, a pure API module that does not have an integration with it, should test its API.

And: Is it worth it? The performance is in my case:

* Unit test: ~40ms
* Kernel test: ~400ms

But note that the unit test may be much more complex, and miss some failures that the kernel test covers (like a broken .info.yml, or the work of service providers).

That said, here's the shootout for my sessionless module:

UnitTest:

```
<?php

declare(strict_types=1);
namespace Drupal\Tests\sessionless\Unit;

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\YamlFileLoader;
use Drupal\Core\KeyValueStore\KeyValueMemoryFactory;
use Drupal\Core\State\State;
use Drupal\sessionless\TokenGeneration\TokenServiceInterface;
use Drupal\Tests\UnitTestCase;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;

final class ServicesUnitTest extends UnitTestCase {

  protected $container;

  protected function setUp(): void {
    parent::setUp();

    $moduleRoot = dirname(dirname(dirname(__DIR__)));
    // @see \Drupal\Core\DrupalKernel::compileContainer
    $container = new ContainerBuilder(new ParameterBag());
    // Add all external dependencies, maybe as doubles or mocks.
    $container->set('state', new State(new KeyValueMemoryFactory()));
    // Load the services.yml file
    $yamlLoader = new YamlFileLoader($container);
    $yamlLoader->load("$moduleRoot/sessionless.services.yml");
    $container->compile();
    $this->container = $container;
  }

  public function testServices(): void {

    $this->assertInstanceOf(TokenServiceInterface::class, $this->container->get('sessionless.encrypted_signed_token_service'));

    $this->assertInstanceOf(TokenServiceInterface::class, $this->container->get('sessionless.only_signed_token_service'));

  }

}

```

KernelTest:

```
<?php

declare(strict_types=1);
namespace Drupal\Tests\sessionless\Kernel;

use Drupal\KernelTests\KernelTestBase;
use Drupal\sessionless\TokenGeneration\TokenServiceInterface;

final class ServicesKernelTest extends KernelTestBase {

  protected static $modules = ['sessionless'];

  public function testServices(): void {
    $this->assertInstanceOf(TokenServiceInterface::class, $this->container->get('sessionless.encrypted_signed_token_service'));
    $this->assertInstanceOf(TokenServiceInterface::class, $this->container->get('sessionless.only_signed_token_service'));
  }

}

```

---
Tags: 8, testing
---


# Question
Title: How to know current active installation profile like standard/minimal etc. on existing drupal site?
I have installed minimal installation profile. Is there any entry in database where profile name is mentioned, current active profile.

I wanna get the profile name which is get installed in existing site.

# Answer
If you go to `/admin/reports/status`, under Drupal if you see something written after Drupal version, that's your installation profile. If there is nothing, that means it is Standard profile.
> 3 votes

# Answer
Have a look at the function drupal\_get\_profile

> Gets the name of the currently active installation profile.
>
> When this function is called during Drupal's initial installation process, the name of the profile that's about to be installed is stored in the global installation state. At all other times, the "install\_profile" setting will be available in settings.php.
> 2 votes

# Answer
You could easily get it with the config api.

```
$profile = \Drupal::service('config.factory')->get('core.extension')->get('profile');

```

In the database, it is in the **config** table, serialized under the **core.extension** entry.
> 1 votes

# Answer
Retrieve Drupal distribution and installation profile information.

```
$profile = drupal_get_profile();
  $profile_info = system_get_info('module', $profile) + array(
    'distribution_name' => 'Drupal',
    'version' => VERSION,
  );

```

More information visit here
> 0 votes

# Answer
If you use Drush:

```
drush core-status | grep profile

```

Sample output:

```
Install profile  : demo_umami

```
> 0 votes

---
Tags: 8, installation-profiles
---


# Question
Title: 'stale_file_threshold' is not a supported key
I have installed "Advanced CSS/JS Aggregation" on my Drupal 10. but after installation, I faced a problem.

In performance page, when I want to save configuration (for example I checked/Unchecked Aggregate CSS files & Aggregate JavaScript files checkboxes and want to update config.), I see this error

```
 'stale_file_threshold' is not a supported key.

```

I tried to check aggregator settings. but I found no solution. I replaced alpha version with .dev version. but problem hasn't gone. Even I uninstalled and remove the module, but problem still exists and I can't save performance configuration.

what is your solution?

# Answer
The issue is in the *Advanced CSS/JS Aggregation* module that, in its `SettingsForm::submitForm()` method, sets the *stale\_file\_threshold* value in the *system.performance* configuration object.

```
$this->config('system.performance')
  ->set('stale_file_threshold', $form_state->getValue('stale_file_threshold'))
  ->set('css.gzip', $form_state->getValue('css_gzip'))
  ->set('js.gzip', $form_state->getValue('js_gzip'))
  ->save();

```

Drupal core validates the configuration objects with schema files like system.schema.yml; since *stale\_file\_threshold* is not defined in that file, Drupal reports an error.

This can only be fixed by the project maintainers. The module should not write a configuration value the System module does not recognize in its configuration object.
It is fine to change the *css.gzip* and the *js.gzip* values because the configuration schema defines both of them, but adding new values just causes errors like the one you saw.
> 2 votes

---
Tags: configuration, performance, css-js-aggregation
---


# Question
Title: How to solve the huge HTTPRL error that fills down all of Cron \ Status report?
## Background

For some time now, **and only in some occasions**, when I run CRON (Status report), I see a huge error (About 170 rows) at the HTTPRL section (related to the HTTP Parallel Request & Threading Library module). It happens randomly - Sometimes it happens and sometimes it doesn't. When the error does not appear, the HHTPRL "section" in status report is all green. Here is a screenprint of it:

## What I already tried

I've tried to play a bit with the HTTPRL preferences, but nothing really helped... For example, tried to change at "IP Address to send all self server requests to": from **-1** to **1**. Also tried to **uncheck** "Enable background callbacks", But IIRC nothings has changed.

The only changes I saw (When the error **was** apparent) were when I unchecked "Enable background callbacks", or otherwise, when I check-marked "Use httprl to handle drupal\_http\_request" --- When I ran Cron afterwards the error's text went from about 170 rows to 90 rows. But this data doesn't help me to understand Why the error was there on the first place and even worse - Why it appears randomly?

## Bottom line

Is this a known problem? You might have an idea why this happens or a tip how to try to solve it?

# Answer
> 5 votes
The solution (or at least work around?) could be what is described in Comment # 8 of Issue # 2450725 related to the HTTP Parallel Request & Threading Library module:

> change "'timeout' =\> 7," to "'timeout' =\> 1,"
>
> This timeout is used in `lock_acquire()` that probably locks Drupal for 7 seconds, but in httprl config httprp waits only 5 seconds for a response.

Comment # 17 in that issue also contains a corresponding patch, which looks like so:

```
diff --git a/httprl.install b/httprl.install
index d7e2963..e2d4f04 100644
--- a/httprl.install
+++ b/httprl.install
@@ -177,7 +177,7 @@ function httprl_install_http_test($mode, $blocking = FALSE) {
       // Setup options array.
       'options' => array(
         'blocking' => $blocking,
-        'timeout' => 7,
+        'timeout' => 1,
         'max_redirects' => 0,
         'headers' => $headers,
       ),

```

# Answer
> 0 votes
I faced the same issue. Executing the following code did the trick:

```
variable_set('httprl_install_lock_time', 1);

```

I use devel/php. It can be done via drush as well:

```
drush php-eval "variable_set('httprl_install_lock_time', 1);"

```

---
Tags: 7, caching
---


# Question
Title: Why isn't Drupal's core once() function working in my simple test script?
I am trying to console.log a message once and only once in Drupal 10. I am cutting and pasting examples from https://www.drupal.org/node/3158256 into my file and I am still seeing the message appear multiple times in the console.

I have added the dependencies to the library:

```
my-library:
  version: VERSION
  js:
    js/my-library.js: { }
  dependencies:
    - core/drupal
    - core/once

```

And I have this simple test script in which I have cut & paste the example code from https://www.drupal.org/node/3158256

```
(function ($, Drupal, once) {
  'use strict';

  Drupal.behaviors.myBehavior = {
    'attach': function attach(context, settings) {

      once('init-once', context === document ? 'html' : context)
      .forEach(function initOnce(doc) {
        console.log('init-once', doc);
      });

    }

  };

})(jQuery, Drupal, once);

```

My goal is simply to console.log a message once and only once. How can I log a message only once?

# Answer
`core/once` isn't for doing something just once, but for attaching a script just once. Then it's up to your script's logic to actually do something just once. You could for example toggle a simple CSS class on the `<body>` tag like `oops-i-did-it` and check in your JS if this class already exists or not before you trigger your magic.

And your libraries definition is missing the `core/jquery` dependency.

Bookmark this change record: https://www.drupal.org/node/3158256, it gives you a few really nice examples on how to use `once()` with and without jQuery. (You know that every times you use jQuery a small kitten dies? )

```
myfeature:
  js:
    js/myfeature.js: {}
  dependencies:
    - core/drupal
    - core/once

```

```
(function (Drupal, once) {
  Drupal.behaviors.myfeature = {
    attach(context) {
      // '[data-myfeature]' in the next line can also be 'div.my-class'
      // or '#my-id' etc.
      const elements = once('myfeature', '[data-myfeature]', context);
      // `elements` is always an Array.
      elements.forEach(processingCallback);
    }
  };

  // `value` in the next line is your actual DOM element. Do something with
  // `value` like `value.classList.add('hello-world')`.
  function processingCallback(value, index) {}
}(Drupal, once));

```
> 4 votes

# Answer
I found something that works:

```
(function ($, Drupal, once) {
  'use strict';

  Drupal.behaviors.myBehavior = {
    'attach': function attach(context, settings) {

      if ($(once('my-test', 'body')).length) {
        console.log('my test');
      }

    }
  };

})(jQuery, Drupal, once);

```

Though I can't say I understand the syntax. It seems quite verbose and more difficult to grasp than Jquery .once().
> 0 votes

---
Tags: javascript, 10
---


# Question
Title: What causes this error? 'You have requested a non-existent service "user.private_tempstore"'
I recently upgraded a site to Drupal 9. For content types that have media type as PDF documents, now I am not able to edit or save any uploaded pdf file. The drupal log shows this error.

> Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "user.private\_tempstore". in Drupal\Component\DependencyInjection\Container-\>get() (line 157 of /app/web/core/lib/Drupal/Component/DependencyInjection/Container.php).

Has anyone come across this issue? I am not sure what is causing this error. Any guidance to resolve this issue please?

# Answer
> 1 votes
Yes, other people have come across this. You can find them by searching the Internet for ‘You have requested a non-existent service "user.private\_tempstore"’. It means that you did not complete the preparatory work for upgrading. A module or theme on the site is not compatible with Drupal 9. `user.private_tempstore` was deprecated in 2018.

It is not possible to say more in this answer without more information from you. But here is a tip: search the site code for “user.private\_tempstore”.

Further I will mention that at the time I write this, Drupal 9 is end-of-life. It isn’t safe to use. You should move to Drupal 10 as soon as possible.

---
Tags: 9, upgrading
---


title: I can't upgrade from 9.5.11 to 10.2.0

text:
# Question
Title: I can't upgrade from 9.5.11 to 10.2.0
I'm not able to upgrade my website from Drupal 9.5.11 to 10.2.0 via Composer. I don't think there is something wrong with the module versions; the *Upgrade status* module gives me a *good to go*. The problem is that I don't get any detail on the error.

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

Problem 1
  - Root composer.json requires drupal/core-recommended 10.2.0 -> satisfiable by drupal/core-recommended[10.2.0].
  - drupal/core-recommended 10.2.0 requires drupal/core 10.2.0 -> found drupal/core[10.2.0] but these were not loaded, likely because it conflicts with another require.

```

This is the content of the composer.json file.

```
{
    "name": "drupal/recommended-project",
    "description": "Project template for Drupal 9 projects with a relocated document root",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "homepage": "https://www.drupal.org/project/drupal",
    "support": {
        "docs": "https://www.drupal.org/docs/user_guide/en/index.html",
        "chat": "https://www.drupal.org/node/314178"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        {
            "type": "composer",
            "url": "https://asset-packagist.org"
        },
        {
          "type": "package",
          "package": {
            "name": "bower-asset/photoswipe",
            "version": "4.1.1",
            "type": "drupal-library",
            "dist": {
              "url": "https://github.com/dimsemenov/PhotoSwipe/archive/v4.1.1.zip",
              "type": "zip"
            }
          }
        },
        {
            "type": "package",
            "package": {
                "name": "cure53/dompurify",
                "version": "3.0.3",
                "type": "drupal-library",
                "source": {
                    "url": "https://github.com/cure53/DOMPurify.git",
                    "type": "git",
                    "reference": "3.0.3"
                }
            }
        }
    ],
    "require": {
        "arthurkushman/query-path": "^3.0",
        "bower-asset/lazysizes": "^5.1",
        "bower-asset/photoswipe": "^5",
        "campaignmonitor/createsend-php": "^6.1",
        "composer/installers": "^1.9",
        "cure53/dompurify": "^3.0",
        "cweagans/composer-patches": "^1.6",
        "drupal/account_field_split": "^2.0.2",
        "drupal/address": "^1",
        "drupal/addtoany": "^2.0",
        "drupal/admin_toolbar": "^3.4",
        "drupal/advagg": "^6.0@alpha",
        "drupal/antibot": "^1.3",
        "drupal/better_exposed_filters": "^6.0.3",
        "drupal/blazy": "^2.22",
        "drupal/block_class": "^1.0",
        "drupal/block_field": "^1.0@alpha",
        "drupal/cer": "^5.0@beta",
        "drupal/ckeditor_config": "^3.2",
        "drupal/clientside_validation": "^4.0",
        "drupal/composer_deploy": "^1.7",
        "drupal/condition_query": "^1.4",
        "drupal/conditional_fields": "^4.0@alpha",
        "drupal/config_ignore": "^2.1",
        "drupal/config_views": "^2.0",
        "drupal/core-composer-scaffold": "9.5.11",
        "drupal/core-project-message": "9.5.11",
        "drupal/core-recommended": "9.5.11",
        "drupal/ctools": "^4.0",
        "drupal/ctools_views": "dev-4.x",
        "drupal/devel": "5.x-dev",
        "drupal/draggableviews": "^2.0",
        "drupal/easy_breadcrumb": "^2.0",
        "drupal/email_registration": "^2.0@RC",
        "drupal/entity": "^1.2",
        "drupal/entity_reference_revisions": "^1.10",
        "drupal/extlink": "^1.1",
        "drupal/feeds": "3.x-dev",
        "drupal/feeds_ex": "^1.0@beta",
        "drupal/feeds_log": "^2.0@alpha",
        "drupal/feeds_tamper": "^2.0@beta",
        "drupal/fences": "3.x-dev",
        "drupal/field_group": "~3.0",
        "drupal/fivestar": "^1.0@alpha",
        "drupal/flag": "^4.0@alpha",
        "drupal/flood_control": "^2.2",
        "drupal/formblock": "^2.0@beta",
        "drupal/geofield": "^1.8",
        "drupal/geofield_map": "^3.0",
        "drupal/google_tag": "^1.4",
        "drupal/honeypot": "^2.0",
        "drupal/image_delta_formatter": "^1.0",
        "drupal/image_effects": "^3.0",
        "drupal/imageapi_optimize": "^4.0@beta",
        "drupal/imageapi_optimize_binaries": "^1.0",
        "drupal/imageapi_optimize_tinypng": "1.x-dev",
        "drupal/imageapi_optimize_webp": "^2.0@beta",
        "drupal/imagefield_tokens": "^3.1",
        "drupal/imagemagick": "^3.4",
        "drupal/imce": "^3.0",
        "drupal/inline_entity_form": "^1.0@RC",
        "drupal/jquery_ui_autocomplete": "^2.0",
        "drupal/jquery_ui_datepicker": "^2.0",
        "drupal/jquery_ui_menu": "^2.0",
        "drupal/jquery_ui_slider": "^2.0",
        "drupal/lazy": "3.x-dev",
        "drupal/libraries": "^4.0",
        "drupal/link_attributes": "^2.1",
        "drupal/login_destination": "^2.0@beta",
        "drupal/masquerade": "^2.0@beta",
        "drupal/menu_item_extras": "^2.11",
        "drupal/menu_link_attributes": "^1.3",
        "drupal/menu_trail_by_path": "^2.0",
        "drupal/mgv": "^2.2",
        "drupal/mobile_detect": "^3.0",
        "drupal/module_filter": "^4.0",
        "drupal/module_missing_message_fixer": "^2.0",
        "drupal/node_class": "2.0.x-dev",
        "drupal/office_hours": "^1.2",
        "drupal/path_redirect_import": "^2.0",
        "drupal/pathauto": "^1.11",
        "drupal/pathologic": "^2.0@alpha",
        "drupal/photoswipe": "^5.0@alpha",
        "drupal/physical": "^1.3",
        "drupal/poll": "^1.4",
        "drupal/profile": "^1.7",
        "drupal/queue_ui": "^3.1",
        "drupal/quick_node_clone": "^1.11",
        "drupal/r4032login": "2.2.x-dev@dev",
        "drupal/recaptcha": "^3.0",
        "drupal/redirect": "^1.8",
        "drupal/responsive_favicons": "^1.4",
        "drupal/rules": "^3.0@alpha",
        "drupal/scheduler": "^1.1",
        "drupal/schema_metatag": "3.0.x-dev@dev",
        "drupal/search_api": "^1.29",
        "drupal/search_api_autocomplete": "1.x-dev",
        "drupal/search_api_location": "^1.0@alpha",
        "drupal/search_autocomplete": "^3.0",
        "drupal/semanticviews": "^2.2",
        "drupal/sophron": "^1.3",
        "drupal/state_machine": "^1.10",
        "drupal/structure_sync": "^2.0",
        "drupal/svg_image": "^1.15",
        "drupal/symfony_mailer": "^1.1@beta",
        "drupal/tablefield": "^2.1",
        "drupal/taxonomy_manager": "2.0.9",
        "drupal/taxonomy_menu": "^3.4",
        "drupal/telephone_validation": "^2.2",
        "drupal/token": "^1.3",
        "drupal/token_filter": "^2.1",
        "drupal/tvi": "^2.0@alpha",
        "drupal/twig_tweak": "^3.2",
        "drupal/unpublished_nodes_redirect": "^2.0",
        "drupal/unused_modules": "^1.0",
        "drupal/upgrade_status": "^4.0",
        "drupal/user_registrationpassword": "2.0.x-dev@dev",
        "drupal/video_embed_field": "2.x-dev",
        "drupal/viewfield": "^3.0@alpha",
        "drupal/views_block_area": "^1.0@beta",
        "drupal/views_block_filter_block": "^2.0",
        "drupal/views_conditional": "^1.5",
        "drupal/views_extras": "^3.0",
        "drupal/views_random_seed": "^1.2",
        "drupal/votingapi": "^3.0@beta",
        "drupal/webform": "6.2.2",
        "drupal/webform_node_element": "^1.2",
        "drupal/xmlsitemap": "^1.4",
        "drupal/yaml_editor": "^1.0",
        "drupal/yoast_seo": "^1.7",
        "drush/drush": "^11",
        "kint-php/kint": "dev-master",
        "npm-asset/photoswipe-dynamic-caption-plugin": "^1",
        "oomphinc/composer-installers-extender": "^2.0",
        "php-http/httplug": "^2.2",
        "psr/http-factory": "1.0.x-dev",
        "roave/better-reflection": "6.14.x-dev",
        "softcreatr/jsonpath": "^0.7.5",
        "symfony/error-handler": "^4|^5|^6",
        "symfony/filesystem": "^4|^5|^6",
        "symfony/http-client-contracts": "^2.5.2",
        "tijsverkoyen/css-to-inline-styles": "^2.2",
        "wikimedia/composer-merge-plugin": "v2.x-dev",
        "guzzlehttp/guzzle": "^6 || ^7.5",
        "psr/container": "^1"
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "dev",
    "prefer-stable": false,
    "config": {
        "sort-packages": true,
        "platform-check": false,
        "allow-plugins": {
            "composer/installers": true,
            "drupal/console-extend-plugin": true,
            "cweagans/composer-patches": true,
            "drupal/core-composer-scaffold": true,
            "drupal/core-project-message": true,
            "wikimedia/composer-merge-plugin": true,
            "oomphinc/composer-installers-extender": true
        }
    },
    "merge-plugin": {
        "include": [
            "www/modules/contrib/webform/composer.libraries.json"
        ]
    },

    "extra": {
        "drupal-scaffold": {
            "locations": {
                "web-root": "www/"
            },
            "file-mapping": {
              "[web-root]/sites/development.services.yml": false
            }
        },
        "patches": {

        },

        "installer-types": ["bower-asset", "npm-asset"],

        "installer-paths": {
            "www/core": [
                "type:drupal-core"
            ],
            "www/libraries/{$name}": [
                "type:drupal-library",
                "type:bower-asset",
                "type:npm-asset"
            ],
            "www/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "www/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "www/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ],
            "www/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "www/profiles/custom/{$name}": [
                "type:drupal-custom-profile"
            ],
            "www/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ]
        },
        "drupal-core-project-message": {
            "include-keys": [
                "homepage",
                "support"
            ],
            "post-create-project-cmd-message": [
                "<bg=blue;fg=white>                                                         </>",
                "<bg=blue;fg=white>  Congratulations, you’ve installed the Drupal codebase  </>",
                "<bg=blue;fg=white>  from the drupal/recommended-project template!          </>",
                "<bg=blue;fg=white>                                                         </>",
                "",
                "<bg=yellow;fg=black>Next steps</>:",
                "  * Install the site: https://www.drupal.org/docs/8/install",
                "  * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html",
                "  * Get support: https://www.drupal.org/support",
                "  * Get involved with the Drupal community:",
                "      https://www.drupal.org/getting-involved",
                "  * Remove the plugin that prints this message:",
                "      composer remove drupal/core-project-message"
            ]
        }
    }
}

```

Do you have a hint on where to start?

# Answer
First confirm that you have php8.1

```
php -v

```

Then I recommend that you check each of the modules that you have installed in Drupal, and confirm that it is in the require section in the composer.json file.

my composer.json:

```
"require": {
    "composer/installers": "^1.9",
    "drupal/admin_toolbar": "^3.2",
    "drupal/better_exposed_filters": "^6.0",
    "drupal/bootstrap": "^3.24",
    "drupal/ckeditor5": "^1.0@dev",
    "drupal/ckeditor_font": "^1.3",
    "drupal/ckeditor_loremipsum": "^2.2",
    "drupal/ckeditor_media_embed": "^1.11",
    "drupal/ckeditor_spoiler": "^2.0",
    "drupal/ckeditor_videodetector": "^2.1",
    "drupal/ckwordcount": "^2.1",
    "drupal/codesnippet": "^1.9",
    "drupal/color": "^1.0",
    "drupal/colorbutton": "^1.3",
    "drupal/core-composer-scaffold": "^9.0",
    "drupal/core-project-message": "^9.0",
    "drupal/core-recommended": "^9.0",
    "drupal/core-vendor-hardening": "^9.0",
    "drupal/ctools": "^3.9",
    "drupal/devel_php": "^1.3",
    "drupal/domain_registration": "^1.6",
    "drupal/easy_breadcrumb": "^2.0",
    "drupal/editor_advanced_link": "^2.1",
    "drupal/examples": "^3.0",
    "drupal/field_group": "^3.3",
    "drupal/google_analytics": "^4.0",
    "drupal/hal": "^1.0",
    "drupal/honeypot": "^2.0",
    "drupal/jquery_ui_slider": "^1.1",
    "drupal/metatag": "^1.16",
    "drupal/pathauto": "^1.10",
    "drupal/quickedit": "^1.0",
    "drupal/rdf": "^2.0",
    "drupal/recaptcha_v3": "^1.8",
    "drupal/typed_data": "^1.0@beta",
    "drupal/video_embed_field": "^2.4",
    "drupal/xmlsitemap": "^1.2",
    "drush/drush": "^10.6"
},

```

If, for example, you have the drush module installed, but you do not see it in your composer file, I recommend that you install the module through composer:

```
composer require drush/drush

```

After you have all the modules installed in the composer.json file, proceed to install the following module:

```
composer require drupal/upgrade_status

```

This module will help you with the update process.
> 0 votes

---
Tags: composer
---


title: Subtheme update

text:
# Question
Title: Subtheme update
An update has become available for a given theme (Bootstrap Barrio). I had configured the previous release into a subtheme. How can I update the subtheme, or at least make a new subtheme of the updated one, and be sure that no modification performed in the old subtheme get lost?

# Answer
If you have made all the adjustments in the subtheme, I understand that there will be problems, because what will be updated is the parent theme.

Just confirm that the subtheme in the info.yml file has at least this:

bootstrap\_barrio\_subtheme.info.yml

```
name: Bootstrap Barrio Subtheme
type: theme
description: 'Basic structure for a Bootstrap Barrio SubTheme.'
core: 8.x
core_version_requirement: ^8 || ^9 || ^10
base theme: bootstrap_barrio

```
> 0 votes

---
Tags: theming, updating
---


title: Upgrade via Composer shows errors

text:
# Question
Title: Upgrade via Composer shows errors
I'm trying to upgrade Drupal 9.5.11 to Drupal 10 via composer.

The upgrade status module shows everything is ok. I've disabled every module except the toolbar and configuration manager. I've done this

```
composer remove drupal/console --no-update
chmod 777 web/sites/default
chmod 666 web/sites/default/*settings.php
chmod 666 web/sites/default/*services.yml
composer require 'drupal/core-recommended:^10' 'drupal/core-composer-scaffold:^10' 'drupal/core-project-message:^10' --no-update
composer update
composer install
drush updatedb
chmod 755 web/sites/default
chmod 644 web/sites/default/*settings.php
chmod 644 web/sites/default/*services.yml

```

It all seems to go ok but whn I go to my site I get these sorts of errors;

On the main site front page;

```
The website encountered an unexpected error. Try again later.

`Drupal\Core\Asset\Exception\InvalidLibrariesExtendSpecificationException: The specified library "olivero/dialog.off_canvas" does not exist. in Drupal\Core\Asset\LibraryDiscoveryCollector->applyLibrariesExtend() (line 155 of core/lib/Drupal/Core/Asset/LibraryDiscoveryCollector.php)`.

```

On the admin page;

```
The website encountered an unexpected error. Try again later.

InvalidArgumentException: The callable definition provided "`[Drupal\Core\Render\Element\HtmlTag,preRenderConditionalComments]" is not a valid callable. in Drupal\Core\Utility\CallableResolver->getCallableFromDefinition() (line 69 of core/lib/Drupal/Core/Utility/CallableResolver.php).`

```

The original nodes come from Drupal 7.97 and I successfully migrated to 9.5.11 where I disabled and removed all contributed modules.

All I want to move are my nodes from the 9.5.11 installation to Drupal 10. Been at it for days and days. Tried everything.

# Answer
Turns out there was a drush problem where my drush command was using drush from a different drupal installation. Once I fixed this the dependencies updated correctly and the problem went away.
> 1 votes

# Answer
The error is apt: `olivero/dialog.off_canvas` has been removed in Drupal 10. I encourage you to search the site's codebase for `olivero/dialog.off_canvas`. There is probably custom or contributed code that tried to load the now-removed library. By providing more information about that, we could make this answer more detailed.
> 0 votes

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


# Question
Title: What is the best way to access css and js from drupal 8 theme
I am integrating angular 2 in a drupal 8 theme. Angular 2 needs to access multiple CSS and js files for the components.

If I include it using the libraries it gets concatenated and gets exported into files directory. I need concatenation for other resources. Is their a way to avoid concatenation for just one library alone.

The solution I took was to hardcode path to assets. Like /themes/themename/app/main.js etc...

Is this okay? Will it work in multi site as well?

# Answer
> 0 votes
1. Custom module

Follow the examples module.

2. Header attributes

Via the module file

```
function module_preprocess_html(&$variables) {
  $xuacompatible = [
    '#tag' => 'base',
    '#attributes' => [
      'href' => '/my-will',
    ],
  ];

  $variables['page']['#attached']['html_head'][] = [
    $xuacompatible,
    'x-ua-compatible',
  ];

  $variables['html_attributes']['data-critters-container'] = "";
}

```
3. Include js via module hook.

I want to keep it on a specific page

```
function module_js_alter(&$javascript,) {
  $current_path = \Drupal::service('path.current')->getPath();
  if ($current_path === '/node/4') {
    $javascript = [];

    $polyfill = Drupal::service('extension.list.module')
        ->getPath('will_exporter') . '/docwills/browser/polyfills.js';

    $javascript[$polyfill] = [
      'weight' => 100,
      'minified' => FALSE,
      'group' => 'interlated',
      'type' => 'file',
      'data' => $polyfill,
      'version' => '1.0.1',
      'cache' => TRUE,
      'preprocess' => FALSE,
      'attributes' => ['type' => 'module'],
      'licence' => [
        'name' => 'custom',
        'url' => 'https://www.interlated.com.au',
        'gpl-compatible' => FALSE,
      ],
      'scope' => 'footer',
    ];

    $angular_main = Drupal::service('extension.list.module')
        ->getPath('will_exporter') . '/docwills/browser/main.js';

    $javascript[$angular_main] = [
      'weight' => 100,
      'minified' => FALSE,
      'group' => 'interlated',
      'type' => 'file',
      'data' => $angular_main,
      'version' => '1.0.1',
      'cache' => TRUE,
      'preprocess' => FALSE,
      'attributes' => ['type' => 'module'],
      'licence' => [
        'name' => 'custom',
        'url' => 'https://www.interlated.com.au',
        'gpl-compatible' => FALSE,
      ],
      'scope' => 'footer',
    ];
  }
}

```
4. Include css via module.libaries.yml

module: css: theme: docwills/browser/styles.css: { }
5. Create a block for the html element. Use the block example from the examples module

In the past I've attached the js files here. Link the inclusion of the files to the presence of the block.

```
/**
 * @Block(
 *   id = "will_exporter",
 *   admin_label = @Translation("Will Exporter"),
 *   category = @Translation("Interlated"),
 * )
 */
class AngularAppBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    return [
      '#type' => 'html_tag',
      '#tag' => 'app-root',
      '#attached' => [
        'library' => [
          'module/module',
        ],
      ],
    ];
  }
}

```
6. Change the build destination in the angular app to the module location

Configure in *angular.json*

"outputPath": "../../web/modules/custom/module/exporter",

All the paths above point here

7. No output hashing in the package.json build script

If you keep this, you need to change the main.js and polyfills.js file names every time you build

```
"prod": "ng build --configuration=production --output-hashing=none --base-href=./wills",

```
8. Run the "prod" script

npm run prod

rebuild caches. Repeat until the javascript console shows no errors.

---
Tags: 8, theming
---


# Question
Title: Drush 10 is not working - seems unable to properly find the site
Greetings to all of you.

Drush seems unable to properly find the site.

The output of vendor/drush/drush/drush status

```
PHP binary    : /usr/bin/php
PHP config    : /etc/php.ini
PHP OS        : Linux
Drush script  : /usr/share/site_dir/vendor/drush/drush/drush
Drush version : 10.5.0
Drush temp    : /tmp
Drush configs : /usr/share/nginx/site_dir/vendor/drush/drush/drush.yml
Drupal root   : /usr/share/nginx/site_dir/web/web

```

Please notice that the reported Drupal root shows web/web

```
/usr/share/nginx/site_dir/web/web

```

In fact the Drupal root, seems to me, should be

```
/usr/share/nginx/site_dir/web

```

Any ideas, please.

Many thanks.

# Answer
> 0 votes
This errors gets thrown when $alteredRoot and $root do not match during Preflight. Often occurs with incorrect web-root settings in composer.json as can be seen here: https://www.drupal.org/forum/support/upgrading-drupal/2023-08-09/drush-unavailable-after-drupal-upgrade-from-9510-to-1012

In my case there was an extra composer.json in /web (just like the original poster). Removing this resolved it for me. But other solutions offered in the D.O topic might be helpful for some, so thought to share this.

---
Tags: drush
---


# Question
Title: Is it possible to use Drupal to host an online asset?
I have tried to host a CSS asset file on Github's raw content library to call it from a local Windows JavaScript file, like this:

```
cssElement.setAttribute("href", "https://raw.githubusercontent.com/USER/REPOSITORY/main/DIRECTORY/FILE.css");

```

GitHub prevented access to such files to reduce bandwith from their servers.

I have a Drupal website, can I somehow host this CSS asset file on that website securely and then call it from the local JS file?

# Answer
> 1 votes
Breaking it down:

> can I somehow host this CSS asset file on that website

Yes. Conventionally, you might store it in a subfolder of a custom theme/module, but it's your codebase so you can essentially choose where it goes. You could put it in the public file system, for example (typically /sites/default/files), or in a folder you add to the docroot and track/deploy with git, it's really up to you.

> securely

Assuming you mean TLS, this is down to your server config. If your site is served over https, then any static assets can/will be too.

> then call it from the local JS file

Assuming your website has an accessible domain, then yes. A file uploaded to ./docroot/assets/foo.css, for example, would be available at https://bar.com/assets/foo.css. You may need to adjust CORS settings on the host website to allow this.

# Answer
> 1 votes
On a site where Drupal is installed, static files are still served first. This means that, for example, in a site that answer to https://example.com, the *assets/FILE.css* file placed in the documentation root directory of Apache server can be accessed using https://example.com/assets/FILE.css.

This happens because the .htaccess file used by Drupal contains the following directives. (The comment explains what the directives do.)

```
# Pass all requests not referring directly to files in the filesystem to
# index.php.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]

```

If you use Nginx, you need a file that is equivalent to .htaccess, which is only used by Apache Server, and that file would contains analogous directives.

If then you need the *FILE.css* to be dynamic, you can create a module that responds to the *assets/FILE.css* route and return CSS content.

---
Tags: 10
---


title: Chosen dropdown in Claro subtheme

text:
# Question
Title: Chosen dropdown in Claro subtheme
I created a subtheme for Claro theme in drupal 10. Before adding any custom code, I expected it to not be different from the parent theme, but the chosen dropdowns are off. (first pic - claro, second - claro subtheme)

This is what I have in my my\_theme.info.yml

```
name: 'My Theme'
type: theme
core: 9.x
core_version_requirement: ^9 || ^10
base theme: claro
screenshot: screenshot.png
libraries:
 - my_theme/my-theme-style
 - claro/global-styling
regions:
  header: Header
  pre_content: Pre-content
  breadcrumb: Breadcrumb
  highlighted: Highlighted
  help: Help
  content: Content
  page_top: Page top
  page_bottom: Page bottom
  sidebar_first: First sidebar
regions_hidden:
 - sidebar_first

```

I tried to add all that is under libraries, libraries-override and libraries-extend in the claro.info.yml, but nothing changes. How can I inherit also the style for chosen?

# Answer
> 0 votes
You have to specify all the components you want to use from the base theme in your subtheme .info file.

Maybe you didn't rebuild cache the time you added all the libraries and their overrides.

I see a specific component related to your case:

```
  core/drupal.dropbutton:
    CSS:
      component:
        misc/dropbutton/dropbutton.css: css/components/dropbutton.css

```

You at least need to add that (under the appropriate config), although I expect you'll want more, if not all of the settings copied from Claro info file.

---
Tags: theming, 10
---


title: What is the purpose of the Stark theme?

text:
# Question
Title: What is the purpose of the Stark theme?
Claro is for administration, Olivero is general, but what is Stark for?

> An intentionally plain theme with no styling to demonstrate default Drupal’s HTML and CSS. Learn how to build a custom theme from Stark in the Theming Guide.

If it's plain and with **no styling**, how does it demonstrate Drupal's (HTML) and **CSS**?

# Answer
> 2 votes
The theme's online documentation explains further:

> The Stark theme is provided for demonstration purposes; it uses Drupal’s default HTML markup and CSS styles. It can be used as a troubleshooting tool to determine whether module-related CSS and JavaScript are interfering with a more complex theme, and can be used by designers interested in studying Drupal’s default markup without the interference of changes commonly made by more complex themes.
>
> Users should not use it as a base theme as future core updates may break your theme.

In addition there is an issue to further discourage its use as a base theme.

---
Tags: theming, 10
---


# Question
Title: How to let users write private letters to me about a node?
I want to let users the ability to write personal letters to me based on nodes they read while letters are stored in the Drupal database itself (no emails involved) and will include these fields:

1. **Name**
2. **Email**
3. **Phone**
4. **The name of the node form which the user wrote the letter.**

Ideally, I'd want the form to be in a sidebar block but if I can't then a node containing **75% width node** text and **25% width form** column is also fine.

# Answer
Drupal's Webform module is a perfect fit for this use-case. Webform allows you to attach a form as a reference to any node and when the form is submitted, Webform keeps a record of which form was submitted, and on which node it was submitted, in a central submissions view. Whether a webform sends an email is entirely the webform author's decision. By default the only action is saving the results to the database.
> 0 votes

---
Tags: nodes, database, blocks, 10, layout-builder
---


# Question
Title: Why does RedirectResponse not work on production server?
I have a very simple custom block/form that takes a user id and jumps to their profile page. The form submitForm has this:

```
$uid = $form_state->getValue('uid');
$path = '/user/' . $uid;
$response = new RedirectResponse(Url::fromUserInput($path)->toString());
$response->send();

```

This works as expected on my local dev system and on our staging server. For some reason, it does not work on the production site (different server but same configuration as the staging server, afaik).

There are no errors. The page does do a page load but stays on the same page.

I have added a log point to capture the response object. It is identical on both the prod site and the staging site.

The only thing I have seen in the past which appears similar to this (a page load with no errors but simply fails to do anything) is from Apache mod\_security. Hosting company assures me it is not mod\_security.

Any thoughts on something which could cause this or how to further debug the issue?

# Answer
Never send a response in custom Drupal code. You can add it to $form\_state when submitting a form:

```
$form_state->setResponse($response);

```

## Why you can't send a response?

Answering the last comment. The Drupal kernel is stacked. Each layer returns a response for the request it receives. If one layer sends response headers prematurely, this will not stop the process of building the real response also sent to the client. It's unpredictable how a platform reacts to this unclear situation. In your dev environment the browser is directly connected to the web server and what you see is that it reacts on the first redirect headers received. But this can change in production ...

If you want to alter the response returned by Drupal then it's probably the best idea to use your own layer in form of a middleware. See this great answer https://drupal.stackexchange.com/a/303653/47547

However, if you can use the Symfony/Drupal API, like in this case the Form API, there is no need for that. See https://drupal.stackexchange.com/a/304037/47547
> 4 votes

---
Tags: 9
---


# Question
Title: How can I get a printable version of a node?
I have a node with a simple article in it (an `<H1>`, a bit of \<`H2`\>s and some `<p>`s).

If I print this page from the web browser as-is, I will get it with grandiose spacings, Drupal blocks, images and even JavaScript popups repeating in each printable page often.

Copy-pasting the node content into LibreOffice Writer where I can easily remove the images and don't get the Drupal blocks and the JavaScript popups was not rendered properly with some whitespaces actually turning into strange gray rectangles (are these line breaks?).
I don't use Microsoft Word so I don't have a say on this one.

Anyway, how will you suggest to get a printable version of a Drupal node?

# Answer
> 2 votes
Use the Printer and PDF versions module.

---
Tags: theming, nodes, 10
---


title: Paginated ajax form with non-sql data

text:
# Question
Title: Paginated ajax form with non-sql data
Using Drupal 8 I created a form to load data from a webservice with ajax below the form. Now i'm trying to add pagination to result, but the paginator is not been loaded, i'm doing something wrong?. I've tried to follow the guide from https://www.drupal.org/docs/7/creating-custom-modules/howtos/paging-non-sql-data but it's for Drupal 7. Thanks in advance.

Here's my code:

$response contains an array with data from webservice.

$total contains the record of results

```
//number of records per page
$num_per_page = 3;
//get current page
$current_page = pager_default_initialize($total, $num_per_page);
$chunks = array_chunk($response, $num_per_page);
$current_page_items = $chunks[$current_page];
foreach ($current_page_items as $i => $item) {
  $current_page_items[$i] = array(
    '#theme' => 'ajax_search',
    '#item' => $item,
  );
}

// Generate the render array for our page
$render_array['page'] = array (
  '#theme' => 'item_list',
  '#items' => $current_page_items,
);
// Calls Drupal standard pager theme and set 5 page links on pager
$render_array['pager'] = array (
  '#theme' => 'pager',
  '#quantity' => 5,
);

$response = new AjaxResponse();
$response->addCommand(
  new HtmlCommand(
    '.result_message',
    $render_array)
  );
return $response;

```

# Answer
> 0 votes
Old question but I've spent a lot of time to find the solution so decided to share it here.

So I have some table inside some $form and list of rows - need to init pager for this.

```
  // Number of items on the one page.
  $per_page = 10;
  $pager = $this->pagerManager->createPager(count($rows), $per_page);
  $current_page = $pager->getCurrentPage();
  $chunks = array_chunk($rows, $per_page, TRUE);

  // Add a wrapper to the $form
  $form['#prefix'] = '<div id="form-wrapper-for-ajax-pager">';
  $form['#suffix'] = '</div>';

```

Next - create a table and pager render elements.

```
    'table' => [
      '#type' => 'table',
      '#header' => [
        $this->t('bla-bla'),
        $this->t('bla-bla'),
        $this->t('bla-bla'),
        '...',
      ],
      '#rows' => $chunks[$current_page],
    ],
    'ajax_pager' => [
      '#type' => 'pager',
      '#element' => 0,
      '#route_name' => 'example_module.ajax.pager', // Rout to update table by ajax.
    ],

```

Next - need to create the route.

```
 example_module.ajax.pager:
  path: '/ajax/example/pager'
  defaults:
    _controller: '\Drupal\example_module\Form\BlaBlaForm::updatePager'
  requirements:
    _access: 'TRUE'

```

Create updatePager Ajax callback. Just rerender the form and replace it.

```
  /**
   * Ajax callback for the pager.
   */
  public function updatePager(): AjaxResponse {
    $response = new AjaxResponse();
    $form = $this->formBuilder->getForm('\Drupal\example_module\Form\BlaBlaForm');
    $response->addCommand(new ReplaceCommand('#form-wrapper-for-ajax-pager', $form));
    return $response;

```

}

In the theme create new suggestions.

```
  if ($hook === 'pager' && $variables['pager']['#route_name'] === 'example_module.ajax.pager') {
    $suggestions[] = 'pager__ajax';
  }

```

And create a template pager--ajax.html.twig (Just need to copy the original pager.html.twig from the system module)

Inside this template to all links need to add the class "use-ajax"

example:

```
<a href="{{ items.previous.href }}" title="{{ 'Go to previous page'|t }}" rel="prev" class="use-ajax">

```

Thats all.

---
Tags: ajax, paging
---


# Question
Title: How do I create a Url object from the public file URI?
How can a `Url` object be created from a file URI? Using the URI for a public file as a parameter for `Url::fromUri()` gives this error.

> UnexpectedValueException: External URLs do not have internal route parameters. in Drupal\Core\Url-\>getRouteParameters().

```
$file = File::load($file_id);
$file_uri = $file->getFileUri();
$menu_link['url'] = Url::fromUri($file_uri);

```

Here is the class and method in question: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Url.php/function/Url%3A%3AfromUri/8.2.x

Note that I don't need to get the actual URL in string format, I need to generate a Url object from the Url class that points to a file. This is because I am attempting to modify the path of a menu link and unfortunately that is not a simple matter of providing a URL string in Drupal 8.

This is the code I am using.

```
function teeprop_preprocess_menu__main(&$vars) {
  foreach($vars['items'] as $key => $menu_link) {
    if (!empty($menu_link['url']->getRouteParameters())) {
      $node_id = $menu_link['url']->getRouteParameters()['node'];
      $node_entity = Node::load($node_id);
      $node_type = $node_entity->getType();

      if ($node_type == 'pdf') {
        $file_id = $node_entity->get('field_pdf_file')->getValue()[0]['target_id'];
        $file = File::load($file_id);
//         $file_url = $file->url();
        $file_uri = $file->getFileUri();
        $vars['items'][$key]['url'] = Url::fromUri($file_uri, ['absolute' => TRUE]);
      }
    }
  }
}

```

# Answer
I believe that the following should do what you need:

```
Url::fromUri(
  File::load(1)->url()
);

```

(I've tested this in a local 8.4.2 installation, and it yields a Url object that can be rendered without an error.)

The functions are admittedly named very misleadingly. Even though `::fromUri()` *sounds* like it should accept the return value of `::getFileUri()`, namely `public://...`, it actually only accepts `internal:`, `base:`, `entity:` and "external" URLs.

So you need to use `->url()` to get the external URL of the file, and then pass that to `::fromUri()`.
> 2 votes

# Answer
```
$url = \Drupal::service('file_url_generator')->generate($file_uri);
$form['elements']['my_link'] = Drupal\Core\Link::fromTextAndUrl('Your_link_title', $url)->toRenderable();

```

You can also use other methods from `Drupal\Core\File` like `generateAbsoluteString`,
> 0 votes

# Answer
In Drupal 10

```
$file = File::load($file_id);
$vars['items'][$key]['url'] = $file->createFileUrl();

```

That will give you the relative URL as a string. Something like `"/sites/default/files/my_file.pdf"`. If you want an absolute URL for some reason you can use `$file->createFileUrl(FALSE)`.
> 0 votes

---
Tags: 8, files, uri
---


title: Rendering for AJAX

text:
# Question
Title: Rendering for AJAX
Within my module I have a button that calls an ajax request. The controller for this request is to collect some data, then render a Twig template using that data.

Using Drupal 10, how do I render the data/twig file, assign it to a variable, then send it back so the JS script can then place the code in the page?

Thanks.

# Answer
> 1 votes
This is how I got it to work. Thanks to Angrytoast on Slack for the pointer!

```
public function paginateListing(Request $request) {
$rc = new RemindersController();
\Drupal::service('page_cache_kill_switch')->trigger();
$activeReminders = $rc->getAllActiveReminders($request->get('numrows'), $request->get('goto'));
$tableData = $rc->getReminderStatus($activeReminders);
$build = [
  '#theme' => 'rmdrs_table_listing',
  '#activeReminders' => $tableData,
  '#pagination' => array(
    'page_now' => (int) $_SESSION['rmdrs']['pager']['page_now'],
    'next_page' => (int) $_SESSION['rmdrs']['pager']['next_page'],
    'previous_page' => (int) $_SESSION['rmdrs']['pager']['previous_page'],
  ),
];

$output = \Drupal::service('renderer')->render($build);
return new JsonResponse($output);

```

}

The service is what I needed, along with building a $build array. I also had to create an entry in my .module file's hook\_theme method.

```
'rmdrs_table_listing' => array(
  'variables' => array(
    'activeReminders' => null,
    'pagination' => null,
  ),
),

```

---
Tags: ajax
---


title: What version of Drupal am I running?

text:
# Question
Title: What version of Drupal am I running?
I have a really old site that has been neglected for almost 20 years, it runs Drupal, only problem is that I cannot figure out which version of Drupal I am running.

Index.php has this:

// $Id: index.php,v 1.90.2.1 2006/12/12 13:50:59 killes Exp $

# Answer
> 2 votes
That's a version somewhere between 4.7.5 and 4.7.11.

You mentioned in a deleted comment that you were hoping to upgrade one version at a time, presumably to a much more recent version; to be honest, I'm not sure there's much hope of upgrading a site that old.

I don't think there was an official migration path from 4.x to 5.x, maybe not even a proper one for 5.x to 6.x. 6.x to 7.x had a path, but was a pretty challenging process if memory serves. Same again for 7.x to 8.x.

It might be worth considering whether a rebuild, or a custom migration straight out of the old database into Drupal 10, is a better option.

# Answer
> 2 votes
That comment is one of those comments CVS created by replacing the `$Id$` string present in files.
In that comment you read the CVS username of the person who committed the last change to that file, killes@www.drop.org, who was a Drupal 4.7 core maintainer, and who helped to push out the release during Dries' absence between March and April 2006.

To answer your question, that site is running on Drupal 4.7. It could be Drupal 4.7.5, 4.7.6, 4.7.7, 4.7.8, 4.7.9, 4.7.10, or 4.7.11, for which the first lines of the *index.php* file are the following ones.

```
// $Id: index.php,v 1.90.2.1 2006/12/12 13:50:59 killes Exp $

/**
 * @file
 * The PHP page that serves all page requests on a Drupal installation.
 *
 * The routines here dispatch control to the appropriate handler, which then
 * prints the appropriate page.
 */

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

$return = menu_execute_active_handler();

```

If you look at the same lines for that same file in Drupal 4.7.4, you will see they are the following ones.

```
<?php
// $Id: index.php,v 1.90 2006/01/27 18:51:51 dries Exp $

/**
 * @file
 * The PHP page that serves all page requests on a Drupal installation.
 *
 * The routines here dispatch control to the appropriate handler, which then
 * prints the appropriate page.
 */

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

$return = menu_execute_active_handler();

```

If you look at the content of the other files, you could be able to understand exactly which Drupal 4.7 version is, but that would not help you much, as migrating a Drupal 4.7 site would be problematic independently from the exact Drupal 4.7 version the site is using.

---
Tags: migrations
---


title: Sidebars don't appear

text:
# Question
Title: Sidebars don't appear
I am trying to add two sidebar regions, `sidebar_first` and `sidebar_second`, one region on top the other region.
Both regions should share the CSS styling from `sidebar` region but my problem is that both new sidebar regions don't appear at all, even though each one of them contain blocks.
`sidebar` doesn't contain any block.
What have I done wrong?

---

**subtheme.info.yml**

```
regions:
  sidebar_first: 'Sidebar First'
  sidebar_second: 'Sidebar Second'
  sidebar: 'Sidebar'

```

**templates/layout/page.html.twig** includes the following code

```
<div class="sidebar-grid grid-full">
  <main role="main" class="site-main">
    {{ page.content_above }}
    {{ page.content }}
  </main>
  {{ page.sidebar_first }}
  {{ page.sidebar_second }}
  {{ page.sidebar }}
</div>

```

**templates/layout/region--sidebar\_first.html.twig**

```
{%
  set classes = [
    'region',
    'region--sidebar',
    'region--' ~ region|clean_class,
  ]
%}

{{ attach_library('MY_SUBTHEME_NAME/sidebar') }}

{% if content %}
  <aside{{ attributes.addClass(classes) }}>
    {{ content }}
  </aside>
{% endif %}

```

**templates/layout/region--sidebar\_second.html.twig**

```
{%
  set classes = [
    'region',
    'region--sidebar',
    'region--' ~ region|clean_class,
  ]
%}

{{ attach_library('MY_SUBTHEME_NAME/sidebar') }}

{% if content %}
  <aside{{ attributes.addClass(classes) }}>
    {{ content }}
  </aside>
{% endif %}

```

Flushing all Drupal cache and all browser cache.

# Answer
I had to do these actions to get the new sidebar regions to appear:

## First action

I had to add a **placeholder block** empty of any content to the `sidebar` region, for that region to be parsed and used as a base to parse the other two new sidebar regions.

## Second action

I had to do some CSS with classes Drupal creates.
Drupal has created the following two classes and I had to work with them:

```
.region--sidebar-first
.region--sidebar-second

```

Note that these have h hyphen (`-`) after sidebar instead of an underscore (`_`) as I have originally used.
> 0 votes

---
Tags: theming, 10
---


# Question
Title: How can I alter a field group programmatically?
How can I alter a field group description programmatically? If I dump the $form variable in my implementation of hook\_form\_alter, my fields are in the array, but my field groups are not. What function do I need to use?

# Answer
Field group has a bunch of its own hooks, listed in the field\_group.api.php file within the module.

To alter the form element(s) you can use `hook_field_group_form_process_alter()`, e.g.:

```
function MODULE_field_group_form_process_alter(array &$element, &$group, &$complete_form) {
  $element['#description'] = $foo;
}

```
> 2 votes

---
Tags: 10
---


title: Add target blank to an image link

text:
# Question
Title: Add target blank to an image link
How do I add target='blank' to a href in a Drupal 8 custom module? Below I have the image being wrapped by the uri. I don't know how to add target='blank'

```
  $element[$delta] = array(
        '#theme' => 'image_formatter',
        '#item' => $item,
        '#image_style' => '',
        '#url' => $uri,
      );

```

# Answer
I think (not checked) that you need to add "target" =\> "\_blank" ((note underscore)) to the #attributes array. However, that attribute must appear on an element that encloses the , not the itself, and I'm not sure if adding it to the structure in your question would do that... have a go.

If it doesn't work, simplest option is to override the twig template in question and then extend attributes with "attributes.setAttribute('target', '\_blank')" in the appropriate place.

Determine the right file name to override the twig template with by using twig debug (look in the sites/default/local.services.yml for the setting to change). , and then view-source of the page (noting there are now lots and lots of html comments), find the existing image html and look before it to see the table of possible templates. There is lots more about this in the official Drupal documentation on twig.
> 0 votes

# Answer
You can set the attributes of the link like this

```
  $element[$delta] = array(
        '#theme' => 'image_formatter',
        '#item' => $item,
        '#image_style' => '',
        '#url' => Url::fromUri($uri, ['attributes'=>['target'=>'_blank']]),
      );

```
> 0 votes

---
Tags: 8, theming
---


title: How do I add HTML markup to the title?

text:
# Question
Title: How do I add HTML markup to the title?
I am trying to alter my title to include html. I have tried the following

```
function MODULENAME_views_pre_render(\Drupal\views\ViewExecutable $view) {
  if ($view->id() == 'products_test') {
    foreach($view->result as $value) {
      $value->_object->set('title', 'test - <b>My new Title</b>');
    }
  }
}

```

This outputs the title as `test - <b>My new Title</b>`, rather than rendering the text as HTML markup.

I tried passing the title to `decode_entities()`, but nothing changed.

I am using the *Full content* mode, rather than the *Fields* mode, if this makes any difference.

# Answer
If you want to alter html, generally you'll be working with hook\_preprocess\_hook or a twig template override. This is the case for views as well. In the case of views, the template that renders the title is `views-view.html.twig`.

EDIT: Fastest way is just to use #markup

```
function my_module_preprocess_views_view(&$variables) {
  $variables['title'] = [
    '#markup' => 'test - <b>My new Title</b>'
  ];
}

```

So if you wanted to render the title with a **b** tag, you could do:

```
function my_module_preprocess_views_view(&$variables) {
  $existing_title = $variables['title'];
  $variables['title'] = [
    '#type' => 'inline_template',
    '#template' => '<b>{{ title }}</b>',
    '#context' => [
      'title' => $existing_title,
    ],
  ];
}

```

However, it's maybe not ideal to use tags for presentation and better to use classes and CSS styling. If you just want to add a CSS class to target, you could do a similar thing:

```
function my_module_preprocess_views_view(&$variables) {
  $existing_title = $variables['title'];
  $variables['title'] = [
    '#type' => 'container',
    '#attributes' => [
      'class' => [
        'views-title', // or whatever
      ],
    ],
    '#value' => $existing_title
  ];
}

```

Both `#container` and `#inline_template` are render elements, and there are a lot available to you.

Of course, depending on what your theme and other modules are doing, the existing `$variables['title']` might not just be a string, so you may need to adjust accordingly.
> 2 votes

# Answer
To change a view title, you can implement `hook_preprocess_views_view()`, which is what the *Views UI* module does, with `views_ui_preprocess_views_view()`.

```
// Render title for the admin preview.
if (!empty($view->live_preview)) {
  $variables['title'] = [
    '#markup' => $view->getTitle(),
  ];
}

```

Using that code avoids the HTML markup used in the title is escaped/sanitized.

When the *View UI* module is installed, and you want to set the same view title in the the admin preview, the hook implemented by your module needs to be invoked after the one implemented by the *View UI* module. Keep in mind that `views_ui_preprocess_views_view()` uses also the following code.

```
if (!empty($view->live_preview) && \Drupal::moduleHandler()->moduleExists('contextual')) {
  $view->setShowAdminLinks(FALSE);
  foreach (['title', 'header', 'exposed', 'rows', 'pager', 'more', 'footer', 'empty', 'attachment_after', 'attachment_before'] as $section) {
    if (!empty($variables[$section])) {
      $variables[$section] = [
        '#theme' => 'views_ui_view_preview_section',
        '#view' => $view,
        '#section' => $section,
        '#content' => $variables[$section],
        '#theme_wrappers' => [
          'views_ui_container',
        ],
        '#attributes' => [
          'class' => [
            'contextual-region',
          ],
        ],
      ];
    }
  }
}

```

As side note, the default views-view.html.twig template used by the Views module used two template variables more: `title_prefix` and `title_suffix`.

```
  {{ title_prefix }}
  {{ title }}
  {{ title_suffix }}

```
> 1 votes

# Answer
The other answers here are either clunky, don't cover all cases, or open security vulnerabilities. Instead, check out HTML Title module.
> 0 votes

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


# Question
Title: Give all users including anonymous ones the option to add nodes of certain content types to a list like "interested", at least once
I'd like to give all users including anonymous ones the option to add nodes of certain content types to a list like "interested", at least once.

The logic is identical to that of a shopping cart in ecommerce websites **but this website is not ecommerce and there is no payment mechanism and even no `submit` button** so the user can just add each node at least once to the list, increment or decrement (`zero = deleted`).

How to do that if I want the data saved in Drupal database?

# Answer
OK here we go:

Once you get through all the below you should be fine.

Do it all on the frontend then when want to save this data you now need to know

1. Look in to creating a custom module https://www.drupal.org/docs/develop/creating-modules
2. look in to how to create custom tables in a module (hook\_schema) https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Database%21database.api.php/function/hook\_schema/9
3. look in to adding a controller to your new module https://www.drupal.org/docs/creating-custom-modules/step-by-step-tutorial-hello-world/adding-a-basic-controller
4. Use Ajax to post Data to your new controller see this to get you to start Googling https://www.drupal.org/project/2958601/issues/3037313

take that posted data and save it to your custom table with reference to the user who is posting it which you can get in your controller eg \Drupal::currentUser();

5. Learn how to save the data https://www.drupal.org/docs/drupal-apis/database-api/insert-queries
6. (Bonus) learn how to use this data with views https://api.drupal.org/api/drupal/core!modules!views!views.api.php/function/hook\_views\_data/8.2.x#:~:text=function%20hook\_views\_data&text=Describe%20data%20tables%20and%20fields,plugins%20topic%20for%20more%20information.
> 0 votes

---
Tags: nodes, commerce, javascript, ajax, 10
---


# Question
Title: How to switch template for search results without using views and display modes?
I want to show my Drupal 10 Solr search results in either grid view or list view. I set this up using Views and Display Modes, and I have icons on the page which simply link to the URLs of the different display modes.

However I am using Facets with my search, and using the above approach requires setting up duplicate Facet Blocks for each display mode. This is inefficient and difficult to maintain.

Is there a more efficient way of re-rendering the same page but with a different set of templates for displaying the search results?

# Answer
There is a solution for this limitation of Facets applying to only one display in one view, discussed here: https://www.drupal.org/project/facets/issues/2826650

The workaround consists of altering the search query event and overriding the checkbox widget for the facet blocks.
> 0 votes

---
Tags: views, theming, search
---


# Question
Title: How to add a class to the site logo of the system branding block
I'd like to add a class of 'svg' to my site\_logo img itself using template preprocess. Here's what I have written:

```
 function mythemename_preprocess_block__system_branding_block(&$variables) {
      $variables['elements']['content']['site_logo']['attributes']['class'][] = 'svg';
      kint($variables);
 }

```

The kint($variables) readout for where I'd expect my class to be shows *DEPTH TOO GREAT*. See:

I've seen some documentation saying it has to do with Kint's depth limit, which doesn't seem right as the preprocess isn't very complex. It suggested using `+Kint::dump();`, which I tried and can't seem to get working. `+Kint::dump($variables)` didn't work.

# Answer
You don't need to dig into `$variables['element']`. In a block preprocess function, the content of the block is available in `$variables['content']`, so you could use the following code.

```
$variables['content']['site_logo']['#attributes']['class'][] = 'svg';

```

Edit:

Altough this is generally valid for blocks, it doesn't work for the system branding block. The branding block overrides the block template with **block--system-branding-block.html.twig**, where the output of `{{ content }}` is removed, which breaks the normal rendering of the block. Instead the template contains the html markup for the `<img>` tag directly:

```
{% extends "block.html.twig" %}
{#
/**
 * @file
 * Theme override for a branding block.
 *
 * Each branding element variable (logo, name, slogan) is only available if
 * enabled in the block configuration.
 *
 * Available variables:
 * - site_logo: Logo for site as defined in Appearance or theme settings.
 * - site_name: Name for site as defined in Site information settings.
 * - site_slogan: Slogan for site as defined in Site information settings.
 */
#}
{% block content %}
  {% if site_logo %}
    <a href="{{ path('<front>') }}" title="{{ 'Home'|t }}" rel="home">
      <img src="{{ site_logo }}" alt="{{ 'Home'|t }}" />
    </a>
  {% endif %}
  {% if site_name %}
    <a href="{{ path('<front>') }}" title="{{ 'Home'|t }}" rel="home">{{ site_name }}</a>
  {% endif %}
  {{ site_slogan }}
{% endblock %}

```

To reinstate the correct behavior you could override **block--system-branding-block.html.twig** in your theme and replace the `<img>` markup with the render array:

```
{{ content.site_logo }}

```

Then the changes made in preprocess are effective again.

Or simply go along with the template as it is now and add the attributes to the html markup of the template.
> 5 votes

# Answer
Another possibility:

```
 function mythemename_preprocess_block__system_branding_block(&$variables) {
    $variables['logo_class'] = 'svg';
 }

```

... and in the Twig template:

```
<img src="{{ site_logo }}" class="{{ logo_class }} alt="{{ 'Home'|t }}" />

```
> 0 votes

---
Tags: 8, theming
---


title: Add target _blank on ckeditor5

text:
# Question
Title: Add target _blank on ckeditor5
I'm using the experimental ckeditor5 editor on my drupal 9 project. I have the need to allow the editor to choose whether to open a link in a new tab (target: \_blank) or in the same tab.

Usually there where possibilities on the link field in the editor to specify this settings, but I found out here https://www.drupal.org/project/drupal/issues/3247683 that somehow on D9 it has been removed.

Still, I cannot understand how to allow the editor to specify the target on a link, no option is showing up neither I know where I could allow these.

# Answer
You can use the Editor Advanced Link module to add the ability to open links in a new window. (It would be nice for this to be in Core, but at least there's a contrib solution!)

The module enables these settings in the text format filters: ARIA label () Title () CSS classes () ID () Open in new window () Link relationship ()
> 0 votes

---
Tags: 9, wysiwyg
---


title: Missing or invalid themes

text:
# Question
Title: Missing or invalid themes
I created 2 custom themes a while ago and I deleted them since I don't need them anymore.

Although I deleted all the files, I am still getting this error.

> Missing or invalid themes
> The following themes are marked as installed in the core.extension configuration, but they are missing.

Is there a way to avoid this error message?

# Answer
You need to **uninstall** modules and themes before removing the files.

To fix:

1. Restore the deleted themes (if you don’t have them, create stub themes with the same machine names and a single .info.yml file each describing them as a theme)
2. Uninstall the themes using the UI
3. Remove the files again

The alternative is manually editing the active configuration, which is potentially much more messy.
> 3 votes

# Answer
If the theme is not there anymore and you cannot put the files back, you can use drush to force uninstall it (replace MYTHEME with the name of your theme).

```
drush eval "\$theme_data = \Drupal::config('core.extension')->get('theme'); unset(\$theme_data['MYTHEME']); \Drupal::configFactory()->getEditable('core.extension')->set('theme', \$theme_data)->save();"

drush php-eval "\Drupal::keyValue('config.entity.key_store.block')->delete('theme:MYTHEME');"

drush cr

```
> 1 votes

---
Tags: 8
---


# Question
Title: Why won't my fieldtype plugin save the settings form values?
I have a custom field. The FieldType plugin provides a settings form that adds a field to the form. The field is a group of checkboxes...think the paragraph types selection when adding a entity revisions field to a content type.

The form displays correctly. Two of the checkboxes are checked by default correctly. But the values don't get saved.

I've put a breakpoint where the settings are retrieved:

```
   $def = $items->getFieldDefinition();
   return $def->getSetting('allowed_schemes') ?? UrlItem::getSchemes();

```

which returns null, as does $def-\>getSettings(). I've also put a breakpoint in FieldItemBase where it retrieves the settings...also null.

It might have something to do with the schema method. I haven't figured out yet what I need to put there.

Here is my plugin.

```
<?php

namespace Drupal\url_text\Plugin\Field\FieldType;

use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * Defines the 'url' entity field type.
 *
 * @FieldType(
 *   id = "url",
 *   label = @Translation("URL"),
 *   description = @Translation("A field containing a plain string URL value."),
 *   category = @Translation("General"),
 *   default_widget = "url_textfield",
 *   default_formatter = "url"
 * )
 */
class UrlItem extends FieldItemBase {

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition): array {
    return [
      'columns' => [
        'value' => [
          'type' => $field_definition->getSetting('is_ascii') === TRUE ? 'varchar_ascii' : 'varchar',
          'length' => (int) $field_definition->getSetting('max_length'),
          'binary' => $field_definition->getSetting('case_sensitive'),
        ],
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function isEmpty(): bool {
    $value = $this->getValue();
    return empty($value['value']);
  }

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition): array {

    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function fieldSettingsForm(array $form, FormStateInterface $form_state): array {

    $settings = $this->getSettings();

    $element['allowed_schemes'] = [
      '#type' => 'checkboxes',
      '#title' => $this->t('Allowed Schemes'),
      '#options' => $this->getSchemes(),
      '#default_value' => $settings['allowed_schemes'] ?? ['http', 'https'],
      '#description' => $this->t('Allowed URL schemes for the URL. If none are selected, then all are allowed.'),
    ];

    return $element;
  }

  /**
   * Provide an array of URL schemes to allow.
   */
  public static function getSchemes(): array {

    return [
      'http' => 'http://',
      'https' => 'https://',
      'ftp' => 'ftp://',
      'mailto' => 'mailto://',
      'sftp' => 'sftp://',
      'ssh' => 'ssh://',
      'tel' => 'tel://',
    ];
  }

}

```

# Answer
> -1 votes
Shortest way to answer is that my plugin was a mess. Lesson (re)learned...try to find examples of each method in an exemplar that takes the mystery out of the method.

Sorry, I had pasted the plugin again, but as pointed out, nothing meaningful had changed in it. I believe the issue was that I did not have a schema for the settings.

I added the file *url\_text.schema.yml* to src/Plugin/Field/FieldType

```
field.field_settings.url:
  type: mapping
  label: 'URL settings'
  mapping:
    allowed_schemes:
      type: string
      label: 'Allowed Schemes'

```

The values are now saved.

---
Tags: plugins
---


# Question
Title: Login via POST method returns a 403 error
I have enabled the Rest and the Basic Auth core modules on a Drupal 10 site, but I am unable to log in using the following code. I keep getting a 403 error.

```
$drupalUsername = 'myuser';
$drupalPassword = 'mypass';
$drupalApiEndpoint = 'https://mysite.com/user/2'; // Replace with the correct user ID

$authHeader = 'Basic Authentication ' . base64_encode($drupalUsername . ':' . $drupalPassword);

$ch = curl_init($drupalApiEndpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [$authHeader]);

$response = curl_exec($ch);
curl_close($ch);

echo $response;

```

Do you have any hint?

PS

Got it working with two small changes!!!

```
$drupalApiEndpoint = 'https://mysite.com/user/2?_format=json'; // Replace with the correct user ID

$authHeader = 'Authorization: Basic ' . base64_encode($drupalUsername . ':' . $drupalPassword);

```

# Answer
> 1 votes
There are two changes necessary in the code:

* The endpoint should be `'https://mysite.com/user/login?_format=json'`
* ~~The headers should include the *Accept* one, which must be set to `'application/json'`~~ (*****)

If, without being logged in, you try to access a user profile page, which is what happens when the request is for https://mysite.com/user/2, you would get either:

* a 403 error, if anonymous users are not allowed to access user profiles (The *View user information* permission is not given to anonymous users.)
* the user profile, if anonymous users are allowed to access user profiles (The *View user information* permission is given to anonymous users too.)

Drupal will not redirect from https://mysite.com/user/2 to https://mysite.com/user/login. That would eventually happen when the requested page is https://mysite.com/user.

(*****) - Earlier Drupal 8 versions used the *Accept* header, but that was latter changed (starting from Drupal 8.0.0-beta12). See Accept header based routing got replaced by a query parameter.

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


# Question
Title: Configure default domains for new content
We're using the Domain Access module to assign content to different domains.

When creating new content the default domain record is checked, but not the others.

The desired behavior: Example.com should also be checked by default when creating new content. (regardless of the content type)

Where would this behavior be configured/coded?

Drupal Version: 9.5.11
Domain Access: 8.x-1.0-beta8

# Answer
> 0 votes
As @apaderno mentioned, one possible solution is to manipulate the form field (field\_domain\_access).

```
function module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  try {
    if (array_key_exists('field_domain_access', $form)) {
      $node = $form_state->getFormObject()->getEntity();

      if ($node->isNew()) {
        $form['field_domain_access']['widget']['#default_value'] = ['www_example_ch', 'www_example_com'];
      }
    }
  } catch(\Throwable $any) {
    \Drupal::logger('global')->info('Exception: %msg', ['%msg' => $any->getMessage() ]);;
  }
}

```

I'm not a big fan of this approach. Probably I don't understand the system good enough yet.

---
Tags: domain-access
---


# Question
Title: How to resolve TypeError: Drupal\Core\Field\FieldTypeCategory::getDescription()
I updated Drupal core to 10.2.0 yesterday. For reference, I am using the commerce module version 2.32. After the update, I am unable to create a new field (Commerce-\>Configuration-\>Order Item Types-\>Manage Fields-\>Create New Field). I receive the following error:

> The website encountered an unexpected error. Try again later.
>
> TypeError: Drupal\Core\Field\FieldTypeCategory::getDescription(): Return value must be of type Drupal\Core\StringTranslation\TranslatableMarkup, string returned in Drupal\Core\Field\FieldTypeCategory-\>getDescription() (line 26 of core/lib/Drupal/Core/Field/FieldTypeCategory.php). Drupal\field\_ui\Form\FieldStorageAddForm-\>buildForm() call\_user\_func\_array() (Line: 536)
> Drupal\Core\Form\FormBuilder-\>retrieveForm() (Line: 283)
> Drupal\Core\Form\FormBuilder-\>buildForm() (Line: 73)
> Drupal\Core\Controller\FormController-\>getContentResult() call\_user\_func\_array() (Line: 123)
> Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() (Line: 627)
> Drupal\Core\Render\Renderer-\>executeInRenderContext() (Line: 121)
> Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>wrapControllerExecutionInRenderContext() (Line: 97)
> Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() (Line: 181)
> Symfony\Component\HttpKernel\HttpKernel-\>handleRaw() (Line: 76)
> Symfony\Component\HttpKernel\HttpKernel-\>handle() (Line: 58)
> Drupal\Core\StackMiddleware\Session-\>handle() (Line: 48)
> Drupal\Core\StackMiddleware\KernelPreHandle-\>handle() (Line: 106)
> Drupal\page\_cache\StackMiddleware\PageCache-\>pass() (Line: 85)
> Drupal\page\_cache\StackMiddleware\PageCache-\>handle() (Line: 48)
> Drupal\Core\StackMiddleware\ReverseProxyMiddleware-\>handle() (Line: 51)
> Drupal\Core\StackMiddleware\NegotiationMiddleware-\>handle() (Line: 36)
> Drupal\Core\StackMiddleware\AjaxPageState-\>handle() (Line: 51)
> Drupal\Core\StackMiddleware\StackedHttpKernel-\>handle() (Line: 704)
> Drupal\Core\DrupalKernel-\>handle() (Line: 19)

I found the same issue here, but this is specific to the bibleref module which I do not have installed. The same error arises if I try to create a new field for any content type. How can I resolve this issue?

# Answer
Drupal core 10.2.0 throws this for any field type that does not have a "description" in its definition. As @clifen noted, this is what this core issue is about.

It is fixed in drupal/core 10.2.1.
> 2 votes

---
Tags: 10, upgrading
---


# Question
Title: how to change ckeditor4 classses for alignment?
As you know ckeditor4 has alignment buttons. when you press on each button, it adds a default class.

rteleft for left, rteright for right, rtecenter for center and rtejustify for justify alignment.

I want to know a way to change these default css classes? for example for left align, I want to use uk-text-left or for center align, I want uk-text-center

# Answer
I found the solution.

Just need to add this config to custom javascript confiurations in advanced section of ckeditor profile.

```
config.justifyClasses = [ 'uk-text-left', 'uk-text-center', 'uk-text-right', 'uk-text-justify' ];

```
> 0 votes

---
Tags: wysiwyg
---


# Question
Title: How can I get the token value added at end of css and js files?
As you know in drupal 7 css and js files added to the rendered page. at end of href or src values you see a token.

for example

```
<link type="text/css" rel="stylesheet" href="/sites/all/themes/uikit/css/icomoon.css?s6y431" media="all" />

<link type="text/css" rel="stylesheet" href="/sites/all/themes/uikit/css/styles.css?s6y431" media="all" />

```

I want to know is there any way that I can access the variable that take "s6y431" value?

# Answer
> 2 votes
That value is stored in a persistent variable (*css\_js\_query\_string*) which is used by either `drupal_pre_render_styles()` or `drupal_pre_render_scripts()`.

```
// A dummy query-string is added to filenames, to gain control over
// browser-caching. The string changes on every update or full cache
// flush, forcing browsers to load a new copy of the files, as the
// URL changed. Files that should not be cached (see drupal_add_js())
// get REQUEST_TIME as query-string instead, to enforce reload on every
// page request.
$default_query_string = variable_get('css_js_query_string', '0');

```

```
// A dummy query-string is added to filenames, to gain control over
// browser-caching. The string changes on every update or full cache
// flush, forcing browsers to load a new copy of the files, as the
// URL changed.
$query_string = variable_get('css_js_query_string', '0');

```

Its value is initialized by `_drupal_flush_css_js()`, but code needing it should use `'0'` as default value for *css\_js\_query\_string*.

---
Tags: 7
---


# Question
Title: REGEX_REPLACE error when running DB query from update hook
This MySQL statement runs fine on MySQL 8.0.33-0ubuntu0.20.04.2:

```
mysql> UPDATE node__body SET body_value = REGEXP_REPLACE(body_value, "<img.*base64.*>", "");
Query OK, 0 rows affected (1.58 sec)
Rows matched: 14136  Changed: 0  Warnings: 0

```

However, when I run the command in an update hook like this:

```
$database = \Drupal::database();
$database->query('UPDATE node__body SET body_value = REGEXP_REPLACE(body_value, "<img.*base64.*>", "")');

```

There is an error complaining about unknown column.

```
>  [error]  SQLSTATE[42S22]: Column not found: 1054 Unknown column '<img .*base64.*>' in 'field list': UPDATE node__body SET body_value = REGEXP_REPLACE(body_value, "<img .*base64.*>", ""); Array

```

# Answer
Was able to get `REGEXP_REPLACE` to work with the following way:

```
$database->update('node__body')
  ->expression('body_value', "REGEXP_REPLACE(body_value, '<img.*base64.*>', '')")
  ->execute();

```
> 0 votes

---
Tags: database, 10
---


# Question
Title: Is there a starter theme? If so what is it?
Does Drupal have a starter theme? If so what is it?

If this is Stark<sup>, , </sup>, then I don't think it's practically **the** starter theme of Drupal.

# Answer
> 3 votes
The most popular are (counting only Drupal 8/9/10):

The contrib Stable is used to upgrade Drupal 8/9 sites, it shouldn't be used for new Drupal 10 projects. There is no replacement for Stable, put `base theme: false` in your theme info file if you only want to depend on core styling or use the new https://www.drupal.org/docs/core-modules-and-themes/core-themes/starterkit-theme

---
Tags: 10
---


title: Programmatically delete blocks

text:
# Question
Title: Programmatically delete blocks
Is there a way to programmatically delete blocks in a Drupal 10 site?

I need to delete the *Powered by Drupal* block.

# Answer
> 0 votes
Delete all instances of the Powered by Drupal block:

```
$blocks = \Drupal::entityTypeManager()->getStorage('block')
  ->loadByProperties(['plugin' => 'system_powered_by_block']);
foreach ($blocks as $block) {
  $block->delete();
}

```

---
Tags: blocks, 10
---