# Question
Title: How to change the condition to AND in accessing content by role in a view-block?
I have a view-block 'Expo', I want to display this block only if current user has two specific user roles i.e., 'Actor' and 'Singer'.

When I checked the both 'Actor' and 'Singer' , The block is displaying in users who have either 'Actor' or 'Singer' user role. When the user has two user roles it's displaying two blocks.

As per my understanding, It's using conditional OR in between the checked user roles. How can I change it to conditional AND?

# Answer
Yes, the `Role` access plugin is written in a way that its `access` method works effectively like an `OR`:

```
public function access(AccountInterface $account) {
  return array_intersect(array_filter($this->options['role']), $account->getRoles());
}

```

To change this behavior, you can do it in two ways:

* Creating a new `ViewsAccess` plugin that mostly works like `Role` but operates with an `AND`. To do this, extend the `Role` class, override the `access` method, and then declare this class as a new `@ViewsAccess` plugin (remember to give it a unique ID and a new name). This new plugin will show up beside the existing `Role` plugin.
* Alternatively, you can add an option on the existing `Role` plugin to make it behave like an `AND` when told to. To do this, you extend the existing `Role` class, override `buildOptionsForm` method to add the option, override the `access` method to only work like an `AND` if it's configured to, then alter the existing `Role` plugin's class to point to your extended version instead of the one from Views.

+ If you're familiar with working with form alters and view alters to modify forms and how things render based on the form values, this approach is almost similar.
> 2 votes

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


# Question
Title: Calling a twig template depending on the number of field items
I need to call different twig templates of an image field depending on the number of items of this field. If there is only 1 image item, I'd like to use template1.html.twig. If there are \> 1 image items, I'd like to use template2.html.twig.

Is that possible? If yes, how?

# Answer
Sounds like a simple template suggestion added from a custom module or theme along the following snippet.

```
/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function MYTHEME_theme_suggestions_field_alter(array &$suggestions, array $variables) {
  if ($variables['element']['#field_name'] === 'field_MYFIELD') {
    // Fallback.
    $values = '';

    /** @var \Drupal\Core\Field\FieldItemList $items */
    $items = $variables['element']['#items'];
    if ($items->count() == 1) {
      $values = '__single_image';
    }
    if ($items->count() > 1) {
      $values = '__slideshow';
    }

    $suggestions[] = 'field__' . $variables['element']['#field_name'] . $values;
  }
}

```

This would allow you to have `field--field-MYFIELD--single-image.html.twig` or `field--field-MYFIELD--slideshow.html.twig`.

Flush cache!
> 3 votes

---
Tags: theming
---


# Question
Title: How to write SQL Statements With Spaces In Column Names
I am trying to write a dynamic query to get data from columns with spaces in their names.

The *Product\_Details* table is the following.

| S.No. | Product line | Product type | Product | Year |
| --- | --- | --- | --- | --- |
| 1 | Camp Equipment | Cooking Gear | Cook Set | 2015 |
| 2 | Golf Equipment | Irons | Titanium | 2014 |

I am using this code, which returns a *syntax error or access violation* error.

```
$query = \Drupal::database()->select('Product_Details', 'n');
$query->addField('n', 'S.No.');
$query->condition('n.Product type', 'Irons');
$results = $query->execute()->fetchAll();

```

While looking into the error log after the SQL Query has been executed, I found out this.

> 1: SELECT n.S.No. AS SNo FROM {Product\_Details} n WHERE n.Producttype = :db\_condition\_placeholder\_0; Array ( \[:db\_condition\_placeholder\_0\] =\> Irons )

If you look into it, *Product type* is changed to *Producttype* and *S.No.* is changed to *SNo*.

How can I write a SQL query when column names has spaces?

EDIT: This has been handled in the issue #2986452. This is committed to branch 9.0.x

# Answer
Ideally your column names shouldn't have spaces in them, but if you're stuck with that then you'll need to do a manual query, like this:

```
$q = \Drupal::database()
  ->query("select `S.No.` from `Product_Details` where `Product type` = 'Irons'")
  ->execute();

```
> 0 votes

---
Tags: 8, database
---


# Question
Title: LogicException: The controller result claims to be providing relevant cache metadata, but leaked metadata was detected
> LogicException: The controller result claims to be providing relevant cache metadata, but leaked metadata was detected. Please ensure you are not rendering content too early. Returned object class: Drupal\rest\ResourceResponse. in Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>wrapControllerExecutionInRenderContext() (line 154 of /srv/bindings/8c5ccf24ccc9492bb85469725da608ea/code/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php).

I am facing this issue when i try to access REST endpoint through ajax get request. Important thing, when i was logged-in then every works find but when i am not logged it it through above exception.

Here is my code

```
namespace Drupal\one_rest_api\Plugin\rest\resource;

use Drupal\file\Entity\File;
use Drupal\image\Entity\ImageStyle;
use Drupal\media_entity\Entity\Media;
use Drupal\node\Entity\Node;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\taxonomy\Entity\Term;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\HttpException;

/**
 * Provides article resource endpoint
 *
 * @RestResource(
 *   id = "one_article_resource",
 *   label = @Translation("One Article Resource"),
 *   uri_paths = {
 *     "canonical" = "/api/one/v1/articles"
 *   }
 * )
 */
class ArticleResource extends ResourceBase
{
    /**
     * A current user instance.
     *
     * @var \Drupal\Core\Session\AccountProxyInterface
     */
    protected $currentUser;

    /**
     * Constructs a Drupal\rest\Plugin\ResourceBase 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 array $serializer_formats
     *   The available serialization formats.
     * @param \Psr\Log\LoggerInterface $logger
     *   A logger instance.
     * @param \Drupal\Core\Session\AccountProxyInterface $current_user
     *   A current user instance.
     */
    public function __construct(
        array $configuration,
        $plugin_id,
        $plugin_definition,
        array $serializer_formats,
        LoggerInterface $logger,
        AccountProxyInterface $current_user) {

        parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

        $this->currentUser = $current_user;
    }

    /**
     * {@inheritdoc}
     */
    public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
        return new static(
            $configuration,
            $plugin_id,
            $plugin_definition,
            $container->getParameter('serializer.formats'),
            $container->get('logger.factory')->get('one_rest'),
            $container->get('current_user')
        );
    }
    /**
     * Responds to GET requests.
     *
     * Returns a list of bundles for specified entity.
     *
     * @throws \Symfony\Component\HttpKernel\Exception\HttpException
     *   Throws exception expected.
     */
    public function get() {
        global $base_url;

        $response_result = [];
        $response_code = 200;
        // You must to implement the logic of your REST Resource here.
        // Use current user after pass authentication to validate access.
        if (!$this->currentUser->hasPermission('access content')) {
            throw new AccessDeniedHttpException();
        }

        $entities = \Drupal::entityQuery('node')
            ->condition('status', 1)
            ->condition('type', 'article')
            ->condition('langcode','en')
            ->notExists('field_f1')
            ->sort('created', 'DESC')
            ->range(0, 20)
            ->execute();

        if(!empty($entities)){
            foreach ($entities as $node_id) {
                $node = Node::load($node_id);

                if(is_object($node)){
                    $image_url = '';
                    $image_target = $node->get('field_image')->target_id;
                    if(!empty($image_target)){
                        $media = Media::load($image_target);
                        if(is_object($media)){
                            $image = File::load($media->get('field_image')->target_id);
                            $image_url = ImageStyle::load('rest_api')->buildUrl($image->getFileUri());
                        }
                    }

                    $output_tags = [];
                    $tags = $node->get('field_tags')->getValue();
                    if(!empty($tags)){
                        foreach($tags as $key => $tag){
                            $term = Term::load($tag['target_id']);
                            $output_tags[] = $term->get('name')->value;
                        }
                    }

                    $result = [
                        "nid" => $node->id(),
                        "base_url" => $base_url,
                        "title" => $node->getTitle(),
                        "field_image" => $image_url,
                        "field_tags" => $output_tags
                    ];

                    $response_result[] = $result;
                }

            }
        }

        if(!empty($response_result)) {
            $headers = [
                'Access-Control-Allow-Origin' => '*',
                'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PATCH, DELETE',
                'Access-Control-Allow-Headers' => 'Authorization'
            ];

            $response = new ResourceResponse($response_result, $response_code, $headers);
            return $response;
        }

        throw new HttpException(t("Empty Response"));
    }
}

```

And Below is my typescript code

```
load(){

    if(this.data){
      return Promise.resolve(this.data);
    }

    return new Promise(resolve => {
      this.http.get('https://example.com/api/one/v1/articles?_format=json')
        .subscribe(data => {
          this.data = data;
          resolve(this.data);
        },err => {
          console.log(err);
        });
    });

  }

```

I didn't understand what i am missing in drupal code

# Answer
> 8 votes
Modify your entity query to something like below

```
$entities = \Drupal::entityQuery('node')
            ->condition('status', 1)
            ->condition('type', 'article')
            ->condition('langcode','en')
            ->notExists('field_f1')
            ->sort('created', 'DESC')
            ->range(0, 20)
            ->accessCheck(false)
            ->execute();

```

# Answer
> 13 votes
I have solved it by adding code at the end because class ResourceResponse is using CacheableResponseTrait which is responsible to cache metadata. In POST, PATCH, DELETE we don't want that because resources are modified.

```
return new ModifiedResourceResponse($node);

```

# Answer
> 3 votes
I think the answers that are currently listed are the proper methods to follow. However, I think its relevant to note, that I was able to fix this (possibly temporarily) by reinstalling the jsonapi module in drupal using composer. In case it may help someone, this is what I ran from the command line:

```
composer require 'drupal/jsonapi:^1.24'

```

Don't forget to change the code to the version you are trying to install. As you can see, this is specifically for version 1.24.

# Answer
> 3 votes
For me, wrapping the query in a render context fixed the issues without having to define the the accessCheck(FALSE):

```
// Wrap Query in render context.
$context = new RenderContext();
$nids = \Drupal::service('renderer')->executeInRenderContext($context, function () {
  // Query some nodes.
  $my_query = \Drupal::entityQuery('node')
    ->condition('type', 'my_type')
    ->condition('status', 1);
  return $my_query->execute();
});

```

https://www.lullabot.com/articles/early-rendering-a-lesson-in-debugging-drupal-8

---
Tags: entities, caching, 8
---


title: Machine-translate a node by menu link

text:
# Question
Title: Machine-translate a node by menu link
I have an "About us" *main-navigation* menu link.

I want to create several other *main-navigation* menu links, in languages other than English, which will link to that very webpage, for example:

* **เกี่ยวกับเรา** (about us in Thai)
    + If the user clicked that link, the destination would be the same "About us" webpage, but the content would be machine-translated to Thai.

---

The English content of "About us" is generally small (up to 1000 characters), well formatted, accessible and names and slang are avoided (unless some escaping is utilized).

---

I didn't find data about "machine" or "auto(matic)" in the *Content Translation* module documentation<sup>,</sup> but it might be worth to still ask if there any way inside Drupal itself to achieve that?

# Answer
Drupal core (a standard Drupal install) does not have support for machine translation out-of-the-box.

However, you can add it easily by installing a contributed module.

TMGMT is a reliable module that will enable you to do machine translation with the following services:

* Google Translate
* Microsoft Translator
* Deepl

If you later decide to have professionals translate the site, TMGMT will support that too, which makes it better in my opinion than a module that only does machine translation.
> 0 votes

---
Tags: i18n-l10n
---


title: alter image style attribute

text:
# Question
Title: alter image style attribute
i am trying to develop a CKEDITOR plugin to add padding/margin to images,

after looking in the documentations i have written this code :

```
const style = new CKEDITOR.style( { element: 'img', attributes: { 'style': 'margin:100px' } } );
editor.applyStyle(style);

```

but it didn't work so i tryied :

```
const style = new CKEDITOR.style( { element: 'image', attributes: { 'style': 'margin:100px' } } );
editor.applyStyle(style);

```

and still did not work, i read that on drupal 9 the image is a widget and not an element so i tryied:

```
const style = new CKEDITOR.style( { type:'widget', widget: 'image' , attributes: { 'style': 'margin:100px' } } );
editor.applyStyle(style);

```

and still did not work, so i tryied :

```
const style = new CKEDITOR.style( { element: 'p', attributes: { 'style': 'margin:100px' } } );
editor.applyStyle(style);

```

and it did work but it was added to the 'p' wraping the img so i know that the code is currect but i can't seem to add it to the img...

# Answer
Trying to create a CKEditor plugin is not as easy as it might look. I'd suggest to check the amazing module CKEditor Templates (in a nutshell, you will need to extend the CKEditorPluginBase class).
> 1 votes

---
Tags: 9
---


# Question
Title: How to increase image resolution in gallery?
Not sure if I am asking the correct question here as I am more of a PHP coder than a graphics designer. My client's site has a Views img gallery which displays 3 columns wide on desktop and 1 wide on mobile. The image resolution on mobile is not very good and I am trying to increase it. I suspect it is the same resolution on desktop but no one is concerned about that.

I think the correct solution here is to use a larger img style for the image and then adjust with CSS to shrink it to fit the device (responsive). But if I do that, the images do not size to fit in the 3 wide columns on desktop.

Does this all make sense? Is there a module to do this properly. I have looked at Responsive Images and Styles and Picture modules but they sound like simply make images which resize but don't allow starting with a larger img to start with (larger style).

# Answer
One thing is defining the responsive image styles to set specific breakpoints and another thing is to improve the quality of the uploaded pictures. For instance, the Image toolkit allows you to set the JPEG quality of the manipulated images, resulting in better image quality at expense of higher network transfers.

I would try to avoid as much as possible shrinking images by CSS because this works but you are opening the door to a slow page: imagine someone uploads a carousel of 5MB pictures and you are displaying 220px thumbnails in mobile -\> the page size will become unusable.
> 0 votes

---
Tags: 7
---


title: How do I mock \Drupal::httpClient()?

text:
# Question
Title: How do I mock \Drupal::httpClient()?
I'm unit testing a utility library (of our own making) that makes calls to an external REST API with `\Drupal::httpClient()`

So, I have a library class with static functions:

```
class myUtils {
  public static function getFromApi($path)
  {
    ...
    $response = \Drupal::httpClient()->request( ... );
    ...
  }

...

}

```

and I want to call that from a test class:

```
class myUtilsTest extends \Codeception\Test\Unit
{
  // Lots of other stuff ...
  public function testGetFromApi()
  {
     // Do some mocking magic
     ...
     myUtils::getFromApi('/some/test/path');
     ...
  }
}

```

I realize I can make a `\GuzzleHttp\Handler\MockHandler` and set it up to return whatever I want it to, but how do I set it to "overwrite" the call to `\Drupal->httpClient()`?

I've seen some examples which seem to assume you have an instance of a class that has its own `httpClient` member, and this is easily mocked - but in my use case, there's no reason at all to design the utilities like that. So how do I mock the *global* `\Drupal::httpClient()` in this case?

Thanks in advance for any response.

# Answer
> 3 votes
Converting your class to use dependency injection would look something like this:

```
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use GuzzleHttp\Client

class myUtils implements ContainerFactoryPluginInterface {

  /**
   * The http service.
   *
   * @var \GuzzleHttp\Client
   */
  protected $httpClient;

  final public function __construct(array $configuration, $plugin_id, $plugin_definition, Client $httpClient) {
    $this->httpClient = $httpClient;
    parent::__construct($configuration, $plugin_id, $plugin_definition);
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('http_client')
    );
  }

  public function getFromApi($path)
  {
    ...
    $response = $this->httpClient->request( ... );
    ...
  }

...

}

```

---
Tags: testing
---


title: Read entity reference node field

text:
# Question
Title: Read entity reference node field
I have a referenced entity named - field\_cp\_level2\_ref\_level3. This field belongs to level3 content type. when I dump the $entity, I see the field as below:

```
entity:node:level3::field_cp_level2_ref_level3 => Drupal\Core\Field\EntityReferenceFieldItemList (9) Depth Limit

```

how to read the value of this field? I tried to read the value as below:

```
$var =  $entity->$node->field_cp_level2_ref_level3->value;

```

dpm($var) returns null. how to read this field?

# Answer
You can use `$entity->field_x->referencedEntities();` which will return an array of referenced entity objects
> 1 votes

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


# Question
Title: Drupal 8 how to show entity reference field in views exposed filter as select list?
I have content types as Leaves and Branch. and I have an Branch ER field in Leaves. How to show Branch as **select list** in views exposed filter Drupal 8?

I really need a solution asap.

Thanks.

# Answer
How about the Views Entity Reference Filter module? The module is also capable of showing the values of the referenced entities in a filter instead of the IDs.
> 3 votes

# Answer
I came across same situation long before. I did not remember exactly.

Check this link https://www.drupal.org/node/2429699
> 1 votes

# Answer
I think what you're looking for is entityreference\_filter module. it' working on drupal 8 and 9

> This module provides the views filter for entity ID or entity reference fields:
>
> node ID user ID taxonomy term ID term reference field (Drupal core) entity reference field (Entity reference module) Exposed filter functionality Taxonomy term filtering: Imagine the following case - you have taxonomy terms in exposed filter widget (drop down select list). But for some reason you want to show just several terms, not all the dictionary. With this module, you can do this by creating a separate view which generates the desired list of terms.
>
> The similar functionality is available for other type of fields - you create a separate view (or a new display of the same view) which returns the list of items to show in drop down select list of the exposed filter.
> 1 votes

---
Tags: 8, views
---


# Question
Title: Use first 3 digits of views contextual filter as filter criteria
I have a view that fetches a Belgian postal code, which always has 4 digits, from the URL and uses it as contextual filter to only show nodes for that postal code. This works fine.

I would like to also show sub-localities in this view. Given a postal code equal to 9990, the view should show the node for 9990 but also the nodes for 9991 and 9992, and other nodes whose postal code's first three digits are 999.

Is it possible to use the regex operator in the view filter for this, for example `REGEXP_EXTRACT(%,"^.{0,3}")` which doesn't actually work?

Preferably I'd like to solve this in the view itself and not with code.

# Answer
> 0 votes
## Views Custom Regex

Module VCR has a String filter according to the code which maybe help using **Start with**.

## Views Contextual Filter Validator: Regular Expression (regex)

Maybe usefull to validate the input?

You **cannot** use Views Contextual Filter Validator: Regular Expression (regex) as it is a validator only as explained in Can the regex extract portion of filter value for use?

> Views Contextual Filter Validator: Regular Expression adds a Views contextual filter validator that can evaluate an argument based on user-supplied regular expression pattern.

---
Tags: views, 9
---


title: Files migration issue

text:
# Question
Title: Files migration issue
I am following this tutorial on how to migrate files from D7 into D8.

I have the migration setup with the following yml configuration:

```
uuid: a685a4e0-1022-4bf2-a787-f6f1bef587ea
langcode: en
status: true
dependencies: {  }
id: d8_files
class: null
field_plugin_method: null
cck_plugin_method: null
migration_tags:
  - 'Drupal 7'
  - Content
migration_group: D7-TO-D8
label: 'D7 to 8 Public files'
source:
  plugin: d7_file
  scheme: public
  constants:
    # source_base_path: 'sites/default/files/'
    # source_base_path: '/var/www/d8/sites/default/files/'
    # source_base_path: '/var/www/d8/sites/default/files/d7_download/page/files/'
    # source_base_path: '/sites/default/files/d7_download/page/files/'
    # source_base_path: '/var/www/d7/sites/default/files/page/files/'
    source_base_path: '/var/www/d7/sites/default/files/'
process:
  fid: fid
  filename: filename
  source_full_path:
    -
      plugin: concat
      delimiter: /
      source:
        - constants/source_base_path
        - filepath
    -
      plugin: urlencode
  uri:
    plugin: file_copy
    source:
      - '@source_full_path'
      - uri
  filemime: filemime
  status: status
  created: timestamp
  changed: timestamp
  uid: uid
destination:
  plugin: 'entity:file'
migration_dependencies: null

```

Migrate-status indicates I have over 2000 files detected in the D7 database ready for migration **but** when I try migrating it just reports 0 migrated content and errors, shown below:

My guess is the migration does not know where to find the images **but** I have tried a variety of paths to those image by altering the **source\_base\_path** value however I still get no migrated files.

Can anyone help, please?

**UPDATE:**

I found out more on the issue preventing the migration.

When I checked the logs for the d8\_files migration, I found messages such as the following:

```
File'/var/www/d8/sites/default/files/d7_download//sites/default/files/field/image/imagefield_OvRwVF.jpeg' does not exist

```

The issue is how the module is creating the file url.

In the *source* section of my d8\_file.yml, I had set the following:

```
source_base_path: '/var/www/d8/sites/default/files/d7_download/'

```

... which is the absolute path to the directory containing the files I wish to migrate. The migrate module is concatenating `/sites/default/files` to the end of the path which makes it wrong. I have tried doing things like navigating up the directory path by using `../../` in the *source\_base\_path* settings but it doesn't work ... it's just seen as a string.

**Can anyone tell me how to correct this?**

In the process section, I saw the following:

```
process:
  fid: fid
  filename: filename
  source_full_path:
    -
      plugin: concat
      delimiter: /
      source:
        - constants/source_base_path
        - filepath

```

I suspect that **concat** value is the problem. BUT, I have no idea what other value to set it to.

**PS:** *Can anyone advice where is the system to find such information on any plugin ???*

# Answer
You can find the active issue here on Drupal.org: https://www.drupal.org/project/drupal/issues/3123350

As a workaround you could run this in the source database copy to remove the prefix:

```
DELETE FROM variable WHERE name="file_private_path";

```

See the issue for further discussion and background.
> 1 votes

# Answer
If you need to do replacements in the files path like "public://" and "private://" to the full path to your public or private files, instead of just giving the filepath as the source, make the necessary replacements before:

```
  source_public_absolute_path:
    -
      plugin: str_replace
      source: uri
      search: 'public://'
      replace: 'sites/default/files/'
  source_full_path:
    -
      plugin: concat
      delimiter: /
      source:
        - constants/source_base_path
        - '@source_public_absolute_path'

```
> 1 votes

---
Tags: 8, files, migrations
---


title: add field to user in hook_update_n

text:
# Question
Title: add field to user in hook_update_n
The latest release of our existing module needs to define MANY new fields that are attached to the drupal user. For each field, in {module}/config/optional there is a field config and a field storage config. I then implement hook\_update\_n in {module}/{module}.install to detect new config entries and add them if they don't exist. Running the code installs the config (I can see it with drush cget), but does not create the corresponding DB tables for the new fields.

If I go to most pages, such as `/admin/config/people/accounts/fields`, I get "The website encountered an unexpected error. Please try again later."

If I clear the caches (`drush cr`), I get an error that says,

```
In ExceptionHandler.php line 53:

  SQLSTATE[42S02]: Base table or view not found: 1146 Table 'intranet.user__field_s_uid' doesn't exist: SELECT "t".*
  FROM
  "user__field_s_uid" "t"
  WHERE ("entity_id" IN (:db_condition_placeholder_0)) AND ("deleted" = :db_condition_placeholder_1) AND ("langcode" IN (:db_condition_placeholder_2, :db_c
  ondition_placeholder_3, :db_condition_placeholder_4))
  ORDER BY "delta" ASC; Array
  (
      [:db_condition_placeholder_0] => 0
      [:db_condition_placeholder_1] => 0
      [:db_condition_placeholder_2] => en
      [:db_condition_placeholder_3] => und
      [:db_condition_placeholder_4] => zxx
  )

In StatementWrapper.php line 116:

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

```

To get the site working again I have to delete the config (drush cdel...).

***What am I missing that keeps the db storage from being created? Do I need to programatically create the db table for the field to use? (if so,how?)***

*file: {module}.install*

```
<?php
use Drupal\Component\Serialization\Yaml;
use Drupal\Component\Utility\NestedArray;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;

function {module}_update_9001(&$sandbox = NULL){
  $modulePath = \Drupal::service('extension.list.module')
        ->getPath('{module}');
  $config_factory = \Drupal::configFactory();
  $configPathObjects = \Drupal::service('file_system')
    ->scanDirectory($modulePath.'/config/optional','~field.*~');

  foreach ($configPathObjects as $configPath){

    $config = $config_factory->getEditable($configPath->name);
    if($config->isNew()){
      $configSettings = NestedArray::mergeDeep(
          Yaml::decode(
            file_get_contents(
              "$modulePath/config/optional/{$configPath->filename}"
              )
            ),$config
          );
      $config->setdata($configSettings);
      $config->save(TRUE);
    }
  }
}

```

*file: config/optional/field.field.user.user.field\_s\_uid.yml*

```
langcode: en
status: true
dependencies:
  config:
    - field.storage.user.field_s_uid
  module:
    - user
id: user.user.field_s_uid
field_name: field_s_uid
entity_type: user
bundle: user
label: s_uid
description: 'The unique ID for this user, set automatically by the DB, should not be modified by users/admins.'
required: false
translatable: false
default_value: {  }
default_value_callback: ''
settings:
  min: null
  max: null
  prefix: ''
  suffix: ''
field_type: integer

```

*file: config/optional/field.storage.user.field\_s\_uid.yml*

```
langcode: en
status: true
dependencies:
  module:
    - user
id: user.field_s_uid
field_name: field_s_uid
entity_type: user
type: integer
settings:
  unsigned: false
  size: normal
module: core
locked: false
cardinality: 1
translatable: true
indexes: {  }
persist_with_no_fields: false
custom_storage: false

```

# Answer
You need the config entity classes FieldStorageConfig::create() and FieldConfig::create(). You have already the use statements and are not using them. Otherwise the entity events like postcreate and presave are not invoked.

BTW if you modify the configuration of a config entity via `$config_factory->getEditable()` this only works as long as you don't modify anything affecting the mentioned entity events. If you need to save config entities override free, then better load them instead with ConfigEntityStorageInterface::loadOverrideFree().
> 2 votes

# Answer
# Final Solution based on accepted solution from @4k4 (see answer).

```
<?php
use Drupal\Core\Database\Database;
use Drupal\Component\Serialization\Yaml;
use Drupal\Component\Utility\NestedArray;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
use Drupal\Core\Utility\UpdateException;

/**
 *  Add required fields to user entities.
 */
function {module}_update_9001(){
  $modulePath = \Drupal::service('extension.list.module')
        ->getPath('{module}');
  $configPathStorageObjects = \Drupal::service('file_system')
    ->scanDirectory($modulePath.'/config/optional','~field\.storage\.user\..*~');
  \Drupal::logger('staffdb')->notice('storage objects: <pre>'.print_r($configPathStorageObjects,true).'</pre>');

  //add missing field storage
  foreach ($configPathStorageObjects as $configPath){
    $config = FieldStorageConfig::loadByName('user',str_replace('field.storage.user.','',$configPath->name));
    if(is_null($config)){
      $configSettings = Yaml::decode(
          file_get_contents(
            "$modulePath/config/optional/{$configPath->filename}"
            )
          );
      $fieldStorage = FieldStorageConfig::create($configSettings);
      $fieldStorage->save();
    }
  }

  //add missing fields to users
  $configPathFieldObjects = \Drupal::service('file_system')
    ->scanDirectory($modulePath.'/config/optional','~field\.field\.user\.user\..*~');
  foreach ($configPathFieldObjects as $configPath){
    $config = FieldConfig::loadByName('user', 'user', str_replace('field.field.user.user.','',$configPath->name));
    if(is_null($config)){
      $configSettings = Yaml::decode(
          file_get_contents(
            "$modulePath/config/optional/{$configPath->filename}"
            )
          );
      $field = FieldConfig::create($configSettings);
      $field->save();
    }
  }
}

```
> 2 votes

---
Tags: users, hooks
---


title: Clear form fields after AJAX submit

text:
# Question
Title: Clear form fields after AJAX submit
Given:

* I am using Drupal 8.
* I have a custom "add form" of the custom entity type.
* Form has an ajax submission.

Problem:

* When I submit form all the values remain in fields.

Expected:

* Form fields should be cleared after submission.

Form source code:

```
<?php

namespace Drupal\mymodule\Form;

use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Form\FormStateInterface;

/**
 * Form controller for the add/edit entity forms.
 */
class MymoduleForm extends ContentEntityForm {

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildForm($form, $form_state);

    $form['#prefix'] = "<div id=\"{$this->getFormId()}-wrapper\">";
    $form['#suffix'] = '</div>';

    $form['actions']['submit']['#ajax'] = [
      'wrapper' => $this->getFormId() . '-wrapper',
      'callback' => array($this, 'ajaxRebuildCallback'),
      'effect' => 'fade',
    ];

    return $form;
  }

  /**
   * Callback for ajax form submission.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @return array
   *   The rebuilt form.
   */
  public function ajaxRebuildCallback(array $form, FormStateInterface $form_state) {
    drupal_set_message(t('Entity was successfully created'));

    // @todo Clear form values.
    //$form_state->setRebuild(TRUE);
    //$form_state->setValues([]);
    /*$entity = \Drupal::entityTypeManager()->getStorage('liveblog_post')->create([]);
    $form_object = \Drupal::entityTypeManager()
      ->getFormObject('liveblog_post', 'add')
      ->setEntity($entity);*/
    //$new_form_state = new FormState();
    //$form = \Drupal::formBuilder()->rebuildForm($this->getFormId(), $form_state);

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $entity = $this->getEntity();
    $entity->save();
  }

}

```

P.S. you can find my attempts in the `ajaxRebuildCallback()` method.

# Answer
@Berdir's answer helped me to figure out the solution. We should indeed clear the user input, but we can not simply just say `$form_state->setUserInput([])`, because there are some system values, that should stay(e.g. `form_id`, `form_token`, `_triggering_element_name`, etc.).

I have created a custom method for it:

```
  /**
   * Clears form input.
   *
   * @param array $form
   *   The form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   */
  protected function clearFormInput(array $form, FormStateInterface $form_state) {
    // Replace the form entity with an empty instance.
    $this->entity = $this->entityTypeManager->getStorage('my_entity_type')->create([]);
    // Clear user input.
    $input = $form_state->getUserInput();
    // We should not clear the system items from the user input.
    $clean_keys = $form_state->getCleanValueKeys();
    $clean_keys[] = 'ajax_page_state';
    foreach ($input as $key => $item) {
      if (!in_array($key, $clean_keys) && substr($key, 0, 1) !== '_') {
        unset($input[$key]);
      }
    }
    $form_state->setUserInput($input);
    // Rebuild the form state values.
    $form_state->setRebuild();
    $form_state->setStorage([]);
  }

```

I am calling `$this->clearFormInput($form, $form_state);` in the `MymoduleForm::save()` method(the very last step of the submission).

**Update 08.03.2021**

If you have a `created` date field in the entity form, it will be cached in `$form_state` after submission. You will have to reset it's value for the entities. You can do it by overriding the `\Drupal\Core\Entity\EntityForm::processForm`:

```
 /**
   * {@inheritdoc}
   *
   * Resets default values for a new entity.
   */
  public function processForm($element, FormStateInterface $form_state, $form) {
    $element = parent::processForm($element, $form_state, $form);

    if ($this->entity->isNew()) {
      $this->entity->set('created', $this->time->getRequestTime());
    }

    return $element;
  }

```
> 11 votes

# Answer
You are looking for https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Form%21FormStateInterface.php/function/FormStateInterface%3A%3AsetUserInput/8.2.x.

The values are the validated input, for setting the default values, the form system respects the original user input, which you can change with the method above.

However, for entity forms, it is a bit more complicated. $this-\>entity is a reference to the entity, you will still have that and it will fallback to that. What you probably need to do is create a new entity in save, assign it to $this-\>entity, then empty user input and $form\_state-\>setRebuild(). That should then rebuild the form with a new and empty entity.
> 9 votes

# Answer
In your ajax callback

```
$response->addCommand(new InvokeCommand('#edit-new-note', 'val', ['']));

```
> 1 votes

---
Tags: forms, 8, ajax
---


# Question
Title: Is there a way to pull the 'description' metadata from Media's Remote Videos?
We have a Drupal 9 site that is using Media's Remote Video for YouTube videos. We need to pull the YouTube video's description but I do not see any way to accomplish this. The end result will be to display the YouTube description in a View.

EDIT: The screenshot shows that there is no "description" field in the Remote Video's field mapping.

# Answer
Media has the ability to map remote media metadata to fields on the media entity. To do this, create a media type whose Media Source is *remote video*, hit save, then add your fields. Edit the media type again, then map the metadata to the fields you created.

When you create a media entity of that type, Drupal will grab the metadata from the source (e.g. YouTube, Vimeo, etc.) and then map the metadata to the fields you configured for them. There is an outstanding issue to refresh this metadata after the entity is created, as currently it only does this mapping on creation.

Also, if I remember correctly, this only works on *public* videos. The video cannot be unlisted, private, age-restricted, or worse, 404. Otherwise, this mechanism will fail getting the metadata.
> 2 votes

---
Tags: media
---


# Question
Title: How to add comment field to custom entity
I tried to add a comment field in the Basefieldsdefinitions of my custom entity but in my view the add comment form doesn't appear:

Here's the basefielddefinition

```
 $fields['comments'] = BaseFieldDefinition::create('comment')
  ->setLabel(t('Kommentare'))
  ->setDescription(t('Kommentare.'))

  ->setSettings(
    array(
      'default_mode'=> 1,
      'per_page'=>50,
      'anonymous'=> 0,
      'form_location'=>1,
      'preview'=> 1,
      'comment_type'=>'image_comment',
      'locked'=>false,

      ))
->setDefaultValue(
        array(
            'status'=>2,
            'cid'=>0,
            'last_comment_timestamp'=> 0,
            'last_comment_name'=> null,
            'last_comment_uid'=> 0,
            'comment_count'=> 0,
)
)
->setDisplayOptions('form', array(
 'type' => 'comment_default',
 'settings' => array(
   'form_location' => 1,
   'default_mode'=> 1,
   'per_page'=>50,
   'anonymous'=> 0,
   'form_location'=>1,
   'preview'=> 1,
   'comment_type'=>'image_comment',
   'locked'=>false,

 ),
 'weight' => 1,
))
->setDisplayConfigurable('form', TRUE)
->setDisplayConfigurable('view', TRUE);

```

# Answer
In order to any changes on `BaseFieldDefinition` effects, you should uninstall/install your module. your syntax seems Ok and I only guest you did some changes after your module( entity) installed.
> 2 votes

# Answer
use this to create the field in your custum module:

```
$fields['comments'] =  BaseFieldDefinition::create('comment')
      ->setLabel(t('comment'))
      ->setDescription(t('Add new comment'))
      ->setSettings(
        array(
          'default_mode'=> 1,
          'per_page'=>50,
          'anonymous'=> 0,
          'form_location'=>1,
          'preview'=> 1,
          'comment_type'=>'your_comment_type',
          'locked'=>false,
          'status'=>2
        ))
      ->setDefaultValue(
        array(
          'last_comment_timestamp'=> 0,
          'last_comment_name'=> null,
          'last_comment_uid'=> 0,
          'comment_count'=> 0
        )
      )
      ->setDisplayOptions('form', array(
        'type' => 'comment',
        'settings' => array(
          'form_location' => 1,
          'default_mode'=> 1,
          'per_page'=>50,
          'anonymous'=> 0,
          'form_location'=>1,
          'preview'=> 1,
          'locked'=>false
        ),
        'weight' => 1,
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

```

you can get the form in your module.page.inc and send it in your template:

```
$form = \Drupal::service('comment.lazy_builders')->renderForm(entity_type_id,entity_id,'comments',comment_type);
$variables['yourVarialbeInTemplate']=$form;

```
> 0 votes

# Answer
I have tried with `BaseFieldDefinition` ,to create comment field for one of custom Entity using `hook_update_N`. But it is not creating Field Storage. So create Comment storage first and added comment field to entity.

```
// Create storage defention for comment field for entity.
  $field_storage_config_storage = \Drupal::entityTypeManager()->getStorage('field_storage_config');
  $field_storage_config_storage->create([
    'entity_type' => $entity_type_id,
    'field_name' => $field_name,
    'type' => 'comment',
    'translatable' => TRUE,
    'settings' => [
      'comment_type' => $comment_type_id,
    ],
  ])->save();

  $field_config_storage = \Drupal::entityTypeManager()->getStorage('field_config');
  $default_value = CommentItemInterface::OPEN;
  $field_config_storage->create([
    'label' => 'Comments',
    'description' => '',
    'field_name' => $field_name,
    'entity_type' => $entity_type_id,
    'bundle' => $entity_type_id,
    'required' => 0,
    'default_value' => [
      [
        'status' => $default_value,
        'cid' => 0,
        'last_comment_name' => '',
        'last_comment_timestamp' => 0,
        'last_comment_uid' => 0,
      ],
    ],
  ])->save();

  // Entity form displays: assign widget settings for the 'default' form
  // mode, and hide the field in all other form modes.
  entity_get_form_display($entity_type_id, $entity_type_id, 'default')
    ->setComponent($field_name, [
      'type' => 'comment_default',
      'weight' => 20,
    ])
    ->save();

```
> 0 votes

# Answer
One thing I noticed that may help someone. If you have a custom entity, and you have instances of those entities already in existence. And if you add a comment field the 'status' field will be set to "Closed" for all existing entities. Take for example:

```
    $fields['comment'] = BaseFieldDefinition::create('comment')
      ->setLabel(t('Task comments'))
      ->setSetting('comment_type', 'task_comments')
      ->setDefaultValue([
        'status' => CommentItemInterface::OPEN,
      ])
      ->setDisplayOptions('view', [
        'type' => 'comment_default',
        'settings' => ['view_mode' => 'default'],
      ]);

```

Even though the setDefaultValue for status is set to open. Any existing entities may be set to "closed". So you may need some sort of script to go back through the existing entities to turn comments to "open" on the field. Not sure how to do that since my solution was to delete my custom entities and start over.
> 0 votes

---
Tags: 8, comments
---


# Question
Title: Hook for field not triggered when using delta in template
I tried to hook my Link type field with machine name "field\_link". This field is rendered in template using delta index to extract some values, e.g.:

```
{{ content.field_link[0]['#title'] }}

```

I have noticed that when I use **content.field\_link\[0\]** or **content.field\_link.0** my hook **HOOK\_preprocess\_field\__field\_link(&$vars, $hook)** is not triggered. But as soon as I use **content.field\_link** the hooks works.

Is there some workaround or using deltas to extract some field's values is not the best practice?

Thanks

# Answer
> 1 votes
The field preprocess hook only works when you render *the field*. Once you start extracting values off the field object (like individual properties or specific deltas), you're no longer rendering the field itself thus not triggering the hook.

I also do not recommend extracting and rendering data this way because you're losing some metadata that come with these objects (e.g. cacheability, theme info, formatter info, modifications from other modules, etc.). You could:

* Create a Field Formatter for that field type and only render a specific delta (by overriding `viewElements()` and only adding specific deltas). You can make the delta configurable.
* Or a combination of `hook_field_formatter_third_party_settings_form` and `hook_preprocess_field`. The former will let you save configuration into field display config, while the latter allows you to pick up that config and modify the field output.
    + A good example of this combination (albeit used for a different purpose) can be found in the Fences module.

In both cases, you can choose to make them configurable via admin and not hardcoding the delta selection into template. You can even make it so that you can ignore both entirely, leaving the field rendering the default output.

---
Tags: hooks, 9
---


# Question
Title: Output JSON string into PHPTemplate file
I want to output a JSON string as part of a data attribute on an HTML tag for a template in Drupal 7. For the life of me, I cannot figure out why it does not work (works perfectly in 8+).

I need to list a set of image urls and media sizes which is parsed by Javascript later.

In template.php:

```
    $variables['background_images'] = [];

    $variables['background_images'][] = [
      'srcset' => 'https://placeimg.com/1600/600/tech, https://placeimg.com/3200/1200',
      'media' => '(min-width: 100rem)',
    ];

    $variables['background_images'][] = [
      'srcset' => 'https://placeimg.com/1600/600/tech, https://placeimg.com/3200/1200',
      'media' => '(min-width: 48rem)',
    ];

    $variables['background_images'] = json_encode($variables['background_images']);

```

In the tpl file:

```
<div data-background="<?php print $background_images; ?>"></div>

```

The output is a mixed bag of issues in the browser. The URLs are escaped, and there are far more double quotes than I entered:

```
data-background="[{" srcset":"https:\="" \="" placeimg.com\="" 1600\="" 600\="" tech,="" https:\="" 3200\="" 1200","media":"(min-width:="" 100rem)"},{"srcset":"https:\="" 48rem)"}]"

```

I can't figure out why there is an extra spacing on the keys or why it escapes early and breaks the rest of it. It looks right (to me) with xdebug, but when its printed to the browser its wrong.

A second way I also tried (generate example data):

```
    $items = [];

    for ($x = 0; $x < 3; $x++) {
      $items[$x] = [
        'srcset' => 'https://placeimg.com/1600/600/tech, https://placeimg.com/3200/1200',
        'media' => '(min-width: 100rem)',
      ];
    }

    $variables['background_images'] = drupal_json_encode($items);

```

# Answer
> 0 votes
It's the double quotes that are causing the problem, whether they've been encoded with `JSON_HEX_QUOT` or not. They must be confusing a parser or something somewhere in the render pipeline.

Fortunately it's an easy fix, just use single quotes for the HTML attribute:

```
<div data-background='<?php print $background_images; ?>'></div>

```

The same problem doesn't occur for single quotes, as long as you use `drupal_json_encode` rather than `json_encode` (or `json_encode` with the `JSON_HEX_APOS` flag). So if your strings ever include single quotes in future this will still work.

---
Tags: 7, theming
---


# Question
Title: Custom field formatter fails in create()
PHPStorm, PHP 7.4 IDE highlights $container-\>get('date.formatter'), with

> "Expected parameter of type '\Drupal\Core\Datetime\DateFormatterInterface', 'object' provided"

This function is an exact copy of the core TimestampFormatter (which also shows the error)

```
/**
 * {@inheritdoc}
 */
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  return new static(
    $plugin_id,
    $plugin_definition,
    $configuration['field_definition'],
    $configuration['settings'],
    $configuration['label'],
    $configuration['view_mode'],
    $configuration['third_party_settings'],
    $container->get('date.formatter'),
    $container->get('entity_type.manager')->getStorage('date_format')
  );
}

```

The \__construct is looking for a DateFormatterInterface (see below) and not sure how this works in core, but my "viewElements" is never firing since this error started.

```
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, **DateFormatterInterface $date_formatter**, EntityStorageInterface $date_format_storage) {

```

What is the proper container-\>get to use to return a proper date.formatter and not an object which causes the create to fail without any errors logged that I can see?

# Answer
Your code is fine, but you can remove the warnings by installing the PHPStorm Symfony plugin.

It teaches the IDE how to resolve the correct class from the service name you provide to `$container->get()`.
> 3 votes

---
Tags: datetime, plugins
---


# Question
Title: Database Error after updating from Webform 6.0.5 -> 6.1.0 in Drupal 9.2.7 (PHP 7.4.14)
After updating to Webform 6.1.0 the following error occurs:

> webform module 8626 - Issue #3240399: Move form #method, #action, and #attributes from properties to settings
>
> #8626 Fehlgeschlagen: Drupal\Component\Serialization\Exception\InvalidDataTypeException: Malformed inline YAML string at line 21. in Drupal\Component\Serialization\YamlSymfony::decode() (Zeile 40 in C:\xampp\htdocs\drupal8\core\lib\Drupal\Component\Serialization\YamlSymfony.php)

What can I do now?

# Answer
> 4 votes
I think that there is a webform with invalid elements YAML that is only now being rejected by Drupal 9.x.

You can probably execute `drush repair` and it should detect the invalid elements YAML.

@see https://www.drupal.org/project/webform/issues/3240399#comment-14277361

---
Tags: webforms
---


# Question
Title: Problem with upgrading because an unmigrated module
I am trying to migrate a Drupal 8 site to Drupal 9. Though most of the migrations have gone easily, this site breaks because it uses the Video module, which hasn't been updated for Drupal 9.
Specifically, the problem happens when I try to run `drush updb`. I geet this error message.

> Unable to determine class for field type 'video' found in the 'field.storag e.paragraph.field\_video\_item' configuration

What would the steps needed to by-pass the problem be?

The module seems quite abandoned; I don't keep my breath waiting Drupal 9 version to be created.

# Answer
I assume you are talking about the Video module.

For any module that does not have a Drupal 9 release, you basically have three options, in order of difficulty (easy to hard):

1. Find patches/a fork of the module (usually in the issue queue) that supports Drupal 9.
2. Update the module to be compatible with Drupal 9 yourself.
3. Find a replacement module that is compatible with Drupal 9 and migrate your data to that, then uninstall the incompatible module.

For #1, looking through the issue queue, there are a few patches you could try:

For #3, Drupal now has excellent Media support in core, so if possible, I would try to migrate your video data to core media, as that would guarantee you an easy upgrade path to Drupal 10 and beyond.
> 1 votes

# Answer
Well, I got over the problem by just marking the video module Drupal 9 compatible. It probably isn't very good/healthy a solution but got me over the obstacle and I can try to implement now the similar functionality with Media core support.

As I haven't worked earlier with the site I have to find out how heavily the video module is used in the site but at least so far hasn't hit my head into a stone.

If someone comes here but doesn't know how to mark the module Drupal 9 compatible it's by adding the following line to the video.info.yml

```
core_version_requirement: ^8 || ^9

```

Of course, that doesn't actually mean that the module *works*, only that Drupal thinks it has found a compatible version of the module and can go on updating the database.

Thanks Patrick for the pointer

hank
> 0 votes

---
Tags: migrations, 9
---


title: How do I display an SVG image?

text:
# Question
Title: How do I display an SVG image?
I added the following code for a "Global: Custom Text" field.

```
<div class="messages-list__item messages messages--warning" data-drupal-selector="messages" role="contentinfo" aria-label="Warning message" data-once="messages">
    <div class="messages__container" data-drupal-selector="messages-container">
        <div class="messages__header">
            <h2 class="visually-hidden">Warning message</h2>
            <div class="messages__icon">
                <svg xmlns="http://www.w3.org/2000/svg" width="32px" height="32px" viewBox="0 0 32 32"><path d="M16,0C7.2,0,0,7.2,0,16c0,8.8,7.2,16,16,16c8.8,0,16-7.2,16-16C32,7.2,24.8,0,16,0z M18.7,26c0,0.4-0.3,0.7-0.6,0.7h-4c-0.4,0-0.7-0.3-0.7-0.7v-4c0-0.4,0.3-0.7,0.7-0.7h4c0.4,0,0.6,0.3,0.6,0.7V26z M18.6,18.8c0,0.3-0.3,0.5-0.7,0.5h-3.9c-0.4,0-0.7-0.2-0.7-0.5L13,5.9c0-0.1,0.1-0.3,0.2-0.4c0.1-0.1,0.3-0.2,0.5-0.2h4.6c0.2,0,0.4,0.1,0.5,0.2C18.9,5.6,19,5.7,19,5.9L18.6,18.8z"></path></svg>
            </div>
        </div>
        <div class="messages__content">
            <ul class="messages__list">
                {{ field_warning_affiliation }}
                {{ field_warning_investment }}
            </ul>
        </div>
    </div>
</div>

```

The SVG image is not displayed.

>

How do I display an SVG image?

# Answer
> 1 votes
You can use CSS to add your SVG, or if you want it inline you can also add it inside a twig template (like this: `views-view-field--yourviewid--nothing.html.twig`). Then add something like this wherever you want it in the file:

```
{{ include('@youtheme/images/picto.svg') }}

```

Within your `yourtheme.info.yml`, add this:

```
components:
  namespaces:
    yourtheme:
      - .

```

Enable the components module.

or

```
{{ include(directory ~ '/images/picto.svg') }}

```

or

```
{{ source(directory ~ '/images/picto.svg') }}

```

---
Tags: views, 9
---


# Question
Title: Change CSS without changing the website's filetree
I need to change the CSS of my current theme a bit (say, up to 100 lines).

I don't want to create a sub-theme and I don't want to directly edit my theme's files (even though it's premium theme which gets upgraded maybe once in two years so migration, in such a case, would be easy).

Rather, I want to add some global CSS which effects *any current theme* (given selectors are still matched), but preferably in a way which doesn't alter the website's **filetree** (so that if I upgrade Drupal no global CSS file will mistakenly be deleted).

Is there any way to add such "database-global-CSS" (or "database-global-JS" by which I will indirectly add the CSS), via the core? Any nasty trick?

# Answer
Since you do not want to use a subtheme, I'd recommend to create a custom module to attach a custom library with your "global CSS". Simply attach the library on the appropriate preprocess\_hook() and that should do the trick.
> 2 votes

---
Tags: theming, 9
---


title: Options for pml command with Drush 10

text:
# Question
Title: Options for pml command with Drush 10
I just install a Drupal 9.2 site and Drush 10 to manage it. Usually I use Drush 9 and Drupal 8.9.

It appear option for pml command seem not to work in Drush 10 as it do in Drush 9. Example:

```
 drush @pfdevd9pf pml --filter=rss
  The "--filter" option does not exist.

drush @pfdevd9pf pml | grep "rss"
 RRSSB  Ridiculously Responsive Social Share Buttons (rrssb)   Disabled   8.x-2.3

```

This is a weird thing, then I do a module activation:

```
 drush @pfdevd9pf en -y rrssb
 [success] Successfully enabled: rrssb

```

But pml still give the same info about module version:

```
  RRSSB   Ridiculously Responsive Social Share Buttons (rrssb)   Enabled    8.x-2.3

```

I use D8 website too on this server, but installations are distincts. If someone know about this, and why pml doesn't use the option ?

Thanks

EDIt: about the version number for module, as @4k4 say, it depends on the module developpment. This is another example for D9:

```
  Other    Backup and Migrate (backup_migrate) Disabled   5.0.1

```

EDIt2: multiple drush version can be an issue, because in my .bash\_profile I get: Drush 8 globally installed

```
alias drush='$HOME/bin/composer/composer.phar/vendor/drush/drush/drush'

```

then:

```
#Création d'un alias pour Drush 9 pour usage global
alias drush9='$HOME/www/pfdev/multid8/vendor/drush/drush/drush'

#Création d'un alias pour Drush 10 pour usage global
alias drush10='$HOME/www/pfdev/multid9/recommended-project/vendor/drush/drush/drush'

#PATH ajouté manuellement suite retour commande Drush
#export PATH="$PATH:$HOME/www/pfdev/multid8/vendor/drush/drush/drush"

    # Switch drush versions for session. Changer de version pour la session
    alias d8='export PATH=$HOME/bin/drush:$PATH'
    alias d9='export PATH=$HOME/www/pfdev/multid8/vendor/bin:$PATH'
    alias d10='export PATH=$HOME/www/pfdev/multid9/recommended-project/vendor/bin:$PATH'

```

but I use drush as alias, never d9 or d10.In addition, I need to be on the ~/ to use alias...created for D8. So I think I need to change my Drush 8 install, and remove it globally. isn't it ?

# Answer
> 1 votes
> But my question is about the filter option, by the way

The filter option is available in the current Drush version. In general https://www.drush.org/latest/output-formats-filters/#output-filters and for this drush command https://www.drush.org/latest/commands/pm\_list/.

If not, then you are probably running an older Drush version installed somewhere on your computer. To be sure run Drush locally from the root folder of your Drupal site:

```
composer require drush/drush
vendor/bin/drush pml --filter=block

```

This should display the two core modules and one or two others.

---
Tags: drush
---


# Question
Title: get the content moderation value on node update
The module content moderation has been activated and a custom workflow added to a content type. On editing content, when selecting a content moderation state then clicking on save, I would like to programmatically save that value in a variable.

`$mod` in that code doesn't display the latest values for moderation state chosen on update.

I wonder if what I get is the default revision value (as configured for a state, *Révision par défaut Quand le contenu atteint cet état il devrait devenir la révision par défaut; ceci est implicite pour les états publiés.*) but it is definitely not the latest revision value.

```
function my_hook_entity_update(Drupal\Core\Entity\EntityInterface $entity) {
  if ($entity->getEntityTypeId() !== 'node') {
    return;
  }

  $content_id = $entity->id();
  $content = \Drupal\node\Entity\Node::load($content_id);

  $mod=$content->get('moderation_state')->getValue();
  var_dump($mod);
  die();
}

```

How do I get the latest value of content moderation on node update?

# Answer
> 4 votes
Getting the version of the entity meant getting the last revision and allow to get the correct value

```
function my_hook_entity_update(Drupal\Core\Entity\EntityInterface $entity) {
  if ($entity->getEntityTypeId() !== 'node') {
    return;
  }

 $current_entity_lang = $entity->get('langcode')->value;
 $translated_entity = $entity->getTranslation($current_entity_lang);
 $mod = $translated_entity->get('moderation_state')->getValue());
}

```

# Answer
> 1 votes
This will give you the string such as "published" right away

```
$node->moderation_state->value;

```

While `$node->get('moderation_state')->getValue();` returns an array.

---
Tags: 8, hooks, workflows
---


# Question
Title: How to return an XLS file to download on form submit
I am trying to create an XLS file and send it to the browser on a form submit but I cannot figure out how to do it. I am using XLS Serialization module but I'm open to all other suggestions. With this module I successfully created some views with XLS Export feature. But now I have a form and the excel file should be created on form submit depending on the submitted data.

I created the following code but if I send the form, I get no excel file to download:

```
class MyForm extends FormBase {
  private SerializerInterface $serializer;

  public static function create(ContainerInterface $container) {
    return new static($container->get('serializer'));
  }

  public function __construct(SerializerInterface $serializer) {
    $this->serializer = $serializer;
  }

  // Removed the buildForm() etc for simplicity

  public function submitForm(array &$form, FormStateInterface $form_state) {
    $response = (new StreamedResponse(function () use ($selected_values) {
      $this->serializer->serialize([[1, 2, 3], [4, 5, 6]], 'xlsx');
    }))->send();

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

```

# Answer
First off, you need a serializer for xls(x), I used https://www.drupal.org/project/xls\_serialization

The following example code should deliver what you need:

```
public function submitForm(array &$form, FormStateInterface $form_state) {
  $values = $form_state->getValues();
  $filename = "random_file_" . rand() . ".xlsx";

  $response = new StreamedResponse(function () use ($values) {
    echo $this->serializer->serialize([[1, 2, 3], [4, 5, 6]], 'xlsx');
  });
  $response->headers->set('Content-Type', 'application/vnd.ms-excel');
  $response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');

  $form_state->setResponse($response);
}

```

I tried that with the XLS encoder provided https://www.drupal.org/project/xls\_serialization and it worked.

Good luck!

References:
> 4 votes

---
Tags: 8, forms
---


# Question
Title: Data coming from entityTypeManager->getStorage is cached data?
I am working on one Drupal 8.3 site. I created my own custom Authentication provider for REST API authorisation.

Following are the "authenticate" method sample code.

```
/**
   * {@inheritdoc}
   */
  public function authenticate(Request $request) {
      try {

          $uid = 1;// passing 1 for testing.

          $accounts = $this->entityTypeManager->getStorage('user')->loadByProperties(array('uid' => $uid, 'status' => 1));
          $account = reset($accounts);
          if ($account) {
              return $this->entityTypeManager->getStorage('user')->load($uid);
          }
      }
      return [];
  }

```

My doubt here is "$this-\>entityTypeManager-\>getStorage" is getting data from cache table. Or everytime it connect to db and generate response?

# Answer
load() and loadMultiple() are cached, loadByProperties() is a shortcut for an entity query + load, the entity query is not cached.

Do not use loadByProperties() if you know the entity ID.
> 6 votes

# Answer
For anyone coming across this issue;

You can also use the entity `resetCache` without passing an entity ID parameter since the `resetCache` method can accept empty parameters. See documentation on: EntityStorageBase::resetCache

```
$entity_storage = \Drupal::entityTypeManager()->getStorage('YOUR_ENTITY_NAME');
$entity_storage->resetCache(); // reset entity to clear cache
$results = $entity_storage->loadByProperties(['uid' => $uid, 'status' => 1]); // load entity data
return $results;

```
> 3 votes

---
Tags: performance, 8
---


# Question
Title: How to pass an argument to a hook without creating a custom module?
I need to attach a theme-agnostic ("global") CSS file to the `preprocess_hook()` function so that any theme I use, would include that CSS.

I want to do that without creating a custom module because while I am a programmer, I am just not a PHP programmer and I find the documentation about creating custom modules overkill for this specific goal and I won't learn this entire subject just for a CSS file.

# Answer
> 0 votes
As a general rule, you can't use hooks without writing a custom module.

The Rules module provides a UI to access some hooks without writing code, but this is mostly limited to entity-related hooks (add, delete, update / CRUD operations).

**Custom modules aren't that hard**

Custom modules can be as little as ~10 lines of code; they are not hard to write. However, the core documentation is quite thorough and difficult to skim; it may be more information than what you need.

In that case, I recommend beginner-friendly (but paid) tutorials like module development with Drupalize.me.

---
Tags: hooks
---


title: How to add CSS for a sub theme?

text:
# Question
Title: How to add CSS for a sub theme?
I have a sub theme I created this way:

**globalrs/globalrs.info.yml**

```
name: globalrs
type: theme
core_version_requirement: ^8 || ^9
description: globalrs
base theme: tara
libraries:
  - globalrs/global-styling

```

**globalrs/globalrs.libraries.yml**

```
global-styling:
  css:
    component:
      css/style.css: {}

```

**globalrs/style/style.css**

```
* {
    background: red !important;
}

```

The sub theme was set to default but still nothing has a red background (after flushing browser cache). What have I done wrong?

# Answer
> 1 votes
According to the documentation, you want to use `theme` instead of `component`:

```
global-styling:
  css:
    theme:
      css/style.css: {}

```

Also note in addition to flushing the browser cache, you should rebuild the Drupal cache.

---
Tags: theming, 9
---


# Question
Title: How do I unset an entity reference using JSON:API?
I can't figure out how to unset an entity reference (remove a reference to a term from a node) when editing content via JSON:API.

JSON to create a new node:

```
  const myNodeToPost = {
    data: {
      type: 'my_node_type',
      attributes: {
        body: {
          value: `${bodyText}`,
          format: 'basic_html',
        },
      },
      relationships: {
        refTerm: {
          data: {
            type: 'taxonomyType',
            id: `${taxonomyTermUuid}`,
          },
        },
      },
    },

```

The node is posted, and the taxonomy term is referenced correctly.

The entity reference to the taxonomy term is not required. So, users can remove the term reference when editing the node.

When editing a node, if I `PATCH` to JSON:API without referring to the entity reference, the node is updated, but the entity reference remains in place.

```
  const myEditedNode = {
    data: {
      type: 'my_node_type',
      attributes: {
        body: {
          value: `${bodyText}`,
          format: 'basic_html',
        },
      },
    },

```

So, I tried setting the ID to null:

```
  const myEditedNode = {
    data: {
      type: 'my_node_type',
      attributes: {
        body: {
          value: `${bodyText}`,
          format: 'basic_html',
        },
      },
      relationships: {
        refTerm: {
          data: {
            type: 'taxonomyType',
            id: null,
          },
        },
      },
    },

```

However, this gives a `400 Bad Request: No ID specified for related resource`.

How can I remove an entity reference with JSON:API?

# Answer
> 1 votes
Thanks to `franck_lorancy` on drupal.org, I managed to fix this and it is now part of the documentation for PATCH:

```
{
  "data": {
    "type": "node--article",
    "id": "{{article_uuid}}",
    "attributes": {
      "title": "My updated title",
      "body": {
        "value": "Updated body text",
        "format": "plain_text",
        "summary": "Updated summary"
      }
    },
    "relationships": {
      "my_entity_reference_field": {
        "data": {},
      }
    }
  }
}

```

---
Tags: entities
---


# Question
Title: Create a block with related content selected from "page" content type
I've two content-types:

'Page' and 'Bike'

From the page, I use a Entity reference field 'field\_kies\_je\_leasefiets', where I link to several bikes.

I want to create a block, placed on the full node view of the 'page', to show a block with 'linked bikes on this page'.

I am struggeling to remember how I used to do this in the past. What 'CONTEXTUAL FILTERS' do I add? I tried 'NID', but that fails. Will someone please be so kind, to give me some pointers?

And this is the solution, given by a user below:

make relation

# Answer
So you need *a list of bikes* that only show the ones *referenced by the current page*. What you'll need to do first is configure that view to list nodes filtered by the Bike type.

Then, in order to filter by the current Page it's on, you need two things:

1. You need to bring in the Pages relating to the bikes in the list. To do this, add a *reverse relationship* (Bikes \<- Page). It's reverse in a sense that we're bringing in content pointing *to* our list items, instead of content pointed *by* our list items. The description of this relationship should go like:

> **Content using field\_kies\_je\_leasefiets** \- Relate each Content with a field\_kies\_je\_leasefiets set to the content item.

Name this relationship "Page" administratively, so we can tell which one's which.
2. Since we now have a reference to Page content via that relationship, add a contextual filter for ID, using the *Content ID from URL* option. The key piece is to use the Page relationship on this contextual filter so that it filters by Page's ID, not by Bike's ID.

After setting this up, you should now be able to filter Bike content by Page IDs in the preview.
> 1 votes

---
Tags: views
---


# Question
Title: Experiencing problems filtering view programmatically
I'm using a views block in my website, the content of this view is filtered programmatically. I now get messages from users who see the wrong information. The filter is based on the currently logged in user. Since I need this information in the regular filter and not in the contextual filter I created a simple module to change the filter value.

My filter is like this:

```
(
Content type = contenttype_a
AND
uid(nodes author) = */this value is programmatically added*/
)

OR

(
Content type = contenttype_b
AND
user_target_id(reference) =  */this value is programmatically added*/
)

```

Than I use this in my module:

```
 */
function entity_access_views_pre_view(ViewExecutable $view, $display_id, array &$args){
  $currentUser = \Drupal::currentUser();
  $cuid = $currentUser->id();

    /* @ Filter View: Media  */
    if ($view->id() == 'my_view_id') {
      if ($display_id == 'block_1' || $display_id == 'page_1' || $display_id == 'page_2') {
        $filters = $view->display_handler->getOption('filters');
        $filters['uid']['value']['value'] = $cuid;
        $filters['user_target_id']['value']['value'] = $cuid;
        $view->display_handler->overrideOption('filters', $filters);
      }
    }
}

```

Since I can't seem to find the problem I'm having doubts about if above is working as I want it to. So I wanted to check if you see anything strange or false. Can this filter value be cached in some way? Or maybe there is a better way to do this.

I can't use the contextual filter, which I would prefer, because the view is showing two content types where on each content type the filter should be different.

Thanks in advance.

# Answer
First you can try to add a cache context to the render element of the View before it is rendered:

```
/**
 * Implements hook_views_pre_render().
 *
 */
function mymodule_views_pre_render(ViewExecutable $view) {
  if ($view->id() == 'my_view_id') {
    if ($view->current_display == 'block_1') {
      $view->element['#cache']['contexts'][] = 'user';
      // or add a cache max-age 0 for a high user count
      $view->element['#cache']['max-age'] = 0;
    }
  }
}

```

This doesn't help however if Views is caching the query internally. Then you can try to disable caching by configuring the *None* or *Time-based* cache plugin within the View. You can't configure a cache context here, though, only a cache max-age of 0. This is not necessarily a bad idea if you have a high user count and don't want to cache the same amount of variants. Drupal has a great caching system for delivering non-cacheable blocks to authenticated users (Dynamic Page Cache + BigPipe).
> 0 votes

---
Tags: 8, views
---


# Question
Title: How to change the text of the "checkout" button in Drupal commerce cart?
How can I change the text of the "checkout" button in Drupal commerce cart?

I need it to be "continue" instead.

thanks

```
   function rooms_form_alter(&$form, &$form_state, $form_id) {
      dsm($form_id);  // print form ID to messages
      switch ($form_id){
            case 'views_form_commerce_cart_form_default':
                $action['#value'] = 'continue';
            break;
      }
    }

```

# Answer
Try using the string overrides module - http://drupal.org/project/stringoverrides

If you can get it to work, it is a great maintainable way to change text generated by modules
> 3 votes

# Answer
By using the `hook_form_alter()` function, you can change the text of the buttons. It would be something like

```
$action['#value'] = 'continue';

```

Please provide us with more code so I can work out a decent example.
> 3 votes

# Answer
In Drupal Commerce 8 on, the `hook_form_alter()` might not be able to catch the "Checkout" button, because the button is implemented in `commerce_checkout_form_alter()` in `/commerce/modules/checkout/commerce_checkout.module`. So, depends on the name of your custom module, your custom `hook_form_alter()` might get called before `commerce_checkout`.

To make sure your custom module can see the "Checkout" button, go to your configuration: `config/sync/core.extension.yml`, lower your custom module weight, e.g. `custom_module: 1`. The number `1` is the weight of the module; bigger number means that module will get loaded/called later.
> 2 votes

# Answer
You could be interested in the Commerce Checkout Buttons module.

> The Commerce Checkout Buttons module enables the use of shorter button values on Drupal Commerce checkout pages.
>
> What exactly does the module?
>
> * All default button values to be shortened to the shortest meaningful text.
> Texts that are used:
>
> + *Cancel* at the first checkout step.
>     + Back for further checkout steps.
>     + Continue at all checkout steps.
> * The button prefix or will be removed.
> 1 votes

# Answer
Based on my answer to Customize commerce cart form page, here's the section specific to the checkout button:

```
function yourthemename_form_alter(&$form, $form_state, $form_id) {
  switch ($form_id)  {
  case 'views_form_commerce_cart_form_default':

    $form['actions']['checkout']['#value'] = 'New checkout button label';

  break;
  }
}

```

See that above linked answer for the rest of the form!
> 1 votes

# Answer
I am very new to drupal and I had the almost the same problem. I have to change the value of the checkout button and to make it translatable up to which language is selected. I tried different approaches but without any success.

I create a custom module with this function.

```
function md_custom_checkout_mod_form_commerce_checkout_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'commerce-checkout-form-checkout') {
    $form['submit']['#attributes']['title'] = t('Complete order');
  }
}

function md_custom_checkout_mod_form_commerce_checkout_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'commerce-checkout-form-checkout') {
    $form['submit']['#attributes']['title'] = t('Complete order');
  }
}

```

Please can you give me some tips how to make this working.
> 0 votes

# Answer
In Drupal 8 / Commerce 2, you can add a string override to your settings.php file, as such:

```
/**
 * String overrides:
 *
 * To override specific strings on your site with or without enabling the Locale
 * module, add an entry to this list. This functionality allows you to change
 * a small number of your site's default English language interface strings.
 *
 * Remove the leading hash signs to enable.
 *
 * The "en" part of the variable name, is dynamic and can be any langcode of
 * any added language. (eg locale_custom_strings_de for german).
 */
# $settings['locale_custom_strings_en'][''] = [
#   'forum'      => 'Discussion board',
#   '@count min' => '@count minutes',
# ];

 $settings['locale_custom_strings_en'][''] = [
   'Checkout'      => 'CHECKOUT or GET QUOTE',
 ];

```

Specifically, this part:

```
 $settings['locale_custom_strings_en'][''] = [
   'Checkout'      => 'CHECKOUT or GET QUOTE',
 ];

```
> 0 votes

# Answer
```

//exact code goes here

/*
I have also removed the update cart button here as I dont need you, you must have that code if you want it.
*/

function modulename_form_alter(&$form, &$form_state, $form_id) {

  if (strpos($form_id, 'views_form_commerce_cart_form_') === 0) {

    // Only alter buttons if the cart form View shows line items.

    $view = reset($form_state['build_info']['args']);

    if (!empty($view->result)) {

      // Unset update cart button as we dont need it.
      unset($form['actions']['submit']);

      //Change the name of checkout to - Delivery
       $form['actions']['checkout']['#value'] = t('Delivery');
       $form['actions']['checkout']['#submit'] = array('memento_checkout_form_submit');

      // Change any Delete buttons to say Remove.
      if (!empty($form['edit_delete'])) {
        foreach (element_children($form['edit_delete']) as $key) {
          // Load and wrap the line item to have the title in the submit phase.
          if (!empty($form['edit_delete'][$key]['#line_item_id'])) {
            $line_item_id = $form['edit_delete'][$key]['#line_item_id'];
            $form_state['line_items'][$line_item_id] = commerce_line_item_load($line_item_id);

            $form['edit_delete'][$key]['#value'] = t('Remove');
            $form['edit_delete'][$key]['#submit'] = array_merge($form['#submit'], array('commerce_cart_line_item_delete_form_submit'));
          }
        }
      }

    }
    else {
      // Otherwise go ahead and remove any buttons from the View.
      unset($form['actions']);
    }
  }
}

```
> -1 votes

---
Tags: commerce
---


title: How do I install a working demo?

text:
# Question
Title: How do I install a working demo?
I have been struggling with this for quite some time. I am trying to install a demo of the Commerce module as provided by Centarro, but every time the install finishes, I only get an empty site with the Beograd theme enabled but no product catalogue at all.

Here's what I do every time I try.

1. I install the Commerce module via `composer create-project`.

`composer create-project drupalcommerce/demo-project demo-commerce --stability dev --no-interaction`
2. I require the commerce\_demo:2.0 package.

`composer require drupal/commerce_demo`
3. Then I proceed with installing Drupal the standard way by going to my localhost URL. I select the profile provided by the commerce\_demo module which should install the complete package.

However, every time the install finishes, there's still just an empty store with the Beograd theme enabled. I see that the products are created, as well as brand and category taxonomy terms but I don't get any working catalogue made using facets and search API.

Is there anyone who managed to get the entire demo working and can provide a file/database dump or point me in the right direction?

# Answer
> 0 votes
You're hitting issues because the 2.x branch of Commerce Demo is intended to be used in the context of the new 3.x branch of Commerce Kickstart. This is a work in progress. If you're just trying to reproduce what we host at https://commerce.demo.centarro.io, I recommend the following tutorial:

https://www.centarro.io/blog/how-build-drupal-commerce-development-environment

Just bear in mind that even that is now outdated with the Drupal 8 EOL. You shouldn't have any issues for demo purposes, but I do think it should work fine with Drupal 9. I just haven't tested it yet.

---
Tags: commerce, installation-profiles
---


# Question
Title: Views with ajax get current node in hook_views_query_alter
The view has on offset based on a value set in the Basic page node.

```
function domain_config_bu_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
    if($node = \Drupal::routeMatch()->getParameter('node')) {
      if(... // Node has certain field value set) {
        $view->setOffset(0);
      }
    }
}

```

On a page request i can get the current node object by routeMatch() functionality.
But views has ajax enabled, and on ajax callback routeMatch() does not return the node object. Wich is normal. But how can i get the current node object/ nid in an ajax callback so the offset is respected?

# Answer
> 1 votes
Check if request is ajax route (it is not always '.ajax', log it to be certain). Get referer and retrieve the url object. The url object contains the parameters to get the current node.

```
// Get route
$route_name = \Drupal::routeMatch()->getRouteName();

// On ajax request get route_name of page.
if (strpos($route_name , '.ajax') !== FALSE) {
    $previousUrl = \Drupal::request()->server->get('HTTP_REFERER');
    $fake_request = Request::create($previousUrl);
    $url_object = \Drupal::service('path.validator')->getUrlIfValid($fake_request->getRequestUri());
    // Use $url_object to retreive your node.
}

```

---
Tags: views, 8, ajax, paging
---


# Question
Title: Webform 5.3 to 6.1.0 , Error : Call to undefined method Drupal\webform\Routing\WebformUncacheableResponse::addCacheableDependency()
I updated the webform module from 5.3.0 to the latest version (6.1.0) and then when I click submit on one of my forms, I receive this ERROR:

`Error: Call to undefined method Drupal\webform\Routing\WebformUncacheableResponse::addCacheableDependency() in Drupal\webform\Controller\WebformEntityController->javascript () (/home/acelys/www/uno-test.agglonet.com/web/modules /contrib/webform/src/Controller/WebformEntityController.php line 123)`

I wrote the error on google and no response at all AND i looked at the line of code shown in the error message, I noticed that the addCacehableDependency() function was not used in the version Ancient and now it is used in the newer version of webform, but there is no error in this file where the code exists.

any ideas ? Thanks !

# Answer
You need to wait until this issue is fixed https://www.drupal.org/project/webform/issues/3247584

If you want to patch it yourself, addCacheableDependency() works only with the second response:

```
  public function javascript(Request $request, WebformInterface $webform) {
    $assets = $webform->getAssets();
    if ($webform->access('update')) {
      $response = new WebformUncacheableResponse($assets['javascript'], 200, ['Content-Type' => 'text/javascript']);
    }
    else {
      $response = new CacheableResponse($assets['javascript'], 200, ['Content-Type' => 'text/javascript']);
      $response
        ->addCacheableDependency($webform)
        ->addCacheableDependency($this->config('webform.settings'));
    }
    return $response;
  }

```
> 3 votes

---
Tags: 8, webforms, debugging
---


# Question
Title: How to get rendered node according to active theme?
In a `hook_entity_postsave()` function in my custom D7 module, I'm doing the following when a node is saved:

```
$_ = node_view($entity, 'full');
$html = drupal_render($_);

```

But the renderd HTML seems to miss the active theme's templates. e.g. turning on theme debug, I get

```
 FILE NAME SUGGESTIONS:
   * paragraphs-items--field-sections--full.tpl.php
   * paragraphs-items--field-sections.tpl.php
   x paragraphs-items.tpl.php

```

Yet `paragraphs-items--field-sections--full.tpl.php` is defined in the site's active theme (and is used correctly on presentation of normal node pages).

EDIT: I think this may be because the admin theme is active when this code runs? Is there a way to switch that?

# Answer
> 1 votes
It is definitely because your admin theme is active when you do the render.

There is no straight-forward and easy way to switch the theme in the middle of a request and you will likely run into further problems.

I would consider other options, e.g. creating the nodes markup via a menu callback that uses the frontend theme, either directly in your `hook_entity_postsave` or in a cron job for example.

If you still want to try it by switching themes, this is the way it worked for my now after a bit of tinkering with the code from https://stackoverflow.com/a/56358189/368479 and borrowing code from drupal\_theme\_initialize(). The most notable change is the clearing of the cache at the end of the switch function. Performance-wise this is awful, but I couldn't make it work without it.

```
/**
 * Switch to or from an alternative theme in the middle of a request.
 *
 * This is useful if you need to render something (like a node) in a different
 * theme without changing the theme of the entire page. An example use case is
 * when you need to render something for a front end user from an admin page.
 *
 * Usage example:
 *     my_module_switch_theme('bartik');
 *     $node = node_load(1);
 *     $renderable = node_view($node);
 *     $rendered = render($renderable);
 *     my_module_switch_theme();
 *
 * @param string|null $to
 *   The name of the theme to switch to. If NULL, it switches back to the
 *   original theme.
 */
function my_module_switch_theme(string $to = NULL) {
  global $theme, $theme_key;

  // Backup the original theme.
  static $original_theme;
  if (empty($original_theme)) {
    $original_theme = $theme;
  }

  // Perform the switch.
  $theme = $to ?? $original_theme;
  $theme_key = $theme;

  // Find all our ancestor themes and put them in an array.
  $themes = list_themes();
  $base_theme = array();
  $ancestor = $theme;
  while ($ancestor && isset($themes[$ancestor]->base_theme)) {
    $ancestor = $themes[$ancestor]->base_theme;
    $base_theme[] = $themes[$ancestor];
  }
  _drupal_theme_initialize($themes[$theme], array_reverse($base_theme));

  // Themes can have alter functions, so reset the drupal_alter() cache.
  drupal_static_reset('drupal_alter');

  // Clear the cache.
  drupal_flush_all_caches();
}

```

Note that this might not work if you implement hook\_custom\_theme for the page where the action happens, but if you use the admin theme then I guess that is not the case.

The code above can then be used like in the following example and correctly uses the `node.tpl.php` from the bartik theme instead of the one that the current theme uses, at least in my test setup.

```
my_module_switch_theme('bartik');
$node = node_load(1);
$renderable = node_view($node);
$rendered = render($renderable);
my_module_switch_theme();

```

---
Tags: 7
---


# Question
Title: How to pass Paragraph ID from Layout Builder to Views?
This is a bit convoluted; so hopefully it makes sense:

I have a parent entity: Event. Event has a Paragraph field on it: Sessions (paragraph type: Session).

I use Layout Builder to format the Full Content view mode of the Event. In the layout I add a (paragraph) view which lists the Session paragraphs as Teasers (view mode of Session) with a contextual filter of Paragraph: Parent ID. This all works as expected.

Next I set the Session teaser view mode to use Layout Builder. Set up a LB section and add a couple of the Paragraph's fields. This also works as expected. Which means through all of this, Layout Builder knows which paragraph it should be displaying fields for. Excellent.

Next (and finally) I create another View (paragraph) to create a formatted list of some of my Paragraph fields. I set the contextual filter to Paragraph ID. When I preview by entering the PID of one of my Sessions, this works as expected. When I add this view to my Session layout, of course, on my Event page, the View has no results. This is sad but expected as there is no way that Layout Builder could have passed the paragraph ID to the View - even though LB does know which paragraph to use to display individual paragraph fields.

Is this possible? Is there some trick i have missed which allows the "Session fields" view to know which paragraph it is for? Although I think this is a stretch; it does seem like not that far off from it knowing which field to display.

# Answer
I am guessing some that will say this is not a great way to do this; but for now, this is how I managed it:

In views\_query\_alter for the top View (list of Sessions embedded in Event Layout) I create a drupal\_static array of that list of paragraph ids.

Then, in a the various views used to build the view mode layout for the Session paragraph, I simply array\_pop that drupal\_static array and $view-\>setArguments() to the next paragraph id from the array. The paragraph views are set to have contextual filter as Content ID from URL.

Yes, I know I could do some of this using templates for the paragraph view mode but Views gives me a lot of tools for formatting field data which would be painful to build up otherwise. For example, the fields in question here have static google map formatters buried in a views popup field. Easy to put together in a View.
> 0 votes

---
Tags: views, 9, paragraphs, layout-builder
---


# Question
Title: How do I access the protected value of node entity?
I have a view node and I use the below code to Kint out the node objects:

```
$node = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->loadMultiple();
 dpm($node);

```

returns the below output:

I get to see the properties of each node. In this, I want to access the target\_id/value of the highlighted field - field\_cp\_level2\_ref\_level3. I tried the below line and it is coming out as null:

```
$node->field_cp_level2_ref_level3->target_id

```

How to access this field value?

# Answer
> 0 votes
Your problem is that you wrongly assume the result of `loadMultiple` to be a node object, when instead it returns an array of node objects.

You should be able to do this:

```
$nodes = \Drupal::entityTypeManager()
  ->getStorage('node')
  ->loadMultiple();
$node = reset($nodes);

```

You should now be able to access the values you see in your debug output:

```
$node->field_cp_level2_ref_level3->target_id;

```

It's actually a bit questionable to load all the nodes you have in your system. That might still work with your 294 nodes, but it will create problems on sites with more content. Instead you should add conditions, e.g. by using `loadByProperties` on the node storage.

---
Tags: 8, nodes
---


# Question
Title: Allow user to control access to own content for other authenticated users
I just want a field in a content type, so that when a user creates new content he/she can select whether that content can be viewed by other authenticated users or not. I prefer doing this with a selection field displaying 'hidden/visible' to other users and then set the actual access in a custom module using some hook.

This is what I tried so far in my custom module hook entity access with content type test\_adgang and checking field\_test\_adgang, but no effect, meaning all authenticated users can still see, if field set to 'skjult' (hidden).

```

<?php

use Drupal\Core\Access\AccessResult;

function import_functions_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account) {
    if ($entity->bundle() == 'test_adgang') {
        if ($entity->field_test_adgang->value == 'skjult' && $operation == 'view' && in_array('godkendt bruger', $account->getRoles())) {
            return AccessResult::forbidden();
        } elseif ($entity->field_test_adgang->value == 'synlig' && $operation == 'view' && in_array('godkendt bruger', $account->getRoles())) {
            return AccessResult::allowed();
        }
    }

}

?>

```

# Answer
> 1 votes
The Rabbit Hole module allows you to specify if users can view the node. The first setting is for the content type, but there is a setting there to allow that to be set on a per node basis. You can look at using that module, or look at what they're doing to solve this.

---
Tags: 8
---


title: Column isn't responsive

text:
# Question
Title: Column isn't responsive
I have inserted a view and one column refuses to word wrap on mobile display. On normal desktop display it wraps just fine. But as seen in the second image taken on my phone, it puts everything in that one column only as one sentence.

This only happens with this view table. A regular table works fine as seen in the second image.

So, how do I fix this? Most using my site uses it via phone, and this is breaking their experience. Thanks.

# Answer
> 0 votes
You can see the same effect using for example the chrome developer tools, where you can set the screen dimensions.

In you specific case, you have a `white-space: nowrap` applied to your table cells for devices up to 768px. This is what prevents the line wrapping, see these screenshots.

What your site currently has:

With the `white-space: nowrap` removed:

---
Tags: views, theming
---


# Question
Title: SQL Error when trying to remove content type field
I was trying to create a new Content Type for my site and I chose a field name ("description") that already used for other content types.

The problem occurred when saving changes as the machine name for the field already exists for the fields in other Content Types but with a different field type. In other Content types I used the default "Long Text" field type but in this case I chose "Read More Field" as it suited better my use case.

I noticed the problem and went back to change the machine name only to discover I had created two fields and one of them had a machine name with the problem I mentioned before.

When trying to remove such field, I went to `admin/structure/types/manage/my_custom_content_type/fields` and using the UI options selected "Delete".

Then, the admin UI showed me a screen where it displays the changes I'm about to make and when I chose "Accept", my site takes me to a blank page with the message: "The website encountered an unexpected error. Try it again later."

When I check the logs, this is the error message I see:

```
[06-Nov-2021 03:07:49] WARNING: [pool www] child 2014 said into stderr: "NOTICE: PHP message: Uncaught PHP Exception Drupal\Core\Database\DatabaseExceptionWrapper: "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'field_description_teaser_value' in 'where clause': SELECT 1 AS expression"
[06-Nov-2021 03:07:49] WARNING: [pool www] child 2014 said into stderr: "FROM"
[06-Nov-2021 03:07:49] WARNING: [pool www] child 2014 said into stderr: "{node_revision__field_description} t"
[06-Nov-2021 03:07:49] WARNING: [pool www] child 2014 said into stderr: "WHERE (field_description_teaser_value IS NOT NULL) OR (field_description_teaser_format IS NOT NULL) OR (field_description_hidden_value IS NOT NULL) OR (field_description_hidden_format IS NOT NULL)"
[06-Nov-2021 03:07:49] WARNING: [pool www] child 2014 said into stderr: "LIMIT 1 OFFSET 0; Array"
[06-Nov-2021 03:07:49] WARNING: [pool www] child 2014 said into stderr: "("
[06-Nov-2021 03:07:49] WARNING: [pool www] child 2014 said into stderr: ")"
[06-Nov-2021 03:07:49] WARNING: [pool www] child 2014 said into stderr: "" at /var/www/html/web/core/lib/Drupal/Core/Database/Connection.php line 701"
2021/11/06 03:07:49 [error] 2010#2010: *21776 FastCGI sent in stderr: "PHP message: Uncaught PHP Exception Drupal\Core\Database\DatabaseExceptionWrapper: "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'field_description_teaser_value' in 'where clause': SELECT 1 AS expression
FROM
{node_revision__field_description} t
WHERE (field_description_teaser_value IS NOT NULL) OR (field_description_teaser_format IS NOT NULL) OR (field_description_hidden_value IS NOT NULL) OR (field_description_hidden_format IS NOT NULL)
LIMIT 1 OFFSET 0; Array
(
)
" at /var/www/html/web/core/lib/Drupal/Core/Database/Connection.php line 701" while reading response header from upstream, client: 172.18.0.6, server: , request: "GET /admin/structure/types/manage/my_custom_content_type/fields/node.my_custom_content_type.field_description/storage HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm.sock:", host: "custom-site.ddev.site", referrer: "https://custom-site.ddev.site/admin/structure/types/manage/my_custom_content_type/fields"

```

When launching `phpmyadmin`, none of the column names listed in the where clause exist in `node_revision__field_description` table as those columns are created for a different field type.

At this point, I couldn't create any content using this Content Type and I would like to remove it and start from scratch by creating a new one with better machine names and trying to avoid those errors.

My question is: is there a safe way to remove the content type by using SQL or drush? I tried to remove it via the admin interface but it resulted with the same error as when I try to remove the field.

# Answer
> 0 votes
I managed to solve my problem by manually adding the missing columns to the tables involved using `phpmyadmin`.

First:

* Created a db backup (just in case).

Second, I created a copy of the tables involved and moved such copies to another db maintaining both data and structure:

* `node_revision__field_description`
* `node__field_description`

Once the backup was done, I proceeded creating the missing columns and copied their attributes from similar columns in other tables (created for other Content Types).

Then, I removed the Content Type via the admin UI without any problem.

Lastly, I restored the original copies of the tables to the db, replacing the modified versions of them.

I know this is probably not the best solution for everyone but it worked for me.

---
Tags: 8, nodes, drush
---