# Question
Title: How to translate menu items with migrate?
I'm importing menu items from CSV using `migrate`, `migrate_tools`, `migrate_plus` and `migrate_source_csv`.

This is an example of how I'm doing it for the original language:

```
source:
  plugin: csv
  path: 'private://init/links_gl.csv'
  delimiter: ','
  enclosure: '"'
  header_row_count: 1
  keys:
    - id
  column_names:
    0:
      id: id
    1:
      source_id: source_id
    2:
      parent_id: parent_id
    3:
      menu_name: menu_name
    4:
      weight: weight
    5:
      title: title

  constants:
    path: 'entity:node/'

ids:
  id:
    type: string

process:
  title: title
  menu_name: menu_name
  nid:
    plugin: bbaa_migration_lookup
    migration: init_contents_gl
    source: source_id
  'link/uri':
    plugin: bbaa_concat
    source:
      - constants/path
      - '@nid'
  parent:
    plugin: menu_link_parent
    source:
      - parent_id
      - '@menu_name'
  external:
    plugin: default_value
    default_value: 0
  expanded:
    plugin: default_value
    default_value: 1
  enabled:
    plugin: default_value
    default_value: 1
  langcode:
    plugin: default_value
    default_value: 'gl'
  weight: weight

destination:
  plugin: entity:menu_link_content
  bundle: menu_link_content
  no_stub: true

```

It's working but now I need to import another CSV file with translated menu items.

I created another migration configuration for the translated language and I tried adding this code:

```
  id:
    plugin: migration
    source: id
    migration: init_links_gl
  content_translation_source:
    plugin: default_value
    default_value: 'gl'
  langcode:
    plugin: default_value
    default_value: 'es'

destination:
  plugin: entity:menu_link_content
  translations: true
  no_stub: true

```

But it doesn't work.

How can I translate menu items with migrate?

# Answer
I don't see anything obviously wrong in your code, but it would have been a better idea to post the 2 full examples (and ideally, you should try first a simple example that can be imported without custom plugins)

Note that for the second YML file (the translation) you don't need to import most of the stuff: you basically need to process the `id`, the `parent`, and the `title`, no need for `nid` or `'link/uri'`.

As the documentation for this is scarce, I'm posting a working example (using JSON, not CSV).

YML for the first migration:

```
id: menu
label: JSON feed of menu links
migration_group: menu
source:
  plugin: url
  data_fetcher_plugin: file
  data_parser_plugin: json
  urls:
    - modules/custom/migrate_custom/artifacts/menu_en.json
  item_selector: data
  fields:
    -
      name: mlid
      label: 'Unique Id coming from API'
      selector: id
    -
      name: country_migration_id
      label: 'Unique Country Id coming from API. Used to create the relation with the nodes'
      selector: country_migration_id
    -
      name: name
      label: 'Country name'
      selector: name
    -
      name: parent_id
      label: 'Parent menu link id'
      selector: parent
  constants:
    path: 'entity:node/'
  ids:
    mlid:
      type: string
process:
  menu_name:
    plugin: default_value
    default_value: 'main'
  nid:
    plugin: migration_lookup
    migration:
      - country
    source_ids:
      country:
        - country_migration_id
  title:
    plugin: get
    source: name
    language: 'en'
  'link/uri':
    plugin: concat
    source:
      - constants/path
      - '@nid'
  parent:
    plugin: menu_link_parent
    source:
       - parent_id
       - 'main'
  external:
    plugin: default_value
    default_value: 0
  expanded:
    plugin: default_value
    default_value: 0
  enabled:
    plugin: default_value
    default_value: 1
  langcode:
    plugin: default_value
    default_value: 'en'
destination:
  plugin: entity:menu_link_content
  bundle: menu_link_content
  no_stub: true
migration_dependencies:
  required:
    - country
dependencies:
  enforced:
    module:
      - migrate_custom

```

YML file for translation:

```
id: menu_ca
label: JSON feed of menu links (Catalan)
migration_group: menu
source:
  plugin: url
  data_fetcher_plugin: file
  data_parser_plugin: json
  urls:
    - modules/custom/migrate_custom/artifacts/menu_ca.json
  item_selector: data
  fields:
    -
      name: mlid
      label: 'Unique Id coming from API. Used to match the original language of the menu links'
      selector: id
    -
      name: name
      label: 'Country name'
      selector: name
    -
      name: parent_id
      label: 'Parent menu link id'
      selector: parent
  ids:
    mlid:
      type: string
process:
  menu_name:
    plugin: default_value
    default_value: 'main'
  id:
    plugin: migration_lookup
    migration:
      - menu
    source_ids:
      menu:
        - mlid
  title:
    plugin: get
    source: name
    language: 'ca'
  parent:
    plugin: menu_link_parent
    source:
       - parent_id
       - 'main'
  external:
    plugin: default_value
    default_value: 0
  expanded:
    plugin: default_value
    default_value: 0
  enabled:
    plugin: default_value
    default_value: 1
  langcode:
    plugin: default_value
    default_value: 'ca'
destination:
  plugin: entity:menu_link_content
  bundle: menu_link_content
  no_stub: true
  translations: true
migration_dependencies:
  required:
    - country
    - menu
dependencies:
  enforced:
    module:
      - migrate_custom

```

menu\_en.json:

```
{
    "data": [{
        "id": "1_CHE",
        "country_migration_id": "CHE",
        "name": "Switzerland",
        "parent": 0
    }]
}

```

menu\_ca.json:

```
{
    "data": [{
        "id": "1_CHE",
        "country_migration_id": "CHE",
        "name": "Suïssa",
        "parent": 0
    }]
}

```
> 1 votes

---
Tags: 8, i18n-l10n, navigation, migrations
---


# Question
Title: How come Drupal Console is not downloading all commands?
When adding Drupal Console using Composer, we are finding that the list of commands is not complete. How can I resolve the issue?

### Installation steps:

1. change to root directory (`/local/path/drupal-site`)
2. run `composer require drupal/console:~1.0 --prefer-dist --optimize-autoloader`
3. run `composer update drupal/console --with-dependencies`

### Steps to reproduce:

1. Change to either Change to `drupal-site/vendor/bin/` or `drupal-site/vendor/drupal/console/bin` directory
2. run `drupal generate:form`
3. error message below is returned.
4. change to root directory (`/local/path/drupal-site`)
5. run `vendor/bin/drupal generate:form`
6. error message below is returned again.

> \[ERROR\] Command "generate:form", is not a valid command name.

Versions:

1. Drupal core v8.5.5
2. Composer 1.6.3
3. Drupal console 1.8.0

### output of `drupal list`

# Answer
After spending hours on chasing this same issue, i quit and now use drush to create boilerplate stuff such as module, plugins etc. After you install drupal site via composer with --dev try the following.

```
./vendor/drush/drush/drush generate module-standard # other generate commands there as well

```
> 1 votes

---
Tags: 8, composer, console
---


# Question
Title: Language code and country code on the URL
I've been trying to achieve this:

I have a multilingual site with 8 languages (en, fr, es, de, etc) and I want to make all those language available for all countries.

I want Drupal to understand that:

* /en-CO alias of /en
* /en-FR alias of /en
* /es-US alias of /es
* /es-AR alias of /es
* /fr-CO alias of /fr
* /de-US alias of /de

And so on... (They share the exact same content)

If I add all those custom languages is easy, but I don't want because more than 1600 combinations are posible.

Do you know if there is a way to achieve that programmatically or with a module ?

I'm currently looking into PathProcessor, but no result for now.

Any help would be greatly appreciated.

# Answer
> 0 votes
I achieved this using Persistent URLs: https://www.drupal.org/project/purl and a custom LanguageNegotiation plugin

---
Tags: 8, i18n-l10n
---


# Question
Title: How to add / remove tabs from user profile?
By clicking on the "My account" link that on the secondary menu on the site, the user is redirecting to the user's profile page.

In this page there are many tabs. Some tabs are there originally, and some tabs created by some modules. I understood how to add tabs to this menu (by simply create view and give it path of `/user/%user/XXX`).

Is there another way?
How can I remove tabs from the user's profile menu?

Why this user profile menu is not under the menus section of Drupal?

My goal is to remove the following tabs (see screenshot below): "HybridAuth", "Your Questions" and the "Points" tab.

# Answer
> 7 votes
You might be looking for the Tab Tamer module:

> Tab Tamer is an administration utility that provides easy re-ordering, hiding, and deactivation of tabs and subtabs. You can also rename tab labels.

# Answer
> 9 votes
If you don't want to use a contrib module like TabTamer then, In Drupal 7, you can use **hook\_menu\_alter** to disable the **MENU TAB** by using `access callback`

```

    /**
     * Implementing hook_menu_alter
     * Restrict MENU TABS access
     */
    function MODULE_NAME_menu_alter(&$items) {
        if(/* check your conditions */) {
            $items['user/%user/hybridauth']['access callback'] = FALSE;//Change the MENU PATH as per your requirement.
        }
    }

```

Note

* Get the **MENU PATH** by printing `$items` variable.

# Answer
> 9 votes
For Drupal 8, I was able to address this in 2 ways:

**Change the name of a user account tab item / remove a tab item** with hook\_menu\_local\_tasks\_alter:

```
/**
 * Implements hook_menu_local_tasks_alter().
 */
function MYMODULE_menu_local_tasks_alter(&$data, $route_name) {
    if ($route_name == 'entity.user.canonical') {
        foreach ($data['tabs'][0] as $type => &$tab) {
            // Replace the "View" tab name with "Hola"
            if ($type == 'entity.user.canonical' && $tab['#link']['title'] == 'View') {
                $tab['#link']['title'] = 'Hola';
            }
            unset($tab);
        }
        // Hide the "Edit" tab entirely
        unset($data['tabs'][0]['entity.user.edit_form']);
    }
}

```

One thing to note is that this doesn't actually make the edit user link inaccessible -- it merely hides it from the tabs at the top of the user profile. You'll need to implement routing to actually hide something.

**Add a new tab item**, in this case a "Status" form:

mymodule.links.menu.yml:

```
mymodule.account_status:
  title: 'Status'
  parent: 'entity.user.canonical'
  route_name: 'mymodule.account_status'

```

mymodule.links.task.yml:

```
mymodule.account_status:
  title: 'Status'
  route_name: 'mymodule.account_status'
  base_route: 'entity.user.canonical'

```

mymodule.routing.yml:

```
mymodule.account_status:
  path: '/user/{user}/status'
  defaults:
    _form: 'Drupal\mymodule\Form\AccountStatusForm'
    _title: 'Status'
  requirements:
    _permission: 'access content'
    user: \d+

```

mymodule/src/Form/AccountStatusForm.php:

```
namespace Drupal\subscription\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Account status form
 */
class AccountStatusForm extends FormBase {

    /**
     * {@inheritdoc}
     */
    public function getFormId() {
        return 'mymodule_account_status_form';
    }

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

        // TODO: Build form

        return $form;
    }

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

        // TODO: Handle submit

    }

}

```

This answer is pretty detailed so I'll leave it to folks to go through the D8 docs if anything is unclear. At minimum, you should understand the process of using custom forms (and/or controllers depending on what you need here) to implement this code.

# Answer
> 1 votes
> Is there another way?

In Drupal, there's always another way. In fact, easier ways are often overlooked.

> How can I remove tabs from the user's profile menu?

You could hide the Drupal generated tabs specifically from the user pages and add in your own:

1. Go to /admin/structure/block
2. Find "Tabs" Block in the "Content" region and click configure.
3. Under the "Visibility" section select "Pages".
4. Enter `/user/*` in the text area and select "Hide for the listed pages".
5. Create a new menu with your desired links.
6. At the block page used previously and select "Place Block" under the desired region.
7. Choose your new menu.
8. Use previous steps to only show the block on user pages.
9. Theme the Block as needed.

> Why this user profile menu is not under the menus section of Drupal?

The "Tabs" block is contextual which means that it is generated automatically depending on what page you are visiting and what modules hook into it. This is why you should only exclude them from the user pages in this case. Excluding them all together would(probably) have undesired results.

# Answer
> 1 votes
Renaming the tabs can be much easier in Drupal 8.

```
function mymodule_menu_local_tasks_alter(&$data, $route_name) {
  foreach ($data['tabs'][0] as $type => &$tab) {
    // Replace the "View" tab name with "view account"
    if ($type == 'entity.user.canonical') {
      $tab['#link']['title'] = t('view account');
    }

    // Replace the "Edit" tab name with "edit account"
    if ($type == 'entity.user.edit_form') {
      $tab['#link']['title'] = t('change password');
    }
  }
}

```

# Answer
> 0 votes
As hook\_menu\_alter() was not triggered on user page in my Drupal installation, I managed to do it in another way, using hook\_menu\_local\_tasks\_alter():

```
function hook_menu_local_tasks_alter(&$data, $router_item, $root_path) {

    unset($data['tabs'][0]['output'][2]);

}

```

Where 2 is the position of the tab you want to remove.

The problem with this approach is that the position of tab you want to remove is exposed to be changed by another module I guess. Then installing more contrib modules after that, it could be problematic.

At least for my use case it's enough.

# Answer
> 0 votes
In a clean Drupal 8 way, you could alter tasks by using modulename\_local\_tasks\_alter(), as described in the documentation

```
/**
 * Implements hook_local_tasks_alter().
 */
function modulename_local_tasks_alter(&$local_tasks) {
  // Remove unwanted tabs
  // Here, we'll remove the "Payment method" tasks from the user edit tasks
  unset($local_tasks['entity.commerce_payment_method.collection']);
}

```

---
Tags: routes
---


# Question
Title: Put link/button in email to reply to sender on website
I'm having a bit of trouble figuring out how this is meant to work. What I'm trying to achieve is as follows:

1) I've got Webform module installed and working. Just has generic fields for now.

2) What I want it to do is as follows:

User A wants fills in the form (webform) asking for a quote to clean their 3 bedroom house. This form gets submitted and cleaning companies get notified by email. - **This bit I have figured out!**

BUT - What I want to happen is that when the cleaning companies receive this email (name, number of bedrooms etc) I want there to be a link within the email that allows the cleaning company to click on that takes them to another form on the website where they can enter quote information (like price, imagery etc). When the cleaning company clicks submit the original user A gets notified a quote has come in.

Any ideas how I set this up? It doesn't appear to be included in the standard module.

# Answer
I don't think you can do this from webform alone. I would create a custom form (using Form API in a custom module) with a path that includes a parameter to identify the original webform submission. Something like /quote-response/{webform-submission}. The "response form" then queries the webform submission to get the email of the person who submitted the original quote request. Keep in mind if this route doesn't require any authentication, you could be opening yourself up to bots / malicious users, so I recommend implementing some additional security / verification.
> 0 votes

---
Tags: webforms
---


# Question
Title: Custom node access control not working with access filter?
In some of mine content types I have checkbox field "Content protect". If checked that node should be visible only to registered user. If not checked - visible to everyone:

```
function hook_node_access($node, $op, $account) {

  // If $node is a string, the node has not yet been created. We don't care
  // about that case.
  if (is_string($node)) {
    return new AccessResultNeutral();
  }
  if ($node->hasField('field_content_protect')) {
    $protected = ($node->field_content_protect->value == 1) ? TRUE : FALSE;
    $userId = $account->id();
    if ($protected && $userId == 0) {
      return new AccessResultForbidden();
    }
  }
  return new AccessResultNeutral();
}

```

And this works well when I try to access node directly. If it's protected anonymous users can't access it.

Now, I have a view that lists some of those nodes. I want to apply same logic and to exclude protected nodes for anonymous users. So in my view I added filter:

```
Content access: Access

```

But it's not working as expected. For authenticated users content is there, but for anonymous users simply whole block content is missing?!? Nodes that don't have this "Content protect" field checked are also not listed?!? Why is that? This filter has no options/settings.

I do have other option, to duplicate view display, check directly the field and display first or second block view depending on user, but this solution with Content access filter looks more elegant.

# Answer
> 3 votes
Lists like views will not be passed through hook\_node\_access(), as this would create too much overhead. Views does a query on the database to get the results. hook\_node\_access() is run in PHP, so these won't work (easily/well/efficently) together.

To deal with lists, you will need to create a grant system, using hook\_node\_access\_records() and hook\_node\_grants(). This system writes to the `{node_access}` table in the database, and when a list is created, the database query is cross-referenced with that table.

hook\_node\_access\_records() is called when a node is saved. Modules that implement this hook can set up various states by which the node is allowed to be accessed.

hook\_node\_grants() is then called when the node is viewed/updated/deleted. A set of potential grants is created based on the current environment, and these are compared with the states created in hook\_node\_access\_records(). If there is a match, access is provided.

In your case, hook\_node\_access\_records() should create a state whereby if the node has the field `field_content_protect`, then a state should be created upon which view access can be either granted or denied in hook\_node\_grants(). Example:

```
function MODULE_node_access_records(\Drupal\node\NodeInterface $node) {
  if ($node->hasField('field_content_protect')) {
    $grants = [];

    $grants[] = [
      'realm' => 'MODULE_protect_content',
      // This is set to 1. In hook_node_grants(),
      // A value will be created based on the user's
      // logged in state, and compared to this value.
      'gid' => 1,
      'grant_view' => 1,
      'grant_update' => 0,
      'grant_delete' => 0,
    ];

    return $grants;
  }
}

```

The above sets up a state, whereby if a grant is created for the realm `MODULE_protect_content` that has a value of 1, the user should be granted view access. The next thing is to implement `hook_node_grants()` and create a grant based on the current user's status.

```
function MODULE_node_grants() {
  $current_user = \Drupal::currentUser();
  $grants = [];

  // This will set a value of 0 (zero) or 1 (one)
  // for the realm MODULE_protect_content. If the
  // value is 1 (authenticated user) the user will
  // be provided view access to the node. Note
  // that an array of values must be passed for
  // realms.
  $status = (int) $current_user->isAuthenticated();
  $grants['MODULE_protect_content'] = [$status];

  return $grants.
}

```

For the above code, a grant is created based on the logged in status of the current user. If they are logged in, `$status` will equal `1`, which is compared with the state provided in `hook_node_access_records()` providing access to the user.

You could actually alter the above hook\_node\_grants() to only return a grant if the user is logged in. I'm not sure which one would be more efficient. I suspect the code below may be:

```
function MODULE_node_grants() {
  $current_user = \Drupal::currentUser();

  if ($status = (int) $current_user->isAuthenticated()) {
    $grants = [];
    // This will set a value of 1 (one)
    // for the realm MODULE_protect_content, which
    // matches the state created in
    // hook_node_access_records(). Note that
    // an array of values must be passed for
    // realms.
    $grants['MODULE_protect_content'] = [$status];

    return $grants.
  }
}

```

---
Tags: views, 8, hooks
---


title: hook_node_view() is not working

text:
# Question
Title: hook_node_view() is not working
I am building a module for Drupal 8 which needs to use `hook_node_view()`. I tried the following code

```
<?php

/**
 * @file
 * Demonstrates the possibilities of forms in Drupal 8.
 */

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\Node;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_form_alter()
 */
function demo_form_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  drupal_set_message(t('Found a form with ID %form_id', array('%form_id' => $form_id)));
}

/**
 * Implements hook_node_view()
 */
function demo_form_node_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {
   drupal_set_message(t('its working'));
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Only alters the Search form 'search_block_form'.
 */
function demo_form_form_search_block_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form['hello'] = array(
    '#markup' => t('Go ahead, try me ...') . '<br />',
    '#weight' => -1,
  );
}

```

I can't see any message from `demo_form_node_view()`. If the hook was correct, it should have shown the message. I am new to Drupal and I can't figure out why it is not working.

# Answer
> 2 votes
In Drupal 8, the core Drupal hook `hook_entity_view()` is only called when the entity is "being assembled before rendering". See the documentation at https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!entity.api.php/function/hook\_entity\_view

After the entity has been rendered, core Drupal will cache the rendered entity and serve the rendered entity from the cache when needed. The entity is not rendered every time it is used. So BY DESIGN `hook_entity_view()` will not be called again when the rendered entity is loaded from the cache, it will only be called when the entity needs to be re-rendered - that is, when the entity is changed and/or the cache of that entity is invalidated.

This behavior is different from the way it worked in Drupal 7 because Drupal 7 did not cache rendered entities like this.

# Answer
> 1 votes
This doesn't answer the question because the OP says he is building a module, but for others who stumble upon this question: I've found that this hook cannot be called from a theme. It must be called from a module. I could be wrong, but this has been my experience.

---
Tags: 8, hooks
---


# Question
Title: Update failed on Metadata module, any easy fix?
I am very sorry to bring a rather nebulous question here but need any and all help I can get: for the first time, I've had a "White Screen of Death" issue when trying to update a module. I believe it was the "Metadata" module but I don't even remember for sure. I had a previous backup of the database and site files/folders from a day ago, so I didn't make one this time. Followed the Drupal tool for downloading, installing, and...presto....White Screen of Death.

Trying not to panic, I reverted to the older backup. Which I hoped would solve the issue.

Yet it did not.

So my question is whether perhaps (fingers crossed!) there's additional steps I need to take once a backup is in place to get things working again. I tried truncating every "cache\_..." line via PhpMyAdmin, but it didn't help. I tried the "update.php" in the URL hoping it was (maybe) just an index.php issue. Again...no dice.

I've seen a long page about WSOD possible issues but don't want to just muddle around doing that if I don't know what I'm doing, which I don't.

Are there any suggestions for quick, simple things I've either forgotten or could try to get this working again? And if I can't, can I manually copy files and folders over somehow and try again?

Thank you all in advance for any help. I really appreciate it. Stay healthy out there!

# Answer
> 0 votes
So the solution here was that the backup (done by my ISP) did not fully restore. I think they forgot to recursively restore and just did the main Drupal root. Once I asked them if they were sure they restored recursively and there was a long pause (a few hours, at which point the site started working again) they came back and said they'd missed a few files.

So luckily that solved it. I did not need to configure anything or run any update.php or such. Just restored the entire Drupal directory and all subdirs and such, and a database restore to match. That fixed it. Whew!

---
Tags: updating, wsod
---


# Question
Title: How do I give access to only specific roles to buy at my store?
I have a platform with roles for moderators, editors, teachers and students. Only student roles should be able to buy courses and the other roles should not be able to buy courses or see any of the commerce store information e.g. cart etc. How do I set their permissions? All roles still see "cart" in the menu bar. Am I missing a setting in permissions? There doesn't seem to be a permission for cart, only checkout permissions. What am I missing?

# Answer
> 1 votes
## Solution

After a few nights of sleeping on it I believe I have a solution. I tested it and so far it works. But please let me know if you experience any issues with my solution below.

## Step 1

a) Install Roles For Menu module (has a stable releases for this project are covered by the security advisory policy.)

b) Install the Path Access module together with the Chain Menu Access API (which is needed to install the Path Access module)

## Step 2

a) Go to your menu links in the user menu `admin/structure/menu/manage/user-menu` (or wherever your 'my cart' link is located) and set the required roles to show and hide for that menu item.

b) Go to `admin/config/people/pathaccess` and add the paths that you wish to deny access to per role.

Now the roles who don't have access to any of these paths get an access denied page and those who do have access will just be able to use the store as intended.

# Answer
> 0 votes
In D7 you can use hook\_menu\_alter or check out https://www.drupal.org/project/menu\_item\_visibility for a no-code solution. If you can't access a page it won't appear in your menu - once logged in, at least.

---
Tags: 7, commerce
---


title: How to move a theme to a new location?

text:
# Question
Title: How to move a theme to a new location?
I have a site (Drupal 8.4.2) that has Bootstrap and a subtheme located in:

/sites/themes/

With the upgrade from 8.3 to 8.4, I have started using Composer, and subsequently used Composer to upgrade Bootstrap. This added it to my composer.json (I'd previously installed Boostrap using drush), but also put the updated version of Bootstrap here (without touching my existing Bootstrap folder):

/sites/themes/contrib/

I removed my existing Bootstrap folder and cleared the cache. However, I can no longer manage the Boostrap theme or my subtheme - I get a 500 error like this:

> PHP Fatal error: require(): Failed opening required '/var/www/html/drupal/mysite/themes/bootstrap/src/Bootstrap.php' (include\_path='.:/usr/share/pear:/usr/share/php') in /var/www/html/drupal/mysite/vendor/symfony/class-loader/ApcClassLoader.php on line 110

The issue, clearly, is that it's looking for Bootstrap in the old location. The question is - what do I need to do to ensure my site finds Bootstrap in the correct folder? Moving the updated version of Bootstrap from contrib/ to where the original version was located fixes the problem for now, but I'd like to fix it permanently.

I assume there is a config value somewhere that isn't being touched by clearing the cache.

# Answer
1. Put your old theme back into the old location.
2. Enable and set Bartik theme as default theme.
3. Uninstall the old theme.
4. Move your old theme to the new location.
5. Enable the old theme and set as default again.
6. Uninstall Bartik.

Voilà
> 1 votes

# Answer
drush cr

This should clear theme registry and pickup the new location of your theme files
> 0 votes

---
Tags: 8
---


title: How do I get the list of permissions?

text:
# Question
Title: How do I get the list of permissions?
I am trying to use the group method `hasPermission(permission_label, user)`. I found an example that is the following:

```
$group->hasPersmission('administer members', $user)

```

I would like to know what all the different permissions types are. In particular I want to be able to differentiate whether a user can edit or just view a type of content.

How do I a get a list of the different types of permissions?

Thanks,

Olivier

# Answer
> 0 votes
You can go to Admin -\> Group -\> Group Types -\> \[your group type\]. On that page, click the Permissions tab. You can see all the permissions there. If you need to know the permissions string, you can inspect any checkbox for a given role/permission combo, and look at the `name` attribute. It will be something like `admin[permission_label]`, where `permission_label` is the value you would pass as the first argument to `$group->hasPermission()`.

---
Tags: group
---


# Question
Title: Entity Reference: Filter by an entity reference view not working as expected
I am attempting to get a taxonomy reference field select widget that shows a list of taxonomy terms, including some extra data from their fields. I have attempted to use the "Reference method" = "Views: Filter by an entity reference view" and then select an entity reference view I created, then in my entity reference view I have done the following:

However, this gives me only the taxonomy term name despite the settings indicating it might show all the fields inline ("Note: In 'Entity Reference' displays, all fields will be displayed inline unless an explicit selection of inline fields is made here.").

# Answer
You can't at the moment.

See `\Drupal\views\Plugin\EntityReferenceSelection\ViewsSelection::getReferenceableEntities()`, it just uses the view to get the results and then calls $entity-\>label(). Which means you have no way to override that.

Which means that if you want this, you need to provide your own plugin. You can either subclass from ViewsSelection and still a view, or just extend from the default and override that method.

Might also be worth opening a feature request, I've already had this use case multiple times, and a new checkbox or option somewhere would be a nice, backwards compatible way to introduce this feature in a minor release.
> 4 votes

# Answer
The module Entity Reference Views Select supports additional fields in select lists and checkboxes when selecting entities in an entityreference field. We've used it successfully with ECK entities.
> 2 votes

# Answer
There might be a way to get around this, but it also has restrictions as indicated in this issue filed by me : https://www.drupal.org/node/2841330#comment-11854353

In other words, write your own display handler to deal with the result of an entityreference view result.

The webform\_references developers have done that but as you can see in my issue, they also delegate their webform select option theming to the views rendering outcome. Where in my opinion (see second comment) it should be the responsibility (or choice for that matter) of the one who is requesting the entity reference view. In other words, use the `views_get_view_result()` function instead of `$view->execute_display()`.
> 0 votes

# Answer
There is a working patch for this: View output is not used for entityreference options
> 0 votes

# Answer
In Drupal 8, you can use the View Entity Reference Field Formatter module to use the views module to display the referenced entities.
> 0 votes

---
Tags: views, 8, taxonomy-terms
---


# Question
Title: Is it possible to add multiple fields within a single component?
```
    $form['value'] = array(
        '#type' => 'textfield',
        '#title' => t('Webservice URL'),
        '#default_value' => $component['value'],
        '#description' => t('The default value of the field.'),
        '#size' => 60,
        '#maxlength' => 1024,
        '#weight' => 0,
    );

```

I want to make a second textfield in my component where I can specify the second part of my Webservice URL and then concatenate them in my rendering. How can I add a second textfield to my webform\_edit?

# Answer
> 2 votes
For one of my projects I spend almost whole week trying to find similar functionality it turns out that you cannot render the input of two fields as one entry from webform result due to the fact that webform creates separate database entry for every field. I solve my problem by just creating multiple fields value\_1 value\_2 and so on and when exporting result concatenate them in Excell (stupid I know :-) and does not work for your case) . There is module Webform Add More but it only use the same aproach but hides the extra fields and shows them when needed. If you are willing to switch from webform you can try EntityForms this way you can use regular Drupal fields to get entered values and embedding Entityforms on Nodes using Entity Reference

# Answer
> 1 votes
You can use Webform Structured Text module to achieve this

# Answer
> 0 votes
You should use Paragraphs module. This is just awesome. Found a helpful article: https://www.gyanblog.com/gyan/drupal-how-add-multiple-fields-single-button/

Paragraphs module is so powerful, it has lot of other use cases as well. The best part is, no coding required.

---
Tags: entities, webforms
---


# Question
Title: RESTful Web Services : How to simply post a paragraph entity
I have simply activated the default paragraph ressource with core (8.8.3) module :

I would like to post a paragraph but even just with the "type" field, I got 403 error in response ! I have nearly the same request that works fine for node...

```
        var newReleve = {

          type: [{
            target_id: 'releve_de_chantier'
          }],
          parent_id: [{
            value: this.nid,
          }],
          parent_type: [{
            value: 'projet',
          }],
          // field_type_de_releve_de_chantier: [
          //   {
          //     value: this.typeReleve
          //   }
          // ],

        };

        if(this.pid) {
          newReleve.id = [{
            value: this.pid
          }]
        }

        fetch('/entity/paragraph'+(this.pid ? '/'+this.pid : '')+'?_format=json', {
          method: this.pid ? 'PATCH' : 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-CSRF-Token': csrfToken
          },
          body: JSON.stringify(newReleve)})
          .then(response => {
            if(response.ok){
              return response.json();
            } else {
              console.log(response);
              throw('Error posting datas ! Details below \n ' + response.status + ' : ' + response.statusText);
            }
          })
          .then(para => {
            // console.log(para);
            this.pid = para.id[0].value;
            console.log(this.pid);

          })
          .catch( error => {
            alert('Enregistrement du relevé non effectué : erreur interne du programme ! Détail de l\'erreur : \n ' + (error.message ? error.message : error) );
            console.error(error);
          });

```

Any idea ?

thanks

# Answer
Finally, seems it comes from Paragraph module, file *ParagraphAccessControlHandler.php* function *checkCreateAccess* :

```
  protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
// Allow paragraph entities to be created in the context of entity forms.
if (\Drupal::requestStack()->getCurrentRequest()->getRequestFormat() === 'html') {
  return AccessResult::allowed()->addCacheContexts(['request_format']);
}
return AccessResult::neutral()->addCacheContexts(['request_format']);

```

}

Code goes in the second return as request format is not html but json. If I force the return to be AccessResult::allowed(), the paragraph is created. Why this restriction to forms ? How to overwrite this without patching ?
> 0 votes

---
Tags: 8
---


# Question
Title: hook_nodeapi called multiple times with op='update'
I am using the media\_mover module. I added some debug code to media\_mover's hook\_nodeapi:

```
function media_mover_api_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  dsm ("entering hook_nodeapi.  op=$op");
  switch ($op) {
    ...
    case 'update':
       ...
       break;
  }
}

```

When the user edits and saves a node, hook\_nodeapi is getting called *twice* with $op='update'. Anyone know why this might be?

If media\_mover calls node\_save during the process of saving the updated node, might that cause hook\_nodeapi to be called multiple times with $op='update'?

(I am using Drupal-6.x)

# Answer
> 1 votes
You are spot on.

If a module calls `node_save`, `nodeapi` will be called either with `update` or `insert`, depending on what happened.

# Answer
> 0 votes
There is a chance to call hook\_node\_update multiple times if you use field collection items in your content type. The call times depends on the content in the field collection items

---
Tags: hooks, nodes
---


# Question
Title: How to redirect after node insert (not form redirect)?
I am trying to find out how to redirect after I insert a new node. All the answers I have been able to find discuss $form\_state-\>setRedirectUrl(); but this is a form redirect; not a proper redirect after insertion.

The difference is that when I submit the node form; I use hook\_node\_insert to create another entity based on information from the node being inserted. After the parent node is inserted; I want to redirect to a path based on the entity id of the new child entity.

In hook\_node\_insert (for the parent; i.e. original form submit)) I set a drupal\_register\_shutdown\_function which properly saves my child entity and I then have the -\>id() of the new (child) entity.

I have seen various examples using RedirectResponse, such as this:

```
$redirect = new RedirectResponse(Url::fromUserInput('/admin/commerce/orders/' . $order->id() . '/payments')->toString());;
$redirect->send();

```

but none of these work.

# EDIT

to try to line this up with @4k4's suggestion, this is where I am at:

```
function my_module_node_insert($node) {
  $s = \Drupal::service('sia_general.redirects');
  $s->createPolicyRedirect($node);
}

```

in my Service:

```
class RedirectServices implements EventSubscriberInterface {

  static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE] = ['gotoPolicy'];
    return $events;
  }

  public function createPolicyRedirect($policy) {
    $this->policy = $policy;
  }

  public function gotoPolicy(FilterResponseEvent $event) {
    // We only care if this happened after policy was created.
    if (!$this->policy) {
      return;
    }

    $redirect = new RedirectResponse(Url::fromUserInput('/node/' . $this->policy->id() . '/edit')->toString());;
    $event->setResponse($redirect);
  }
}

```

when the Policy node is created; the hook\_node\_insert is called, which in turn calls the createPolicyRedirect() service and passes the newly created Policy object. After this it returns to the event subscriber which originally called the function which created the Policy. After that it hits the final pass of gotoPolicy(); but $this-\>policy is not set at this point.

Just to test that the redirect response worked as i hope; i tried setting a SESSION var in createPolicyRedirect(); but even that isn't set once i get to final gotoPolicy call.

# EDIT #2

Still no luck and guessing due to the event handler within event handler that i am doing... so more context.

The complete flow is as follows:

* create App entity
* this adds items to Commerce cart
* admin adds payment
* PaymentComplete handler "places" the Order
* OrderComplete handler loads the App and sets a Workflows field and then saves the App
* during the App-\>save(), the change in Workflow triggers creating a Policy entity
* this triggers my hook\_node\_insert($policy) (note: this is still within OrderComplete event handler).
* in my insert hook i fire my 1st method above (which sets $this-\>policy)
* i then return to finish the OrderComplete event handler
* after the OrderComplete is finished; i hit my final run through the 2nd method (the KernelEvent); but by this time, $this-\>policy is no longer set.

My guess is that the ordercomplete does a page load before my kernel event is run (not sure that makes sense); so maybe this is a bug in Commerce; or at the very least i need to approach this differently, like alter what commerce is doing. Perhaps Drupal's event handling system isn't quite ready to handle situations this complex yet??

# Answer
> 1 votes
Proof of concept for redirecting on newly created nodes via a response event subscriber, as discussed in the comments:

Hook:

```
function mymodule_node_insert($node) {
  \Drupal::service('mymodule.my_response_subscriber')->setNode($node);
}

```

Service class:

```
<?php

namespace Drupal\mymodule\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Url;

class MyResponseSubscriber implements EventSubscriberInterface {

  protected $node = NULL;

  public function setNode($node) {
    $this->node = $node;
  }

  public function kernelResponse(FilterResponseEvent $event) {
    if (!$this->node) {
      return;
    }
    $redirect = new RedirectResponse(Url::fromUserInput('/node/' . $this->node->id() . '/edit')->toString());
    $event->setResponse($redirect);
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = ['kernelResponse', 127];
    return $events;
  }

}

```

This opens the edit form after you've created a node, instead of rendering the node.

Recycling an existing subscriber this is working on my Drupal install. I've left the priority unchanged. You can test different priorities. For example, if you have set a destination query parameter try a priority \<0 to override the destination.

Also debugging can be a challenge. Besides the main request Drupal fires a lot of other requests, especially for logged in users. So if you don't see a variable you expect to be set it's possible you are in a different request.

# Answer
> 0 votes
You could do a redirect in hook\_node\_insert(), however that would then prevent any other implementations of hook\_node\_insert() that come after your implementation from being executed.

I would instead suggest removing the code you've added in hook\_node\_insert(), and instead adding a custom submit handler to the node creation form. You can get the newly created node ID from `$form_state->get('uid')`. You can use that to load the newly created node, then create your node, and finally add the redirect in the form state, as you've mentioned in your post. This way no APIs are bypassed, and your redirect will happen after everything has been executed.

---
Tags: 8
---


# Question
Title: Invalidate cache on ConfigFormBase submit
I have a ConfigFormBase called TextConfiguration where I have defined several fields for the address, phone number, etc...

These variables are shown in the contact form on my website. When I modify them and enter as anonymous in /contact, the value is not updated.

I've tried this in my ConfigFormBase form submit, but it does not work.

```
// Additionally, clear cache to prevent mismatch data.
$tags = $this->config(static::COMPET_SETTINGS)->getCacheTags();
if ($tags) {
  Cache::invalidateTags($tags);
}

```

I'm doing something wrong? I need to configure or do something to get it to update the data when a value is changed? Thanks all!

Edit: Example of how I'm rendering the fields.

# Answer
> 2 votes
You have to add the cache tags to the rendered output of the config field:

```
$form['example'] = [
  '#markup' => $settings->get('name'),
  '#cache' => [
    'tags' => $settings->getCacheTags(),
  ],
];

```

---
Tags: 8, caching
---


title: Content types versus custom block types

text:
# Question
Title: Content types versus custom block types
I'm trying to understand how to create content for a site and place it somewhere. The two methods I want to compare are:

### Content type

* Create custom content type (with fields)
* Create instances of content
* Create view of this content type
* Create block from view
* Place block in region

### Custom block type

* Create Custom Block Type (with fields)
* Create and place instance of custom block in region

Whats the pros and cons of each approach?

As an example scenario, lets say I have a home page with 4 sections of the same content type (for example product features). These 4 sections need to be ordered down the page. There will be other content on this page.

From what I have seen so far, the Custom Blocks require less effort up front to setup, I don't need a view, and I can arbitrarily order then in the block layout page (drag/drop). However, I feel like I've now 'hidden' content somewhere else that doesnt appear in the main content summary page, and a content manager would need to know to look there, also the default view to manage Custom blocks has less options than the content filter (i know you can add some filters to that view though). Also if I add each item as new instance of a custom block type to the block layout page, that list is going to start getting pretty long.

I guess adding the content as a content type means its created as node (and via the custom block type it isnt?)

Edit: The sites we build are big, and always multi language. This might affect any answers.

# Answer
> 2 votes
I think you should consider this question:

Does the content need to have its own url?

If yes, use nodes. Then you can click on a partial view (teaser) to get a full view of the content with its own url and you can put it in the menu, search for it and so on.

A block content is always only a part of a page, never a full view of its own and therefore has much less features.

# Answer
> 1 votes
In Drupal, content is made with nodes. Blocks are used to give more information that could be related to content (such as the nodes that are part of the same book the viewed node is part of, or the nodes that are in some other way related to the currently shown one), to the users (e.g. the last users who logged in, or the users who saw the current node), or to the site in general.

Drupal offers more feature for nodes, starting from the permissions associated to them. While for blocks a plain Drupal installation just has the *administer blocks* permission, which allows to create new blocks, but also delete the existing ones, for nodes a plain Drupal installation has permission for editing, deleting, viewing, and creating nodes.
Nodes have a more complex system to assign permissions to user for operations on nodes, which involves three hooks (`hook_node_grants()`, `hook_node_records()`, and `hook_node_access()`), while for blocks there is just a hook for that purpose.

You aren't forced to create a view for nodes, in the same way you aren't forced to create a block with a view. In both the cases, the Views module (which is now part of the Drupal core modules) helps you in making a list of entities. For example, when you enable the Views module in Drupal 8, there are some administrative pages that are served from a view, allowing the administrator users to extend those pages easily.

Also, for what I recall, you cannot add comments to blocks, but you can have comments for nodes. In a similar way, there are things that third-party modules implement for nodes, but not for blocks.

# Answer
> 1 votes
The information that you want on block/node. You should consider

* If you want the information to be displayed in more than one place
* If you want the information to be repositioned/placed easily within regions
* If the information doesn't needs its own url / complex permission / query based logic

Then go for a block. Otherwise node. I would go for node for the main pages of my site and within those pages, i would use blocks if it needs to be.

Good luck :)

# Answer
> 0 votes
I would recommend "Content Type - Method" as it's saving the content as node. Saving it as a Node helps you to retrieve and reformat the content with list of Node API functions. Node Data can be efficiently accessed by different Core & Contributed modules like Views, Slider etc - most of the contributed module out there, are built around Nodes.

---
Tags: nodes, 8, blocks
---


# Question
Title: How do I enable PHPUnit testing for a sandbox project on drupal.org?
This questions is specifically about my sandbox project. I have PHPUnit running on other full projects that I maintain.

I have created a sandbox project, fully uploaded to drupal.org, for 8.x and 9.x testing. But there is no "Automated testing" tab on the project page, like there is with full projects. What has to be done to enable testing on drupal.org?

The project has a composer.json, .info.yml and drupalci.yml. My phpunit tests run locally. Everything looks fine. I have searched drupal.org docs https://www.drupal.org/node/1011196 and it does not say that phpunit testing is not available for sandbox projects.

# Answer
> 3 votes
Given the following comment I found on Can enable tests for sandbox projects, testing is disabled on sandbox projects, which means you cannot enable automatic tests on sandbox projects.

> From `pift_project_visibility()`:
>
> ```
> if (!empty($node->field_project_has_releases[LANGUAGE_NONE][0]['value'])) {
> // Ensure user has the 'access project testing tab' permission
> if (user_access('access pift project testing tab')) {
>   return TRUE;
> }
>
> ```
>
> }
>
> So as long as the releases piece is taken care of, the 'enable' checkbox should never appear (and thus users will not be able to enable testing).

The issue has been created in the project that handles the automatic testing for projects hosted on drupal.org. The comment says that the automatic tests are enabled for the projects with enabled releases. Sandbox projects don't have releases enabled, so also the automatic tests are disabled.

As Drupal.org Git administrator I can confirm that none of the sandbox projects has the *Automated testing* tab, which I instead see on full projects. (It's not a matter of permissions, as my role on Drupal.org allows me to set automatic tests for any project.)

To answer How did you enable automated testing on this sandbox project? that project has automatic tests enabled because it's a full project, despite the project name. I can say that because the path alias automatically set for a sandbox project is similar to `https://www.drupal.org/sandbox/grayside/1876908`, the path alias for the #Heading module. Furthermore, a sandbox project has a *Promote* tab as in the following screenshot.

>

For the other project, this is what I see.

>

---
Tags: testing, community-official-site
---


title: Unable to delete a field

text:
# Question
Title: Unable to delete a field
I'm running this code using `drupal src deletefield.php`

deletefield.php

```
\Drupal\field\Entity\FieldStorageConfig::loadByName('article', 'field_govt_dept_')->delete();

// Deleting field.
\Drupal\field\Entity\FieldConfig::loadByName('article', 'bundle', 'field_govt_dept_')->delete();

```

But it's coming out with error:

```
@tsmdc:/var/www/html/govtschemes.in$ drush scr deletefield.php
Error: Call to a member function delete() on null in include() (line 5 of /var/www/html/govtschemes.in/deletefield.php) #0                        [error]
phar:///home/raggupta/bin/drush8.1.16.phar/commands/core/core.drush.inc(1162): include()
#1 phar:///home/raggupta/bin/drush8.1.16.phar/includes/command.inc(422): drush_core_php_script('deletefield.php')
#2 phar:///home/raggupta/bin/drush8.1.16.phar/includes/command.inc(231): _drush_invoke_hooks(Array, Array)
#3 phar:///home/raggupta/bin/drush8.1.16.phar/includes/command.inc(199): drush_command('deletefield.php')
#4 phar:///home/raggupta/bin/drush8.1.16.phar/lib/Drush/Boot/BaseBoot.php(67): drush_dispatch(Array)
#5 phar:///home/raggupta/bin/drush8.1.16.phar/includes/preflight.inc(66): Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#6 phar:///home/raggupta/bin/drush8.1.16.phar/includes/startup.inc(462): drush_main()
#7 phar:///home/raggupta/bin/drush8.1.16.phar/includes/startup.inc(369): drush_run_main(false, '/', 'Phar detected. ...')
#8 phar:///home/raggupta/bin/drush8.1.16.phar/drush(114): drush_startup(Array)
#9 /home/raggupta/bin/drush8.1.16.phar(10): require('phar:///home/ra...')
#10 {main}.
Error: Call to a member function delete() on null in /var/www/html/govtschemes.in/deletefield.php on line 5 #0 phar:///home/raggupta/bin/drush8.1.16.phar/commands/core/core.drush.inc(1162): include()
#1 phar:///home/raggupta/bin/drush8.1.16.phar/includes/command.inc(422): drush_core_php_script('deletefield.php')
#2 phar:///home/raggupta/bin/drush8.1.16.phar/includes/command.inc(231): _drush_invoke_hooks(Array, Array)
#3 phar:///home/raggupta/bin/drush8.1.16.phar/includes/command.inc(199): drush_command('deletefield.php')
#4 phar:///home/raggupta/bin/drush8.1.16.phar/lib/Drush/Boot/BaseBoot.php(67): drush_dispatch(Array)
#5 phar:///home/raggupta/bin/drush8.1.16.phar/includes/preflight.inc(66): Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#6 phar:///home/raggupta/bin/drush8.1.16.phar/includes/startup.inc(462): drush_main()
#7 phar:///home/raggupta/bin/drush8.1.16.phar/includes/startup.inc(369): drush_run_main(false, '/', 'Phar detected. ...')
#8 phar:///home/raggupta/bin/drush8.1.16.phar/drush(114): drush_startup(Array)
#9 /home/raggupta/bin/drush8.1.16.phar(10): require('phar:///home/ra...')
#10 {main}
Error: Call to a member function delete() on null in include() (line 5 of /var/www/html/govtschemes.in/deletefield.php).

```

**What is the problem?**

# Answer
> 0 votes
This:

```
\Drupal\field\Entity\FieldConfig::loadByName('article', 'bundle', 'field_govt_dept_')

```

Is returning NULL.

You likely want:

```
\Drupal\field\Entity\FieldConfig::loadByName('node', 'article', 'field_govt_dept_')

```

Also, check that the field name `field_govt_dept_` is correct. Does it really end in a trailing underscore? (that can happen, but it's not common).

---
Tags: 8
---


# Question
Title: How do I load a Media entity from a File entity?
I have a File entity loaded programmatically. I want to load a Media entity from it. Is there a way to achieve this?

# Answer
Example - if your `File` entity is loaded in a variable named `$file`, and the field name on the `Media` entity is `field_media_image`:

```
$media_entities = \Drupal::entityTypeManager()->getStorage('media')->loadByProperties([
  'field_media_image' => $file->id(),
]);

$media_entity = is_array($media_entities) ? array_pop($media_entities) : NULL;

```

Note1 : If the `File` object belongs to more than a single `Media` entity, you will need to loop through `$media_entities` to find the one you want.

Note 2: `$media_entity` will either contain the `Media` entity the `File` entity belongs to, or be `NULL` if the `File` entity doesn't belong to a `Media` entity.
> 4 votes

# Answer
Actually i found a good answer, i used :

`$result = \Drupal::service('file.usage')->listUsage($file);`

and then in the $result i am checking if any keys called `media` exist. If so, i can then load my Media :)
> 1 votes

---
Tags: 8, media, files
---


# Question
Title: How to change the view for a rendered product?
I'm learning Drupal Commerce with a Commerce Kickstart installation. I understood in part the way products are displayed, with variation types and content types.

Have made some changes like visible/hidden product fields, and change the order product fields are displayed.

I would like to modify the position of the image to be on the left side and title, description and *Add to cart* button should stay on the right side.

How can I do that?

# Answer
You have two high level options: 1) create page templates for your product displays in the theme layer that include the markup your CSS needs to position things or 2) use a module like Panels that lets you build page layouts from within the Drupal admin UI itself. (I'm assuming this is Drupal 7, but if you are on Drupal 8, you should give the core Layout Builder module a try vs. Panels.)
> 1 votes

---
Tags: theming, commerce
---


title: How to override a service

text:
# Question
Title: How to override a service
I am trying to override a service by using a ServiceProvider Class

```
class MyModuleServiceProvider extends ServiceProviderBase
{
    public function alter(ContainerBuilder $container)
    {
        // Overrides MessageNotifier class to add loggin facilities to each message.
        $definition = $container->getDefinition('message_notify.sender');
        $definition->setClass('Drupal\my_module\MyModuleMessageNotifier')->addArgument([
            new Reference('logger.channel.message_notify')
        ]);
    }
}

```

This is out of topic, but FYI, the overrode service "message\_notify.sender" is created by the message\_notify module pertaining to the message stack modules

As you can see, I am adding an argument (a logger) to my new service

Here is the `__construct()` method of the **parent** (overrode) class:

```
  public function __construct(Manager $notifier_manager) {
    $this->notifierManager = $notifier_manager;
  }

```

Here is the `__construct()` method of my new class:

```
    public function __construct(Manager $notifier_manager, LoggerChannelInterface $logger)
    {
        parent::__construct($notifier_manager);
        $this->logger = $logger;
    }

```

But for an unknown reason the $logger variable is not an object but an array with one item... and this item is the LoggerChannel object.

Thus this code is not working but the following does:

```
    public function __construct(Manager $notifier_manager, array $logger)
    {
        parent::__construct($notifier_manager);
        $this->logger = $logger[0];
    }

```

What am I doing wrong?

# Answer
> 2 votes
The problem is that you are adding your argument as an array, so your `__construct()` method receives an array. So this:

```
$definition->setClass('Drupal\my_module\MyModuleMessageNotifier')->addArgument([
  new Reference('logger.channel.message_notify')
]);

```

Should be this:

```
$definition->setClass('Drupal\my_module\MyModuleMessageNotifier')
  ->addArgument(new Reference('logger.channel.message_notify'));

```

(notice that the Reference is not wrapped in an array.

---
Tags: symfony-services, message-subscribe
---


# Question
Title: Show a block on the user registration form depending on destination parameter
How can I show a block, or a a mini panel, on the user registration form depending on the destination parameter?

Right now, I'm showing, in a view, a link that leads the users to user/register?destination=courses. This works fine, but I want to show certain infomation to the still anonymous users who are going to register an account.

# Answer
As @runswithscissors pointed out this module does the trick Block Conditional Visibility by URI Query Parameters Thank you!

## Step 1

Download and enable `drush en block_query`

## Step 2

Go to blocks `admin/structure/block` and create a block or enable one of your choice. There are no specific configurations elsewhere. It's a very lightweight feature.

## Step 3

At the page of your block, under the "Visibility settings" you will now see "Queries" to "show block on specific pages", add the query parameter ONLY. E.g. if you have a destination parameter that leads to that particular page, only add the part behind the question mark `?`, not the entire path.

## Test it out

Let us know if it worked for you too.
> 0 votes

---
Tags: 7, users
---


# Question
Title: Drush cim: error "Table xyz already exists"
I'm trying to deploy a dev website to a dev server. When running `drush cim` on the dev server, drush ends with an error message:

> Table honeypot\_user already exists

When running `drush cim` again right after that, the same error comes up again for a while with different table-names. The database does definitely not have these tables before running the config import.

What's the underlying problem and how can I solve that?

Using drush 8.1.17 on a Drupal 8.3.7 (both running offline and soon to be updated for security patches)

# Answer
Like event said, and In my case, this was solved when the `drush cr` command is entered before `drush cim`
> 1 votes

# Answer
Did you try `drush cim --yes`

Same thing happened to me over the weekend. The

> --yes

flag seemed to fix the problem
> 1 votes

---
Tags: 8, drush
---


title: Variable in file-audio.html.twig

text:
# Question
Title: Variable in file-audio.html.twig
I created the following preprocess function to add a value.

```
function mytheme_preprocess_node__audio(&$variables) {
  $node = $variables['node'];
  $media_field = $node->get('field_image')->entity->uri->value;
  $variables['poster'] = file_create_url($media_field);
}

```

I want to output the content of `$variables['poster']` in the *file-audio.html.twig* template.

```
<audio {{ attributes }} poster="{{ poster }}">
  {% for file in files %}
    <source {{ file.source_attributes }} />
  {% endfor %}
</audio>

```

`{{ poster }}` outputs an empty string. I have tried multiple methods, with no success.

I can get the variable in the field template (*field--field-audio.html.twig*), but it is not available to the child file template I am using.

How do I get the value of `$variables['poster']` in the template file I am using?

# Answer
> 0 votes
So I figured this out, it was not straightforward or obvious, and I could find no forum or post detailing this method, so hopefully it helps others. The preprocess function changes to preprocess field as:

```
function MYTHEME_preprocess_field(array &$variables, $hook) {
  $element = $variables['element'];

  switch ($element['#field_name']) {
    // Machine name of the field
    case 'field_audio':
      $node = \Drupal::request()->attributes->get('node');
      // separate field (machine name = field_image) that holds image for poster
      $media_field = $node->get('field_image')->entity->uri->value;
      $variables['poster'] = file_create_url($media_field);
      break;
  }
}
```

Then in the field twig file (field--field-audio.html.twig), replace the appropriate item.content section (or all of them as I did, just in case!)

```
      {% set attr = item.content['#attributes']|merge({'poster': poster}) %}
      {% set mycontent = item.content|merge({'#attributes': attr}) %}

      <div{{ attributes.addClass(classes, 'field--item') }}> {{ mycontent }} </div>

```

Finally in the file-audio.html.twig template you just need to add the poster="{{poster}}" like:

```
<audio {{ attributes }} style="background: transparent url({{ attributes.poster }});">
```

I've done the same for Video, i.e. using a separate field for the poster of the html5 video tag, using the same method EXCEPT in the field template #attributes is #player\_attributes as you should be able to see in the file twig template, named video-player-formatter.html.twig in my case. Happy to post the code if anyone needs it.

Thanks to the drupal forums, twig documentation and of course stackexchange for the snippets I picked up along the way to figure this out.

---
Tags: theming
---


# Question
Title: How can I pass multiple values to drupal_view()?
I'm on Drupal 8 and I have a view with multiple argument (list of node ID) but I can't embed this on my node.twig.html.

That's my code:

```
{% set myArray = [] %}
{% for item in content.field_articles_lies['#items'] %}
    {% set myArray = myArray|merge([item.entity.nid.value]) %}
{% endfor %}

{{ drupal_view('articles_lies','default', myArray()) }}

```

if I do that: `{{ drupal_view('articles_lies','default', myArray.0) }}` it's ok but obviously only for one.

How can I pass an argument with multiple values to a view rendered via `drupal_view()` in a template?

# Answer
> 1 votes
You can't pass an array. You have to implode the array to a string first. And use `'+'` as glue for OR and `','` as glue for AND. Like `'1+2+3'` or `'1,2,3'`. And maybe you also have to enable *Allow multiple values* in your view (in the very bottom of the contextual filter screen).

I have try that and it works but I'm not sure it's very clear:

```
{% set arguments = '' %}
{% set i = 0 %}
{% for item in content.field_articles_lies['#items'] %}
    {% if i == 0 %}
        {% set arguments = item.entity.nid.value %}
    {% else %}
        {% set arguments = arguments ~ "+" ~ item.entity.nid.value %}
    {% endif %}
    {% set i = i + 1 %}
{% endfor %}

{{ drupal_view('articles_lies', 'default', arguments) }}

```

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


# Question
Title: Where do I fetch myself complete definition for a bundle?
I can fetch entity-type definition...

```
$entityType = \Drupal::entityTypeManager()
  ->getDefinition($this->entityType);

```

and I can fetch myself *some* of the bundle specific information...

```
if ($bundleName !== null) {
    $bundleConfig = $entityType->getBundleConfigDependency($bundleName);
    $config = HelperConfiguration::instance($bundleConfig["name"]);
    $configValues = $config->getConfigValue();
}

```

$configValues carries properties like description, preview\_mode, display\_submitted, even langcode, but what I cannot find, is how to find translatability status for a bundle.

On `/admin/config/regional/content-language` I can wonderfully manipulate translatability bulk-wise, from entity-coarseness, up to specific fields.

So, while there is an isTranslatable() method on `EntityTypeInterface` (and also on`FieldDefinitionInterface`), where is the bundle equivalent? Where is the rest of bundle's metadata hidden?

# Answer
To get the language specific configuration of a bundle use ContentLanguageSettings::loadByEntityTypeBundle.

For the translatability of the bundle, you'd use:

```
$settings = ContentLanguageSettings::loadByEntityTypeBundle($entity_type_id, $bundle_name);
$isBundleTranslatable = $settings->getThirdPartySetting("content_translation", "enabled");

```

You could also use ContentTranslationManager:

```
/** @var ContentTranslationManager $contentTranslationManager */
$contentTranslationManager = \Drupal::service('content_translation.manager');
$isBundleTranslatable = $contentTranslationManager->isEnabled($entity_type_id, $bundle_name);

```
> 5 votes

---
Tags: 8, entities, i18n-l10n
---


# Question
Title: How to set Class for a particular image style?
I'm trying to add a CSS class to a particular image style, in Drupal 8. For this purpose, I'm trying to set up a template, but am open to all solutions since I know I lack knowledge (I've been teaching myself this stuff over the past couple of months).

Specifically, I want all images with the style machine name 'feature\_main\_960\_x\_640\_' and field machine name of 'field\_image' to include the following class during 'Full content' view mode. I would like this class to be added to the img tag.

The purpose: to have my articles' feature images to be centered when the full content is being viewed.

Specifications: Drupal 8, theme is Bootstrap 3, using Display Suite module.

I've used Display Suite to add the Bootstrap 3's 'center-block' class. The class is added before the img tag, in a div. This doesn't center the image. I could only get the image to center when I manually added 'center-block' within img. I also used the Field Formatter Class module for this purpose and it also added the class to a div rather than img: so the problem persists.

So far, I've taken a sledgehammer to the problem and used the following template to apply the class to all images but would like to be precise in application, as mentioned above. This is the template I used:

image.html.twig

```
{% set classes = [
  theme.settings.image_shape ? theme.settings.image_shape,
  theme.settings.image_responsive ? 'img-responsive',
  'center-block',
] %}
<img{{ attributes.addClass(classes) }} />

```

Any solution?

# Answer
> 3 votes
In Drupal 8 you can do this with `hook_preprocess_image` in your themes `mytheme.theme` file.

```
/**
 * Implements hook_preprocess_image().
 */
function mytheme_preprocess_image(&$variables) {
  if ($variables['style_name'] == 'my_custom_image_style') {
    $variables['attributes']['class'][] = 'my_css_class';
  }
}

```

# Answer
> -2 votes
I found very simple solution. just add your custom bootstrap 3 style.css...will work as you want..applied over usps tracking site to look

```
.img-responsive{
  margin-left: auto;
  margin-right: auto;
  display:block
}

```

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


title: How can I have an URI with two GET?

text:
# Question
Title: How can I have an URI with two GET?
I wrote my custom rest endpoint. I need to 2 URI both called with GET

* /api/item/{id} to get single item identified by ID
* /api/item to get the list of items.

i try with

```
  @RestResource(
    id = "my_id",
    label = @Translation("My label"),
    uri_paths = {
      "canonical" = "/api/item",
      "https://www.drupal.org/link-relations/index" = "/api/item/{id}",
    }

```

into my class i have

```
class ApiRestResource extends ResourceBase {

    public function get($id = NULL) {

```

but only canonical URI is found. the message for the second URI is

```
"message": "No route found for \"GET /api/item/1\""

```

how can i have 2 GET in my class? thanks in advance

# Answer
> 3 votes
you can create two resource files, one that receives the parameter and another that does not.

Example:

> demo\_rest\_api.info.yml.

```
name: Demo REST API
description: Define's a custom REST Resource
package: Custom
type: module
core: 8.x

```

> /src/Plugin/rest/resource/DemoResource.php

```
<?php

namespace Drupal\demo_rest_api\Plugin\rest\resource;

use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;

/**
 * Provides a Demo Resource
 *
 * @RestResource(
 *   id = "demo_resource",
 *   label = @Translation("Demo Resource"),
 *   uri_paths = {
 *     "canonical" = "/api/item"
 *   }
 * )
 */
class DemoResource extends ResourceBase {

  /**
   * Responds to entity GET requests.
   * @return \Drupal\rest\ResourceResponse
   */
  public function get() {

      $response = ['message' => 'Hello, this is a rest service:'];

    return new ResourceResponse($response);

  }
}

```

> /src/Plugin/rest/resource/DemoResource\_item\_id.php

```
<?php

namespace Drupal\demo_rest_api\Plugin\rest\resource;

use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;

/**
 * Provides a Demo Resource
 *
 * @RestResource(
 *   id = "DemoResource_item_id",
 *   label = @Translation("Demo Resource item id"),
 *   uri_paths = {
 *     "canonical" = "/api/item/{id}"
 *   }
 * )
 */
class DemoResource_item_id extends ResourceBase {

  /**
   * Responds to entity GET requests.
   * @return \Drupal\rest\ResourceResponse
   */
  public function get($id= null) {

      $response = ['message' => 'Hello, this is a rest service and parameter is: '.$id];

    return new ResourceResponse($response);

  }
}

```

# Answer
> 0 votes
According to the RestResource documentation, uri\_paths are:

> Key-value pairs, with link relation type plugin IDs as keys, and URL templates as values.

Your second uri\_paths item needs a key to tell Drupal what kind of endpoint it is.

core.link\_relation\_types.yml contains the available types. In your case I'm going to hazard a guess that `item` is the most appropriate.

If that doesn't work, maybe try creating two classes.

# Answer
> 0 votes
this page , contains information that may interest you.

Just modify the path in your file: .routing.yml

```
test_api.getitemid:
  path: '/api/item/{id}'
  defaults: { _controller: '\Drupal\test_api\Controller\TestAPIController::getitemid_example' }
  methods:  [GET]
  requirements:
    _access: 'TRUE'

test_api.getallitem:
  path: '/api/item'
  defaults: { _controller: '\Drupal\test_api\Controller\TestAPIController::get_example' }
  methods:  [GET]
  requirements:
    _access: 'TRUE'

```

In your file: TestAPIController

add the functions

> getitemid\_example

```
public function getitemid_example( Request $request, $id=null ) {

    $response['data'] = 'your id parameter is:'.$id;
    $response['method'] = 'GET';

    return new JsonResponse( $response );
  }

```

# Answer
> 0 votes
I do not think for the same operation, We need to create multiple files.

Request URL: http://localhost/drupal/product-list?search=abc

```
use Symfony\Component\HttpFoundation\Request;

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "drupal_rest_api",
 *   label = @Translation("rest  api"),
 *   uri_paths = {
 *     "canonical" = "/product-list"
 *   }
 * )
 */

public function get( Request $request) {
        $search = \Drupal::request()->query->get('search');
        kint($search)

}

```

You can be added multiple arguments without creating multiple files

---
Tags: 8
---


# Question
Title: Database error: Lost connection to MySQL server at 'reading initial communication packet'
this has driven me crazy, I just couldn't find out what is wrong with it.

I moved my site onto a test directory under my domain '/drupal\_test', I have transferred the database over, set up everything properly, and then I got this error:

```
PDOException: SQLSTATE[HY000] [2013] Lost connection to MySQL server at 'reading initial communication packet', system error: 111 in lock_may_be_available() (line 167 of /var/www/drupal_test/includes/lock.inc).

```

I have set up settings.php like this:

```
$databases = array (
  'default' =>
  array (
    'default' =>
    array (
      'database' => 'websitedb',
      'username' => 'websitedbnm',
      'password' => 'thepass',
      'host' => 'xxx.xxx.xxx.xxx',
      'port' => '',
      'driver' => 'mysql',
      'prefix' => '',
    ),
  ),
);

```

I am really sure all the data is right. I can connect to my database through command lines using this account and I can also see all the right tables in this database.

I also tried commenting and editing this line:

```
$base_url = 'http://www.example.com/drupal_test';  // NO trailing slash!

```

I still get this error and can't see my site...what could have gone wrong?

# Answer
> 1 votes
If you are pretty much sure that database credentials are correct than please verify the `database hostname` because the reason of the above error is database configuration only.

# Answer
> 3 votes
To share a bit more detail: the reason for this is generally that your MySQL GRANT is configured as `user@localhost`. Therefore, connecting over the external IP address does not match the `@localhost` portion, and your connection is rejected. Specifically, because no users in the `mysql.user` table match the external address in their `host` column, the connection is rejected immediately. You can see this by the simple expedient of `telnet`ing to the port:

```
$ telnet example.com 3306
Trying 255.0.0.71...
Connected to example.com.
Escape character is '^]'.
FHost '255.0.0.70' is not allowed to connect to this MySQL serverConnection closed by foreign host.
$

```

As you can see, before authentication is even attempted, the connection is killed. If you had a `host` entry that could have satisfied this request, you would have gotten an authentication failed message, instead. But in this case, the connection died before authentication was even requested or sent, thus the lost connection at "reading initial communication packet"; the very first packet sent included a disconnection!

To resolve this, either use a `hostname` value in your databases array for which there will be a corresponding `host` column entry in the `mysql.user` table, or add an explicit grant that covers the use case, e.g.:

```
GRANT ALL ON drupal.* TO 'drupal'@'255.0.0.70' IDENTIFIED BY 'YjbW7dUT';
FLUSH HOSTS; FLUSH PRIVILEGES;

```

Note that you can also use '%' as a wildcard, as in:

```
GRANT ALL ON drupal.* TO 'drupal'@'255.0.0.%' IDENTIFIED BY 'YjbW7dUT';

```

or even:

```
GRANT ALL ON drupal.* TO 'drupal'@'%' IDENTIFIED BY 'YjbW7dUT';

```

Don't use this last one unless you have a firewall in front of your MySQL server. (Which you already have anyway, right? Right.)

**Bonus Section**

MySQL treats `localhost` specially. Specifically, `localhost` means to use the UNIX socket, whereas `127.0.0.1` means to use TCP/IP networking. Therefore, you can run into the strange case where the two are not interchangeable, despite the fact that in every other part of the \*NIX world, they are. This can commonly happen when you have `skip-name-resolve` specified in your `my.cnf`; your GRANTs for `localhost` now don't cover access over TCP/IP, and vice versa.

To fix, either add a `localhost` GRANT for each `127.0.0.1` one (and vice versa), or change all `host` columns in the `user` table to `%`—which, at the risk of repeating myself from earlier, should only be done if you are behind a firewall in which you are eminently confident.

# Answer
> 0 votes
Best way to handle this error is when you switch your drupal website from one host to another that delete your settings.php file and switch to host where you place your drupal website .then it ask to install drupal and their are two option first add new site and second use previous site if we select second option then your drupal site will appear their and new settings.php created automatically with require configuration...I solved problem this way

# Answer
> 0 votes
I had the same error, but the database configuration was correct.

*I'm using a multisite configuration.*

I knew the config was right because it was the same for other sites.

The error was in sites.php, the new site was not added to the list, once added it started to work again.

Writing this answer in case anyone has a similar issue. :)

# Answer
> 0 votes
In MySQL speak, system error 111 is ECONNREFUSED (e.g. from connect(2): "No one listening on the remote address."). This means that the client library was unable to connect to the database server. Either you spelled the server name/IP wrong, used the wrong port, or the server is not running and/or listening on the specified port at all.

To check if the server is there, run the command:

```
# 3306 is the standard MySQL port. Change if using other.
$ telnet mysql.example.com 3306

```

Don't be fooled by the "Lost connection" in the error message -- there never were a connection at first place.

# Answer
> 0 votes
For others who might stumble upon this question after their local Acquia Dev Desktop database suddenly stopped working after importing a database from a remote cloud server: restarting the Apache and MySQL servers fixed the error for me.

# Answer
> 0 votes
You must enable SSH TCP forwarding otherwise packets will drop.

In /etc/ssh/sshd\_config:

```
#AllowTcpForwarding yes

```

---
Tags: database
---


# Question
Title: How can I programmatically delete a custom menu?
I'm writing a `hook_deploy_N` that moves a bunch of menu items from a deprecated custom menu to some newer ones. So far, so good. After moving the items, I want to delete the old menu, but can't figure out how. `\Drupal\Core\Menu\MenuTreeStorage` has a `delete` function that **may** be what I'm looking for, but the `\Drupal\Core\Menu\MenuTreeStorage` object is housed inside the `\Drupal\Core\Menu\MenuLinkTree`, which I can at least load, but has protected status, and I don't see a way to get to it. Plus, I'm not not 100% convinced that's what I want any way.

# Answer
Since menus are configuration items, my poking into `\Drupal\Core\Menu\MenuTreeStorage::delete()` was wrong. You delete a custom menu thusly:

```
\Drupal::configFactory()->getEditable('system.menu.name-of-custom-menu')->delete();

```

Note that I'm assuming the menu is empty. I don't know what would happen if you deleted a menu that had menu items in it, whether they'd be orphaned or deleted.
> 0 votes

---
Tags: 8, navigation
---


# Question
Title: Are there migration plugins for D8 sources?
I found 2 references here for migrating D8 to D8, but both are very outdated.

Certainly there will be a need to do D7 -\> D9 or D8 -\> D9 migrations for many, but there are also current use cases. One is migrating from a multisite to individual sites.

Mine is the site restructuring its content types, and it would be far simpler to add custom code to a source plugin than to do all of it in custom code.

# Answer
> 2 votes
Yes there is. Drupal core has a `content_entity` source plugin that's a part of the Migrate Drupal module.

The one caveat with this plugin is it can only handle scenarios where the source/destination DB is the same, which sounds like your scenario here.

If source/destination DB isn't the same, the Drupal 8 migration provides a `d8_entity` source plugin that does support this scenario.

---
Tags: migrations
---


# Question
Title: How to hide body field in a view only on certain content types
I have a search result view of different content types, and i want to show the body field (trimmed) on some content types, but show no body on other content types. Since they all share the same body field, I would need to exclude the body field from displaying on the content types that I don't want to see them on.

Right now I am doing this with Views rewrite results and CSS. I add the content type field and exclude, then add the body field. Under rewrite results I rewrite the output of the body field with this:

`<span class="search-body-[type]">[body]</span>`

I then hide the content type bodies that I don't want to see with CSS:

```
span.search-body-MY-TYPE1,
span.search-body-MY-TYPE2 {
  display: none;
}

```

This works "visually", but the class and the trimmed body are still rendered in the HTML. Is there a better way to do this perhaps with a `views_pre_render` hook?

(I am completely inexperienced with PHP.)

# Answer
This can be done really easily with views\_conditional module. Once you enable the module, having the content type and body fields already added and excluded from display, do the following steps:

1. add a views conditional field
2. set the `if` condition to the \[type\] == Indexed Content: Content Type
3. set `is` condition to `contains`
4. Set the `value` to the content type name for the body that you want to display
5. Then in `Then output this...` Use the \[body\] replacement pattern

Works like a charm!
> 0 votes

---
Tags: 7, views, hooks
---


# Question
Title: I'm unable to access variables in template from preprocess function
I am using a preprocess function to get data from specific content types. I am able to print the data in the pre-process function but unable to view the same in the twig file.

This is the code I am using.

```
    function themename_preprocess_node__custom_content_type_name(&$variables) {
      $query = \Drupal::entityTypeManager()->getStorage('node')->getQuery();
      // Get all products node IDs.
      $nids = $query->condition('type', 'content_type_products')->execute();
      // Load all product nodes.
      $nodes = \Drupal\node\Entity\Node::loadMultiple($nids);
      // Pass them to node--custom-content-type-name.html.twig.
      $variables['products'] = $nodes;
     //echo "<pre>";
     //print_r($variables['products']); exit;
    }

```

`print_r($variables['products'])` shows the content of `$variables['products']`, but the *node--custom-content-type-name.html.twig* file doesn't print anything for `{{products}}`.

Why?

# Answer
> 2 votes
You need to apply EntityViewBuilderInterface::viewMultiple before you can render the nodes in a twig template:

```
$variables['products'] = \Drupal::entityTypeManager()
  ->getViewBuilder('node')
  ->viewMultiple($nodes);

```

Twig:

```
{{ products }}

```

You can add a view mode to viewMultiple() as second argument, for example `teaser`.

---
Tags: 8, theming
---


# Question
Title: How do I get block relationships for a content type?
As part of a migration from drupal 7 to drupal 8, I currently have a rather original node display method that I'm trying to reproduce to Drupal 8, but without success. Currently on Drupal 7, this method is filled by a custom preprocess that I try to remove in favor of views / entity reference.

**Here is the procedure:** I have a node type that contains tags (field\_tags), with for example the vocabulary 'news' from the 'Users terms' term. And basic content (title, body...). I would like, via an already existing block having a field tags and value 'news', recover all the nodes with the tag 'news'.

**Recap of entities I have tried:**

**Node:** \- title \- body \- field\_tags / value: 'news' (reference to "User terms")

**Views name 'flow':** \- display: content \- contextual filter: 'Content: Has taxonomy term ID' \> 'Display all results for the specified field' & Content: Nid \- relationsips: nothing, because I can't add a entity reference to a block

**Block name 'block flow' :** \- title \- field\_tags / value: 'news' (reference to "User terms")

I would like when I create a block type 'block flow' with 'news' tags, **get all node type that containing the 'news' tag.**

I can't get it working **because the views relationships don't allow me to reference the field 'field\_tags' from my block** (only content or taxonomy available). We have a theme preprocess who can do that but I would like to know if there is a workaround ou any contrib module doing that.

Why I don't create a block from the view? Because in our process, we don't give access to the views of our contributors.

# Answer
> 0 votes
Finally, I got this working by creating a simple view "custom block". Then, I created 3 relations, one for my node content, one for my content tags and last one for block tags

After that, we just need a contextual filter : Content: Has taxonomy term ID' \> 'Display all results for the specified field

And that's all.

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


# Question
Title: How can I create 301 redirects from "unclean" URLs?
I am moving a Wordpress site to Drupal and want to ensure that proper 301 redirects are in place for SEO purposes.

The old urls are in the form of: `http:www.domain.com/?page_id=123`

I was hoping this would be simple enough with the Redirect module, but when attempting to enter a path such as `?page_id=123` I see the following message.

> The source path /?page\_id=123 is likely a valid path. It is preferred to create URL aliases for existing paths rather than redirects.

I want to be absolutely sure that a 301 redirect is created but I am unsure that adding an alias is the correct method for this.

Another approach I have considered is adding the following code to the .htaccess file in the web root.

```
Redirect 301 /?page_id=123 https://www.exacmple.com/node/321

```

Again, I am unsure if this approach is recommended for Drupal 8.

How should I add redirects and avoid the new Drupal site is penalized in search results?

# Answer
The warning you're seeing is generated by the Redirect module when you try to redirect from a *path* (the part without the query string) which is already a valid Drupal path, which is true for your case (your redirect's source path is the site root, `/`): https://git.drupalcode.org/project/redirect/-/blob/8.x-1.x/src/Plugin/Field/FieldWidget/RedirectSourceWidget.php#L68. The query string is ignored in this validation step.

Without a query parameter, this would "cover up" the existing path and make it inaccessible, which is why the warning exists. But since your redirect does specify a query, this isn't a problem - the redirect only happens if the query matches `?page_id=123`.

The warning should be safe to ignore; your initial approach was likely correct.
> 1 votes

---
Tags: 8, redirection
---


# Question
Title: Can we use one product for multiple display nodes in Commerce D8?
I used to work with Drupal 7 Commerce and now I need help to work on D8 Commerce.

I have nodes on my D8 website and I need to sell them through Drupal Commerce. Each node can be sold in the same conditioning with four variations, based on customer types.

I have created a store, a product variation type, an attribute, a product type and one product with four variations, considering that one product would be enough.

Each node needs to be available as an order item. For that, I have added an entity reference field, linked to the product type. I have thus filled the default value with the product created.

Now on each node page, I have my add to cart button (through Commerce block or custom Views block, it works).

My problem :

Viewing the node A, I choose the variation and add the product in the cart and everything is fine.

Viewing the node B, I choose the exact same variation and add the product and there I need a second order item line with the node title (added through Views with relation to the entity reference field, not the issue here).

Unfortunately I get one order line item with quantity 2 (if I add the node title, I get two order line items with quantity 2 for each).

It may look obvious but I need to know if I really have to create one product with four variations for each node (2000+)?

Or is there a way to achieve this with D8 Commerce with only one product?

My concern here is to use properly Drupal Commerce and of course avoid the long multiple creation of products, especially in the future for my end user.

Related threads:

Automatically generate product variations

# Answer
Drupal 8 Commerce does not need product display nodes anymore. When we create a product, we get a page automatically for this product.

But if you need, like me, to keep a "node environment" on your website then you will have to create as much products as nodes and link them through an entity reference field (Type : Reference \> Other...)

To create products, variations and links between nodes and products, I use Feeds, Commerce Feeds and Feeds Tamper. In my case, each feed type is based on upload file technique with CSV file created from Excel.

First, you build a Variations Feed type to create product variations with simple data (sku (unique), price, your\_attribute). In my case, customer type was the attribute.

Second, you build a Products Feed type to create products using variations imported before (title (unique), variations (skus), store (required, ID=1 if you have only one). Here goes Feeds Tamper with List explode to get multiple variations for one product.

Third, you build a Nodes feed type to link nodes and products with two data (node title (unique), product title (in entity reference field)).

Finally, you get display nodes with specific products and variations and when you add to cart, products are well separated.

Hope this helps.
> 0 votes

---
Tags: 8, commerce
---


# Question
Title: View showing a list of tagged nodes related to term reference field
Drupal 7

Taxonomy vocabulary = Company activity (Activity 1, Activity 2, Activity 3 ….). This vocabulary has an OG group field.

Content type 1 = Company with an entity (terms) reference field showing the list of the terms of the activity vocabulary. The widget is “radio button box” and the administrator of the Company, during the creation of the content, may tag and save the appropriate activities performed. This content type has an OG group field. Example: Company 1 --\> tag Activity 1 and Activity 2 – Company 2 --\> tag Activity 1 and Activity 3

Content type 2 = Request of Service. Any Company can create a new request of service and first of all choose the needed activity in a entity (terms) reference field (fiel\_tipologia\_macchina) showing the list of the terms of the activity vocabulary. The widget is “selection list” – only one choice. This content type has an OG group audience field.

Now the question: In Content type 2 (request of service) I need to add a field that show the Company qualified to perform the requested service. Example: the service requested is “Activity 1” --\> show Company 1 and Company 2.

The field has to be a radio button box so the author of the request can choose the company to send the request (one or more company).

I think that I have to use a view (page or block) but I am not able to find the right relation and contextual filters (entity reference or OG).

Thank you in advance for help.

# Answer
> 0 votes
I have accomplished something along the lines of what you describe with a combination of a `hook_form_alter` and some Javascript. The following should help you set up something that will interactively enable/disable possible company choices based on the selected activity. Take note that it really only works if those inputs are selects and not Drupal's default autocompletes.

In a `hook_form_alter` directed at the "Request" node and node edit forms, create a simple of array of arrays, where the key is the term IDs of the activity, and the subarrays are the node IDs of the companies. Here is some pseudo-code, since I don't the actual structures of your entities:

```
$nested_array = [];

$term_query = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->getQuery();
$term_ids = $term_query->condition('vid', 'activity')->execute();

foreach($term_ids as $term_id) {
    $node_query = \Drupal::entityTypeManager()->getStorage('node')->getQuery();
    $node_ids = $term_query
      ->condition('type', 'company')
      ->condition('field_ref_activity', $term_id, 'IN')
      ->execute();

    $nested_array[$term_id] = $node_ids;
 }

 $form['#attached']['drupalSettings']['company_activities'] = $nested_array;
 $form['#attached']['libraries'][] = 'my_module/my_module.library_name';

```

The above makes the nested arrays available to the front end for on-the-fly manipulation. Create a library for your module with this jQuery-based Javascript. Again, pseudocode which you'll have to modify to your form structure:

```
function limitCompanySelection(selected_activity) {
    let allowed_companies = drupalSettings.company_activities[selected_activity.val()];

    $('company-input-selector option').each(function(){
        if ($.InArray($(this).val(), allowed_companies)) {
            $(this).prop('disabled', false);
        }
        else {
            $(this).prop('disabled', true);
        }
    });
}

```

Set the above function to run on initial load and every time the selected activity is changed, finding the selected activity and passing it into the function.

# Answer
> 0 votes
Hi Beltouche and thank you.

After two months of mental confusion, finally I solved the problem with https://www.drupal.org/project/reference\_option\_limit.

I followed this post: https://www.drupal.org/docs/7/modules/reference-field-option-limit/examples (Example 3) but I fixed my brain to use in the *Request* content a new entity ref field pointed to the activity vocabulary.

This was wrong because I should use, as conditional value, the existing field in the *Company* content. Now the dipendent entity ref field shows only the Companies that tagged the specific activity in their own account and this is perfect.

In any case, thank you very much for cooperation. Ciao.

Closed.

---
Tags: entities, organic-groups
---


title: Print author details for a node

text:
# Question
Title: Print author details for a node
How do I print the author details for a node? In particular, I am interested to the following values.

* Author picture
* Name
* Description

In Drupal 7, I would use this code.

```
<?php print $author_data['picture'];?>
<?php print $author_data['name']; ?>
<?php print $author_data['description']?>

```

What is the equivalent in Drupal 8?

# Answer
> 7 votes
You can see the available variables at the top of the twig file, two are already there:

> * author\_picture: The node author user entity, rendered using the "compact"
> * author\_name: Themed author name field.

For other fields of the author you can print the field value:

```
{{ node.Owner.name.value }}

```

And description, if you have added this field to user:

```
{{ node.Owner.description.value }}

```

# Answer
> 10 votes
This is what worked for me in the node template for any custom field:

```
{{ node.uid.entity.field_name.value }}

```

I'm using Drupal 8.3.7

**EDIT:** This is what I'm doing for the profile picture. I'm creating a rendering object so I can specify a theme and an image style:

```
            {% set imagestyle = {
              '#theme':      'image_style',
              '#style_name': 'user_avatar_80x80',
              '#uri':        node.uid.entity.user_picture.entity.uri.value,
              '#attributes': { class: 'authorImg' },
            } %}
            <div class="authorCol1">{{ imagestyle }}</div>

```

# Answer
> 0 votes
You can use `<span>{{ 'Author: '|t ~ author_name|striptags }}</span>` in Drupal 8.

---
Tags: 8, theming, nodes
---