title: Sort views by number of related tags

text:
# Question
Title: Sort views by number of related tags
I want to create a view block with related content based on shared terms. For this I created a term reference field inside the content type and created a views where I use a contextual filter Taxonomy term - ID to fetch all nodes sharing the samen terms. I also added a contextual filter to excluded the current node using Content: ID.

This all works great, but I now want to sort the view by the number of sharing terms. So the nodes with the most shared terms should end up on top.

I found these two articles: Create a related content block which sorts the nodes of related content by how many tags they share? Sorting view results by the number of matched arguments (contextual filters)

Following these two I enabled aggregation and for testing purposes I added the taxonomy reference field and used the aggregation setting count distinct.

Doing this the number of distinct terms is count instead of counting the number of shared distinct count. What step am I missing here?

# Answer
The difficulty about this was finding the right way to search for a solution. But I found it. It's a module that does exactly what I want. It's called Similar By Terms.
> 0 votes

---
Tags: views, taxonomy-terms, 9
---


# Question
Title: Add/enable language to Language Module from code
I'd like to add/enable a language, just like one would from the admin ui at */admin/config/regional/language/add*

**but, from code**. I've found old options such as locale\_add\_language which no longer exists, since Drupal 5 or 6. Everything else I can find is in Tests, which seems like a bad route to take and I'm still a little new to Drupal development to understand how to make it happen, or if I should.

I'm building an app that checks the server for content in the device's language and, if it doesn't have it, the server hits Google Translate and stores the translation, and sends it on to the app. The problem is that if that language hasn't been enabled in Drupal, it doesn't store properly and effectively doesn't exist. If I pre-add the language, no problem.

Therefore, unless there's a code solution to adding a language when a new language is encountered, I'd have to enable all languages on the server. I'm not against that, but I'm also wondering if there is overhead on that, or other problems it could cause.

Thank you for any help or suggestions you might have!

# Answer
Languages can be added the same way as any other entity. The entity type is *configurable\_language* and you can use the LanguageManager to get the proper settings (name, LTR/RTL) from the stock languages in admin.

So, where $lang is the language code sent by the device:

```
$standard_languages = LanguageManager::getStandardLanguageList();
$label = $standard_languages[$lang][0];
$direction = $standard_languages[$lang][2] ?? ConfigurableLanguage::DIRECTION_LTR;

$entity = \Drupal::entityTypeManager()->getStorage('configurable_language')->create();
$entity->set('id', $lang);
$entity->set('label', $label);
$entity->set('direction', $direction);
$languages = \Drupal::languageManager()->getLanguages(ConfigurableLanguage::STATE_CONFIGURABLE);
$last_language = end($languages);
$entity->setWeight($last_language->getWeight() + 1);
$entity->save();

```

What threw me off was that you do not *enable* a pre-defined language. The languages shown in the admin UI come from a variable in json format in Core, and they're added as entities when you enable them.
> 3 votes

---
Tags: nodes, i18n-l10n
---


# Question
Title: How to render a twig template in the meta data of a cacheablejson response?
In a json response I'm returning some prerendered data. However I got tired of constructing the html by concatenating strings in php and decided to make a twig template for it.

```
$render_facets_arr = [
  '#theme' => 'facets',
  '#facets' => $data['meta']['facets'],
];
$data['meta']['renderedFacetsTest'] = \Drupal::service('renderer')->render($render_facets_arr)->__toString();

```

However when I do so I get this error

> 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\Core\Cache\CacheableJsonResponse.

I saw this question but I don't think it'd applied because I didn't need to change the context the query was done in, I just wanted to add the rendered twig with some variables filled in. LogicException: The controller result claims to be providing relevant cache metadata, but leaked metadata was detected

Any ideas? Should I just go back to constructing the html as strings in php?

# Answer
Use renderRoot() and, most importantly, add the cache metadata of the build array (after it was rendered) to the response, so that the response can be invalidated in cache if necessary:

```
use Drupal\Core\Cache\CacheableMetadata;

  $build_facets = [
    '#theme' => 'facets',
    '#facets' => $data['meta']['facets'],
  ];
  $data['meta']['renderedFacetsTest'] = (string) \Drupal::service('renderer')
    ->renderRoot($build_facets);

  $response = new CacheableJsonResponse($data);
  $response->addCacheableDependency(CacheableMetadata::createFromRenderArray($build_facets));
  return $response;

```

By returning a response with the rendered result the controller takes control of the entire rendering process and the rendering becomes the top level render call in this request, which makes it a renderRoot() call.
> 4 votes

# Answer
Looks like I needed to use renderPlain instead of render
> 0 votes

---
Tags: 9
---


# Question
Title: How do I disable/enable the Advanced Content Filtering (ACF) in CKEditor 4.8.0?
Please tolerate me for asking such a question. All the answers I found are for Drupal 7. There is barely any talk on this issue for Drupal 8. I am a beginner in Drupal and I am not a programming oriented person. However, I am determined to find the solution to make this work.

It seems the most straight forward solution is to add the following line of setting:

```
CKEDITOR.config.allowedContent = true;

```

However, where should I add it in Drupal 8? There's no (ckeditor).config.js, as far as I can find within my Drupal's installation directories. How or where should I proceed? Does this matter need coding in order to achieve my goal in Drupal 8?

Many of the CSS classes and scripts embedded within the content are stripped off by the CKEditor either after saving or works in the initial save but are then stripped after editing the content the second time.

If you have the patient for someone like me, please help. Much appreciated! If I am tackling the problem in a completely wrong direction, please advise as well. Thank you!

# Answer
> 0 votes
It seems that the short answer is "no" in Drupal 8. You should ensure that your HTML is W3C compliant and changes to your code will be minimal.

# Answer
> 0 votes
You can use the CKEditor Custom Config module

This should enable a config area on the text format where you can add:

```
allowedContent = true

```

A snippet of how to use it here:

Drupal CKEditor 4 Module Overview

---
Tags: wysiwyg
---


# Question
Title: Prevent node from being saved in hook_node_presave
When saving / updating node, i need to validate if certain fields combination is unique. Unique field module is supposed to allow this, but that feature is not working (validating only single field). So i created my own hook:

```
function mymodule_node_presave(\Drupal\Core\Entity\EntityInterface $node) {

  if ($node->bundle() == 'mycontent') {

    $term = \Drupal\taxonomy\Entity\Term::load($node->get('field_mytaxonomy')->target_id);

    $query = \Drupal::entityQuery('node');
    $query->condition('type', 'mycontent');
    $query->condition('field_mydate', $node->get('field_mydate')->value, '=');
    $query->condition('field_mytaxonomy', $term->id(), '=');

    $nids = $query->execute();

    if ($nids) {
      drupal_set_message('Fields are not unique!', 'error');
      // I need to prevent saving of node here
    }
  }
}

```

Detection of node with duplicite values being created works. **How do i prevent saving that node?**

# Answer
**How do i prevent saving that node?**

If you want to prevent that the node is saved in a presave method or hook you have to throw an exception:

```
throw new \Exception(t('Fields are not unique!'));

```

More user friendly would be to check this in the form first and give the user a chance to correct the input before you throw an exception.

Double checking this in presave is still a good idea to make sure, that no incorrect node content gets saved, no matter which form, Rest API or code is used. If someone gets past the first level of checks in the form you have no other option than to throw an exception.

Edit:

In case an exception is raised, you can replace the default 500 response with a custom error handling in an exception subscriber, see Handle database connection exception via custom handler
> 14 votes

# Answer
That is not the right hook to do validations. Use hook\_form\_FORM\_ID\_alter() to add a validation function.

```
$form['#validate'][] = 'my_custom_validate';

```

Then in your custom validation function:

```
$term = $form_state->getValue('field_mytaxonomy');
// Your logic here.
$form_state->setErrorByName('field_mytaxonomy', t('Fields are not unique!'));

```
> 6 votes

# Answer
Ideally, for such needs - a Constraints should be implemented.

See documentation at Defining Constraints (Validations) on Entities and/or Fields
> 1 votes

---
Tags: nodes, 8
---


# Question
Title: Alter a route according the current user
I'm on D 9.4.x, trying to redirect the `node.add` route to a custom one, only when the current user has the right role\permission.

So I don't think I can't work in the alterRoutes but I probably need to override the controller of that route. In a custom RouteSubscriber I have:

```
protected function alterRoutes(RouteCollection $collection) {
    if ($route = $collection->get('node.add')) {
      $route->setDefault('_controller', '\Drupal\my_module\myController::alterRoute');
    }
  }

```

and in the controller

```
  public function alterRoute(RouteMatchInterface $route_match) {
    if ($my_condition) {
       return $this->redirect('my_route');
    }
    else {
      $node_type = $route_match->getRawParameter('node_type');
      return $this->redirect('node.add', ['node_type' => $node_type]); //this goes loop
    }
  }

```

This code causes a loop, as when the condition fails the redirect return in my custom controller and so on. Any idea I could implement this feature? Thanks

# Answer
Thanks to the comment of @4uk4 I've develop an Event Subscriber where is easy to implement the logic I need:

```

  public function onKernelRequest(RequestEvent $event) {
     if ($this->account->hasPermission('my permission')) {
      return;
    }

    $route_name = $this->routeMatch->getRouteName();

    if($route_name === 'node.add') {
     $url = Url::fromRoute('custom_route')->toString();
     $response = new RedirectResponse($url);
     $event->setResponse($response);
    }

  }

```
> 1 votes

---
Tags: entities, routes
---


# Question
Title: Composer not respecting constraint defined in composer.json
I have a build, with the following constraint on `drupal/core`, for some reason the constraint is not respected.

Upon running composer install this comes up:

```
 - Downloading drupal/core (9.5.0-rc1)

```

Composer show -i drupal/core:

```
name     : drupal/core
descrip. : Drupal is an open source content management platform powering millions of websites and applications.
keywords :
versions : * 9.5.0-rc1

```

I seriously would prefer having stable drupal/core. I am able to "force the universe" by doing  `composer require drupal/core --update-with-dependencies`, and committing the generated .lock file.

Why, *composer*, why?!?

composer.json:

```
{
    "name": "acme/drupal",
    "description": "Acquia-compatible Drupal application based on the Drupal Recommended Project",
    "license": "GPL-2.0-or-later",
    "authors": [
        {
            "name": "Acquia Engineering",
            "homepage": "https://www.acquia.com",
            "role": "Maintainer"
        }
    ],
    "repositories": {
        "asset-packagist": {
            "type": "composer",
            "url": "https://asset-packagist.org"
        },
        "drupal": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    },
    "require": {
        "php": ">=8.1",
        "acquia/acquia-cms-starterkit": "^1",
        "acquia/blt": "^13.5",
        "acquia/drupal-environment-detector": "^1",
        "acquia/http-hmac-php": "6.0.0",
        "acquia/memcache-settings": "^1",
        "composer/installers": "^2.1",
        "cweagans/composer-patches": "^1.6",
        "drupal/address": "^1.11",
        "drupal/admin_toolbar": "^3.1",
        "drupal/coffee": "^1.2",
        "drupal/config_ignore": "^2.3",
        "drupal/config_readonly": "^1.0@beta",
        "drupal/config_split": "^1.9",
        "drupal/core": "~9.4",
        "drupal/core-composer-scaffold": "^9",
        "drupal/core-recommended": "~9.4",
        "drupal/drimage": "^2.0",
        "drupal/entity_browser": "^2.8",
        "drupal/entity_clone": "^1.0@beta",
        "drupal/field_group": "^3.2",
        "drupal/focal_point": "^1.5",
        "drupal/fpa": "^3.0",
        "drupal/gin": "^3.0@beta",
        "drupal/insert": "^1.0",
        "drupal/link_attributes": "^1.11",
        "drupal/module_filter": "^3.2",
        "drupal/paragraphs": "^1.15",
        "drupal/pathauto": "^1.11",
        "drupal/scheduler": "^1.4",
        "drupal/seckit": "^2.0",
        "drupal/section_library": "^1.0",
        "drupal/section_library_reusable": "^1.0@beta",
        "drupal/shield": "^1.6",
        "drupal/twig_tweak": "^3.1",
        "drupal/upgrade_status": "^3.13",
        "drupal/webprofiler": "^9.0",
        "drush/drush": "^10.6 || ^11",
        "oomphinc/composer-installers-extender": "^1.1 || ^2"
    },
    "require-dev": {
        "acquia/blt-phpcs": "^1.0",
        "acquia/coding-standards": "^1.0.0",
        "behat/behat": "^3.11",
        "behat/mink": "^1.10",
        "drupal/devel": "^4.1",
        "drupal/drupal-extension": "^4.2",
        "drupal/twig_vardumper": "^3.0",
        "mglaman/phpstan-drupal": "^1.1",
        "phpspec/prophecy-phpunit": "^2.0",
        "phpstan/extension-installer": "^1.1",
        "phpstan/phpstan": "^1.6",
        "phpstan/phpstan-deprecation-rules": "^1.0",
        "phpunit/phpunit": "^9.5",
        "squizlabs/php_codesniffer": "^3.6"
    },
    "config": {
        "allow-plugins": {
            "composer/installers": true,
            "cweagans/composer-patches": true,
            "dealerdirect/phpcodesniffer-composer-installer": true,
            "drupal/core-composer-scaffold": true,
            "ergebnis/composer-normalize": true,
            "oomphinc/composer-installers-extender": true,
            "phpstan/extension-installer": true,
            "acquia/blt": true,
            "acquia/blt-phpcs": true,
            "drupal/console-extend-plugin": true
        },
        "platform": {
            "php": "8.1"
        },
        "sort-packages": true
    },
    "extra": {
        "composer-exit-on-patch-failure": true,
        "drupal-scaffold": {
            "allowed-packages": [
                "acquia/acquia_cms"
            ],
            "file-mapping": {
                "[profile-root]/.editorconfig": false,
                "[profile-root]/.gitattributes": false,
                "[profile-root]/.travis.yml": false,
                "[profile-root]/acquia-pipelines.yml": false,
                "[web-root]/sites/default/default.services.yml": {
                    "mode": "replace",
                    "overwrite": false,
                    "path": "docroot/core/assets/scaffold/files/default.services.yml"
                },
                "[web-root]/sites/default/default.settings.php": {
                    "mode": "replace",
                    "overwrite": false,
                    "path": "docroot/core/assets/scaffold/files/default.settings.php"
                }
            },
            "gitignore": true,
            "locations": {
                "profile-root": "docroot/profiles/contrib/acquia_cms",
                "web-root": "docroot/"
            }
        },
        "enable-patching": true,
        "installer-paths": {
            "docroot/core": [
                "type:drupal-core"
            ],
            "docroot/libraries/{$name}": [
                "type:drupal-library",
                "type:bower-asset",
                "type:npm-asset"
            ],
            "docroot/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "docroot/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "docroot/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "docroot/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "docroot/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ]
        },
        "installer-types": [
            "bower-asset",
            "npm-asset"
        ],
        "patchLevel": {
            "drupal/core": "-p2"
        },
        "patches": {
            "drupal/core": {
                "Break long text strings in layout edit": "https://www.drupal.org/files/issues/2020-12-22/3016507-50.patch",
                "Improve StringItem::generateSampleValue()": "https://www.drupal.org/files/issues/2020-06-24/3091478-15.patch",
                "Not all form elements can't use in vertical_tabs": "https://www.drupal.org/files/issues/2021-01-02/3122920_group_patch_5.patch",
                "PHP message: Error: Call to a member function getEntityTypeId() on null (Layout Builder)": "https://www.drupal.org/files/issues/2020-08-05/3049332-inline-35.patch",
                "Stream wrapper reference in JS library causes error in _locale_parse_js_file()": "https://www.drupal.org/files/issues/2020-05-08/2735717-28.patch",
                "New non translatable field on translatable content throws error": "https://www.drupal.org/files/issues/2021-02-10/3025039_42.patch"
            },
            "drupal/section_library": {
                "#3228163: Add create or update logic.": "https://git.drupalcode.org/project/section_library/-/merge_requests/3.patch"
            }
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "scripts": {
        "acms:install": [
            "./vendor/bin/acms acms:install"
        ],
        "nuke": [
            "rm -rf docroot vendor composer.lock"
        ]
    }
}

```

# Answer
1. Set `"minimum-stability": "stable"`.
2. Remove `drupal/core` from `composer.json` requirements section. It is superfluous.
3. `composer require drupal/core-recommended:^9.4 drupal/core-composer-scaffold:^9.4 -W`.

Once you do that you have more work to do because of things that don't make sense, like `drupal/insert 1.0.0 requires drupal/core ^8`. If that is removed you have:

```
 Root composer.json requires drupal/gin ^3.0@beta -> satisfiable by drupal/gin[3.0.0-beta1, ..., 3.0.0-beta5].
    - drupal/gin[3.0.0-beta1, ..., 3.0.0-beta5] require drupal/gin_toolbar ^1.0@beta -> found drupal/gin_toolbar[dev-1.x, 1.0.0-alpha1, ..., 1.x-dev (alias of dev-1.x)] but it does not match your minimum-stability.

```

When that happens you have to specify dev versions of the dependencies explicitly.
> 3 votes

---
Tags: composer
---


# Question
Title: Why does Drupal >= 9.4.7 not allow including .php files in Twig templates?
I have been handed a site with an old custom theme purchased from a third party.

After the last drupal update - 9.4.8 - logged in users stopped being able to access the front end of the site. Administration pages were still accessible.

After some digging I found the error was this line in a twig template:

```
{% include directory ~ '/customize/form.php' %}

```

It was causing the following error:

```
Twig\Error\LoaderError: Template "themes/gavias_tico/customize/form.php" is not defined in "themes/gavias_tico/templates/addon/skins.html.twig" at line 4. in Twig\Loader\ChainLoader->getCacheKey() (line 98 of /var/www/mysite.org.au/vendor/twig/twig/src/Loader/ChainLoader.php).

```

The template (php) file is present at the location listed so it appears twig is finding the correct path, however, the site is still WoD after this for logged-in users.

Has there been a change to the way twig includes should be done in drupal? How can I fix this?

# Answer
This is from Drupal 9.4.7 and its release notes explain:

“Following this release, by default, Twig may load the following file types:

* .css
* .html
* .js
* .svg
* .twig

If your site, module, or theme must load additional file types via Twig, consult the documentation for twig.config.allowed\_file\_extensions in default.services.yml.”

But allowing other types may be dangerous. Read the security advisory for more information.
> 5 votes

# Answer
I faced an same type of issue when updating the Drupal core from 9.4.5 to 9.4.8

**Twig\Error\LoaderError: Template "themes/gavias\_tico/customize/form.php" is not defined in "themes/gavias\_tico/templates/addon/skins.html.twig" at line 4. in Twig\Loader\ChainLoader-\>getCacheKey() (line 98 of /var/www/mysite.org.au/vendor/twig/twig/src/Loader/ChainLoader.php).**

Based on the @cilefe, due to the security advisory only the following extensions are allowed to use in twig fix.

.css .html .js .svg .twig

Using php file in twig file is not allowed. I just changed the name of the file from yourfilename.php to yourfilename.html, and the same file called in the skins.html.twig

Hope this could helps to sort out this issue
> 2 votes

---
Tags: 9
---


# Question
Title: How to get fields of a product type using a database dynamic query
So I currently have multiple different product types that have varying fields. I was able to fetch all products using EntityTypeManager the following way:

```
$productStorage = \Drupal::entityTypeManager()->getStorage('commerce_product');
$ids = $productStorage->getQuery()->execute();
$allProducts = $productStorage->loadMultiple($ids);

```

This works quite well, and I see how this can be used to execute more complicated queries. However, I'd like to now get a certain product (perhaps based off the product\_id). I saw a previous post showing that a dynamic query is faster than an EntityFieldQuery. So if for example my custom api call (my drupal is communicating with a frontend server) gets a request for a certain product by product\_id and product type, how can I determine the fields of the product type with which I can then create a dynamic database query to get the product and the field values that go along with it? I read somewhere that this information is stored in the config table in the database and shouldn't really be queried, which is why I'm asking this question.

Thanks for the help in advance, and let me know if there's anything unclear about my post!

# Answer
> 1 votes
> how can I determine the fields of the product type with which I can then create a dynamic database query to get the product and the field values that go along with it?

You shouldn't do that. That's what the entity API *already does*. You would just be rebuilding the existing functionality of core Drupal for no benefit. Then there's contrib modules, which extend and augment that functionality. You would need to reproduce everything relevant that they do as well.

This sounds like a classic case of premature optimisation, which rarely has the intended benefits in my experience. Drupal has a great caching system, it would be advisable to look into that as a way to mitigate issues, if and when they actually present as real world problems.

As an aside, as a literal answer to the original question, this is how you get the fields of an entity bundle:

```
$field_defs = \Drupal::service('entity_field.manager')
  ->getFieldDefinitions('commerce_product', 'bundle');

$fields_names = array_keys($field_defs);

```

---
Tags: commerce, database, 9
---


# Question
Title: How to group results by multiple fields?
I have values in database like:

`x submits file 1`

`x submits file 2`

`y submits file 1`

`y submits file 3`

`x submits file 1`(again)

I had my output with aggregation settings as group results together as

`x submits file 1`

`x submits file 2`

`y submits file 1`

`y submits file 3`

it just grouped file 1 submissions of x

i want it to be :

`x submits file 1,2`

`y submits file 1,3`

Can anyone please help?

# Answer
> 1 votes
In D7 - you can achieve your grouping structure in Views with the help of the Views Merge Rows module.

You'd use the option "Use values of this field as a filter" for the field that produces x & y. And for the file name field you'd use the option "Merge unique values of this field".

# Answer
> 0 votes
I have completed this by using https://www.drupal.org/project/views\_field\_view

I created a view with a contextual filter to show the extra information in one field

---
Tags: views
---


# Question
Title: Drush does not acknowledge release of new core update
I am trying to update my drupal 7.31 core to 7.32 via Drush.

I ran the following commands

**$ drush pm-releases**

```
Project  Release  Date         Status
drupal   7.x-dev  2014-Oct-15  Development
drupal   7.32     2014-Oct-15  Supported, Recommended, Security
drupal   7.31     2014-Aug-06  Security

```

After the above command i ran the following:

**$ drush pm-update drupal**

```
Update information last refreshed: Thu, 10/16/2014 - 07:33
 Name    Installed Version  Proposed version  Message
 Drupal  7.31               7.31              Unknown

No code updates available.

```

so i ran the following command:

**$ drush pm-update drupal-7.32**

```
Update information last refreshed: Thu, 10/16/2014 - 07:33
 Name         Installed Version  Proposed version  Message
 drupal-7.32  Unknown            Unknown           Specified version not found

No code updates available.

```

Here are the versions for drush and composer. Both are to the latest versions.

$ drush version

```
 Drush Version   :  7.0-dev

```

Composer version 1.0-dev

# Answer
> 1 votes
The solution offered by Danny Englander worked.

Restarting mysql server did the trick.

Thanks Danny.

# Answer
> 19 votes
`drush rf` will refresh the available releases and at that point you should be able to run `drush up` or `drush up drupal`.

# Answer
> 3 votes
I have the same problem. Can't get to update list of modules and core. Tried CC, cache\_update truncate. Well everything I could come up with and still nothing. What is strange is that on localhost is where I get this, on remote server it is ok.

So I fixed it somehow with disabling and uninstaling update manager and installing it again.

# Answer
> 3 votes
In addition to all the great answers above, be sure to do a double check for possible \[facepalm\] brain-fail issues:

* are you logged in to the right server?
* the right drupal site path on that server?
* did you mess with your /etc/hosts file and forget?
* is www and non-www pointed to the same place?
* are you looking at a local or dev copy in your browser?

If you run `drush status` and it has the updated version but you still see the update alerts in the GUI Reports \> Available Updates page then you might be a *total f#¢&ing idiot* like me and be looking at different copies of the site.

If you've already tried `drush rf` and you compare `drush status` and it has the same current version number you get when you run `drush pm-releases drupal` then you definitely have an issue other than drush not working properly.

# Answer
> 2 votes
I also had the same problem.

Restarting MySQL server didn't work for me.

Disabling update manager, uninstalling it and then re-enabling it worked for me.

```
$ drush -y dis update
$ drush -y pm-uninstall update
$ drush -y en update

```

# Answer
> 1 votes
First of all execute:

```
drush pm-releases drupal

```

Then you should see all tag names like this:

```
 Project  Release  Date         Status
  drupal   7.38     2015-Jun-17  Supported, Recommended, Security, Installed
  drupal   7.x-dev  2015-Jun-17  Development

```

Now you can get Project name and Release number like this 'drupal-7.38' and execute this to force update to that release:

```
drush dl drupal-7.38

```

You can even choose a development version of update by write the development release number.

This also work with update modules. If you need to force update for a module like ctools for a dev release you can execute:

```
drush dl ctools-7.x-1.x-dev

```

Enjoy drush \<3

# Answer
> 1 votes
I had the same problem, the command

```
drush up drupal

```

was not finding the new drupal version. Even the update module, from the admin interface, was not showing the new drupal core release. I've managed truncating the **cache\_update** table

```
TRUNCATE TABLE  cache_update

```

For what I've seen, the update module caches the new release informations in this table, for some strange reasons the `drush cc all` command was not cleaning this table so the new drupal core release colund't be found.

# Answer
> 0 votes
All the answers here and no one suggested the simplest one which works every time for me:

```
drush cc drush

```

`drush cc all` clears all the Drupal caches, but does not clear the drush cache.

# Answer
> 0 votes
It is an old question, but I will share my recent experience regardless. For me, it was just a silly problem with drush not being able to access the internet (as I am behind a proxy).

The solution was to set HTTP\_PROXY and HTTPS\_PROXY (and their lower-case versions) env variables to the proper values.

---
Tags: drush, updating
---


# Question
Title: Migrating from D7 / MySQL 5.6 to D9 / MySQL 8
I've read the documentation of upgrading (migrating) from D7 to D9, but didn't see anything about how to handle changing MySQL versions in the process.

My D7 instance is on MySQL 5.6, which is unsupported in D9. Can I use the process described in the official docs linked above, or do I have to take any special actions with respect to the change in MySQL versions?

Note: from the MySQL docs, the recommended upgrade path is (I believe) 5.6 -\> 5.7 -\> 8.

# Answer
The best option would be to upgrade the source site to MySQL 5.7 before migration.

If that’s not an option, you can install the mysql56 module in the D9 site while you’re migrating. This module makes D9 fully compatible with mysql 5.6. It can be removed without issue once the migration is complete

If you do neither, the migration may still work, but you’re in best-effort territory and you’ll probably never be 100% confident that there isn’t a little nugget of migration error waiting to haunt you in the future.
> 3 votes

---
Tags: 7, database, migrations
---


# Question
Title: Remove settings no-longer present in custom modules config form from drupalSettings
Hello Drupal Code Land,

I have created a custom admin form in a custom module as a class extending ConfigFormBase. I use this form as an admin config form to set pricing options for different variables used with a custom content type (called estimates) where the form settings are used having been passed in from drupalSettings and are used in a js file containing several custom Drupal.behaviors to calculate pricing interactively when creating a new estimate.

This all works 100% beautifully.

The problem (which isn't a huge problem) that I'm facing, is I've started going back through things cleaning up code and in a couple cases I have changed the names of several of the custom admin form fields. This appears to be causing the old named form fields with their set value to remain in drupalSettings in addition to the new form fields (modified fields) and their values.

Upon viewing the config form where I can change the form field values to update the form settings the old form fields aren't there (which they shouldn't be) so why are they still present in drupalSettings? I would have assumed they would be removed from drupalSettings once the form is resaved with any updated values, yet they are not...they remain!

I've cleared all caches in a browser on the site, and I've used drush cashe:rebuild several times which doesn't have any affect.

So I'm fairly certain I'm missing something probably in modules config form, but haven't been able to find any specific documentation regarding removal of "no-longer in existence" form field settings from drupalSettings. I've found how to override but not remove...

Here is the a snippet of the submit form function:

```
 public function submitForm(array &$form, FormStateInterface $form_state) {
        parent::submitForm($form, $form_state);
        $this->config('newlooks.pricesettings')
          ->set('estimate_gutter_install_base_price', $form_state->getValue('estimate_gutter_install_base_price'))

// a lot more of ->set()'s for form fields

          ->save();
 }

```

Thinking about it now a little more - Do I need some kind of rebuild form within the submit? Or something in the buildForm function to get drupalSettings or Drupal to remove the fields and data no-longer present in buildForm or submit functions?

Here is a snip of the buildForm function as well:

```
 public function buildForm(array $form, FormStateInterface $form_state) {
        $config = $this->config('newlooks.pricesettings');

        // Lots and lots of $form[estimate_something_base_price] = []
        // fields to display...

        return parent::buildForm($form, $form_state);
 }

```

I'm also trying to avoid dumping it directly from the DB which would be a quick fix (and not overly difficult) but really wouldn't solve this issue in the future as I will probably make more changes to the form over time.

Oh, and I'm currently working with Drupal 9.4.8

Thank You!

Update Edit:

using:

```
function newlooks_update_9101() {
  \Drupal::configFactory()->getEditable('newlooks.settings')->clear('estimate_gutter_cover_size_five');
}

```
* did not clear the key in question

tried:

```
function newlooks_update_9102() {
  \Drupal::configFactory()->getEditable('newlooks.settings')->delete('estimate_gutter_cover_size_five');
}

```
* and it deleted all the settings not the keyed one

This for my particular use case is not ideal having to run an update hook each time a configuration/settings form is edited. Seeing that if I add new form elements to the buildForm function and they become available instantly there has to be a better method.

I feel this over time could lead to a huge .module file with endless update hooks (as your not supposed to remove them once added).

Don't get me wrong hook\_update\_N() will work it just seams drastic.

Is there not some way to rebuild the settings or purge settings in another manor where I could actually use the existing form key:values to check against removing key:value pairs that no-longer exist?

I really feel there should be something that can handle that, another hook perhaps that runs anytime cache is cleared (just shooting in the dark on that) but something!

I definitely thank you Jaypan, I will need to use hook\_update\_N() else where at some point - it's just if I can avoid it in this use case it would be ideal.

Update Edit: I'll try to add a little clarity!

So in my buildForm function for example I started with this:

```
$form['estimate_gutter_cover_size_five'] = [
            '#type' => 'number',
            '#group' => 'cover_sizes',
            '#step' => '.01',
            '#prefix' => '<div class="gutters gtcovers gtcovers-size estimate-form-item">',
            '#title' => $this->t('5 inch Covers'),
            '#description' => $this->t('This is the base price for a standard gutter cover size <em>and is multiplied by quantity in feet for a total cost.</em>'),
            '#min' => '0.00',
            '#max' => '999.99',
            '#placeholder' => '0.00',
            '#default_value' => $config->get('estimate_gutter_cover_size_five_base_price'),
            '#suffix' => '</div>',
            '#required' => TRUE,
        ];

```

But later I went back and changed that to:

```
$form['estimate_gutter_cover_size_five_base_price'] = [
            '#type' => 'number',
            '#group' => 'cover_sizes',
            '#step' => '.01',
            '#prefix' => '<div class="gutters gtcovers gtcovers-size estimate-form-item">',
            '#title' => $this->t('5 inch Covers'),
            '#description' => $this->t('This is the base price for a standard gutter cover size <em>and is multiplied by quantity in feet for a total cost.</em>'),
            '#min' => '0.00',
            '#max' => '999.99',
            '#placeholder' => '0.00',
            '#default_value' => $config->get('estimate_gutter_cover_size_five_base_price'),
            '#suffix' => '</div>',
            '#required' => TRUE,
        ];

```

I open the form in a web browser and replace the placeholder with a value as it is now seen as a new element. Does exactly what I want aside from leaving garbage in the settings that aren't readily visible. Only reason I noticed it was I wanted to check variables on page load so in my js file I added: `console.log(window);`

While inspecting them via browser console I saw drupalSettings and figured what the heck I'll take a peak.

Upon viewing I saw both:

* estimate\_gutter\_cover\_size\_five: "2.37"
* estimate\_gutter\_cover\_size\_five\_base\_price: "2.37"

Having changed estimate\_gutter\_cover\_size\_five to estimate\_gutter\_cover\_size\_five\_base\_price I would have expected that estimate\_gutter\_cover\_size\_five would have been removed but was not. Considering I had to open the form for settings in a browser and set/add the new/changed elements value (where the old element and value is no longer displayed, in my mind it was "should be" gone).

Now that is just one element/field on a form with probably about 70 now and it will be growing and changing as I build everything moving forward.

That in combination with the fact I do a lot of quick testing sometimes/many times not properly naming things in reference to everything else it is or needs to be associated with, using hook\_update\_N() isn't going to be very helpful.

# Answer
> 1 votes
Configuration snapshots are stored in cache, and therefore are cleared with a cache clear, but the base value is still part of the system's active configuration, and will be part of the rebuilt configuration snapshot. This is why clearing the cache isn't removing your configuration.

The way to deal fix your issue is to implement hook\_update\_N(), and either remove unused keys from the configuration, or if the entire configuration object needs removal, delete it.

```
function HOOK_update_N() {
  // Delete a key from a configuration object. For example, to
  // delete example_module.settings.some_key:
  \Drupal::configFactory()->getEditable('example_module.settings')->clear('some_key');

  // Or, you can delete an entire config object, if none of the keys
  // are necessary any longer. For example, to delete example_module.settings:
  \Drupal::configFactory()->getEditable('example_module.settings')->delete();
}

```

# Answer
> 0 votes
Instead of setting single values you could set the entire array:

```
public function submitForm(array &$form, FormStateInterface $form_state) {
  $data = [];
  $data['estimate_gutter_install_base_price'] = $form_state->getValue('estimate_gutter_install_base_price');

  // add more values

  $this->config('newlooks.pricesettings')
    ->setData($data)
    ->save();

  parent::submitForm($form, $form_state);
}

```

Or you can even try to use the form values structure if you have defined the form build accordingly:

```
public function submitForm(array &$form, FormStateInterface $form_state) {
    // Get all values.
    $values = $form_state->getValues();

    // Remove Form API values.
    unset(
      $values['form_build_id'],
      $values['form_token'],
      $values['form_id'],
      $values['op'],
      $values['actions']
    );

    // Save config.
    $this->config('webform_example_custom_form.settings')
      ->setData($values)
      ->save();

    // Display message.
    parent::submitForm($form, $form_state);
  }

}

```

Found this in the great Webform module.

---
Tags: forms
---


# Question
Title: Test if template files (.tpl.php) are used by theme
I've inherited a custom Drupal 7 theme with many template files. I'm sure lots of them aren't actually used by the website, and were part of the testing process.

Is there a method to list which .tpl.php files are being used in the website, or for a particular page?

# Answer
Just print the theme hook suggestion variable in any preprocess function in template.php

```
print_r($variables['theme_hook_suggestions']);

```

If you use the Devel module then

```
dpm($variables['theme_hook_suggestions']);

```
> 1 votes

# Answer
I don't know if its 'right' because I'm new to Drupal, but I also inherited a Drupal site and I had the same problem. I'm using custom Google Analytics events to track what URLs load certain things. For example, every time a view is loaded it fires a custom GA event with the view's machine name and URL. A few weeks later I can see exactly what views are used and where.
> 0 votes

---
Tags: theming
---


title: How to show the slogan in Olivero?

text:
# Question
Title: How to show the slogan in Olivero?
I have added a slogan in Olivero but it doesn't appear.

Only the (textual) web site **name** appears.

I went to edit the Site Branding block and under "Toggle branding elements" I have all three elements check-marked (Logo, Site Name and Site Slogan).

Maybe Olivero just don't support slogans, if so, what can be do about that?

# Answer
> 1 votes
This is an open bug in Drupal. Use a patch from the issue: https://www.drupal.org/project/drupal/issues/3188136

---
Tags: 9
---


title: How to hide the comment subject field?

text:
# Question
Title: How to hide the comment subject field?
In Drupal 7, there used to be a checkbox: "Allow comment title". Unchecking that, and there was no comment title.

I am unable to locate a similar setting in Drupal 9.

I've found: How to remove or hide the Subject field for comments?

It explains how to auto-generate the subject field for a comment. This is *not* what I am asking. I don't want to *display* any subject field when showing a comment. If you're familiar with how comments work in issues posted on Drupal.org, that is the solution I am looking for.

**Edit**: In comments, it is suggested that you can do this by navigating to the "Manage display" tab for the comment type. However, this is a screen dump (Drupal 9.4.8) of that tab for the default comment type:

I see no *obvious* way to set the title not to be shown.

# Answer
> 3 votes
A solution is to copy core's comment.html.twig and put it in your theme's /templates folder and remove the `<h3{{ title_attributes }}>{{ title }}</h3>` line.

# Answer
> 3 votes
If one installs the contributed extension named **Manage display** the "Subject" field becomes exposed under the "Manage display" tab for a comment. You can then move it to the "Disabled" section to hide it.

---
Tags: 9, comments
---


# Question
Title: How to prevent search engines from indexing all nodes of a certain content type?
How to prevent search engines from indexing all nodes of a certain content type?

The nodes of this certain content type **should be published**, but just not indexed by search engines.

Since content types don't allow a specific URL structure, I can't use robots.txt for that sake.

# Answer
> 4 votes
> Since content types don't allow a specific URL structure

Each content (node) of any type allows to configure an URL alias. The URL alias may include sub paths. If an URL alias has been configured, Drupal will redirect the generic `node/*` URLs to the configured alias. So you can actually use a `robots.txt` file to exclude certain paths from crawling.

Using the pathauto module, you can even generate those human-readable and search engine friendly URL aliases automatically. It allows you to define different patterns for different content types. This way, all your "hidden" content could automatically be placed on a certain URI path.

***Other approaches:***

In general, a search engine will index all pages found on your site, if not told otherwise. Most major search engines as Google, Bing, Yahoo or Yandex will obey the `noindex` directive. As of writing, of all top 5 search engines used worldwide, only the Chinese Baidu search engine still ignores `noindex` and requires a `robots.txt` with `Disallow` directive instead.

`noindex` can be given

* in a HTTP response header `X-Robots-Tag: noindex`
* or as meta tag `<meta name="robots" content="noindex">`.

*Meta tags:*

To configure an according meta tag, you can use the metatag module which allows you to define meta tag presets per content type. (Whether for your use case or in general, I highly recommend using the metatag module for any of your Drupal sites that are publicly accessible and should be optimized for search engines or content sharing.)

*Response headers:*

If you (additionally?) want to go the response header way, you could create a custom module (e.g., `my_noindex_module`) with a response event subscriber and add the header whenever a response with a node of your type is delivered:

*src/EventSubscriber/MyNoindexResponseSubscriber.php*:

```
<?php

namespace Drupal\my_noindex_module\EventSubscriber;

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\node\NodeInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Response subscriber to add noindex HTTP headers to responses.
 *
 * Adds the noindex header to responses that were created for routes with
 * a `'my_noindex_type'` node as parameter.
 */
class MyNoindexResponseSubscriber implements EventSubscriberInterface {

  /**
   * The current route match service.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * Constructs a new noindex response subscriber.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The current route match service.
   */
  public function __construct(RouteMatchInterface $route_match) {
    $this->routeMatch = $route_match;
  }

  /**
   * Sets extra HTTP headers for custom node type.
   */
  public function onRespose(FilterResponseEvent $event) {
    if (!$event->isMasterRequest()) {
      return;
    }

    // Get node from route parameters.
    $node = $this->routeMatch->getParameter('node');
    // Whether we have no node or the node type doesn't
    // match our `'my_noindex_type'` type.
    // You may have to adjust the node type here.
    if (
      !$node instanceof NodeInterface
      || $node->getType() !== 'my_noindex_type'
    ) {
      return;
    }

    $response = $event->getResponse();
    $response->headers->set('X-Robots-Tag', 'noindex');
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = ['onResponse', -100];
    return $events;
  }

}

```

*services.yml*:

```
services:
  my_noindex_module.noindex_response_subscriber:
    class: 'Drupal\my_noindex_module\EventSubscriber\MyNoindexResponseSubscriber'
    arguments: ['@current_route_match']
    tags:
     - { name: event_subscriber }

```

---
Tags: nodes
---


# Question
Title: How to embed content from one place inside two or more nodes?
There is some content (a list of data) which I need to embed/call *inside the main content area* of two or more nodes.

Calling data from location A inside location B and C or more.

Something similar to an "include" in PHP.

So, if any change is needed to be done to the embedded content, it would be done in one place only and effect all places in which it is embedded.

The content I need to embed would be in the same website (in the same database).

I don't mind where to **put/store** the content I embed --- it can be in another node or in a view or in a block (or in any other content-structure available in Drupal that would be good for the cause).

It doesn't matter to me how to do the embedding (I would even use `<iframe>` if I must), but, I would prefer not to install a module if I can.

How would you suggest to do that in Drupal?

# Answer
> 0 votes
If you want to do a custom design for specific nodes, use Layout Builder. You can create an override for each node that you want to have a unique design and then set the blocks however you like.

Layout Builder is included in Drupal as standard and is fully supported by the core team, so it is the recommended approach for doing basic custom designs.

# Answer
> 0 votes
You can put a list in a block. If there is more than one list, you can create multiple blocks.

Then Entity Embed will let you embed the blocks wherever you want using CKEditor.

# Answer
> -1 votes
Adding on Patrick Kenny's great (and conventional) answer, another way I have found to do it is to create a content type that doesn't have any fields and which its nodes are comprised of blocks.

1. Create a content type and name it as, for example, "No fields content type".
2. Create a node of that content type.
3. Create new custom blocks and then add these blocks in the desired order and limit them to appear in each node of that content type as you wish

This method is generally inefficient and should not be used for more than 1-5 nodes because it can cause extremely long and possibly duplicated and confusing block lists.

---
Tags: 9
---


# Question
Title: How do I add a node ID as class to the <body> tag?
In Drupal 7, there is a class like path-node-NID (with NID replaced by the node ID of the node being viewed) added to the `<body>` tag so we can easily add CSS styles to specific nodes. This is missing in Drupal 8.

How can I add the node ID as CSS class to the `<body>` tag?

# Answer
> 15 votes
In **mytheme.theme** file: add the below code.

```
function MYTHEME_preprocess_html(&$variables) {
  // Add node ID to the body class.
  $node = \Drupal::routeMatch()->getParameter('node');
  if (is_object($node)) {
    $variables['attributes']['class'][] = 'node-' . $node->id();
  }
}

```

This will add "node-{{nid}}" class in body tag.

**Another Option**

You can try Node Class module as well.

> Node Class is a simple module that allows users to add custom CSS classes to any node through the node/add interface.

# Answer
> 0 votes
Further to the comment made by @hockey2112, the accepted answer throws an error when viewing revisions. The code below is more reliable.

In mytheme.theme file: add the below code.

```
function mytheme_preprocess_html(&$variables) {
   // Add node id to the body class.
   $node = \Drupal::routeMatch()->getParameter('node');
   if(is_object($node)) {
     $variables['attributes']['class'][] = 'node-' . $node->id();
   }
}

```

# Answer
> 0 votes
For those you might still be looking for this on Drupal 9, you may check out this module: https://www.drupal.org/project/body\_node\_id\_class

---
Tags: theming, 8
---


# Question
Title: Show node IDs along with titles in Entity reference Autocomplete list
I'll like to add this functionality to the autocomplete widget in Entityreference field to show node ID next to the titles in the dropdown list. The reason behind the idea is to differentiate between multiple nodes with same title.

Example:

* This is a title (3)
* This is a title (2)
* This is a title (1)

I know the node ID is shown once a selection is made but I like to show it in the dropdown list in order to pick the right node quickly based on the node ID.

# Answer
> 22 votes
Install the Views and Entity Reference modules, create a new View and Add a Entity Reference Display:

Then Add in the fields the content title and the nid, click in the nid and check Exclude from display, Save and click in the title and go to rewrite the output of the title as `[title] - ([nid])`

Go to edit the settings of the format and check the title, this will allow you to search by title.

Save the view.

Go to edit your Entity Reference field and select in the Mode Views: .... (like the following image) and select your View (in this case the name is: articles\_with\_id) and save the settings:

Then go to see the result:

**EDIT:** This is now working in Drupal 8, at least in the version 8.3.4.

# Answer
> 5 votes
Create Entity Reference field with the default configuration

The function entityreference\_autocomplete\_callback\_get\_matches determines what the output of the autocomplete should be.

```
function entityreference_autocomplete_callback_get_matches($type, $field, $instance, $entity_type, $entity_id = '', $string = '') {
  $matches = array();

  $entity = NULL;
  if ($entity_id !== 'NULL') {
    $entity = entity_load_single($entity_type, $entity_id);
    $has_view_access = (entity_access('view', $entity_type, $entity) !== FALSE);
    $has_update_access = (entity_access('update', $entity_type, $entity) !== FALSE);
    if (!$entity || !($has_view_access || $has_update_access)) {
      return MENU_ACCESS_DENIED;
    }
  }

  $handler = entityreference_get_selection_handler($field, $instance, $entity_type, $entity);

  if ($type == 'tags') {
    // The user enters a comma-separated list of tags. We only autocomplete the last tag.
    $tags_typed = drupal_explode_tags($string);
    $tag_last = drupal_strtolower(array_pop($tags_typed));
    if (!empty($tag_last)) {
      $prefix = count($tags_typed) ? implode(', ', $tags_typed) . ', ' : '';
    }
  }
  else {
    // The user enters a single tag.
    $prefix = '';
    $tag_last = $string;
  }

  if (isset($tag_last)) {
    // Get an array of matching entities.
    $entity_labels = $handler->getReferencableEntities($tag_last, $instance['widget']['settings']['match_operator'], 10);

    // Loop through the products and convert them into autocomplete output.
    foreach ($entity_labels as $values) {
      foreach ($values as $entity_id => $label) {
        $key = "$label ($entity_id)";
        // Strip things like starting/trailing white spaces, line breaks and tags.
        $key = preg_replace('/\s\s+/', ' ', str_replace("\n", '', trim(decode_entities(strip_tags($key)))));
        // Names containing commas or quotes must be wrapped in quotes.
        if (strpos($key, ',') !== FALSE || strpos($key, '"') !== FALSE) {
          $key = '"' . str_replace('"', '""', $key) . '"';
        }
        /* *** */$matches[$prefix . $key] = '<div class="reference-autocomplete">' . $label .' - ('. $entity_id . ')</div>';//****
      }
    }
  }
  drupal_json_output($matches);
}

```

the last line `$matches[$prefix . $key] = '<div class="reference-autocomplete">'` determines the output and the `$entity_id` is available which is the ID. You can do what I did in that line (shown by `**`), simply write:

```
 $matches[$prefix . $key] = '<div class="reference-autocomplete">' . $label .' - ('. $entity_id . ')</div>';

```

you can use `$entity_id` to fetch other fields and anything you want.

# One More Thing!

Some times it is not a good idea to change the function of the core module (if it is not important to you the above solution is enough).

If you need to override the core function of the `entity_reference` module, build a small module and name it `elabel`

it is `elabel.info`

```
;$Id;
name = My Entity Reference Label
description = This module creates special Entity Reference Label
package = My Modules
core = 7.x
php = 5.1
files[] = elabel.module

```

and it is `elabel.module`

```
<?php function elabel_menu_alter(&$items){
    unset($items['entityreference/autocomplete/single/%/%/%']);
    unset($items['entityreference/autocomplete/tags/%/%/%']);

      $items['entityreference/autocomplete/single/%/%/%'] = array(
    'title' => 'Entity Reference Autocomplete',
    'page callback' => 'elabel_autocomplete_callback',
    'page arguments' => array(2, 3, 4, 5),
    'access callback' => 'entityreference_autocomplete_access_callback',
    'access arguments' => array(2, 3, 4, 5),
    'type' => MENU_CALLBACK,
  );

    $items['entityreference/autocomplete/tags/%/%/%'] = array(
    'title' => 'Entity Reference Autocomplete',
    'page callback' => 'elabel_autocomplete_callback',
    'page arguments' => array(2, 3, 4, 5),
    'access callback' => 'entityreference_autocomplete_access_callback',
    'access arguments' => array(2, 3, 4, 5),
    'type' => MENU_CALLBACK,
  );
  return $items;

}

function elabel_autocomplete_callback($type, $field_name, $entity_type, $bundle_name, $entity_id = '', $string = '') {
  // If the request has a '/' in the search text, then the menu system will have
  // split it into multiple arguments and $string will only be a partial. We want
  //  to make sure we recover the intended $string.
  $args = func_get_args();
  // Shift off the $type, $field_name, $entity_type, $bundle_name, and $entity_id args.
  array_shift($args);
  array_shift($args);
  array_shift($args);
  array_shift($args);
  array_shift($args);
  $string = implode('/', $args);

  $field = field_info_field($field_name);
  $instance = field_info_instance($entity_type, $field_name, $bundle_name);

  return elabel_autocomplete_callback_get_matches($type, $field, $instance, $entity_type, $entity_id, $string);
}

function elabel_autocomplete_callback_get_matches($type, $field, $instance, $entity_type, $entity_id = '', $string = '') {
  $matches = array();

  $entity = NULL;
  if ($entity_id !== 'NULL') {
    $entity = entity_load_single($entity_type, $entity_id);
    $has_view_access = (entity_access('view', $entity_type, $entity) !== FALSE);
    $has_update_access = (entity_access('update', $entity_type, $entity) !== FALSE);
    if (!$entity || !($has_view_access || $has_update_access)) {
      return MENU_ACCESS_DENIED;
    }
  }

  $handler = entityreference_get_selection_handler($field, $instance, $entity_type, $entity);

  if ($type == 'tags') {
    // The user enters a comma-separated list of tags. We only autocomplete the last tag.
    $tags_typed = drupal_explode_tags($string);
    $tag_last = drupal_strtolower(array_pop($tags_typed));
    if (!empty($tag_last)) {
      $prefix = count($tags_typed) ? implode(', ', $tags_typed) . ', ' : '';
    }
  }
  else {
    // The user enters a single tag.
    $prefix = '';
    $tag_last = $string;
  }

  if (isset($tag_last)) {
    // Get an array of matching entities.
    $entity_labels = $handler->getReferencableEntities($tag_last, $instance['widget']['settings']['match_operator'], 10);

    // Loop through the products and convert them into autocomplete output.
    foreach ($entity_labels as $values) {
      foreach ($values as $entity_id => $label) {
        $key = "$label ($entity_id)";
        // Strip things like starting/trailing white spaces, line breaks and tags.
        $key = preg_replace('/\s\s+/', ' ', str_replace("\n", '', trim(decode_entities(strip_tags($key)))));
        // Names containing commas or quotes must be wrapped in quotes.
        if (strpos($key, ',') !== FALSE || strpos($key, '"') !== FALSE) {
          $key = '"' . str_replace('"', '""', $key) . '"';
        }
        /* *** */ $matches[$prefix . $key] = '<div class="reference-autocomplete">' . $label .'('.$entity_id.')' .'</div>';
      }
    }
  }

  drupal_json_output($matches);
}

```

**I tried this code and it works perfectly If there are other type of entity references and you don't need to do this for them, simply add an `IF` statement and check for bundle or content type.**

# Answer
> 1 votes
```
(function ($, Drupal, drupalSettings) {
  'use strict';

  Drupal.behaviors.my_module = {
    attach: function (context) {

      function autocomplete_tid_remove(field) {

        var autocomplete_tid = $(field).val();
        var autocomplete_tid_stripped = autocomplete_tid.replace(/(\([^*]+\))(?=.*\1)/,'');
        $(field).val(autocomplete_tid_stripped);

      }

      jQuery('.form-autocomplete').on('click', function () {
        window.currentElement = jQuery(this);
      });

      jQuery('.form-autocomplete', context).once('my_module').on('autocompleteclose', function () {
        autocomplete_tid_remove(currentElement);
      });
    }
  };

})(jQuery, Drupal, drupalSettings);

```

@Adrian Cid Almaguer answer is great! But shows nid twice as mentioned by @yuri. I was able to overcome this using js.

---
Tags: 7, views, nodes, entities, ajax
---


# Question
Title: How can I make the relation I am using in a view work again?
I'm currently migrating from Drupal 7 to Drupal 9, and i'm rebuilding all views (as I can't find a good migration procedure for views from 7 to 9), also trying to understand the changes (this is a side project for a friend, i'm not an expert in Drupal). I'm having difficulties with something I have running on 7. This is the situation on 7:

* I have a content type named "club" for sports clubs. Amongst other fields, it has the logo
* I have a content type named "club events". It includes a "club" field wich is an Entity Reference to said field.
* I have a view for displaying the events with the name and logo of the club. For the logo I created a relation in the view, to pick the image of the logo.

The results are as expected:

After migrating the installation to Drupal 9, all content is there, all clubs have their logo, and all fields are ok. So I try to rebuild the view, but I can't make the relation to work. Here is the config of the relation in 9.4

And the view configuration in 9.4 with said relation for the image

But the results don't show the image. If I set the "Behavior when no results" text to something, that text gets displayed, so it is not getting results out of the relation.

I'm stuck. I've been trying some options, but I can't find what I'm doing wrong. Anyone has any hint?

# Answer
I'll post the solution, just in case someone else has the same problem. I was making the relation wrong, it seems. When selecting the field, you have to check on "Content referenced from -the content type-". I was using another one :(
> 1 votes

---
Tags: views, 9
---


title: How to check for differences in config

text:
# Question
Title: How to check for differences in config
Is there any way to check for differences with config in Drush 8?

I checked the list of drush 8 config commands and I couldn't find anything.

The reason I need this is that I have a site that runs behat tests via CircleCI, and sometimes I need to import the configuration more than once. So, I wanted to write a bash script that uses Drush to check whether there are any configuration differences, and if so, automatically re-imports the config in a loop until there are no more differences.

I'm stuck on Drush 8 because the behat extension only supports Drush 8.

# Answer
`drush cim --diff`

Since drush 9 there is a `diff` option that gives a diff on the config in code vs config in database

`drush cex --diff`

reverses the order of diff
> 6 votes

# Answer
The Drush 8 commands `config:export` (cex) and `config:import` (cim) accept a `--no` to prevent the actual import or export.

This allows you to write an `if` statement in Bash. Here is an example:

```
if drush config:import --no | grep file.settings; then
  # Do something
  echo "Found in diff";
fi

```

---

In Drush 9 and 10, the return value `$?` will tell you if there are differences between the database and the directory containing YAML files:

* 0 means no differences
* 1 means differences

Drush 9 and 10 also accept a parameter `--diff`. If there are differences, Drush will print them.
> 8 votes

# Answer
If you have Drupal console installed, you could try `config:diff`
> 3 votes

---
Tags: drush, configuration
---


# Question
Title: Enable placeholder translation for exposed filters
I'm building a multilingual site using Drupal 8 and I already managed the creation of a search tool using Views and Exposed Filters. My issue is with the translation of this tool: Drupal gives me the option for the translation of most of the elements of the view, but I can't find any options to translate the placeholder used in the exposed filter.

Is there any way to translate placeholders for those filters?

# Answer
> 1 votes
I'll post the solution I worked out just in case someone might need it. Using the `hook_form_alter()` function:

```
/**
 * @param $form
 *   Nested array of form elements that comprise the form.
 */
function YOUR_THEME_form_alter(&$form){
  if($form['#id'] == 'your_form_id'){
    foreach ($form['#info'] as $filter_info) {
      $filter = $filter_info['value'];
      if ($form[$filter]['#type'] == 'field_type' && $filter == 'field_title') {
        $form[$filter]['#attributes']['placeholder'] = t('your_placeholder');
      }
    }
  }
}

```

# Answer
> 0 votes
I found a really interesting way to do this which really doesn't affect core or mess with code. Rather, play with twig files this way:

1. Copy the *input.html.twig* file to your theme
2. Edit that file and include the following lines

```
{% if (attributes.placeholder is defined) %}
  {% set placeholder = attributes.placeholder|render|trans %}
  <input{{ attributes.addClass("form-control")|without('placeholder') }} placeholder="{{ placeholder }}" />{{ children }}
{% else %}
  <input{{ attributes.addClass("form-control")|without('placeholder') }} />{{ children }}
{% endif %}

```
3. Clear the cache
4. Open the translated page so that Drupal picks up that new string to translate
5. Head over to your translation UI (admin/config/regional/translate)

If you are fortunate, your placeholder text will now be available to translate.

# Answer
> 0 votes
Just a note that you must visit the page in the translated language. If you never visit the page, the string will not be generated and not be available as an option in admin/config/regional/translate.

---
Tags: views
---


# Question
Title: How to read JSON data from external URL and display it in a node
I want to read json data from external url and display those data in a node. After that I would like to add filters in the result using views. I have created a view using external url(query settings) and display result in a block.. But I cant add filters for that. How to add Filters for that data.. I am new to this.. Please help me..

# Answer
If the data does not have to be live and can be fetched / updated every x number of minutes, then I suggest you create a task with scheduler which loads the remote data into a local database table at a specified interval (`drupal_json_decode` can help converting the JSON string into an array that can be inserted in the database). After you do that you would be able to adopt that table into Drupal & Views using the Data module. This would make the data available as a view with sort handlers and filters, like any other view. Otherwise, to handle live data I would suggest integrating Angular JS to retrieve the remote JSON and to filter the results. NgApp module can help you in this regard.
> 0 votes

# Answer
There could be options like Web Service Data and External Entities.
> 0 votes

---
Tags: nodes, uri
---


# Question
Title: How can I control node access based on entity reference to multiple users
I have multiple uses for this functionality now but mainly for a private message system.

What I want to do:

* Configure a content type with an entity reference to users
* Create nodes of that type and select multiple users using the entity reference field
* Limit visibility of each node of that type to the users selected in that field

I believe there was a module for this in D7, though I can't find it now. But I've had no success finding one for D9.

Is there a module or set of modules anyone is aware of that could provide this kind of access control?

If a module was to be built, any suggestions for best way to approach it? (Is it a really bad idea to put some conditional logic in a template... "if logged in uid = one of values in field x, print, otherwise don't" ? (I don't know the twig syntax for that))

(Since I mentioned private messages, I'm aware of the D9 PM module. But for a lot of reasons, I'd rather just use nodes and comments system. The node+comment system is already well developed and the only thing missing really is multiple-user visibility control.)

# Answer
Yes, it's a bad idea to do this in templates as their output will be cached by default.

If it's just for viewing the full node via its canonical URL (`/node/123` or `/my-node-alias`) you can achieve that easily by implementing `hook_ENTITY_TYPE_access` in a custom module.

```
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;

/**
 * Implements hook_ENTITY_TYPE_access().
 */
function MYMODULE_node_access(EntityInterface $entity, $operation, AccountInterface $account) {

  // Check node type and operation.
  if ($entity->bundle() === 'article' && $operation === 'view') {

    $uids = [];
    // Get the allowed users.
    if ($users = $entity->get('field_users')->getValue()) {
      $uids = array_column($users, 'target_id', 'target_id');
    }
    // Add the node author.
    $uids[$entity->getOwnerId()] = $entity->getOwnerId();

    // Return "forbidden" if current user is not in that list.
    return AccessResult::forbiddenIf(!isset($uids[$account->id()]))
      ->cachePerUser()
      ->addCacheableDependency($entity);
  }

  // No opinion.
  return AccessResult::neutral();
}

```

But note that this hook is **not called from Views** or entity queries for performance reasons and for proper functioning of the pager system. For that you need to implement a different access strategy, see \[Drupal API\] Node access rights and \[Question\] Views Search Ignoring Custom Node Access permissions.

Note also that this hook is bypassed for user 1 (if you during development wonder why breakpoints/`dump()` are ignored).
> 2 votes

# Answer
I added condition to give the node author access also, without including the author in the entity reference field:

```
<?php
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;

/**
 * Implements hook_ENTITY_TYPE_access().
 */
function MYMODULENAME_node_access(EntityInterface $entity, $operation, AccountInterface $account) {
  if ($entity->bundle() === 'pm' && $operation === 'view') {
    if ($users = $entity->get('MYFIELDNAME')->getValue()) {
      $uids = array_column($users, 'target_id', 'target_id');
      $author_id = $entity->getOwnerID();
      if (isset($uids[$account->id()]) || $author_id == $account->id()) {
        return AccessResult::neutral();
      }
    }
 return AccessResult::forbidden();
  }
}

```
> 0 votes

---
Tags: nodes, 9, security
---


# Question
Title: Webform javascript CSS selectors with table
I'm currently trying to add javascript via the settings tab for a webform that is supposed to dynamically update the displayed totals at the bottom of the webform page for the user.

A part of this involves me targeting a custom webform composite I created myself for this webform so I can hook onto an event that runs every time a value within this composite element changes.

The composite element looks like this:

Here's the JavaScript I have for selecting the product select element, summarized:

```
jQuery('table[data-drupal-selector|="edit-product-list-items"]').on('change', 'select.form-select[required]', updateValues);

function updateValues(event){
//perform updates here
}

```

As it is, The event is called whenever a value changes as long as the user just fills in the fields in the currently displayed table rows and nothing else. However, once they add a new item to the table, this event no longer gets called.

I've tried using the data-drupal-selector and ID attributes, but both give the same outcome. Not to mention, every time a row is added to the composite table, the ID of the table has a random string appended onto it.

Is there a better way to select the elements in this table so that my function runs consistently?

# Answer
> 3 votes
My heart is bleeding each time a developer starts working with Drupal and adds code to a Drupal site that doesn't take advantage of its features.

When using JavaScript with Drupal, please ALWAYS familiarize yourself with the concept of libraries (to manage JavaScript dependencies and inclusion to your site), as well as the relatively simple but powerful Drupal JavaScript behaviors (and while you're at it, the once feature, as you'll very often use it as well).

In brief, a Drupal JavaScript behavior is a JavaScript object provided by your module or theme JavaScript that features an `attach` and/or a `detach` method. Attach is called whenever a page load completed. That is the initial page load, as well as after dynamically loading page content using AJAX requests. It receives a context parameter that holds the wrapper DOM element of the changed part.

That said, your JavaScript didn't fire for dynamically added content, because you didn't use Drupal behaviors and thus the change event handler won't be bound to dynamically added page content.

The "workaround" you posted in your own answer on the other hand will cause the `updateValues` callback to fire on every change of a select element of your site. Regardless of whether it's part of your webform or not.

A solution that works better and conforms with the Drupal JavaScript API (for simplicity of code, I kept your jQuery dependency):

*js/my-update-values.js:*

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

  'use strict';

  Drupal.behaviors.myUpdateValues = {
    attach: function (context) {
      // Apply once to all required select elements within the
      // current context.
      once('myUpdateValues', 'select.form-select[required]', context)).forEach(function (element) {
        var $element = $(element);
        // Ensure the select element is part of the custom webform.
        // A CSS class selector would be better here.
        if ($element.closest('table[data-drupal-selector|="edit-product-list-items"]').length === 0) {
          return;
        }
        // Bind the change handler.
        $element.on('change.myUpdateValues', updateValues);
      });
    },
    detach: function (context) {
      // Process all required select elements of the detaching context
      // that where previously processed by our attach function, and
      // unbind the change handler.
      $(once.remove('myUpdateValues', 'select.form-select[required]', context)).off('change.myUpdateValues');
    }
  };

  function updateValues(event) {
    // Your code here.
  }

}(Drupal, jQuery, once));

```

This example depends on the Drupal 9.2+, jQuery and Drupal once libraries. So your library definition may look as such:

*libraries.yml:*

```
myUpdateValues:
  js:
    js/my-update-values.js: {}
  dependencies:
    - core/drupal
    - core/jquery
    - core/once

```

On older versions of Drupal, you may have to use `jquery.once` instead.

# Answer
> -2 votes
I found a solution: using bubbling to attach the event to something other than the table stops the listeners from being removed every time a new row is added.

```
jQuery('body').on('change', 'select.form-select[required]', updateValues);

```

---
Tags: javascript, webforms
---


# Question
Title: I'm not quite sure what this error is but it's breaking my site
Can anyone help me in discovering what is wrong and what needs to be fixed? I did a bunch of updates and now certain portions of my site don't work. I get the following error:

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

InvalidArgumentException: $string ("") must be a string. in Drupal\Core\StringTranslation\TranslatableMarkup->__construct() (line 132 of core/lib/Drupal/Core/StringTranslation/TranslatableMarkup.php).

t() (Line: 81)
Drupal\date_range_formatter\Plugin\Field\FieldFormatter\DateRangeFormatterRangeFormatter->viewElements() (Line: 89)
Drupal\Core\Field\FormatterBase->view() (Line: 263)
Drupal\Core\Entity\Entity\EntityViewDisplay->buildMultiple() (Line: 340)
Drupal\Core\Entity\EntityViewBuilder->buildComponents() (Line: 282)
Drupal\Core\Entity\EntityViewBuilder->buildMultiple() (Line: 18)
Drupal\paragraphs\ParagraphViewBuilder->buildMultiple() (Line: 239)
Drupal\Core\Entity\EntityViewBuilder->build()
call_user_func_array() (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 772)
Drupal\Core\Render\Renderer->doCallback() (Line: 363)
Drupal\Core\Render\Renderer->doRender() (Line: 201)
Drupal\Core\Render\Renderer->render() (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 67)
__TwigTemplate_1374a0db93cb5ffb66a86c8e82b2cfe483209a1e42126eef3a571177931e1ea8->doDisplay() (Line: 405)
Twig\Template->displayWithErrorHandling() (Line: 378)
Twig\Template->display() (Line: 390)
Twig\Template->render() (Line: 55)
twig_render_template() (Line: 384)
Drupal\Core\Theme\ThemeManager->render() (Line: 422)
Drupal\Core\Render\Renderer->doRender() (Line: 435)
Drupal\Core\Render\Renderer->doRender() (Line: 201)
Drupal\Core\Render\Renderer->render() (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 69)
__TwigTemplate_360f5440ca76b514a17b345e7d36b2699abc51c84808d584bd67804dbd080ed9->block_content() (Line: 182)
Twig\Template->displayBlock() (Line: 57)
__TwigTemplate_360f5440ca76b514a17b345e7d36b2699abc51c84808d584bd67804dbd080ed9->block_paragraph() (Line: 182)
Twig\Template->displayBlock() (Line: 45)
__TwigTemplate_360f5440ca76b514a17b345e7d36b2699abc51c84808d584bd67804dbd080ed9->doDisplay() (Line: 405)
Twig\Template->displayWithErrorHandling() (Line: 378)
Twig\Template->display() (Line: 390)
Twig\Template->render() (Line: 55)
twig_render_template() (Line: 384)
Drupal\Core\Theme\ThemeManager->render() (Line: 422)
Drupal\Core\Render\Renderer->doRender() (Line: 201)
Drupal\Core\Render\Renderer->render() (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 124)
__TwigTemplate_1374a0db93cb5ffb66a86c8e82b2cfe483209a1e42126eef3a571177931e1ea8->doDisplay() (Line: 405)
Twig\Template->displayWithErrorHandling() (Line: 378)
Twig\Template->display() (Line: 390)
Twig\Template->render() (Line: 55)
twig_render_template() (Line: 384)
Drupal\Core\Theme\ThemeManager->render() (Line: 422)
Drupal\Core\Render\Renderer->doRender() (Line: 435)
Drupal\Core\Render\Renderer->doRender() (Line: 201)
Drupal\Core\Render\Renderer->render() (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 110)
__TwigTemplate_34f26291d58dc980f31587baa8f8f2a6c0775ce1b84fbec586439fd99fe6c0eb->doDisplay() (Line: 405)
Twig\Template->displayWithErrorHandling() (Line: 378)
Twig\Template->display() (Line: 390)
Twig\Template->render() (Line: 55)
twig_render_template() (Line: 384)
Drupal\Core\Theme\ThemeManager->render() (Line: 422)
Drupal\Core\Render\Renderer->doRender() (Line: 201)
Drupal\Core\Render\Renderer->render() (Line: 241)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 564)
Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare() (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse() (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray()
call_user_func() (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch() (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 58)
Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 23)
Stack\StackedHttpKernel->handle() (Line: 709)
Drupal\Core\DrupalKernel->handle() (Line: 19)

```

I'm happy to supply whatever info you need, just let me know and I can add more.

# Answer
*Can anyone help me in discovering what is wrong?*

When you look up this part of the stack trace:

```
t() (Line: 81)
Drupal\date_range_formatter\Plugin\Field\FieldFormatter\DateRangeFormatterRangeFormatter->viewElements() (Line: 89)

```

you find the error in these lines of the contrib module Date range formatter:

```
$single_format = $this->getSetting('single');
$elements[$delta] = ['#markup' => \Drupal::service('date.formatter')
  ->format($start_date, 'custom', t($single_format))];

```

The problem is a missing setting `single`, probably a date format string you have to set in the field display settings. If you can't find it in UI then export the config and check the YAML files of the content type where this field is configured.

*... and what needs to be fixed?*

It seems like this is already fixed in the modules issue queue. Try this patch:

```
diff --git a/src/Plugin/Field/FieldFormatter/DateRangeFormatterRangeFormatter.php b/src/Plugin/Field/FieldFormatter/DateRangeFormatterRangeFormatter.php
index 798ce2b..6635ac8 100644
--- a/src/Plugin/Field/FieldFormatter/DateRangeFormatterRangeFormatter.php
+++ b/src/Plugin/Field/FieldFormatter/DateRangeFormatterRangeFormatter.php
@@ -77,7 +77,7 @@ class DateRangeFormatterRangeFormatter extends DateTimeCustomFormatter {
         }
         if (!array_key_exists($delta, $elements)) {
           // No end date provided or end date equals start date use single formatting.
-          $single_format = $this->getSetting('single');
+          $single_format = $this->getSetting('one_day');
           $elements[$delta] = ['#markup' => \Drupal::service('date.formatter')->format($start_date, 'custom', t($single_format))];
         }
       }

```

https://www.drupal.org/project/date\_range\_formatter/issues/3309324#comment-14755079
> 2 votes

---
Tags: 9
---


title: Bootstrap failed

text:
# Question
Title: Bootstrap failed
I have Drupal 8.8.1 and Drush 10.1.1, both installed with Composer.

I'm running the following to update my site DB:

```
$ drush updb

In BootstrapHook.php line 32:

  Bootstrap failed. Run your command with -vvv for more information.

```

As it suggests I run with the `-vvv` flag to get more information:

```
$ drush updb -vvv
Begin redispatch via drush_invoke_process().                                                                               [notice]
Calling proc_open(env COLUMNS=131 /var/www/drupal/drupal-8.8.1/vendor/drush/drush/drush  --root=/var/www/drupal/drupal-8.8.1 --verbose  updatedb 2>&1);

In BootstrapHook.php line 32:

  [Exception]
  Bootstrap failed. Run your command with -vvv for more information.

Exception trace:
  at /var/www/drupal/drupal-8.8.1/vendor/drush/drush/src/Boot/BootstrapHook.php:32
 Drush\Boot\BootstrapHook->initialize() at /var/www/drupal/drupal-8.8.1/vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php:34
 Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher->callInitializeHook() at /var/www/drupal/drupal-8.8.1/vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php:27
 Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher->initialize() at /var/www/drupal/drupal-8.8.1/vendor/consolidation/annotated-command/src/CommandProcessor.php:145
 Consolidation\AnnotatedCommand\CommandProcessor->initializeHook() at /var/www/drupal/drupal-8.8.1/vendor/consolidation/annotated-command/src/AnnotatedCommand.php:289
 Consolidation\AnnotatedCommand\AnnotatedCommand->initialize() at /var/www/drupal/drupal-8.8.1/vendor/symfony/console/Command/Command.php:221
 Symfony\Component\Console\Command\Command->run() at /var/www/drupal/drupal-8.8.1/vendor/symfony/console/Application.php:1000
 Symfony\Component\Console\Application->doRunCommand() at /var/www/drupal/drupal-8.8.1/vendor/symfony/console/Application.php:255
 Symfony\Component\Console\Application->doRun() at /var/www/drupal/drupal-8.8.1/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /var/www/drupal/drupal-8.8.1/vendor/drush/drush/src/Runtime/Runtime.php:118
 Drush\Runtime\Runtime->doRun() at /var/www/drupal/drupal-8.8.1/vendor/drush/drush/src/Runtime/Runtime.php:49
 Drush\Runtime\Runtime->run() at /var/www/drupal/drupal-8.8.1/vendor/drush/drush/drush.php:72
 require() at /var/www/drupal/drupal-8.8.1/vendor/drush/drush/drush:4

$ drush status
 Drupal version : 8.8.1
 Site URI       : http://default
 PHP binary     : /opt/remi/php72/root/usr/bin/php
 PHP config     : /etc/opt/remi/php72/php.ini
 PHP OS         : Linux
 Drush script   : /var/www/drupal/drupal-8.8.1/vendor/drush/drush/drush
 Drush version  : 10.1.1
 Drush temp     : /tmp
 Drush configs  : /var/www/drupal/drupal-8.8.1/vendor/drush/drush/drush.yml
 Drupal root    : /var/www/drupal/drupal-8.8.1
 Site path      : sites/default

```

Can anyone advise on how to resolve this?

# Answer
The clue is in the "status" message, which shows the site path is *sites/default*. In previous versions of Drush, I was able to just change the current directory to the directory containing the settings.php file and Drush would detect the site. Drush 9/10 seems to require I specify it.

Running `drush updb --uri=http:example.com` from the *DRUPAL\_ROOT/web* directory worked perfectly.
> 1 votes

# Answer
Delete drush from vendor directory

Go to DRUPAL\_ROOT:

```
rm -Rf vendor/drush # in case of Linux system

composer install # Will reinstall requisite drush verion from composer.lock file

```

It worked for me as well as building again detects the site\_path to connect database properly

can refer as well Bootstrap failing with Drush 9.1.0
> 1 votes

# Answer
I have the error while deploying to server

```
In BootstrapHook.php line 32:

Bootstrap failed. Run your command with -vvv for more information.

```

After run `drush -vvv` I saw an error connected with wrong credentials to DB.
So it can be caused also by **wrong credentials/.env file.**
> 0 votes

---
Tags: 8, drush
---


# Question
Title: Display local actions only on nodes of given type
I have defined a local action in `my_module.links.action.yml`. I have defined, that it should be displayed on a single route `appears_on: entity.node.canonical`. - And it works fine.

Now I try to achieve, that the local action only will be displayed on nodes of type `page`.

How can I manage this clean within the Drupal API?

# Answer
> 1 votes
You have to block access to the route for other content types

In your `routing.yml`

```
my_module.node_custom_action:
  path: '/node/{node}/custompath'
  defaults:
    _form: '\Drupal\my_module\Form\CustomActionForm'
    _title: 'Do custom stuff'
  options:
    _node_operation_route: TRUE
    parameters:
      node:
        type: entity:node
  requirements:
    _custom_access: '\Drupal\my_module\Form\CustomActionForm::isAllowedAccess'

```

In your Form (or Controller)

```

  public function isAllowedAccess(AccountInterface $account) {
    $bundle = FALSE;
    $route = \Drupal::routeMatch();
    $node = $route->getParameter('node');
    if ($node instanceof NodeInterface) {
      $bundle = $node->bundle();
      if (!$node->access('update', $account)) {
        return AccessResult::neutral();
      }
      return AccessResult::allowedIf($bundle === 'my_content_type');
    }
    return AccessResult::neutral();
  }

```

Source

---
Tags: nodes, actions
---


title: Debugging #AJAX and FormAPI

text:
# Question
Title: Debugging #AJAX and FormAPI
What is the easiest way to view current `$form_state` variables while working with `#ajax`?

Is there a way I can get `dpm()` to update automatically on each AJAX load?

If it matters, I'm testing AJAX on a Node Submit form.

# Answer
Using `dd($form_state);` within the callback function works beautifully.

On linux you can `tail -f /tmp/drupal-debug.txt` to see the `$form_state` in real time. (Or whatever the temp directory for your site is set to, often something like `sites/yoursite.com/files/tmp`.)

Otherwise, you can find drupal-debug.txt in your systems /tmp/ directory. http://ratatosk.net/drupal/tutorials/debugging-drupal.html#dd
> 19 votes

# Answer
The best thing I've found: https://drupal.org/project/devel\_debug\_log

Part of/depends on Devel and uses `ddl` to output anything in kpr fashion at admin/reports/debug.
> 8 votes

# Answer
I was also having problems with finding a good way to debug AJAX with the Form API and found debugging with FirePHP to be the best solution:

http://www.thecarneyeffect.co.uk/how-debug-ajax-drupal-using-firephp
> 2 votes

# Answer
You could also try with something like this, and looking into the response tab on FireBug:

```
function _exit($var) {
  print_r($var);
  exit;
}

```
> 1 votes

# Answer
Chrome developer console can help a lot.

* Open the page where you fire up the ajax call
* Open Chrome developers tools
* Click tab "Network"
* Click the below "preview" tab
* Clean all current records
* Open a page with autocomplete field
* Fire up the ajax (IE: push submit buttom)
* Check output
> 0 votes

---
Tags: forms, ajax, debugging
---


title: How to get route inside RequestEvent

text:
# Question
Title: How to get route inside RequestEvent
I need to redirect all existing links targeting a few hand-picked nodes to an external domain. I created an EventSubscriber listening to RequestEvents

my.services.yml

```
services:
  my.request_subscriber:
    class: Drupal\my\EventSubscriber\EventSubscriber
    arguments: ['@current_route_match', '@redirect.checker']
    tags:
      - { name: event_subscriber }

```

EventSubscriber.php

```
/* trimmed constructor, etc. for simplicity */

  public static function getSubscribedEvents() {
    // This needs to run before Redirect module
    $events[KernelEvents::REQUEST][] = ['onKernelRequestCheckRedirect', 34];
    return $events;
  }
  public function onKernelRequestCheckRedirect(RequestEvent $event) {
    // the follwing lines are taken from redirect module
    // @see https://git.drupalcode.org/project/redirect/-/blob/8.x-1.x/src/EventSubscriber/RedirectRequestSubscriber.php#L111
    $request = clone $event->getRequest();
    if (!$this->checker->canRedirect($request)) {
      return;
    }

    /**
     * No matter which route I visit, the $this->routeMatch->getRouteObject is always null,
     * therefore the following lines also don't work as I hoped
     */
    $routeName = $this->routeMatch->getRouteName(); // returns NULL :(
    $nodeId = $this->routeMatch->getParameter('node'); // returns NULL :(

    if ($routeName !== 'entity.node.canonical' || !in_array($nodeId, [MY_HANDPICKED_NODE_IDS]) ) {
      return;
    }
    else {
       // do $event->setResponse(my TrustedRedirectResponse);
    }
}

```

Why is my route object always NULL? How do I get the routing information in my subscriber?

# Answer
The problem was caused by the priority inside the subscribe function. The redirect module used priority `34` here, but this was not fitting my case. Simply removing/using the default priority in the subscribe function solved the issue.

```
  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = ['onKernelRequestCheckRedirect'];
    return $events;
  }

```

This answer is coming from @4uk4's comment below the original question.
> 2 votes

---
Tags: routes, event-subscribers
---


# Question
Title: How to render the correct variation price in catalogs?
I have a product catalog built using search api, facets, and views like this: https://docs.drupalcommerce.org/commerce2/developer-guide/products/marketing-products/product-catalog-facets. My add to cart form is using the Variation Title widget.

I want to render the product price, and when there's multiple variations I want the price of the variation currently selected to render.

If I add a relationship to the referenced variations and display the price I get from that, prices for all variations are rendered (and not just the price of the variation currently selected in the add to cart dropdown).

If I add a relationship to the default variation, only one price is rendered but it is not updated when another variation is selected in the dropdown.

If I edit the add to cart form itself (Commerce \> Configuration \> Order item types \> Edit Default \> Manage form display) and add the unit price, it's rendered as an editable text field and selecting another variation with a different price doesn't update the price.

Would love some input on this. There's a similar question here, but the suggested answers doesn't work.

# Answer
> 0 votes
"I want to render the product price, and when there's multiple variations I want the price of the variation currently selected to render."

-- please read this ---

http://drupal.org/project/commerce/issues/2930046#comment-12384089

if that does not help then perhaps could get tricky with something like this

http://drupal.org/project/view\_entity\_ref\_field\_formatter

---
Tags: views, commerce
---