# Question
Title: Using Views to list nodes that have the same field value as current node
I have a content type with a field. I need to create a block that lists all the nodes with the same value for that field.

Doing this for related taxonomy terms is easy: *Contextual Filter \> Taxonomy term ID \> Taxonomy term ID from URL \> Limit terms by vocabulary \> Vocabulary*.

I cannot make to the contextual filter work for that field. Under all combinations I tried, either everything appears or nothing does.

# Answer
> 1 votes
Views Token Argument is the module you are looking for. It allows you to use Tokens in your contextual filters fixed values.

Here is what to do to have your View working:

1. Set a contextual filter on your field (let's say Publication with machine name "field\_publication") and under the section "When the filter value is not available", select `Provide a default value` and choose `Token` from the select list. Now, you need to fill the Token textfield with the token name (e.g. \[node:field\_publication\]). Save your filter.
2. Add a second contextual filter on "Content: ID", select `Provide default value` and `Content ID from URL` and under the "More" section, check the `Exclude` box to have the view return all matching nodes but the current one. Save your filter and your view.
3. Set your block display and you're done.

PS: Maybe it is unrelated but when using this "Token" option, the View preview does not work anymore for me.

---
Tags: views
---


# Question
Title: Find all webpages without internal links
In MediaWiki there is a nice feature allowing the user to list all webpages without internal links in that MediaWiki website.

Is there a way to get such data in Drupal?

# Answer
> 1 votes
No, there isn't. Drupal is not a wiki and it doesn't function like one.

In Drupal, a simple "page" may include:

* a node of a content type ("Page" or "Article"
* one or more menus (header and footer, for example)
* one or more blocks (footer, sidebar, information block, etc.)

All of these may have internal links.

More complex Drupal pages can be made with the Views module and include multiple nodes or other entities.

As a result, there is no function for isolating individual "pages" of a Drupal website, and it would be very hard to implement one.

---
Tags: 9
---


# Question
Title: How to find all broken links in a website?
I can use external tools to scan for broken links in my website (Screaming Frog for instant check and even Google Search Console for non instant check come to mind) but I wish to use Drupal.

Is there a page that lists all the broken links?

# Answer
> 2 votes
Actual broken internal links (when a user clicks a link that is broken) are reported on the status report at `/admin/reports/dblog`. You can filter by "page not found" to show all the bad links.

If you want to find external links and also identify broken internal links before your users do, you can use the Link Checker module.

That said, I think a better approach is to use one of the sitemap modules (Simple XML Sitemap or XML Sitemap) to list all the public content on your site and then point an external tool at the sitemap.

---
Tags: 9
---


# Question
Title: Unable to apply a user.module Core patch in Drupal 7.x site using Composer
I have a patch https://www.drupal.org/files/user\_reset\_password\_privacy-1521996-10.patch, which is to be applied to user.module using Composer. I have added the URL under `"patches"` as well.

```
"patches" : {
   "drupal/module" : {
     "string" : "patch_link"
  }
}

```

After running the command composer update drupal/core I am getting:

> Nothing to install or update

Need expert assistance here on where I am going wrong here.

# Answer
> 2 votes
It should be `drupal/core` in the `patches` section of composer.json, not `drupal/module`.

`patches` must be nested under `extra`. I cannot determine from the question as written if that is the case.

---
Tags: composer
---


# Question
Title: How to add a width attribute to a responsive image with srcset?
When using a responsive image with `srcset` the `width` and `height` attributes are not available in twig. Both of them are `NULL` When an image is uploaded that is too small images are stretched or blown up as described in this post: Responsive Images, The sizes Attribute, and Unexpected Image Sizes

Being able to set a with equal to the pixelsize of the image would solve this issue. How can I make these attributes available for twig?

# Answer
This is not going to be easy due to Drupal's way of rendering images, you should not touch this unless you know how to write code. The code below is untested, but should give you a direction.

```
function THEMENAME_preprocess_responsive_image_formatter(array &$variables) {
  //this is the hook where you do get access to the image file entity
  //don't use 'width' as attribute name, it might get unset by Drupal in the following hook
  $variables['responsive_image']['#attributes']['data-original-image-width'] = $variables['item']->width;
}

function THEMENAME_preprocess_responsive_image(array &$variables) {
  //this is the preparing the rendering, here you can set the width attribute again
  $variables['#attributes']['width'] = $variables['img_element']['#attributes']['data-original-image-width'];
}

```

This is code just an outline, and most likely will only work if responsive images module is configured for an single `img[srcset]` and will not work with `<picture>` tags.

The hooks are quite good documented though, check the API docs for more information

hook\_preprocess\_responsive\_image\_formatter

hook\_preprocess\_responsive\_image
> 1 votes

# Answer
Check out that issue on Drupal : https://www.drupal.org/project/drupal/issues/3192234. At time of writing, I was able to apply patch https://www.drupal.org/project/drupal/issues/3192234#comment-14438786 to have width/height attributes added on the children DOM elements.
> 0 votes

---
Tags: 8, media, theming
---


# Question
Title: How to create a new submission from a previous submission?
Currently, when I submit a new form, there is no problem (WebFormSubmission::create() and save()). When I reload this Webform submission and modify some fields of form and record it, there is no problem (WebformSubmission::load() and save()).

But I not able to create a new Webform submission from this previous Webform submission. Aim is to have 2 independant submissions.

I tried to create() and save() after moditication but something is wrong.

# Answer
In the Webform UI, you are able to duplicate submission via the results table submission operations.

Via the Webform APIs, you can use \Drupal\webform\Entity\WebformSubmission::createDuplicate.
> 1 votes

---
Tags: webforms
---


# Question
Title: How can I loop on checkboxes to hide all using mlid: from the datatable?
```
function ts_core_form_menu_overview_form_alter (&$form, &$form_state, $form_id) {
  $form['mlid:11242']['hidden']['#type'] = 'hidden';
  $form['mlid:11246']['hidden']['#type'] = 'hidden';
  $form['mlid:11249']['hidden']['#type'] = 'hidden';
  $form['mlid:11250']['hidden']['#type'] = 'hidden';
  $form['mlid:11252']['hidden']['#type'] = 'hidden';
  $form['mlid:11253']['hidden']['#type'] = 'hidden';
  $form['mlid:11254']['hidden']['#type'] = 'hidden';
  $form['mlid:11255']['hidden']['#type'] = 'hidden';
  $form['mlid:11256']['hidden']['#type'] = 'hidden';
  $form['mlid:11257']['hidden']['#type'] = 'hidden';
  $form['mlid:11258']['hidden']['#type'] = 'hidden';
  $form['mlid:11262']['hidden']['#type'] = 'hidden';
  $form['mlid:11263']['hidden']['#type'] = 'hidden';
  $form['mlid:11264']['hidden']['#type'] = 'hidden';
  $form['mlid:11265']['hidden']['#type'] = 'hidden';
  $form['mlid:11285']['hidden']['#type'] = 'hidden';
  $form['mlid:11286']['hidden']['#type'] = 'hidden';
  $form['mlid:11287']['hidden']['#type'] = 'hidden';
  $form['mlid:11290']['hidden']['#type'] = 'hidden';
  $form['mlid:16459']['hidden']['#type'] = 'hidden';
  $form['mlid:6698']['hidden']['#type'] = 'hidden';
  $form['mlid:11241']['hidden']['#type'] = 'hidden';
  $form['mlid:11267']['hidden']['#type'] = 'hidden';
  $form['mlid:11243']['hidden']['#type'] = 'hidden';
  $form['mlid:16969']['hidden']['#type'] = 'hidden';
}

```

# Answer
> 0 votes
function ts\_core\_form\_menu\_overview\_form\_alter (&$form, &$form\_state { $dest = drupal\_get\_destination(); //call back function to

if ($dest\['destination'\] == 'homepage\_rbf') return; // query string search foreach ($form as $key =\> $item ) { if (strpos($key, 'mlid') === 0) { $form\[$key\]\['hidden'\]\['#type'\] = 'hidden'; } }

---
Tags: 7, forms, hooks
---


title: hook_node_view_alter not working

text:
# Question
Title: hook_node_view_alter not working
I'm hoping to finally find some solutions here. I'm new to custom module development in Drupal and I'm trying to learn the basics. What I'm trying to do is use hook\_node\_view\_alter, however even at the simplest step (showing a status message) it does not work.

My module (test\_module) is installed and enabled on the site. Currently the custom module has only two files: test\_module.info.yml and test\_module.module

Code from test\_module.info.yml file

```
name: test_module
type: module
description: Test module
core: '8.x'

```

Code from test\_module.module file

```
<?php
/*
* Implementation of hook_node_view_alter
*/

use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\NodeInterface;

function test_content_node_view_alter(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) {
    drupal_set_message(t('Hello!'));
}

?>

```

It doesn't show the message when I'm opening a node (/node/1) at my Drupal site. As I understand it, it should show the message for any existing node when it is viewed. I've cleared the cache, nothing's changed.

---

Update

* changed test\_content\_node\_view\_alter() to test\_module\_node\_view\_alter()
* adjusted the code to coding standards
* removed the php closing tag

My code in test\_module.module looks like this right now:

```
<?php

/**
 * @file
 * Implementation of hook_node_view_alter();
 */

use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\NodeInterface;

function test_module_node_view_alter(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) {
  drupal_set_message(t('Hello!'));
}

```

I've cleared all cache and now the website gets this error:

> The website encountered an unexpected error. Please try again later.

# Answer
After researching more examples out there in the Web, I've finally managed to make this work, however I'm still not sure why it was not working before...

Working code:

```
<?php

/**
 * @file
 * Implementation of hook_entity_view_alter();
 */

function test_module_entity_view_alter($entity, $type, $view_mode) {
    drupal_set_message(t('Hello world!'));
}

```

Moving on to further modifications. Thanks everyone!
> 2 votes

# Answer
You need replace

```
function test_content_node_view_alter(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) {
    drupal_set_message(t('Hello!'));
}

```

to

```
 /**
 * Implements hook_entity_view().
 */
  function test_module_entity_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $display, $view_mode) {
        drupal_set_message(t('Hello!'));
  }

```

`hook_node_view()` it's invoked has just changed. As you mentioned, it's now handled by hook\_ENTITY\_TYPE\_view(). or hook\_entity\_view()
> 0 votes

# Answer
This DOES still work in D8 and D9 :)

```
function MYMODULE_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
  if ($entity->bundle() == 'company') {
    \Drupal::messenger()->addMessage(t('Hello!!!'));
  }
}

```
> 0 votes

---
Tags: nodes, hooks, 9
---


title: How can I install centreon/centreon?

text:
# Question
Title: How can I install centreon/centreon?
My website is built with Drupal 8.3.2. I want to update to to Drupal 8.9.x, but I don't want to move to Drupal 9.x. I ran the following command.

```
composer update drupal/core-recommended:8.9 --with-dependencies

```

I am getting these errors. The site uses PHP 7.3.33.

> Could not load package centreon/centreon in http://repo.packagist.org: \[UnexpectedValueException\] Could not parse version constraint optimize-browser-configuration-dev: Invalid version string "optimize-browser-configuration-dev"

I tried to install centreon/centreon, but there is no package.

Can anybody help me with resolving this issue?

This is the content of the *composer.json* file used for the site.

```
{
    "name": "drupal/drupal",
    "description": "Drupal is an open source content management platform powering millions of websites and applications.",
    "type": "project",
    "license": "GPL-2.0+",
    "require": {
        "composer/installers": "^1.9",
        "wikimedia/composer-merge-plugin": "^1.4"
    },
    "replace": {
        "drupal/core": "^8.3"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "preferred-install": "dist",
        "autoloader-suffix": "Drupal8"
    },
    "extra": {
        "_readme": [
            "By default Drupal loads the autoloader from ./vendor/autoload.php.",
            "To change the autoloader you can edit ./autoload.php.",
            "This file specifies the packages.drupal.org repository.",
            "You can read more about this composer repository at:",
            "https://www.drupal.org/node/2718229"
        ],
        "merge-plugin": {
            "include": [
                "core/composer.json"
            ],
            "recurse": false,
            "replace": false,
            "merge-extra": false
        },
        "installer-paths": {
            "core": ["type:drupal-core"],
            "modules/contrib/{$name}": ["type:drupal-module"],
            "profiles/contrib/{$name}": ["type:drupal-profile"],
            "themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/contrib/{$name}": ["type:drupal-drush"],
            "modules/custom/{$name}": ["type:drupal-custom-module"],
            "themes/custom/{$name}": ["type:drupal-custom-theme"]
        }
    },
    "autoload": {
        "psr-4": {
            "Drupal\\Core\\Composer\\": "core/lib/Drupal\Core/Composer"
        }
    },
    "scripts": {
        "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
        "post-autoload-dump": [
          "Drupal\\Core\\Composer\\Composer::ensureHtaccess"
        ],
        "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    ]
}

```

# Answer
> 0 votes
I followed these steps to resolve issue.

**Step 1 : Downgrade Composer to 1.10.9**

composer self-update 1.10.9

**Step 2 : Run below command**

composer require drupal/pathauto:^1.6

**Step 3 : Run below command**

composer remove --dev webflo/drupal-core-require-dev

**Step 4 : Run below command**

composer require --update-with-dependencies
drupal/core:^8.8
symfony/finder:^3.4
symfony/filesystem:^3.4

**Step 5 : Run below command**

composer require --dev --update-with-dependencies
drupal/core-dev:^8.8
symfony/debug:^3.4

**Step 6 : Run below Command**

composer remove -n
symfony/finder
symfony/filesystem
symfony/debug

**Step 7 : Run below command**

drush updb

**Step 8 : Run below command**

drush cr

**Step 9 : Update settings.php**

In Drupal 8.8.0 the sync directory is defined in $settings and not $config\_directories, and so the Settings.php file should be updated.

change from:

$config\_directories\['sync'\] = 'foo/bar';

to

$settings\['config\_sync\_directory'\] = 'foo/bar';

---
Tags: 8, updating
---


# Question
Title: View won't update unless caches are cleared
In a Drupal 9 site I've built a view that displays specific content for each day of the month (filtering by a date field).

The view shows the correct content for the admin user but not for anyone else unless the caches are flushed.

I've tried switching off the caching for that view, switching off view caching and switching off all caching on the site but none of that makes any difference.

The only way to make the content update correctly is to click the 'Clear all caches' button every day.

This does not make sense. (I've created this kind of view in the past in Drupal 7 and had no such issue.)

Any help would be greatly appreciated.

# Answer
@Patrick Kenny, there is also one built-in. To disable this cache for anonymous users uninstall the module Internal Page Cache. Then all traffic will be served by the Dynamic Page Cache, which can be controlled by the cache metadata you configure in the View.

Another way would be to invalidate the View cache tag in a cron job. The Internal Page Cache has the advantage over external caches like Varnish or CDNs that you don't need PURGE requests, you can invalidate the cache tag directly:

```
\Drupal\Core\Cache\Cache::invalidateTags(['config:views.view.my_view']);

```
> 2 votes

---
Tags: views
---


# Question
Title: How do I get the user ID of a newly created user?
I've been searching for this for ages, but could not come with a solution. Drupal 7 provided a way to get the user ID of a newly created user after running `user_save()`; the new user has been added and the user ID has been returned in the object.

In Drupal 8, when I use `User::create()`, it only returns a constant based on whether the user has been created or updated. Is there any way to get the user ID after the user has been created?

# Answer
I use the following code in a custom entity method.

```
$storage = $this->entityTypeManager()->getStorage('user');
$owner =  $storage->create(['mail' => $email, 'name' => $this->getName()]);
$owner->save();
$uid = $owner->id();

```

If you don't have access to `entityTypeManager()` in your class, you could alternatively use the following code.

```
$storage = \Drupal::service('entity_type.manager')->getStorage('user');

```

When possible, use dependency injection instead of calling a `\Drupal` method.
> 6 votes

# Answer
> In Drupal 8, when I use `User::create()`, it only returns a constant based on whether the user has been created or updated.

To make it clearer to the users who will read this question: `User::create()` returns the created user entity. It cannot return a value that says whether the user object has been created or updated, as `User::create()` doesn't save the user object in the database, nor does it check there is a duplicated user object in the database.
It's `User::save()` that returns that value, but that isn't an issue, thought, since the value returned from `User::create()` should be stored in a variable. The following code is wrong code to use to create a new user entity.

```
User::create(['mail' => $email, 'name' => $name])->save();

```

The call to `save()` should not be concatenated to the call to `create()` when the code also needs to access the properties of the created user entity, such as its ID. To achieve that, the code should be similar to the following one.

```
$user = User::create(['mail' => $email, 'name' => $name]);
$user->save();

```

Alternatively, the following code is equivalent.

```
$entity_type_manager = \Drupal::entityTypeManager();
$storage = $entity_type_manager->getStorage('user');
$user = $storage->create(['mail' => $email, 'name' => $name]);
$user->save();

```

> Is there any way to get the user ID after the user has been created?

After calling `$user->save()`, the user ID is returned from `$user->id()`.
> 1 votes

# Answer
To get the ID from User::create(); use the id() function after the save() function:

```
$user = \Drupal\user\Entity\User::create();
$user->setPassword(user_password());
$user->enforceIsNew();
$user->setEmail($user_data['user_email']);
$user->setUsername($name);

//Save user
$res = $user->save();
//$res returns the SAVED_NEW or SAVED_UPDATED constant no good for an ID

//But the id function should pass the newly created ID
$newid = $user->id();

```
> 0 votes

---
Tags: 8, users
---


# Question
Title: Drush 11 incompatible with drupal/recommended-project?
https://www.drush.org/latest/install/ indicates that Drush 10 is no longer supported. Drush 11 seems to be incompatible with drupal/recommended-project:9.\* due to its dependency (via drupal/core-recommended:9.\*) on symfony/http-client-contracts:2.5.0.

Is that intentional, or am I missing something?

# Answer
You probably need to update the dependencies using the `--with-all-dependencies` flag, or `-W`. You should be able to do it with this:

```
composer require drush/drush -W

```
> 2 votes

---
Tags: drush, 9
---


# Question
Title: user account custom fields list of boolean type
In configuration form i need to create field with dinamic options. this needs to be rendered from user acount custom fields (i have create custom field earlier type of boolean) so i need reneder this field.

I have started from `$accountFields = \Drupal::service('entity_field.manager')->getFieldDefinitions('user', 'user');`

How do i filter out fields with boolean type

# Answer
After some research i have done this like this :

```
$definitions = array_filter(
        \Drupal::service('entity_field.manager')->getFieldDefinitions('user', 'user'),
        function ($fieldDefinition) {
          return $fieldDefinition instanceof \Drupal\field\FieldConfigInterface;
        }
      );
    $fields = array();
    foreach ($definitions as $field){

        if( $field->getType() === 'boolean') {

            $fields[$field->getName()] = $field->getLabel();
        }
    }
    return $fields;

```

I need it for selection list so the field returns and array field\_name =\> field\_label
> 0 votes

---
Tags: entities, 9
---


# Question
Title: Running tests for a module without requiring a full site installation
I'm building a custom module (for use on multiple projects) with code that relies on stuff from Drupal core and third party modules (e.g. extending classes, implementing interfaces, annotating as plugins, etc.). I would like to start writing tests for them, with unit tests to begin with. But so far, all of the resources point to putting the module in a Drupal installation and test in that setup, as if I'm running a full Drupal site - even for a unit test.

I was more imagining that my module would have the runner, the dependencies, and Drupal core be dependencies (or dev dependencies) - just like how JavaScript tests are usually written, whether it's unit tests or headless browser tests. That is, JavaScript testing doesn't require you to pop your code in some other code before you can start testing.

Can this be achieved? Or is putting the my modules code in a Drupal install really the only way to test Drupal modules?

# Answer
Unit tests do not bootstrap the whole system, and run very fast. Kernel tests, functional tests, and JavaScript tests require bootstrapping the system, and take longer.

With unit testing, you don't declare dependencies upon foreign code. This is because tests unit test a piece of code, not the foreign code. If an error was introduced into the foreign code, and the code being tested depended upon that code, the tests would fail, even though the code being tested was still correct. This would be a false fail, and a developer would probably spend time trying to figure out why their code had failed, even though it had not.

The solution is to use mocks to stub the data. A mock is a fake service, created within the test, that simulates the actual dependent service. So when the code being tested makes a call to foreign code, the mock returns a response (aka a stub) as if the foreign code had responded, taking away any risk of false positives from the foreign code failing, since your test will always respond, and will always respond exactly as you set it to.
> 2 votes

---
Tags: 9, testing
---


# Question
Title: How to make menu items of restricted pages visible to all user roles?
On a website I'm working on, logged in users can post their feedback about some functionalities which the website provides. While only logged in users should have access to fill the form, invisibility of the menu item "Share your experience" caused to not many users navigate to this page and fill the form.

So what I need is to have the menu item being visible and when anonymous user navigated to this link Drupal will show them the login form automatically (which would be a different issue).

There was an Always Visible module for Drupal 7. Now I want to know what technique should I use to make the menu item always visible in Drupal 8?

# Answer
> 3 votes
Ah look, Always Visible already had an issue regarding D8: Drupal 8 port of Always Visible. Some nice person created a Gist you can easily build a custom module from to always display *all* menu items.

I've done that for you and put it on GitLab: Always Visible (D8). Simply download the Zip file, unpack it, rename the folder to `always_visible` and put it into your `/modules/custom` folder, enable the module, done.

# Answer
> 0 votes
It's easy. Just use `Menu Item Role Access` contributed module and check `Anonymous user` and `Authenticated user` roles for a particular menu item to make it visible for ALL! IMPORTANT: to make it working enable `Overwrite internal link target access check` in module config page (admin/config/menu-item-role-access).

Hope that this helps a lot of people! Good luck! Michal.

---
Tags: 8, users, navigation
---


title: insert big array into database

text:
# Question
Title: insert big array into database
```
$array = Array(
  [a001] => Array(
    [0] => Array(
      [id] => 1789823
      [start] => 2014-09-29
      [end] => 2014-10-02
      [status] => 1
    )
  )
)

```

function to insert reservation:

```
    foreach ($array as $room_id => $item) {
      foreach ($item as $reservation) {
        db_insert('reservation')->fields(
          array(
            'room_id' => $room_id,
            'id' => $reservation['id'],
            'start' => $reservation['start'],
            'end' => $reservation['end'],
            'status' => $reservation['status']
          )
        )->execute;
      }
    }

```

I have an multidimensional array `$array` and it has about 30000 records of `$reservation` index. Using looping method above in my personal computer, it takes about 30 minutes to insert all of reservation, my PC spec is (dual core, memory 2GB).

Is any better implementation to do insert job?

# Answer
> 1 votes
You should avoid executing insert many times. It is enough to call `->fields` multiple times, like this:

```
$query = db_insert('reservation');
foreach ($array as $room_id => $item) {
  foreach ($item as $reservation) {
    $query->fields(
      array(
        'room_id' => $room_id,
        'id' => $reservation['id'],
        'start' => $reservation['start'],
        'end' => $reservation['end'],
        'status' => $reservation['status']
      )
    );
  }
}
$query->execute();

```

This will speed up things, allowing database to prepare space for new data in one step, but with 30 thousands of records it still may take time. Be sure to tune your database accordingly - but that's out of the scope of Drupal Answers.

If you can't optimize DB enough, consider using Batch API for the job. It will make things a bit slower than the code above, but by importing a hundred or two each step you will avoid HTTP connection timeouts, PHP timeouts etc. Just make sure you only execute once per step with hundred records - even with Batch API it is good approach to group rows in as few inserts as practical.

# Answer
> 4 votes
Correct mass insert in Drupal is:

```
$values = [
   [ 'intvar' => 5,
    'stringvar' => 'hello world',
    'floatvar' => 3.14, ],
   [ 'intvar' => 6,
    'stringvar' => 'hi anybody',
    'floatvar' => 2.28, ],
   [ 'intvar' => 7,
    'stringvar' => 'good bye',
    'floatvar' => 7.62, ],
];

$q = db_insert('mytable')
  ->fields([ 'intvar', 'stringvar', 'floatvar', ] );
foreach ($values as $record) {
  $q->values($record);
}

$q->execute();

```

In your case it needed to insert by array parts (using "for" and "array\_slice"), because 30000 is too much for one insert.

```
$step = 3000;
for ($i=0; $i<30000; $i+=$step) {
    $ins_part_values = array_slice($total_values, $i, $step);
    ...insert procedure
}

```

# Answer
> 1 votes
Here is a complete example with Drupal 8 and later (inserting into message table provided by message module):

```
$database = \Drupal::database();
$uuid = \Drupal::service('uuid');

$fields = [
  'template',
  'uuid',
  'langcode',
];

$values[] = [
  'template' => 'some_template',
  'uuid' => $uuid->generate(),
  'langcode' => 'en'
];
$values[] = [
  'template' => 'some_template',
  'uuid' => $uuid->generate(),
  'langcode' => 'en'
];

$query = $database->insert('message')->fields($fields);

foreach ($values as $record) {
  $query->values($record);
}

$query->execute();

```

---
Tags: database
---


# Question
Title: How do I set the value of a date and time field with Behat?
I am trying to test my site with Behat.

On my entity edit form, I have a **Datetime** field that uses the **Date and time** widget. I want to use the **Date and time** widget because I need to set the time in increments of seconds, which I cannot do with the **Select list** widget.

I want to set the value of this field with a step like this:

```
And I assign the date "yesterday" with timezone "Asia/Tokyo" for "edit-field-datetime-MYFIELD-0-value"

```

To do so, in `FeatureContext.php`, I wrote the following code.

```
  /**
   * @Then I assign the date :date with timezone :timezone for :field
   *
   * Assign the specified date to the element with the given CSS.
   */
  public function assertEnterDateForField($field, $timezone, $date_string) {
    $date_field = $field . '-date';
    $time_field = $field . '-time';
    // Drupal stores timezones as UTC so we need the base time in UTC.
    $datetime = new DateTime($date_string, timezone_open('UTC'));
    // We need to convert the UTC time to the user's timezone.
    // This is because when saving the entity,
    // Drupal will convert the value to UTC.
    $datetime->setTimezone(timezone_open($timezone));
    $date_output_string = $datetime->format('mdY');
    $time_output_string = $datetime->format('hisA');
    $datetime_debug_string = $datetime->format('Y-m-d\TH:i:sO');
    $this->fillfield($time_field, $time_output_string);
    $this->fillField($date_field, $date_output_string);
    echo "Datetime $datetime_debug_string
    Field set to
    date: $date_output_string
    time: $time_output_string";
  }

```

On my local environment (lando, running the Standalone Chrome container), this code works as expected; the date/time is set correctly for the field.

However, on my test server (Pantheon/CircleCI, running the Behat Chrome Extension, it doesn't work. The debug information is correct; for example:

```
  │ Datetime 2020-08-13T09:00:00+0900
  │     Field set to
  │     date: 08132020
  │     time: 090000AM

```

However, the date/time is not actually filled in, so when the entity is saved, the date/time has not been updated.

How can I set the value of a field that uses the **Date and time** widget with Behat/Mink/Drupal Extension?

# Answer
```
When I fill in the date field "Publish on" with "+1 second"

```

I get it to work with these updates.

```
  /**
   * @Then I fill in the date field :field with :date
   *
   * Assign the specified date to the element.
   */
  public function iFillDateField($field, $date): void {
    $field_label = $this->getSession()->getPage()->find('xpath', "//*[text() = '$field']");
    if ($field_label == NULL | !$field_label->hasClass('form-item__label')) {
      throw new ExpectationException('Could not find date field with label: ' . $field, $this->getSession());
    }

    $datetime = new \DateTime($date, \timezone_open('UTC'));
    $datetime->setTimezone(new \DateTimeZone(\date_default_timezone_get()));

    $date_input = $field_label->getParent()->find('xpath', "//input[@type='date']");
    $date_output_string = $datetime->format('Y-m-d');
    $this->getSession()->getPage()->fillField($date_input->getAttribute('id'), $date_output_string);

    $time_input = $field_label->getParent()->find('xpath', "//input[@type='time']");
    if ($time_input) {
      $time_output_string = $datetime->format('H:i:s');
      $this->getSession()->getPage()->fillField($time_input->getAttribute('id'), $time_output_string);
    }
  }

```

The key to get it work is to set the right formats for date (Y-m-d) and time (H:i:s).

This step will accept the field label instead of the field id.
> 1 votes

# Answer
I haven't been able to find a way to do this, so for now, I rewrote my CI configuration so that I can use Standalone Chrome with Pantheon/CircleCI instead of the Behat Chrome Extension.
> -1 votes

---
Tags: testing
---


# Question
Title: How to fully reproduce dev environment with ddev?
I'm `git clone`ing a project that is run with `ddev`. After doing

* `git clone`
* `ddev config`
* `ddev start`

and opening the hosted site, I get various errors, for instance:

```

    Warning: include_once(/var/www/html/includes/file.phar.inc): failed to open stream: No such file or directory in include_once() (line 716 of /var/www/html/includes/bootstrap.inc).
    Warning: include_once(): Failed opening '/var/www/html/includes/file.phar.inc' for inclusion (include_path='.:/usr/share/php') in include_once() (line 716 of /var/www/html/includes/bootstrap.inc).
    Error: Call to undefined function file_register_phar_wrapper() in drupal_environment_initialize() (line 717 of /var/www/html/includes/bootstrap.inc).
    Notice: Undefined index: base_url in file_create_url() (line 395 of /var/www/html/includes/file.inc).
    Notice: Undefined index: base_url in file_create_url() (line 395 of /var/www/html/includes/file.inc).
    Notice: Undefined index: base_path in base_path() (line 2930 of /var/www/html/includes/common.inc).
    Notice: Undefined index: base_path in base_path() (line 2930 of /var/www/html/includes/common.inc).

```

My colleagues don't get this of course. And the file `file.phar.inc` is indeed not present in the entire repo. This shows that this isn't a small bug in the Drupal code but rather something is different about our environments. How can I get a reproducible build running on my machine? Should I copy the entire `.ddev` folder from a working installation to my machine and rerun `ddev`?

ps. I did try copying down `file.phar.inc` file from the Drupal source and this got rid of the include error, but generated many more other ones. I could go down the rabbit hole of fixing all of them but it works on other devs' machines, so I think it's an environment issue.

# Answer
> -1 votes
Did you run `ddev composer install` from the project root?

Newer versions of Drupal use composer to manage dependencies. Generally, composer projects don't commit these files so you need to "install" them after cloning: `composer install`

Because your project is using ddev, you need to run `ddev composer install` (which runs the command inside the web container) to make sure composer uses your site's PHP version.

---
Tags: 7
---


# Question
Title: Cannot change layout of translated paragraph nodes
I make use of Paragraphs to build content nodes along with Drupal's translations to translate a node to a different language. Although the node can be translated, I am unable to move / reshuffle nested elements in the Paragraph layout, some I can do, others not.

What could possibly be causing this behaviour? Worth noting that on the original version of the node (the default language version) I am able to shuffle these around, it's only on the translated versions that it does not allow us, and also on certain paragraph types, not all of them

# Answer
Translating the layout is not officially supported yet. See D8: Why updated paragraph content does not lead to an updated translation?

For the classic widget there is this unofficial module https://www.drupal.org/project/paragraphs\_asymmetric\_translation\_widgets.

For the experimental widget this issue https://www.drupal.org/project/paragraphs/issues/2904705.
> 1 votes

---
Tags: 9, paragraphs
---


# Question
Title: How to get the context node in a custom block inside a views list?
I have a view which displays all pictures of the content type `photo`. I've set some fields in this view for the display.

This is how iIrender the list of pictures:

**views-view-fields--photo.html**

```
<figure class="element-item {{ fields['name'].content|lower }}">
    <a href="{{ fields['field_photo_1'].content|lower }}">
        <img src="{{ fields['field_photo'].content }}"/>
    </a>
    <figcaption>
        <div class="date">{{ fields['field_date'].content }}</div>
        <div class="lieu">{{ fields['field_lieu'].content }}</div>
    </figcaption>
</figure>
{{ drupal_block('comment_block') }}

```

I use the Twig tweak module to render a custom block in this template. This block should load all comments for the picture. For that, I need to pass the `nid` of the node to my block.

Here's the code of the block:

**CommentBlock.php**

```
/**
 * Provides a 'CommentBlock' block.
 *
 * @Block(
 *  id = "comment_block",
 *  admin_label = @Translation("Comment block"),
 *  context = {
 *    "node" = @ContextDefinition("entity:node", label = @Translation("Node"))
 *  }
 * )
 */
class CommentBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * Drupal\Core\Entity\EntityTypeManagerInterface definition.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Constructs a new CommentBlock object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param string $plugin_definition
   *   The plugin implementation definition.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
  }

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

  /**
   * {@inheritdoc}
   */
  public function build() {

    $build = [];

    $node = $this->getContextValue('node');
    kint($node->id());

    $build['#theme'] = 'comment_ajax';

    return $build;
  }

}

```

What I try is to get the context of the views row into my block. But I get this error:

> ```
> Drupal\Component\Plugin\Exception\ContextException : Required contexts without a value: node
>
> ```

What am I doing wrong?

I can load my block from `template_preprocess_views_view_fields()` to link with the `nid` but I try to understand the context annotation.

---

### Update

Here's a picture of the view, my custom block returns just a link name "Comment".

I now load the block programmatically instead of using `drupal_block` in the preprocess.

```
$block             = \Drupal\block\Entity\Block::load('commentblock');
$variables['test'] = \Drupal::entityTypeManager()
  ->getViewBuilder('block')
  ->view($block);

```

Then I print this block in **views-view-fields.html.twig**:

```
{{ fields['title'].content }}
{{ test }}

```

If I `kint` the context in my block I still get an error except if I set the annotation `required = FALSE`.

```
 *   context = {
 *     "node" = @ContextDefinition(
 *       "entity:node",
 *       label = @Translation("Current Node"),
 *       required = FALSE,
 *     )
 *   }

```

But the context is still empty.

# Answer
> 5 votes
You might have to un-require the context with `required = FALSE`:

```
 *   context_definitions = {
 *     "node" = @ContextDefinition(
 *       "entity:node",
 *       label = @Translation("Current Node"),
 *       required = FALSE,
 *     )
 *   }

```

And when you place the block you have to choose from where the block will get the node value:

# Answer
> 3 votes
Block-plugins that inherit from `BlockBase` can have their context values directly set via `ContextAwarePluginBase::setContextValue($key, $value)`. This method can be used by a preprocess function to inject context that isn't otherwise available from the route or environment.

In my case I have a block that needs a `group` entity in its context:

```
<?php

namespace Drupal\middlebury_course_hub\Plugin\Block;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Session\AccountInterface;

/**
 * Provides a block with a link to the section's roster.
 *
 * @Block(
 *   id = "course_hub_roster_link",
 *   admin_label = @Translation("Roster Link"),
 *   category = @Translation("Course Hub"),
 *   context = {
 *     "group" = @ContextDefinition(
 *       "entity:group",
 *       label = @Translation("Current Group"),
 *       required = FALSE
 *     )
 *   }
 * )
 */
class RosterLinkBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  protected function blockAccess(AccountInterface $account) {
    /** @var \Drupal\group\Entity\GroupInterface $group */
    if (($group = $this->getContextValue('group')) && $group->id()) {
      if ($group->hasPermission('view group_membership content', $account)) {
        return AccessResult::allowed();
      }
    }
    return AccessResult::forbidden();
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    // This block varies per group.
    $build['#cache']['contexts'] = ['group'];
    $build['#theme'] = 'course_hub_roster_link';
    /** @var \Drupal\group\Entity\GroupInterface $group */
    if (($group = $this->getContextValue('group')) && $group->id()) {
      $build['#group'] = $group;
    }

    // If no group was found, cache the empty result on the route.
    return $build;
  }

}

```

I wanted to display this block for each group entity that was a row of a view result. By adding a preprocess function to my module I could inject the `group` context:

```
/**
 * Implements hook_preprocess_hook().
 */
function middlebury_course_hub_preprocess_group(&$variables) {
  if ($variables['view_mode'] == 'dashboard_item') {
    // Add the roster-link block to the build-array.
    $block = \Drupal::service('plugin.manager.block')
               ->createInstance('course_hub_roster_link');
    $block->setContextValue('group', $variables['group']);
    if ($block->access(\Drupal::currentUser())) {
      $variables['content']['roster_link'] = $block->build();
      $variables['content']['roster_link']['#weight'] = 2;
    }
  }
}

```

This same technique should work for nodes as well using `$block->setContextValue('node', $node);` in your `hook_preprocess_node` function.

# Answer
> 2 votes
So after many try, I haven't found a standalone solution for my block with the context plugin. But I found a way with a preprocess function.

Here's how I get the `nid` from my views row :

```
function comment_ajax_preprocess_views_view_fields(&$variables) {

  $block_manager = \Drupal::service('plugin.manager.block');
  $config        = ['nid' => $variables['row']->nid];
  $plugin_block  = $block_manager->createInstance('comment_block', $config);

  $variables['blockComment'] = $plugin_block->build();
}

```

In this preprocess function, I get the row `nid` and I use it in the block config.

And in my custom block:

```
public function build() {

  $build = [];

  $blockConfig     = $this->getConfiguration();
  $build['#theme'] = 'comment_ajax';
  $build['#nid']   = $blockConfig['nid'];

  return $build;
}

```

I get back the `nid` from the block configuration.

That works but I was looking for a way without preprocessing, just with the context.

I'm still looking for a better way :)

# Answer
> 1 votes
In my case I've visited /admin/structure/block remove the block and clear cache. After that I added block again and the context node becomes accessible

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


# Question
Title: Custom entity datetime field in calendar
I created an entity in a module, using code. I generated skeletons with `drupal console generate:entity:content` (without bundles), and then added a datetime field to my TestFieldEntityItem.php, in `baseFieldDefinitions()`.

```
$fields['test_date'] = BaseFieldDefinition::create('datetime')
  ->setLabel(t('Test date'))
  ->setDescription(t('Test.'))
  ->setRevisionable(TRUE)
  ->setSettings([
    'datetime_type' => 'date'
  ])
  ->setDefaultValue('')
  ->setDisplayOptions('view', [
    'label' => 'above',
    'type' => 'datetime_default',
    'settings' => [
      'format_type' => 'medium',
    ],
    'weight' => 14,
  ])
  ->setDisplayOptions('form', [
    'type' => 'datetime_default',
    'weight' => 14,
  ])
  ->setDisplayConfigurable('form', TRUE)
  ->setDisplayConfigurable('view', TRUE);

```

I installed my module, cleared the cache, reinstalled calendar and calendar\_datetime modules, but when I try to add a view from a template, like the calendar module suggests, I can't see any template matching my datetime field.

If I create a datetime field on this entity through the UI, it appears in view templates. What am I missing?

Inspecting the calendar code, I found the function that search datetime fields, in ViewsFieldTemplate.php. This function finds my field, but the field\_info does not match `isDateField()` because of the `argument` property.

isDateField() wants 'datetime' as argument ID.

```
protected function isDateField($field_info) {
  if (!empty($field_info['field']['id']) && $field_info['field']['id'] == 'field') {
    if (!empty($field_info['argument']['id']) && $field_info['argument']['id'] == 'date') {
      return TRUE;
    }
  }
  return FALSE;
}

```

My field\_info argument is 'string'.

```
array (size=7)
  'title' => ...
  'help' => ...
  'field' =>
      'id' => string 'field' (length=5)
  'argument' =>
      'id' => string 'string' (length=6)
  'filter' =>
      'id' => string 'string' (length=6)
  'sort' =>
      'id' => string 'standard' (length=8)
  'entity field' => string 'test_date' (length=4)

```

So thanks to @4k4 answer, I tried to do the same as the working date field, and I created my own EntityViewsData (I tried hook\_views\_data\_alter() first but the field was not present in input data)

```
namespace Drupal\kabukis_tests\Entity;
use Drupal\views\EntityViewsData;

class TestEntityViewsData extends EntityViewsData {
  public function getViewsData() {
    $additionalData = [
      'test_date' => [
        'title' => new TranslatableMarkup('Birth date'),
        'help' => new TranslatableMarkup('Birth date'),
        'field' => [ 'id' => 'field' ],
        'argument' => [ 'id' => 'date' ],
        'filter' => [ 'id' => 'date' ],
        'sort' => [ 'id' => 'date' ],
        'entity field' => 'test_date',
      ]
    ];
    $data['test_field_entity_field_data'] = array_merge($data['test_field_entity_field_data'], $additionalData);
    return $data;
  }
}

```

Now, the field appears in views template list ! However, the generated view is not working, I get the following error :

> \Drupal\calendar\Plugin\views\style\CalendarStyle: A calendar date argument is required when using the calendar style, but it is missing or is not using the default date.

# Answer
`EntityViewsData` provides the information for views for entity types, so that they are included in views. For datetime basefields this is not working at the moment, because of this issue https://www.drupal.org/node/2489476. So you need to provide the data in a `hook_views_data` or by extending `EntityViewsData`. From the documentation:

> * argument: Specifies a handler to make it available to Views as an argument, or contextual filter as it is known in the UI.

https://api.drupal.org/api/drupal/core%21modules%21views%21views.api.php/function/hook\_views\_data/8.3.x

You've mentioned that you have a working example if you use a field configured in UI, so you could try to copy the views data.
> 3 votes

# Answer
There is an error in

namespace Drupal\kabukis\_tests\Entity; use Drupal\views\EntityViewsData;

```
class TestEntityViewsData extends EntityViewsData {
  public function getViewsData() {
    $additionalData = [
      'test_date' => [
        'title' => new TranslatableMarkup('Birth date'),
        'help' => new TranslatableMarkup('Birth date'),
        'field' => [ 'id' => 'field' ],
   ...

```

You have to write :

```
...'field' => [ 'id' => 'date' ],...

```

according to the documentation in api.drupal.org of hook\_views\_data()(it is the same returned format of data like in this class).
> 0 votes

---
Tags: views, 8, entities, datetime
---


# Question
Title: absolute url of inline images in body using views and services
I am using services module in Drupal 8 to output node body in JSON format. The inline images are broken in android app which uses json to render node. Is there any code/method or module for D8 which can rewrite relative inline images path to absolute. My drupal version is 8.0.5

# Answer
> 2 votes
This is discussed for a long time, but unfortunately there is no solution committed to core until now, see https://www.drupal.org/node/2630076

Basically this tells you, that you need a text filter like this

http://cgit.drupalcode.org/drupal/tree/core/modules/editor/src/Plugin/Filter/EditorFileReference.php

where you change the line

```
$node->setAttribute('src', file_url_transform_relative(file_create_url($file->getFileUri())));

```

to

```
$node->setAttribute('src', file_create_url($file->getFileUri()));

```

by removing `url_transform_relative()`.

# Answer
> 2 votes
I know this is an old post but I thought it will be helpful for anyone to know my solution for Drupal 9.

Here is the answer:

* Create a custom module
* Create a file "CustomEditorFileReference" in src/Plugin/Filter

Put the following code:

```
<?php

namespace Drupal\complaints\Plugin\Filter;

use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Image\ImageFactory;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\file\FileInterface;
use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a filter to track images uploaded via a Text Editor.
 *
 * Generates file URLs and associates the cache tags of referenced files.
 *
 * @Filter(
 *   id = "custom_editor_file_reference",
 *   title = @Translation("Track images uploaded via a Text Editor with absolut path"),
 *   description = @Translation("Ensures that the latest versions of images uploaded via a Text Editor are displayed with absolute path."),
 *   type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE
 * )
 */
class CustomEditorFileReference extends FilterBase implements ContainerFactoryPluginInterface {

  /**
   * The entity repository.
   *
   * @var \Drupal\Core\Entity\EntityRepositoryInterface
   */
  protected $entityRepository;

  /**
   * The image factory.
   *
   * @var \Drupal\Core\Image\ImageFactory
   */
  protected $imageFactory;

  /**
   * Constructs a \Drupal\editor\Plugin\Filter\EditorFileReference object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository
   *   The entity repository.
   * @param \Drupal\Core\Image\ImageFactory $image_factory
   *   The image factory.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityRepositoryInterface $entity_repository, ImageFactory $image_factory = NULL) {
    $this->entityRepository = $entity_repository;
    if ($image_factory === NULL) {
      @trigger_error('Calling ' . __METHOD__ . '() without the $image_factory argument is deprecated in drupal:9.1.0 and is required in drupal:10.0.0. See https://www.drupal.org/node/3173719', E_USER_DEPRECATED);
      $image_factory = \Drupal::service('image.factory');
    }
    $this->imageFactory = $image_factory;
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity.repository'),
      $container->get('image.factory')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function process($text, $langcode) {
    $result = new FilterProcessResult($text);

    if (stristr($text, 'data-entity-type="file"') !== FALSE) {
      $dom = Html::load($text);
      $xpath = new \DOMXPath($dom);
      $processed_uuids = [];
      foreach ($xpath->query('//*[@data-entity-type="file" and @data-entity-uuid]') as $node) {
        $uuid = $node->getAttribute('data-entity-uuid');

        // If there is a 'src' attribute, set it to the file entity's current
        // URL. This ensures the URL works even after the file location changes.
        if ($node->hasAttribute('src')) {
          $file = $this->entityRepository->loadEntityByUuid('file', $uuid);
          if ($file instanceof FileInterface) {
            $node->setAttribute('src', $file->createFileUrl(FALSE));
            if ($node->nodeName == 'img') {
              // Without dimensions specified, layout shifts can occur,
              // which are more noticeable on pages that take some time to load.
              // As a result, only mark images as lazy load that have dimensions.
              $image = $this->imageFactory->get($file->getFileUri());
              $width = $image->getWidth();
              $height = $image->getHeight();
              if ($width !== NULL && $height !== NULL) {
                if (!$node->hasAttribute('width')) {
                  $node->setAttribute('width', $width);
                }
                if (!$node->hasAttribute('height')) {
                  $node->setAttribute('height', $height);
                }
                if (!$node->hasAttribute('loading')) {
                  $node->setAttribute('loading', 'lazy');
                }
              }
            }
          }
        }

        // Only process the first occurrence of each file UUID.
        if (!isset($processed_uuids[$uuid])) {
          $processed_uuids[$uuid] = TRUE;

          $file = $this->entityRepository->loadEntityByUuid('file', $uuid);
          if ($file instanceof FileInterface) {
            $result->addCacheTags($file->getCacheTags());
          }
        }
      }
      $result->setProcessedText(Html::serialize($dom));
    }

    return $result;
  }

}

```
* Now go to the "Text formats and editors" page and edit the ones with CKeditor.
* Enable Track images uploaded via a Text Editor with absolute path
* Make sure that filter "Track images uploaded via a Text Editor" is the last one to execute

---
Tags: views, 8
---


title: How to load a node by a field value?

text:
# Question
Title: How to load a node by a field value?
I want to load a certain node. I don't know the id of the node but I do know that it has a certain hash field that is unique and I know that hash.

I want to load the node via the hash field. How can I do that?

# Answer
> 19 votes
You can achieve by using EntityFieldQuery.

For D8 EntityFieldQuery has been rewritten.

Drupal 8:

```
$query = \Drupal::entityQuery('entity_test');
$default_langcode_group = $query->andConditionGroup()
  ->condition('user_id', $properties[$default_langcode]['user_id'], '=', $default_langcode)
  ->condition('name', $properties[$default_langcode]['name'], '=', $default_langcode);
$langcode_group = $query->andConditionGroup()
  ->condition('name', $properties[$langcode]['name'], '=', $langcode)
  ->condition("$this->field_name.value", $field_value, '=', $langcode);
$result = $query
  ->condition('langcode', $default_langcode)
  ->condition($default_langcode_group)
  ->condition($langcode_group)
  ->sort('name', 'ASC', $default_langcode)
  ->execute();

```

How do I fetch the values of an entity's field?

```
$query = \Drupal::entityQuery('node')
    ->condition('status', 1)
    ->condition('changed', REQUEST_TIME, '<')
    ->condition('title', 'cat', 'CONTAINS')
    ->condition('field_tags.entity.name', 'cats');

$nids = $query->execute();

```

# Answer
> 54 votes
The quickest way to load a specific node by field value is to use the method `loadByProperties()`.

You specify one or more field values and returned is an array containing the nodes matching the field values:

```
$nodes = \Drupal::entityTypeManager()
  ->getStorage('node')
  ->loadByProperties([
      'title' => $title,
      'field_hash' => 'YOUR_HASH',
    ]);

```

Normally you loop over the nodes. In your case you are looking for one specific node. A single node is also returned in array, so apply `reset()` and this returns either the node or NULL if nothing was found:

```
if ($node = reset($nodes)) {
  // found $node that matches the title
}

```

# Answer
> 0 votes
To load entities (nodes, users etc.) based on an array of multiple possible values/types you can use the entity query or entity type manager like that:

```
// Get all node IDs of multiple node types.
$query = \Drupal::entityQuery('node')
  ->condition('type', ['page', 'news'], 'IN');
$nids = $query->execute();

```

```
// Get all nodes of multiple node types.
$nodes = \Drupal::entityTypeManager()
  ->getStorage('node')
  ->loadByProperties([
    'type' => ['page', 'news'],
  ]);

```

---
Tags: 8, entities, nodes
---


title: Why cannot I upgrade?

text:
# Question
Title: Why cannot I upgrade?
I'm currently working on upgrading a Drupal site from Drupal 8.9.7 to Drupal 9.

I'm getting this error when I run `lando composer require "drupal/core:^9.3.8" --with-all-dependencies`.

> Your requirements could not be resolved to an installable set of packages.
>
> Problem 1
>
> * Root composer.json requires overtrue/phplint ^0.2.4 -\> satisfiable by overtrue/phplint\[0.2.4\].
> * drupal/core-recommended\[9.3.8, ..., 9.4.x-dev\] require symfony/yaml v4.4.34 -\> satisfiable by symfony/yaml\[v4.4.34\].
> * Conclusion: don't install symfony/yaml v4.4.34 (conflict analysis result)
> * Root composer.json requires drupal/core-recommended ^9.3.8 -\> satisfiable by drupal/core-recommended\[9.3.8, 9.3.x-dev, 9.4.x-dev\].
>
> Installation failed, reverting ./composer.json to its original content.

The content of the *composer.json* is the following.

```
{
    "name": "drupal-composer/drupal-project",
    "description": "Project template for Drupal 8 projects with composer",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "authors": [
        {
            "name": "",
            "role": ""
        }
    ],
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    ],
    "require": {
        "php": ">=5.6",
        "composer/installers": "^1.7",
        "cweagans/composer-patches": "^1.7",
        "drupal/adminimal_admin_toolbar": "^1.9",
        "drupal/adminimal_theme": "^1.4",
        "drupal/bamboo_twig": "^5.0@alpha",
        "drupal/console": "^1.9.7",
        "drupal/core": "^9.3.8",
        "drupal/core-composer-scaffold": "^9.3.8",
        "drupal/core-project-message": "^9.3.8",
        "drupal/core-recommended": "^9.3.8",
        "drupal/ctools": "^3.7",
        "drupal/devel": "^4.1",
        "drupal/entity_reference_revisions": "^1.9",
        "drupal/google_analytics": "^3.0",
        "drupal/menu_trail_by_path": "^1.1",
        "drupal/page_manager": "^4.0@beta",
        "drupal/panels": "^4.3",
        "drupal/paragraphs": "^1.13",
        "drupal/smtp": "^1.0@beta",
        "drupal/twig_tweak": "^2.9",
        "drupal/video_embed_field": "^2.0",
        "drupal/webform": "^6.1",
        "drush/drush": "^9.0.0",
        "vlucas/phpdotenv": "^2.4",
        "webflo/drupal-finder": "^1.0.0",
        "webmozart/path-util": "^2.3"
    },

    "require-dev": {
        "behat/behat": "3.*",
        "behat/mink": "~1.7",
        "behat/mink-extension": "^2.2",
        "behat/mink-goutte-driver": "~1.2",
        "drupal/coder": "^8.2.12",
        "drupal/drupal-extension": "^3.1",
        "drush-ops/behat-drush-endpoint": "^0.0.4",
        "jcalderonzumba/gastonjs": "~1.0.2",
        "jcalderonzumba/mink-phantomjs-driver": "~0.3.1",
        "mikey179/vfsstream": "~1.2",
        "overtrue/phplint": "^0.2.4",
        "squizlabs/php_codesniffer": "2.*",
        "symfony/css-selector": "^3.4.0"
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "sort-packages": true,
        "allow-plugins": {
            "composer/installers": true,
            "cweagans/composer-patches": true,
            "drupal/core-composer-scaffold": true,
            "drupal/console-extend-plugin": false,
            "zaporylie/composer-drupal-optimizations": false
        }
    },
    "autoload": {
        "classmap": [
            "scripts/composer/ScriptHandler.php"
        ],
        "files": ["load.environment.php"]
    },
    "scripts": {
        "pre-install-cmd": [
            "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
        ],
        "pre-update-cmd": [
            "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
        ],
        "post-install-cmd": [
            "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
        ],
        "post-update-cmd": [
            "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
        ]
    },
    "extra": {
        "composer-exit-on-patch-failure": true,
        "patchLevel": {
            "drupal/core": "-p2"
        },
        "installer-paths": {
            "web/core": ["type:drupal-core"],
            "web/libraries/{$name}": ["type:drupal-library"],
            "web/modules/contrib/{$name}": ["type:drupal-module"],
            "web/profiles/contrib/{$name}": ["type:drupal-profile"],
            "web/themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/Commands/{$name}": ["type:drupal-drush"]
        },
        "drupal-scaffold": {
            "initial": {
                ".editorconfig": "../.editorconfig",
                ".gitattributes": "../.gitattributes"
            }
        }
    }
}

```

I'm really at a loss at this point any help would be appreciated.

# Answer
> 1 votes
> but it conflicts with your root composer.json require (^3.4.0).

Yes, because `^` will never auto upgrade library to the next major version.

^3.4.0 is equivalent to saying \>=3.4.0 \< 4.0.0

So change it to `"symfony/css-selector": "^4.0.0"` in your composer.json

---
Tags: 9, composer
---


title: How can I replace drush @sites?

text:
# Question
Title: How can I replace drush @sites?
Since Drush 9 the `@sites` alias to run a command on all available multi-site instances has been removed from Drush core.

```
$ drush @sites cr

  The alias @sites could not be found.

```

Is there a way to get the same behaviour that does not require me typing my 300 multi-site instance names in a config file?

# Answer
> 4 votes
Waiting something similar, I wrote this small script I called "drall" you may adapt:

```
#!/usr/bin/php
<?php

// Path to sites.php file.
include('web/sites/sites.php');

$done = [];
$argv = $_SERVER['argv'];

array_shift($_SERVER['argv']);

$parameters     = implode(' ', $_SERVER['argv']);
$commandPattern = "drush --uri=:key $parameters";

foreach ($sites as $key => $site) {

  if (count($argv) > 1 && !in_array($site, $done)) {

    $command = str_replace(':key', $key, $commandPattern);
    echo "Executing command `$command` on $site\n";
    `$command`;
    $done[] = $site;
  }
}

```

Use example:

```
$ ./drall cc render
Executing command `drush --uri=xxxxxxx cc render` on default
 [success] 'render' cache was cleared.

```

Hope there will be some @sites behaviors later, that was helpfull.

Although from this issue it doesn't look like it:

> Drush 9 no longer supports executing a single command on multiple sites with alias lists (@A,@b,@c) or @sites. Neither of those syntaxes are available in any context. You may still use drush sa @group to see all aliases in a group; that is the only context in which Drush recognizes alias lists.

# Answer
> 2 votes
I'd simply place a lightweight loop into your `~/.bashrc` or `~/.bash_profile` or where ever you prefer. Just update the `SITES=( foo bar )` array to your needs.

Source your bash file, `cd` into your multi-site root and call **`ddrush cim -y`** for example and it will iterate through all sites provided in the `SITES` array.

```
ddrush () {
  # Provide an array of sites you want to loop.
  SITES=( foo bar )

  # Validate and hint if no argument provided.
  if [ "${#}" -eq 0 ]; then
    echo "- ddrush: missing argument(s)"
    echo "EXAMPLE: ddrush cex -y"
  else
    # Loop:
    for SITE in "${SITES[@]}"; do
      echo "drush -l ${SITE} ${@}"
      drush -l "${SITE}" "${@}"
    done
  fi
}

```

You can use nearly the same for running a deployment script. Or you could easily provide multiple aliases like that. `adrush`, `bdrush`, `cdrush` – one for every multi-site environment you need to maintain.

---

I only now read you have 300 instances running. Respect! Well, then it might be easier to only provide an absolute path to the sites folder and have that scanned and then looped through automatically.

```
xdrush () {
  # Provide the absolute path to the sites directory.
  SITES="/var/www/MYMULTISITE/sites"

  # Validate and hint if no argument provided.
  if [ "${#}" -eq 0 ]; then
    echo "- xdrush: missing argument(s)"
    echo "EXAMPLE: xdrush cex -y"
  else
    PWD=${PWD}
    cd "${SITES}"
    # Loop:
    for SITE in $(ls -d */ | cut -f1 -d'/'); do
      # Skip default site.
      if [ ! "${SITE}" == "default" ]; then
        cd "${PWD}"
        echo "drush -l ${SITE} ${@}"
        drush -l "${SITE}" "${@}"
      fi
    done
  fi
}

```

# Answer
> 2 votes
An out-of-the-box solution is provided by a package named jigarius/drall.

I wrote that package and I've used it on a number of multi site Drupal installations.

---
Tags: drush, multi-sites
---


# Question
Title: Is there a way to check which system was used to send mail?
Is there a way to check which system was used to send mail?

I followed Sending html mails in Drupal 8/9 programmatically. I'm using the SMTP module to make sure that emails are sent via SMTP instead of using the PHP mailer. Emails sent via my website seem to have a higher spam score than when the ones sent directly from my SMTP server. I wonder whether my mails are being sent via SMTP or not.

Is there a method to check this?

# Answer
> -1 votes
**A way to check is using Gmail.**

Sometimes it's obvious:

But most aren't, so you can click on the 3 dots and select show original

Here, for example, you can see this other one was sent using Zoho Mail's SMTP

---

By the way, I was also seeing emails sometimes land in the spam box using SMTP. Once I setup SPF, DKIM, and DMARC for my domain, I've never seen them land in spam again.

> There are three main types of authentication used to prove to mailbox providers that your email is worth being placed in the inbox:
>
> **SPF (Sender Policy Framework)** is an IP address-based authentication method used to compare the sender’s IP indicated in the domain’s DNS record with a list of IPs authorized to send from that domain.
>
> **DKIM (Domain Keys Identified Mail)** is a method for validating domains through a publicly available cryptographic signature. This signature is verified on the receiving end using the DNS record.
>
> **DMARC (Domain-based Message Authentication, Reporting, and Conformance)** is a protocol aimed at reducing email phishing and spoofing. It allows a sender to specify that their email is properly authenticated using DKIM and SPF records.
>
> **Senders who authenticate their messages with all three methods may see less filtering and fewer emails going to spam.**
>
> source: How to Prevent Emails from Going to Spam: The Ultimate Guide

---
Tags: emails, 9
---


# Question
Title: How can I fix "Allowed memory size exhausted" on batch finish?
The batch processed all the items, but instead of showing the finish message, I see the error "Allowed memory size of 536870912 bytes exhausted".

When I debug the code, I notice that Drupal loads each proccessed block on batch finish (`ContentEntityBase->__construct`). I can't figure out why Drupal is doing that.

Structure of the code:

This is a custom module with form class, and batch functions in the `custom_module.module` file. On form submit, the module calls the create batch function:

```
public function submitForm(array &$form, FormStateInterface $form_state) {
  custom_module_make_batch();
}

```

The custom\_module\_build\_batch function getting ids of custom blocks (4000 or more) and generating the batch:

```
function custom_module_make_batch()
{

  $batch = [];

  $items = get_blocks_ids();

  $batch = custom_module_generate_batch($items);
  batch_set($batch);
}

function custom_module_generate_batch($items)
{

  $operations = [];

  $operations_groups = array_chunk($items, 50);

  foreach ($operations_groups as $key => $operations_group) {
    $operations[] = [
      'custom_module_batch_op',
      [$operations_group],
    ];
  }

  $batch = [
    'operations' => $operations,
    'finished' => 'custom_module_batch_finished',
    'title' => 'Custom batch',
    'init_message' => 'Batch is starting.',
    'progress_message' => 'Processed @current out of @total parts.',
    'error_message' => 'Batch has encountered an error.',
  ];
  return $batch;
}

function custom_module_batch_op($operations_group, &$context) {

  foreach ($operations_group as $key => $bid) {

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

    $block->field_name = $new_value;

    $block->save();
  }

}

function custom_module_batch_finished($success, $results, $operations)
{

  $messenger = \Drupal::messenger();
  if ($success) {
    // Here we could do something meaningful with the results.
    // We just display the number of nodes we processed...

    if ($total) {
      $messenger->addMessage(t('@count results processed.', ['@count' => $total]));
    } else {
      $messenger->addMessage(t('There no items for the migration'));
    }

  } else {
    // An error occurred.
    // $operations contains the operations that remained unprocessed.
    $error_operation = reset($operations);
    $messenger->addMessage(
      t(
        'An error occurred while processing @operation with arguments : @args',
        [
          '@operation' => $error_operation[0],
          '@args' => print_r($error_operation[0], TRUE),
        ]
      )
    );
  }
}

```

# Answer
> 5 votes
Batch operations are used when the number of items to handle is unknown and there could possibly be so much items that either loading all of them would use all the memory PHP make available, or handling them would take more time than the time PHP gives to the script to run. When data is loaded from a database table, even entity data, it's the batch operation callback that loads the data, like this code does, for example.

```
$batch_builder = (new BatchBuilder())
  ->setTitle(t('Deleting database rows'))
  ->setFinishCallback('mymodule_finished_callback')
  ->addOperation('mymodule_delete_rows', []);

batch_set($batch_builder->toArray());

function mymodule_delete_rows(&$context) {
  $connection = \Drupal::database();

  if (empty($context['sandbox'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_id'] = 0;
    $context['sandbox']['max'] = $connection
      ->query('SELECT COUNT(DISTINCT [id]) FROM {example}')
      ->fetchField();
    $context['results'] = 0;
  }

  $limit = 5;
  $result = $connection
    ->select('example')
    ->condition('id', $context['sandbox']['current_id'], '>')
    ->orderBy('id')
    ->range(0, $limit)
    ->execute();

  foreach ($result as $row) {
    $context['sandbox']['progress']++;
    $context['results']++;
    $context['sandbox']['current_id'] = $row->id;

    if (!empty($row->title) && is_numeric($row->title[0])) {
      $connection->delete('example')
        ->condition('id', $row->id)
        ->execute()
    }
  }
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }
}

function mymodule_finished_callback($success, $results, $operations, $elapsed) {
  if ($success) {
    $message = \Drupal::translation()->formatPlural($results, '@count row deleted.', '@count rows deleted.');
  }
  else {
    $message = t('Finished with an error.');
  }
  \Drupal::messenger()->addMessage($message);
}

```

The relevant values set in the batch operations callback are the following ones:

* `$context['finished']` tells Drupal to stop calling the batch operations callback, when its value is 1 or `$context['finished']` isn't set
* `$context['results']` is passed to the callback invoked when the batch operations are done, as its second parameter
* `$context['message']` is a text message displayed in the progress page

I would not build an array containing a value for each handled item, as that would use all the available memory, when the handled items are much.

### Reference

---
Tags: 9, batch-operations
---


title: Certain users see 404 when logging in

text:
# Question
Title: Certain users see 404 when logging in
We are seeing an odd error with certain users who are trying to log in to a Drupal 9 site. They are using the login form at /user/login, at which point they submit and are redirected to a URL like:

```
/user/form_action_p_pvdeGsVG5zNF_XLGPTvY....

```

Which results in a 404.

This only happens to 2 out of 20 users. If I use Drush to generate a login link, it works fine.

What could be causing this? There isn't much installed besides Pathauto, Token, Redirect, and Acquia Site Studio.

# Answer
`form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM` is used as placeholder for the action URL (for submitting the form).

If you still see this placeholder in the browser HTML source then the placeholder somehow got separated from the attached lazy builder. To debug this you could start with a form alter hook, where you see the placeholder string and the attached lazybuilder callback FormBuilder::renderPlaceholderFormAction. Go step by step through the render pipeline and check for custom code or templates which doesn't render the entire form as it should to carry on attached metadata.
> 1 votes

---
Tags: 9
---


# Question
Title: How to achieve this? (because I think it's not possible to reference a vocabulary)
I'm trying to implement a (i think it's not that complex) functionality but I'm stuck at this moment.

**I'm using Drupal 7** and I have my own custom module so, if necessary I would code, but for now I was defining the content types.

I want the user to be able to create two types of content:

**1. Stock** This content has the following fields:

```
a. name
b. item
c. quantity
d. value

```

**2. Items** (this content is the one that I reference in the Stock content). This content has the following fields:

```
a. name
b. attributes (unlimited)

```

And the last part of the puzzle is the **attributes** field that initially I wanted to use a Vocabulary.

**An example is easier to understand:**

I have 2 attributes (vocabularies):

```
color (with terms yellow, blue and green)
weight (with terms 200, 1000 and 5000)

```

I then create an Item like this:

```
name = "Item Nº1"
attribues = [color, weight] (this field is unlimited so I want to reference the 2 vocabularies. From what I see, it's not possible to reference vocabularies, only terms)

```

Finally, when the user creates a Stock, I want something like this:

```
name = "my First Stock"
item = "Item Nº1" (referenced)
quantity = 3
value = 34

```

The goal I need to achieve is that, in this last step of creating a **Stock** content, I need to choose the terms of the "Item Nº1". In this case it would show up the color and weight and the user would choose one or multiple terms of each one.

I think I'm overthinking this and there is a clean solution so, if someone can help me and suggest a better way to do this, I would really appreciate it.

Thank you

**EDIT:**

I've managed to create the "Items" content type that as an Entity Reference field where I can choose which vocabularies I can reference:

adding a new Item:

So, at this moment I can add another entity reference to the Stock content type BUT that will only allows the user to choose the Item type. What I need at this point is to also be able to choose the terms of the vocabularies that Item type has available (as I'm writing this, I'm getting more certain that is not possible without any coding at all)

# Answer
> 0 votes
To track inventory, take a look at how Drupal Commerce does it.

The Commerce setup may be a little more complex than you need, but it is quite flexible and well supported. If you choose this approach, it will also make it easier to add new features later.

To start, you can make some products, and then create what Commerce calls **product variations** for your "attributes".

To handle inventory, there's the Commerce Stock module. (Disclaimer: Have not used this particular module.)

Even though it's called "Drupal Commerce", all the features are split up into separate modules, so if you only need to handle inventory and do not want a web store, you can just disable the store related modules (Payment, Checkout, etc.)

# Answer
> 0 votes
Vocabularies are configuration entities, but you can still reference them with entity reference fields.

Add a new field and choose *Reference \> Other...* for the field type.

On the next screen you'll be able to select the type of item to reference via a select list with many more options, including configuration entities. On this screen, set "Type of item to reference" to *Configuration \> Taxonomy vocabulary*.

By default this will allow an editor to reference any taxonomy vocabulary. If you need to limit which vocabularies can be referenced, create an entity reference view and configure your field to use if by setting the *Reference method* on your field's edit page (Manage Fields \> My Field \> Edit). For details, see How to Use Entity Reference Views in Drupal 8

---
Tags: entities
---


title: Missing text format: 4 - ckeditor issue

text:
# Question
Title: Missing text format: 4 - ckeditor issue
"Missing text format: 4." reported in log from anonymous user - I have Restricted HTML enabled for anonymous user

Drupal 9.3.8

This really fills the log - it seems a common issue for the anonymous user

What exactly is " text format: 4 "

Anyone know how to drill into this for a fix ??

# Answer
> 1 votes
To fix this issue you can either recreate the text format `4`:

* *admin/config/content/formats/add*
* Name: *4*
* Machine name: `4` (automatically assigned)

Which probably existed when the text fields where saved originally, either on your site or a different site you have imported the data from.

Or re-save the formatted text fields switching to the text format *Restricted HTML* (`restricted_html`) you want to use now.

---
Tags: input-formats
---


# Question
Title: Writing to the temporary directory randomly stops working
In one of the websites on production, when Drupal writes on the temporary directory, it randomly stops working with the following error, even though the permissions are set correctly, and there is enough space.

> Temporary file data could not be written

The temporary directory is set to the *DRUPAL\_ROOT/sites/default/files/tmp* directory.

Removing the content of the temporary directory solves the problem, but it came back again. I can't debug the reason.

How can I fix this issue?

# Answer
I solved the issue, turns out that there was a user quota with a maximum amount of blocks that can be written.

Use this command to check if there is a quota.

```
sudo quota -vs USER

```
> 1 votes

---
Tags: files
---


# Question
Title: How to sub_process a non-associative array in migration.yml
I know I can use `sub_process` to iterate over an associative array like

```
field_categories:
  plugin: sub_process
  source: remote_categories
  process:
    target_id:
      plugin: migration_lookup
      migration: my_existing_taxonomy_migration
      source: name_of_key

```

But I don't know how to iterate over a numeric / non-associative array. Assume the JSON data structure

```
{
  remote_categories: [ 'alpha', 'beta', 'gamma' ]
}

```

how can I pass the values as keys to `migration_lookup`? I.e. what would be `name_of_key` in the example above?

# Answer
I've written a process plugin that transforms a sequential list into an array of associative sub-arrays, so sub\_process and migration\_lookup can use them.

```
namespace Drupal\my_module\Plugin\migrate\process;

use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\Row;

/**
 * Transforms an array of values into an array of associative arrays.
 *
 * The inner array will be filled with one key. E.g. ['alpha', 'beta'] becomes
 * [[value => 'alpha'], [value => 'beta']]
 *
 * Use this plugin to preprocess a numeric/non-associative array for other
 * plugins that requires an associative array as input, such as the sub_process
 * plugin.
 *
 * Available configuration keys:
 * - source: Source property.
 * - keyname: name of the key to be used for the associative sub-arrays,
 *   defaults to 'value'.
 *
 * Example:
 *
 * @code
 * source:
 *   my_flat_array:
 *     - category1
 *     - category2
 * process:
 *   my_associative_array:
 *     plugin: deepen
 *     source: my_flat_array
 *   field_taxonomy_term:
 *     plugin: sub_process
 *     source: '@my_associative_array'
 *     process:
 *       target_id:
 *         plugin: migration_lookup
 *         migration: my_taxonomy_migration
 *         source: value
 * @endcode
 *
 * @see \Drupal\migrate\Plugin\MigrateProcessInterface
 *
 * @MigrateProcessPlugin(
 *   id = "deepen",
 *   handle_multiples = TRUE
 * )
 */
class Deepen extends ProcessPluginBase {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $keyname = (is_string($this->configuration['keyname']) && $this->configuration['keyname'] != '') ? $this->configuration['keyname'] : 'value';

    if (is_array($value) || $value instanceof \Traversable) {
      $result = [];
      foreach ($value as $sub_value) {
        $result[] = [$keyname => $sub_value];
      }
      return $result;
    }
    else {
      throw new MigrateException(sprintf('%s is not traversable', var_export($value, TRUE)));
    }
  }

}

```
> 10 votes

# Answer
I have had success in two different ways. I found your question because I wanted "sub\_process" to "key" my string value into an array, so it goes into a specific property on the field, not the default property.

```
  field_categories:
    -
      plugin: multiple_values
      source: remote_categories
    -
      plugin: migration_lookup
      migration: my_existing_taxonomy_migration
    -
      plugin: skip_on_empty
      method: process
      message: 'Migrate lookup failed, or no value passed!'
    -
      plugin: explode
      delimiter: 'StringThatShoudNotExistIntheValue'
    -
      plugin: sub_process
      process:
        target_id: '0'

```

Alternative method without sub\_process (but will runs a process for each value).

```
  field_categories:
    -
      plugin: multiple_values
      source: remote_categories
    -
      plugin: migration_lookup
      migration: my_existing_taxonomy_migration
    -
      plugin: skip_on_empty
      method: process
      message: 'Migrate lookup failed, or no value passed!'

```

The explode() just casts the string of each array element into a array \[0 =\> $value\], then we use sub\_process with target\_id: 0 to key by the first/0-th element (which is $value).

The skip\_on\_empty is there for sanity check but is optional.
> 0 votes

---
Tags: 8, migrations
---


# Question
Title: Permission granted to a programatically created role is not working!
In a custom module form, I am using this code for the submission handler.

```
$role = Role::create(['id' => 'member', 'label' => t('Member')]);
$role->grantPermission('Renew membership');
$role->save();

```

It seems to work, since the output of `ksm($role)` shows the permission between the permissions given to the role.

```
$role Drupal\user\Entity\Role (23)
  Properties (23)
    protected id -> string (6) "member"
    protected label -> UTF-8 string (8) "Adhérent"
    protected weight -> integer 1
    protected permissions -> array (1)
      0 => string (16) "Renew membership"

```

When I look at */admin/people/permissions*, I notice the role is correctly listed (which means it has been created), the permission too, but the permission isn't granted to the role.

>

What is wrong in the code I use?

# Answer
> 1 votes
`Role::grantPermission()` doesn't check the permission is correct or it's defined by any module; it just adds the permission, if the role doesn't already have that permission.

```
public function grantPermission($permission) {
  if ($this->isAdmin()) {
    return $this;
  }
  if (!$this->hasPermission($permission)) {
    $this->permissions[] = $permission;
  }
  return $this;
}

```

This also means that, if the code uses the permission title, which is what /admin/people/permissions shows, it doesn't use the correct ID for that permission. The code that handles permissions is also case sensitive; this means it considers *Renew membership*, *Renew Membership*, and *renew membership* three different permissions.

Since /admin/people/permissions shows *Renew Membership* as permission, that is a known permission. You just need to use its ID, which in most of the cases is the permission title in lower-case characters.

```
$role = Role::create(['id' => 'member', 'label' => t('Member')]);
$role->grantPermission('renew membership');
$role->save();

```

If that isn't a permission defined from a module you wrote, and you don't know which module defines that permission, and where, you can look up at the markup used in the /admin/people/permissions page, where you will probably find the permission ID.
For example, for the per *Administer contact forms and contact form settings* permission, the value of the *data-drupal-selector* attribute used for its `<tr>` is *edit-permissions-administer-contact-forms*.

```
<tr data-drupal-selector="edit-permissions-administer-contact-forms" class="odd">
  <td><div class="permission"><span class="title">Administer contact forms and contact form settings</span></div></td>
  <!-- omitted markup -->
</tr>

```

Removing *edit-permissions-* and replacing the hyphens with spaces, it becomes *administer contact forms*, which is the permission ID, listed in the contact.permissions.yml file.

```
administer contact forms:
  title: 'Administer contact forms and contact form settings'
access site-wide contact form:
  title: 'Use the site-wide contact form'
access user contact forms:
  title: 'Use users'' personal contact forms'

```

---
Tags: users, 9
---


# Question
Title: Accessing a Paragraphs field's from inside the parent paragraph
I have a paragraph twig file that I'm adding to my subtheme.

Inside of it I have another paragraph that is being used. And there could be more than 1 of the child paragraph.

I have this code:

```
 {% for key, item in content.field_faq_section_question if key|first != '#' %}
  {{ item }}

{% endfor %}

```

And it prints the title and the text fields of the paragraph properly. But What I need to do it access each individually here.

I have tried a lot of different ways to access the fields and none work. A dump and a var\_dump of item ends with a blank screen.

I could create another twig file for this paragraph, and it works, but I'm hoping to use the key to add an id to a wrapper div.

I'd like to:

```
 {% for key, item in content.field_faq_section_question if key|first != '#' %}
  {{ item.title }}
    {{ item.text }}
{% endfor %}

```

What is the best way of doing this?

# Answer
> 1 votes
First, I'd recommend https://www.drupal.org/project/twig\_xdebug to help you debug inside of twig templates. It'll make your life 100 times easier.

Your issue is that `content.field_faq_section_question` is a render array, so looping over its "items" is not actually looping over the referenced entities -- it's looping over the render array elements. That's why you've needed to add that annoying check for whether the key starts with `#`.

If you want to loop over the *value* of the reference field, then you need to loop over the `#items`. Then you need to grab the actual paragraph that is being referenced in order to access its fields, which can be done with `[some_entity_reference_item].entity`.

```
{% for k, paragraph_reference in content.field_faq_section_question['#items'] %}
  {% set paragraph = paragraph_reference.entity %}
  {% set my_id = paragraph.field_some_text_field.0.value %}

  <div id="{{ my_id }}">
    // ... whatever you want to render
    // I think this'll work the same way as the {{ item }} you're using already
    {{ content.field_faq_section_question[k] }}
  </div>
{% endfor %}

```

That said, depending on what you're doing, you may want to use a field template as mentioned by 4uk4, or actually leverage another paragraph template (like you're avoiding).

---
Tags: entities, paragraphs
---


title: Change langcode

text:
# Question
Title: Change langcode
How can I change the entire site `<html lang="en">` to `<html lang="en-US">`? I couldn't find anything on the Internet.

# Answer
> 3 votes
If you want to do it programmatically you can use hook\_preprocess\_HOOK like the this:

```
/**
 * Implements hook_preprocess_HOOK().
 */
function [MODULE|THEME]_preprocess_html(&$variables) {
  /** @var \Drupal\Core\Template\Attribute $html_attribute */
  $html_attribute = $variables['html_attributes'];
  if ($html_attribute->hasAttribute("lang")) {
    $html_attribute->removeAttribute('lang');
    $html_attribute->setAttribute('lang', 'en-US');
  }
}

```

# Answer
> 2 votes
You can do this by adding `en-US` as a custom language.

1. Go to `/admin/config/regional/language`.
2. Click **Add language**.
3. Choose **Custom language...** from the bottom of the list.
4. Enter the language code and language name.

# Answer
> 0 votes
Drupal 8 and laters can handle this via UI.

This is how I set proper `lang` code in a multilanguage content website.

* add/set up languages \[/admin/config/regional/language\]
* set up language detection (optional) \[/admin/config/regional/language/detection\]
* set up language behaviours for a multilanguge content type you want translated in more languages \[/admin/config/regional/content-language\]
* translate your node in more languages.

You can now switch node traslation and compare `lang` codes

---
Tags: 8
---


title: template_preprocess custom block type

text:
# Question
Title: template_preprocess custom block type
I have a custom block type with two different fields. What I am trying to accomplish is, to hide the first field if the second is not empty.

That seems like something that could be done in template\_preprocess, but where would I put it and what would be my template?

thanks!

# Answer
you can utilize twig's if/else condition:

```
{% if field_NAME_OF_YOUR_SECOND_FIELD.0 == false %}
    {{ field_NAME_OF_YOUR_FIRST_FIELD.0 }}
{% endif %}

```

check this for extracting the values of different fields
> 1 votes

# Answer
Preprocessing the `block_content` template was considered undesireable, and they suppressed the functionality. There is a module on github that provides this functionality, but since it lacks composer support, you might just copy it into your project.

All that said, you should find that `template_preprocess_block` allows access to what you want, and this might work:

```
function MYTHEME_preprocess_block(&$variables) {
  unset($variables['content']['field_custom'][0]);
}

```

---
> 0 votes

# Answer
Custom block type is available in `$variables['content']['body']['#bundle']` Refer the below sample function

```
function mytheme_preprocess_block(&$variables) {
  if ($variables['content']['body']['#bundle'] == 'my_block_type') {
    // Do whatever specific to the block type.
  }
}

```

Adding a bit more information as per @berliner commented

```
$variables['content']['#block_content'] //will hold the content entity

$variables['content']['#block_content']->id() //will give you the content id, ie. the custom block content id

```

In order to alter any field you could apply logic inside the conditional statement

Ref. belwo code where the values are assigned to a drupalSettings js variable.

```
function mytheme_preprocess_block(&$variables) {

        if($variables['content']['body']['#bundle'] == 'my_custom_block_type')
        {
        $variables['#attached']['drupalSettings']['block_content_id']=$variables['content']['#block_content']->id();

        $variables['#attached']['drupalSettings']['full_content']=$variables['content'];
        }

}

```

I would prefer to log drupalSettings.full\_content to a javascript console, which would give a bigger picture of the whole variables and manipulate accordingly Ref: JS function

```
(function($, Drupal, drupalSettings) {

Drupal.behaviors.myCustomJSFunction = {
    attach: function (context, settings) {
      console.log(drupalSettings.full_content);
        }
    };

     })(jQuery, Drupal, drupalSettings, window.Cookies);

```
> 0 votes

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


# Question
Title: how to get url of link to content in twig?
I just created one view block to show all my blogs in it. I am getting all fields in twig but unable to call "link to content" to current node of every blog from view block.

Any solution please help me.

I tried like below with url not working

```
<a class="d-inline-block" href="{{ url }}">
<h2 class="blog-head" style="color: #2d2d2d;">{{ content['#view'].field['field_blog_post_title'].value(row) }}</h2>
</a>

```

# Answer
Assuming that your blog is a node type and you got access to the node object in twig, you can use this

```
{{ path('entity.node.canonical', {'node': node.id}) }}

```

First argument **entity.node.canonical** is the route name, here to the node, the second argument **{'node': node.id}** contains route parameters, here the node parameter is mandatory which has to be the node id.

---

How to get the node object? I am making a guess here in which context you are but from the question, I think you are in a view and iterate over the rows variable, so a starter is to debug the **row** variable

```
{{ dd(row) }}

```
> 1 votes

---
Tags: views
---


title: Applying trim to paragraph value

text:
# Question
Title: Applying trim to paragraph value
I have the following Paragraph template which displays a heading with a trailing orange dot. The field itself is a normal text field in Drupal. For some reason, there is a trailing space after the heading, which leads to a space between the heading and the dot. I want to remove it (and |trim is the answer), but when I add trim to the below variable I get a PHP warning saying parameter 1 should be a string, not an array.

How do I then get the absolute value of the paragraph value?

```
{% block paragraph %}
  <div{{ attributes.addClass(classes) }}>
    {% block content %}
      <h1>{{ content.field_heading_h1 }}<i class="orange">.</i></h1>
    {% endblock %}
  </div>
{% endblock paragraph %}

```

The following gives the PHP error:

```
{% block paragraph %}
  <div{{ attributes.addClass(classes) }}>
    {% block content %}
      <h1>{{ content.field_heading_h1|trim }}<i class="orange">.</i></h1>
    {% endblock %}
  </div>
{% endblock paragraph %}

```

> Warning: trim() expects parameter 1 to be string, array given in twig\_trim\_filter()

# Answer
As the warning states, content.field\_heading\_h1 is a (render)-array

you could check it´s structure using `{{ kint(content.field_heading_h1) }}` (devel-module)

probably you can get the plain text value and trim it with:

```
{{ content.field_heading_h1.value|trim }}

```

or

```
{{ content.field_heading_h1.0|trim }}

```

refering to How do I get the raw field value in a twig template?

thats just one way to do "operation on symptoms" but the actual question to ask is why there is a whitespace and is there a way to prevent that already in the form that saves it
> 0 votes

---
Tags: 9, paragraphs
---