title: How can I get all comments for a node?

text:
# Question
Title: How can I get all comments for a node?
I have have a content type (*Stuff*) with an entity reference field (*comments*) for comments (their type is *Stuff comments*) with a single field (*comment\_body*).

Inside a controller, I loaded a node by its ID.

How do I get the list of all the comments for that node?

# Answer
> 3 votes
To answer my own question I guess(better alternatives are more than welcome).

```
use Drupal\Core\Entity\EntityTypeManagerInterface;

class SomeRepository {

  /**
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entity_type_manager;

  /**
   * ProductRepository constructor.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entity_type_manager = $entity_type_manager;
  }

  /**
   * @param $node_id
   *
   * @return array|null
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getNodeComments($node_id) {
    try{
      $node = $this->entity_type_manager
        ->getStorage('node')
        ->load($node_id);
    }catch(\Exception $exception) {
      // log here
      // rethrow error or return, whatever works for you
      return NULL;
    }

    try{
      $comment_ids = $this->entity_type_manager
        ->getStorage('comment')
        ->getQuery('AND')
        ->condition('entity_id', $node->id())
        ->condition('entity_type', 'node')
        ->sort('cid', 'DESC')
        ->execute();
    }catch(\Exception $exception) {
      // log here
      // rethrow error or return, whatever works for you
      return NULL;
    }

    if(empty($comment_ids)) {
      return [];
    }

    $comments = $this->entity_type_manager
      ->getStorage('comment')
      ->loadMultiple($comment_ids);

    $comments_array = [];

    foreach($comments as $comment) {
      // Loop over and get whichever fields you want from the comments
      $comments_array[$comment->id()] = [
        'cid' => $comment->id(),
        'owner_id' => $comment->getOwnerId(), // node to which this comment belongs
        'some_field' => $comment->get('some_field')->value
      ];
    }

    return $comments_array;
  }
}

```

# Answer
> 3 votes
Assuming the your node is a variable $node:

```
$entity_manager = \Drupal::entityTypeManager();
  try {
    /** @var \Drupal\comment\CommentStorageInterface $storage */
    $storage = $entity_manager->getStorage('comment');
    /** @var \Drupal\comment\CommentFieldItemList $commentField */
    $commentField = $node->get('comment');
    $comments = $storage->loadThread($node, $commentField->getFieldDefinition()->getName(), \Drupal\comment\CommentManagerInterface::COMMENT_MODE_FLAT);
    if (empty($comments)){
      return;
    }
    /** @var \Drupal\comment\Entity\Comment $comment */
    foreach ($comments as $comment) {
      //Logic here
    }

  } catch (\Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException $e) {
  } catch (\Drupal\Component\Plugin\Exception\PluginNotFoundException $e) {
  }

```

This will get you all the comments of that node. You can play with the `\Drupal\comment\CommentManagerInterface` to get a threaded version of the comments.

# Answer
> -1 votes
You can do something like

```
foreach ($stuff->get('comments')->referencedEntities() as $comment) {
   ..do whatever on entity comment ..
}

```

---
Tags: 8, nodes, comments
---


title: Question about admin role

text:
# Question
Title: Question about admin role
Does the admin role always has access to everything ?

Because even if my AccessResult returns false, my admin still have acces to it (but it's perfectly working for the other roles)

# Answer
Not the admin role, no. But user 1 does have access to everything, yes.

This is the function responsible, `User::hasPermission`, you can see the unconditional access check at the top:

```
public function hasPermission($permission) {
    // User #1 has all privileges.
    if ((int) $this->id() === 1) {
      return TRUE;
    }

    return $this->getRoleStorage()->isPermissionInRoles($permission, $this->getRoles());
  }

```
> 2 votes

---
Tags: 8
---


# Question
Title: How to display the user's image in a Message Template?
I activated the sub-module "Message Example" of the module "Message".

I added the token in the "Example - User register" message template :

```
[message:author:user_picture:thumbnail]

```

When a message is created, it displays the url of the user's image.

How to display the user's image in a Message Template ?

# Answer
> 1 votes
You can use the following token: `[message:author:user_picture]` i.e. same as yours with the thumbnail subsection

UPDATE: In order to get the image styles to work I had to switch to "Full HTML" text filter, then while editing the "Source" I added this line:

`<img src="[message:author:user_picture:thumbnail]" />`

And it worked for me like this.

---
Tags: 8, tokens, message-subscribe
---


title: Drupal quiz permissions per role

text:
# Question
Title: Drupal quiz permissions per role
How can I set Drupal role to a quiz? I will have more quizez and more roles. Each roles has its quiz.

I have a Drupal 7 with quiz module.

I tried different approaches using node acces and acl and did not work.

# Answer
> 0 votes
If *node access* and/or *acl* are not sufficient to fit your needs, you should have a look at the Group module, either for D7, or D8. To get an idea of what is possible with this module, checkout some of my answers about questions tagged with .

In your case, if you just assign each quiz to an appropriate group, the magic included with the Group module should help you to implement what your question is about.

---
Tags: 7, quiz
---


# Question
Title: Add a svg icon before a link in menu YML
I've created a link menu and I want to add a SVG icon before it.

This is my YML :

```
double_vue_klesia.listeSwitch2:
  title: 'Double vue Klesia'
  route_name: double_vue_klesia.listeSwitch
  menu_name: navigation-principale
  weight: 4
  options:
    attributes:
      class:
        - listeSwitchMenuItem

```

I though adding a class and in CSS, adding the svg content would do the trick, but clearly it doesn't because it's breaking menu CSS.

This is my css :

```
.listeSwitchMenuItem::before{
  content: url(../images/active.svg);
}

```

Is there another way more clean to do this through YML directly ?

# Answer
Presumably this is for the top level of the admin toolbar...

If you want to follow core strictly you could convert your image file to an inline data: image string, but the benefits are negligible.

The icon is purely CSS, not configured, so nothing in the YML can help to control it.

You could, probably, theoretically, add a "style" attribute and put it inline, but you're in the realms of bad practice at that point.
> 1 votes

# Answer
agree with @Clive on comment, but do you want(not before):

> class: not needed

```
  attributes:
    class:
      - listeSwitchMenuItem
    style:
      - "background:url('url-image.svg') no-repeat 0px 0px;background-size:3px 3px"

```
> 0 votes

---
Tags: 8, navigation
---


title: The directory does not exist

text:
# Question
Title: The directory does not exist
### TL;DR

In Report → Status, I’ve the following error:

`Writable (public download method)
The directory /var/priv_fls does not exist. You may need to set the correct directory at the file system settings page or change the current directory's permissions so that it is writable.`

**How can I solve this error?**

### Full Story

In my webhosting at Forpsi, I’ve got FTP access to folder, in which there is `www` folder (let’s call this folder `web_root`). I’ve installed Drupal 8 in `web_root/www`. Then, I’ve added to `web_root` I’ve created a folder called `priv_fls`—for private files—and chmod’ed its permissions to 777 (I know it’s not secure). In `web_root/www/sites/default/settings.php` the following line: `$settings['file_private_path'] = '/var/priv_fls';` and Cleared all caches (in Drupal). Then the error above appeared.

It might be that it is not `/var/priv_fls` from Drupal’s point of view, but even tried to change it `/priv_fls` in `settings.php`, but the error remained.

**Update**

I emphesise that `web_root` is only a *substitution* for the ‘root’ folder to which my webhosting provider (Forpsi) gives me access. If I login to the server using FTP, this `web_root` folder lists the following files:

```
/> ls
drwxr-xr-x    9 66573      users            4096 Sep  5 20:10 .
drwxr-xr-x    9 66573      users            4096 Sep  5 20:10 ..
-rw-rw----    1 66573      users               7 Sep  1 02:39 .ftpquota
dr-xr-xr-x    2 0          0                4096 Jul 15 22:01 backups-forpsi
drwxr-xr-x    2 66573      users            4096 Sep 23  2010 data
drwxrwxrwx    2 66573      users            4096 Sep  5 20:10 priv_fls
drwxr-xr-x    3 66573      users            4096 Sep  1 12:54 softaculous
drwxr-xr-x    2 66573      users            4096 Sep 23  2010 stat
drwxr-xr-x    2 66573      users            4096 Sep 23  2010 tmp
drwxr-xr-x   10 66573      users            4096 Sep  4 19:40 www

```

But I can’t get the absolute path (`pwd` gives me `ftp://user@server.com:/>`; `ls ..` gives me same output as `ls`; both of which are useless from the point of getting the absolute path).

Anyways, Drupal is installed on **shared** webserver.

# Answer
### TL;DR

`web_root` = `/web/htdocs4/username/home/`, where `username` is (at least in my case) my ftp login (they use the following convension: for domain `example.com` the `username` is `examplecom`)

### Full Story

I’ve just accidently found out what is the absolute path of the `web_root`.

I installed TCPDF module and enabled both TCPDF and TCPDF Example. The latter created a link `TCPDF example` in the second (right) sidebar, and when clicked that link, it showed me the following error:

`Fatal error: Class 'TCPDF' not found in /web/htdocs4/username/home/www/modules/tcpdf/src/TCPDFDrupal.php on line 16`
> 0 votes

---
Tags: 8
---


# Question
Title: What is the name of the table where view modes are stored?
We have 10 view modes that we created. When we run `drush @env cex sync` in our local we are able to export the config files related to these view modes such as `core.entity_view_mode.node.related.yml` (where related is the view mode).

Is there a database table where these View modes are stored? If so, what is the name of it?

We are not using Display Suite or Panels, just the out of the box View Modes from Core. We do not plan to add those modules.

Goal:

1. Find out what view modes are being used programmatically.
2. Delete all view modes that are not being used.

Definition of `not being used`:

1. `Article` content type has 3 custom view modes: `listing, minimum, related`
2. `Basic Page` content type has an Entity reference to `Article` pages where the `Article view mode = listing` under `Basic Page Default View Mode`.
3. Custom view modes `listing` and `minimum` are not being used. However, if we consider all content types (e.g. 10 more content types) then it will be a pain to have to go through one by one.

# Answer
> 1 votes
The configuration is stored in the **config** table

```
mysql> describe config;
+------------+--------------+------+-----+---------+-------+
| Field      | Type         | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| collection | varchar(255) | NO   | PRI |         |       |
| name       | varchar(255) | NO   | PRI |         |       |
| data       | longblob     | YES  |     | NULL    |       |
+------------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

```

This is an example query from the *umami demo profile*:

```
    mysql> select name from config where name like 'core.entity_view_display.node.article.%';
+-------------------------------------------------------+
| name                                                  |
+-------------------------------------------------------+
| core.entity_view_display.node.article.card            |
| core.entity_view_display.node.article.card_common     |
| core.entity_view_display.node.article.card_common_alt |
| core.entity_view_display.node.article.default         |
| core.entity_view_display.node.article.full            |
| core.entity_view_display.node.article.rss             |
| core.entity_view_display.node.article.teaser          |
+-------------------------------------------------------+
7 rows in set (0.00 sec)

```

# Answer
> 3 votes
View modes are stored in the configuration entity `entity_view_mode` which you can load like any other entity:

```
$view_mode = \Drupal::entityTypeManager()
  ->getStorage('entity_view_mode')
  ->load('node.teaser');

```

To load all view modes for the entity type `node`:

```
$view_modes = \Drupal::entityTypeManager()
  ->getStorage('entity_view_mode')
  ->loadByProperties(['targetEntityType' => 'node']);

```

View modes don't store much data other than a label for the view mode name.

How a view mode is displayed for a specific content type is stored in a different entity:

```
$display = \Drupal::entityTypeManager()
  ->getStorage('entity_view_display')
  ->load('node.article.teaser');

```

The usage depends on how you define what being used means. If you mean with not used that it is not configured in a content type, which you can query in the config entities mentioned before, this doesn't mean necessarily, that the view mode is not used anywhere. If you configure an entity to be displayed in a view mode, for example in a View or a entity reference field, and this view mode is not configured in the content type, then it fallbacks to the default view mode.

---
Tags: 8, nodes, hooks
---


title: Dependency Injection Syntax

text:
# Question
Title: Dependency Injection Syntax
I'm trying to build a simple module (to learn DI) to return the current user ID, and and apparently I'm missing something in the syntax.

Here's my code and the error it's producing:

```
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\HttpFoundation\Response;

 class LSWController {
  /**
   * @var AccountProxy
   */
     protected $currentUser;

     public function __construct(AccountProxyInterface $currentUser) {
         $this->currentUser = $currentUser;
     }

     public function say() {
         return new Response("Hello");
        //return new Response($this->currentUser->id());
     }
 }

```

and the error

ArgumentCountError: Too few arguments to function Drupal\lsw\Controller\LSWController::\__construct(), 0 passed in C:\wamp64\www\testdrupal\core\lib\Drupal\Core\DependencyInjection\ClassResolver.php on line 31 and exactly 1 expected in Drupal\lsw\Controller\LSWController-\>\__construct()

What am I missing? I'm including the AccountProxyInterface, etc. How come it's saying that 0 arguments are being passed?

# Answer
> 5 votes
Classes aren't naturally aware of the container, you have to implement them in such a way that they are. The most common approach for controllers is to extend `Drupal\Core\Controller\ControllerBase`, and override the `create` method, e.g.

```
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\DependencyInjection\ContainerInterface;

class LSWController extends ControllerBase {
  /**
   * @var AccountProxy
   */
   protected $currentUser;

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

   public function __construct(AccountProxyInterface $currentUser) {
     $this->currentUser = $currentUser;
   }

   public function say() {
     return new Response("Hello");
     //return new Response($this->currentUser->id());
   }
}

```

For you, though, this approach will be bittersweet...on the one hand you've learned how to inject services into a controller, which is great.

On the other hand, `ControllerBase` already has a `$currentUser` property, which resolves to the same object you'd be getting from the injected service. So in applying the common solution, you've removed your original need for DI, and made the `create` and constructor methods completely redundant ;)

As 4k4 very correctly points out in a comment, you don't have to extend `ControllerBase`; implementing `ContainerInjectionInterface` in your own controller class is enough. But the deliciousness of solving the problem with less code than when you started is surely too much to resist.

# Answer
> 2 votes
You need to inject the services through a public static function called create. In your case something like this:

```
   /**
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   *
   * @return static
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('current_user')
    );
  }

```

The services you load through the container should match those in your `_construct` function

---
Tags: 8, dependency-injection
---


title: How can I add CSS or JavaScript files?

text:
# Question
Title: How can I add CSS or JavaScript files?
I want to include a CSS and a JavaScript file, without linking them to a theme in particular.

Sometimes, I create small sites without modifying the theme at all, but I still need some minor CSS/JavaScript changes that don't justify creating a sub-theme. I wouldn't mind creating two "quick" and "global" files directly on the Drupal directory just for that.

Can this be done?

# Answer
> 5 votes
Add a module, give it a libraries file (MODULE.libraries.yml):

```
global:
  js:
    /js.js: {}
  css:
    theme:
      /css.css: {}

```

In the .module file, implement `hook_page_attachments`:

```
function MODULE_page_attachments(array &$attachments) {
  $attachments['#attached']['library'][] = 'MODULE/global';
}

```

When you enable the module (or clear cache if it's an existing module), the CSS and JS will be included on every page.

---
Tags: 8, theming
---


title: Track field dependency with features

text:
# Question
Title: Track field dependency with features
I modified a field dependency on my `Call` content type. Features did not track the change automatically. I cannot figure out how to manually add it to features.

# Answer
> 0 votes
This is a way to it:

* Add the *feature exportable* manually to the *module.info*.
* You can check the available features with the `drush features-list` command. You have to find the *field dependency* format within that list, it could be a variable that looks like your field name.
* If you *module.info* has the new *field dependency*, you can update the feature `drush fu myfeature_module`
* Then review the generated files, maybe with `git diff`. You should see the change.

I am not sure what an exported *field dependency* looks like, there are different formats, these are examples so that you have an idea of what it would look like:

```
features[ctools][] = field_group:field_group:1

features[ctools][] = strongarm:strongarm:1

features[features_api][] = api:2

features[field_base][] = field_image

features[field_group][] = group_teaser|node

features[field_instance][] = node-about_page-field_image

features[node][] = about_page

features[variable][] = comment_about_page

```

---
Tags: 7, features
---


# Question
Title: How to add a language dropdown switcher to top panel?
I try to create a multilingual (3 languages, incl. English) website, and I’d like to create a language dropdown switcher (ideally in the top panel/menu). I tried to accomplish this using Flags, and Language Dropdown Switcher, but couldn’t display it though. It presume, I just don’t know how to add it in a block; although I could find the Language Dropdown Switcher in the block and add it there, but it did not show up. I could set the Flags up in the Configuration, but I did not find it in the blocks.

How do I install/enable/place a language dropdown switcher (preferably Flags, but this is not a condition)? It would be awesome (again: this is not necessary) if this switcher would be in the top panel and that it would contain country flags only (not the language as text).

Drupal 8.5.6 with `configuration translation`, `content translation`, `interface translation` and `language` enabled and the particular languages are already added in the configuration.

# Answer
I believe Flags does not integrate with `Language switcher dropdown` (contrib module) it only integrates with the core `language switcher block`

Here is some alternatives

# 1. Language Switcher Dropdown \+ languageicons

* Install both modules
* Go to `config > regional and language > language icons` and choose
> **Icon placement**
> Before link
> After link
> Replace link
* Go to `Structure > block layout` add `Language dropdown switcher` block to your desired region

# 2. Bootstrap Languages

Compatible with bootstrap based themes only

* Install module
* Go to `Structure > block layout` add `Bootstrap Language switcher` block to your desired region

# 3. dropdown\_language

With this module icons have to be setup manually using css
> 2 votes

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


# Question
Title: How to hide child field collection using jquery
I have 3 field collection 1st is parent in that having other 2 is child field collections.

* parent FC: Student Info
* child FC 1: English Info
* child FC 1: Maths Info

Set field setting "unlimited" to parent field collection(i.e Student Info).

Now I want hide 2 child field collection (i.e English Info and Maths Info) on click of "Add another item" I have hide child FC using jquery

For exmaple:

```
jQuery('.child1').hide();

jQuery('.child2').hide();

```

Child field collection hide initially, but if I click "Add another item" button then jquery removed and child FC shows. I have tried to bind click event in jquery but it's not working.

# Answer
> 1 votes
Can you replace the code in your JS file with the following:

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

  'use strict';

  Drupal.behaviors.myModuleName = {
    attach: function (context, settings) {
        $('#node-student-form .field--type-field-collection .field--name-field-child-english-info').css("display","none"); // Child FC 1
        $('#node-student-form .field--type-field-collection .field--name-field-child-maths-info').css("display","none"); // Child FC 2
    }
  };

})(jQuery, Drupal, drupalSettings);

```

This is based on this article
The `attach()` function ensures that your code runs each time an Ajax call is made

---
Tags: 8, entities
---


# Question
Title: What are the conditions for the "is one of" operator being enabled for filters on a particular field?
When I am creating a filter on a field, the "is one of" operator is not available. What are the necessary condition for the "is one of" operator to be available for field.

I have seen an example in which the "is one of" operator is available for taxonomy values. What is it about taxonomy values that make the operator available for them?

# Answer
`'Is one of'` operator in views filter aka `OR`operator in SQL, it is only available for list fields or fields with allowed values that means any field which has the select list, radio buttons, or checkboxes widget can have and use `'Is one of'` operator in views filter.

Theoretically, any reference field or any list field should have `'Is one of'` operator available in views filter.
> 2 votes

# Answer
It appears that Views Reference Filter is meant to be a fix for this, but there are a number of critical looking bugs on it.
> 0 votes

---
Tags: 7, views
---


title: Error sending e-mail when using webform

text:
# Question
Title: Error sending e-mail when using webform
I know there are already several posts about this subject, but I couldn't find a similar problem. I have several webforms on my site. Each webform has an email action, sending an e-mail to only one recipient. When submitting the form, I get a "Unable to send e-mail. Contact the site administrator if the problem persists." message. However the e-mail is sent without any problem. When looking into the dblog, I see an error:

> Error sending e-mail (from blabla@mydomain.com to )

Note that the e-mail I wrote is not the real one ;-). So it seems that my site is trying to send an e-mail to an empty recipient (in addition to the correct recipient). If I look into the database, in the "webform\_emails" table I see 1 single line for my webform, corresponding to the right recipient. So, why does webform try to send an e-mail to nothing?? Any idea? Thanks, Pierre

# Answer
> 0 votes
My problem is not due to webforms but to a rule that is triggered when a webform is saved. The condition I put in the rule needs to be fixed, in order to run only for a specific webform.

---
Tags: webforms
---


# Question
Title: Error when attempting to create sync directory
I'm installing Drupal 8 with using Composer. During the requirements verification phase I receive this error.

> Requirements problem
> Errors found
>
> Configuration directory: sync
> An automated attempt to create the directory ../config/sync failed, possibly due to a permissions problem. To proceed with the installation, either create the directory and modify its permissions manually or ensure that the installer has the permissions to create it automatically. For more information, see INSTALL.txt or the online handbook.

As I understand it, the full path to the sync directory should be project\_root/web/sites/default/files/config/sync, but if I run `chown myuser:www-data` to the project\_root directory, Drupal will literally place the folder as in the error message, project\_root/config/sync in my case.

I've never installed Drupal 8 via Composer, but this appears wrong and I can't find any relevant information.

# Answer
Nothing wrong with that.

It is recommend to have the *config* folder *outside* of the public web folder; Drupal just doesn't have that. To keep the installation simple for non-experienced users, it puts that folder in the *files* folder, which has to be writable anyway.

Just create that folder and give Drupal write permission to it; you'll be fine.
> 14 votes

# Answer
I just came across this problem with a Drupal 8.3 installation. Drupal couldn't create a directory outside the public web folder (*web*, when you install with Composer) due to permission settings.

Create the *config* and *config/sync* directories in Drupal composer directory (*../web*).
> 4 votes

# Answer
The path to the directory is to be created to related to the web root of your D8 installation.

In your scenario: you are on https://myd8/core/install.php, executing the script "../web/core/install.php". Please be sure your D8 has wite permission to the "../config" directory.

From the command line point of you, you need to have something like:

```
a@mydebian ~/Public/d8_composer $ ll
total 372
drwxrwxr-x  7 a a   4096 set  7 09:48 ./
drwxr-xr-x 26 a a   4096 set  7 08:52 ../
-rw-rw-r--  1 a a   2378 set  7 09:07 composer.json
-rw-rw-r--  1 a a 288832 set  7 09:08 composer.lock
drwxrwxrwx  3 a a   4096 set  7 09:48 config/
drwxrwxr-x  4 a a   4096 set  7 08:52 drush/
-rw-rw-r--  1 a a    357 set  7 08:57 .editorconfig
-rw-rw-r--  1 a a    746 set  7 08:52 .env.example
-rw-rw-r--  1 a a   3858 set  7 08:57 .gitattributes
-rw-rw-r--  1 a a    466 set  7 08:52 .gitignore
-rw-rw-r--  1 a a  18046 set  7 08:52 LICENSE
-rw-rw-r--  1 a a    414 set  7 08:52 load.environment.php
-rw-rw-r--  1 a a    481 set  7 08:52 phpunit.xml.dist
-rw-rw-r--  1 a a   6502 set  7 08:52 README.md
drwxrwxr-x  3 a a   4096 set  7 08:52 scripts/
-rw-rw-r--  1 a a   1875 set  7 08:52 .travis.yml
drwxrwxr-x 51 a a   4096 set  7 09:08 vendor/
drwxrwxr-x  7 a a   4096 set  7 08:57 web/
a@mydebian ~/Public/d8_composer $

```
> 1 votes

---
Tags: 8, installation, composer
---


title: Different 404 behaviour on custom URL

text:
# Question
Title: Different 404 behaviour on custom URL
For a client's website I have these URLs:

```
library
library/{category}

```

I have a ParamConverter to verify that {category} is correct and return the taxonomy term. And each URL requires a "view library" permission which anonymous doesn't have.

The client's requirements are that 404 errors redirect the user to the login page if not logged in.

I created a `RedirectOn404Subscriber` event subscriber to handle the 404 and redirect as needed. (I have tested it with a logged-in user and can redirect using this.)

When not logged in the redirection works fine for any obvious URL error:

```
example.com/xxxxx

```

And works for these:

```
example.com/library
example.com/library/valid-category

```

But this does not redirect:

```
example.com/library/invalid-category

```

It generates the 404 error but does not hit the redirect code.

It's as if it's not executing the ParamConverter when it's wrong - but it can't know that until it's executed the code...

Clearing caches just prior to a test does not alter the behaviour.

UPDATED TO INCLUDE CODE

404 redirect...

```
  /**
   * Prevents this being called when it's not an HTML request.
   *
   * @return array
   */
  protected function getHandledFormats() {
    return ['html'];
  }

  /**
   * Specifies the priority of all listeners in this class.
   *
   * The default priority is 1, which is very low. To have listeners that have
   * a "first attempt" at handling exceptions return a higher priority.
   *
   * @return int
   *   The event priority of this subscriber.
   */
  protected static function getPriority() {
    return 750;
  }

  /**
   *
   *
   * @param GetResponseForExceptionEvent $event
   */
  public function on404(GetResponseForExceptionEvent $event) {
    if ($this->currentUser->isAnonymous()) {
      // Any 404 when not logged in, return to front page.
      $route_name = '<front>';
    }
    else {
      // Any 404 when logged in, return to base page for user.
      #$route_name = 'user.page';
      return;
    }

    $query = $event->getRequest()->query->all();
    $redirect_uri = Url::fromRoute($route_name, [], ['query' => $query]);

    $returnResponse = new RedirectResponse($redirect_uri->toString());
    $event->setResponse($returnResponse);
  }

```

403 redirect...

```
  public function on403(GetResponseForExceptionEvent $event) {
    $request = $event->getRequest();
    $is_anonymous = $this->currentUser->isAnonymous();
    $route_name = $request->attributes->get('_route');
    $is_not_login = $route_name != 'user.login';
    if ($is_anonymous) {
      if ($is_not_login) {
        $query = $request->query->all();
        $redirect_uri = Url::fromRoute('<front>', [], ['query' => $query])->toString();
      }
      else {
        // Do not redirect, this is an anonymous login.
        $redirect_uri = NULL;
      }
    }
    else {
      // Any 403 when logged in, return to base page for user.
      #$redirect_uri = Url::fromRoute('user.page')->toString();
      return;
    }

    if (!empty($redirect_uri)) {
      $returnResponse = new RedirectResponse($redirect_uri);
      $event->setResponse($returnResponse);
    }
  }

```

# Answer
Pasting the code made me think about the problem in more detail.

It's a question of which gets sent first: 403 (Access Denied) or 404 (Page Not Found).

If it's a legal URL ("library" or "library/valid-category") but the user doesn't have access, they get a 403 and redirected.

If it's not a legal URL ("library/invalid-category") it gets reported as a 404 ... even though they don't have access anyway.

Makes sense.
> 0 votes

---
Tags: 8
---


# Question
Title: When the BigPipe module is installed, the animation does not work
On this page :

https://dev.s1biose.com/profil

There is a menu at the top right. It flashes green when the `.views-exposed-form` class is found with this JS code:

```
  if ($("#navbar-collapse-second .views-exposed-form").length) {
       $("#block-togglenavigationsecond .icon-navbar-second-alert").removeClass("icon-navbar-second-alert-disable");
  };

```

When the BigPipe module is installed, the animation does not work (under dev domain).

Here is my site with BigPipe uninstalled (under www domain):

https://www.s1biose.com/profil

The problem is that I do not see any difference in the HTML code.

Why does not the animation work with BigPipe ?

It must work on all browsers. But BigPipe creates problems on some web browser.

Thank you

Here is the complete JS file for my animation:

```
(function ($) {
  'use strict';

  $('#navbar-collapse-first').on('show.bs.collapse', function () {
       $('#navbar-collapse-second').collapse('hide');
  });

  $('#navbar-collapse-second').on('show.bs.collapse', function () {
       $('#navbar-collapse-first').collapse('hide');
  });

  $('#navbar-collapse-first').on('show.bs.collapse', function () {
       $('body').addClass('overlay-is-navbar-collapse');
  });

  $('#navbar-collapse-first').on('hide.bs.collapse', function () {
       $('body').removeClass('overlay-is-navbar-collapse');
  });

  $('#navbar-collapse-second').on('show.bs.collapse', function () {
       $('body').addClass('overlay-is-navbar-collapse');
  });

  $('#navbar-collapse-second').on('hide.bs.collapse', function () {
       $('body').removeClass('overlay-is-navbar-collapse');
  });

  $('#navbar-collapse-first .form-submit').on('click', function () {
       $('#navbar-collapse-first').collapse('hide');
  });

  $('#navbar-collapse-second .form-submit').on('click', function () {
       $('#navbar-collapse-second').collapse('hide');
  });

  $('#navbar-collapse-first .navbar-nav .dropdown').on('shown.bs.dropdown', function () {
       $(this).find('.dropdown-toggle svg').removeClass("fa-plus-circle").addClass("fa-minus-circle");
  });

  $('#navbar-collapse-first .navbar-nav .dropdown').on('hidden.bs.dropdown', function () {
       $(this).find('.dropdown-toggle svg').removeClass("fa-minus-circle").addClass("fa-plus-circle");
  });

  $('.collapse').on('shown.bs.collapse', function () {
       $(this).parent().find('.panel-heading .collapse-change-icon svg').removeClass("fa-plus-circle").addClass("fa-minus-circle");
  });

  $('.collapse').on('hidden.bs.collapse', function () {
       $(this).parent().find('.panel-heading .collapse-change-icon svg').removeClass("fa-minus-circle").addClass("fa-plus-circle");
  });

  $('.bs-tour-action-trigger').on('click', function () {
       $('#comment-ca-marche').modal('hide');
  });

  $('#block-boutonimportant').on('click', function () {
       $('#navbar-collapse-first').collapse('hide');
  });

  $('#block-boutoncharte').on('click', function () {
       $('#navbar-collapse-first').collapse('hide');
  });

  if ($("#navbar-collapse-first .views-manage-menu").length) {
       $("#block-togglenavigationfirst .icon-navbar-first-alert").removeClass("icon-navbar-first-alert-disable");
  };

  if ($("#navbar-collapse-second .views-exposed-form").length) {
       $("#block-togglenavigationsecond .icon-navbar-second-alert").removeClass("icon-navbar-second-alert-disable");
  };

  $('#navbar-collapse-first').on('shown.bs.collapse', function () {
       $(this).find("#block-menuprincipal .dropdown-toggle").dropdown("toggle");
  });

  $('#navbar-collapse-first').on('shown.bs.collapse', function () {
       $(this).find(".views-manage-menu .dropdown-toggle").dropdown("toggle");
  });

}(jQuery));

```

# Answer
> 3 votes
Bigpipe's purpose is to load dynamic/uncachable blocks of content (e.g. forms) in via javascript. This is so that the rest of the site can remain cached and just the dynamic parts get loaded in separate.

So the issue here is probably your own javascript is triggering before big pipe has loaded the targeted content in. Have you got your JS in window.load or something like that? You should place it into a Drupal behaviour which will get called each time something dynamic is loaded in by drupal.

---
Tags: 8, theming, bootstrap-theme
---


title: How do I translate a meta tag?

text:
# Question
Title: How do I translate a meta tag?
I want to translate the *title* meta tag added to views on a Drupal 8 site, but I didn't see any option in the *Translate View* section.

How can I translate meta tags?

# Answer
> 2 votes
I've added a title metatag to the default Content view. Then went to translation page where I found the string to translate under Displays-\> Page Display Settings-\> Display Extenders-\> Test Metatags

# Answer
> -1 votes
For **Meta tags** to work with views you will need to enable `Metatag` module and `Metatag: Views` submodule both part of the Metatag module download.

You need to go to `Extend` from the admin menu and enable the 2 modules

---
Tags: views, 8, meta-tags
---


# Question
Title: Is it possible to cancel a delete request for a node or media item?
I am trying to create a soft delete method and I was hoping to manipulate cores delete method. The plan was to set a flag on the entity to say that it had been deleted and gets moved to a new page for approval before permanently being deleted.

I am aware there are several contrib modules out there but they are either only in beta or don't quite do what I wanted.

I have been trying to use hook\_entity\_pre\_delete() to set this flag, but I am unable to then cancel the request to delete the entity.

Does anyone have any bright ideas?

# Answer
Have you considered the new Content Moderation module in core? It should provide the desired functionality.
> 1 votes

---
Tags: 8, hooks
---


# Question
Title: How do I get link the files in libraries.yml with absolute url path
In my libraries.yml files the css files are linked with the relative url paths.

> Eg : /css/mycss.html

So when in the page source the linked url shows as relative. How do I link those files with absolute URL path?

# Answer
> 0 votes
This is the example from the official documentation, notice this bit `type: external`:

```
angular.angularjs:
  remote: https://github.com/angular/angular.js
  version: 1.4.4
  license:
    name: MIT
    url: https://github.com/angular/angular.js/blob/master/LICENSE
    gpl-compatible: true
  js:
    https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js: { type: external, minified: true }

```

---
Tags: 8, theming, uri
---


# Question
Title: How to install required packages for feeds spreadsheet module as shown required by Composer Manager?
**Modules being used**
Composer Manager
Feeds Spreadsheet
**Requirement**
I need to install the package as mentioned in the configuration page of module composer manager.
The error shown is as given below.

```
Composer's install command must be run to generate the autoloader and install the required packages.
Refer to the instructions on the Composer Manager project page for installing packages.

```

I have access to Cpanel but don't have command line access right now, how can I install the required packages?

# Answer
> 2 votes
You essentially have 2 options:

1. Ask your hosting provider to let you install and run Composer, and access it via the command line
2. Run the Composer install locally, then push all the files up (including the vendor folder)

---
Tags: 7, feeds, composer
---


# Question
Title: How to get an entity create route, given an entity type and bundle?
I am the maintainer for Views Add Button: https://www.drupal.org/project/views\_add\_button , which creates a button (link with classes) in a Views header or footer, that allows the user to add content of a particular type. Link building and access checking are meant to be handled automatically by the module, so that the user does not have to write a custom plugin or put a "view in a view" to handle access control.

While working on a Drupal 8 port I'm running into some trouble getting the correct route for entities. At this time, the options form for the plugin will pass an entity type and bundle, but given that there are many entity types, some with bundles and some without, I am not sure how to calculate the route name for a given entity-bundle combination.

So far, I've written this to manually create the URL, based on some assumptions. I left the options building out as it is not relevant to the topic:

```
// Get the create route
$type = explode('+', $this->options['type'], 2);
$entity_type = $type[0];
$bundle = $type[1];
$u = $entity_type === $bundle ? '/' . $entity_type . '/add': '/' .$entity_type . '/add/' . $bundle;
// Create the link
$url = Url::fromUserInput($u, $opts);

```

The goal is to use Url::fromRoute() instead of Url::fromUserInput, using the entity type and bundle. For example, 'node' and 'article' should return 'node.add' , which would then be given to Url::fromRoute().

# Answer
Given Clive's comment, and some further thought about it, one thing I could do is create an annotation, such that custom entity developers can declare their route. Further, I can add annotations to the module that cover all core cases (node/user/taxonomy), such that the module works with core out of the box.

From there, I could add conditional logic that looks for a given entity's annotation, and if it doesn't find it, it would then make the same assumption (/{entity\_type}/add/{bundle}) as above. I suppose from there either developers can declare an annotation in their own module, or if a particular custom entity is popular and keeps hitting the issue queue, I could add that as well.
> 1 votes

---
Tags: 8, routes
---


# Question
Title: Why isn't the custom validation handler fired in hook_form_alter()?
I am adding a custom validation handler to the node edit form, using the following code.

```
function my_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id != 'node_article_edit_form') {
    return;
  }

  // ...

  $form['#validate'][] = 'my_module_node_article_edit_form_validate';
}

function my_module_node_article_edit_form_validate(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  // ...
}

```

The validation handler is not invoked, though. What is wrong with the code I am using?

# Answer
> 4 votes
Validate and submit handlers can be placed on the form level or on specific buttons. If they are defined on a button, only those will be executed; it only falls back to the top-level if nothing is defined on the pressed button.

The node form, like all entity forms has the callbacks defined on the button, which is complicated by the fact that there are multiple buttons (save as published, save as unpublished and so on). You must define your validate callback on all of them.

Also, for validation of an entity, you should instead use validation constrains on the fields or the entity.

# Answer
> 2 votes
Try Like this

```
/**
  * Implements hook_form_FORM_ID_alter().
  */
  function MYMODULE_form_FORM_ID_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id){
    $form['#validate'][] = 'MYMODULE_validate';
 }

/**
 * Implements custom validate.
 */
function MYMODULE_validate(array &$form, FormStateInterface $form_state){
// YOUE CODE GOES HERE
}

```

# Answer
> 0 votes
On Drupal node edit forms, the validation handlers are defined at button level, so the code should assign the new validation handler to `$form['actions']['submit']['#validate'][]`.

---
Tags: 8, forms
---


title: How to query a map field

text:
# Question
Title: How to query a map field
I am developing the Spectra Analytics module on drupal.org, and one of the interesting new features in Drupal 8 is the ability to create "map" fields in the database. These fields are simply serialized data, such that you can save an associated array to the field, and Drupal will automatically serialize/unserialize the data.

For the main purpose of the module (querying by category and printing large amounts of custom data), this has been great. However, I am looking at applications where it might be useful to query the map data.

How can I do that?

*Additional note:*

I am reading up on MongoDB and other cases where this kind of data would be stored & query-able as a JSON array, so it seems like this is possible. One example application would be a list of alerts, and in a map field we have an associative array of data about the alert, such as "message," "severity," and "dismissed," and in this case we are looking for a particular "dismissed" property. The alternative solution is to use Field API fields, i.e. create an extra table to hold data that is queried in the traditional way.

# Answer
> 1 votes
OK, here's what I've developed so far. I did take Kevn's comment into account, and switched from the Map field to JSONB Field, but the example below does work on a map field *if* you remove the json\_decode() part.

This is the render function for my data viewer, in which users can specify a key. The code will print\_r() arrays, or return a string, depending on what it finds. If there is no key, it will print\_r the entire field.

This doesn't cover querying, i.e. Views filters, just getting the data out for reporting.

```
/**
 * {@inheritdoc}
 */
public function render(ResultRow $values)
{
  $render_key = $this->options['spectra_data_render_key'];
  $data_entity = $this->getEntity($values);
  $data_m = $data_entity->get('data_data')->getValue();
  $data_map = isset($data_m[0]['value']) ? json_decode($data_m[0]['value'], TRUE) : FALSE;
  if ($data_map === FALSE) {
    return array(
      '#markup' => '',
    );
  }
  if (!$render_key) {
    return array(
      '#markup' => '<pre>' . print_r($data_map, TRUE) . '</pre>',
    );
  }
  else {
    if (isset($data_map[$render_key])) {
    $item = $data_map[$render_key];
      $markup = is_array($item) || is_object($item) ? '<pre>' . print_r($item, TRUE) . '</pre>' : (string) $item;
      return array(
        '#markup' => $markup,
      );
    }
    else {
      return array(
        '#markup' => '',
      );
    }
  }
}

```

Note: 'data\_data' is a base field for a "spectra\_data" entity, and $this-\>options\['spectra\_data\_render\_key'\] is a custom field that is added to the settings for the Views field.

If the stored JSON is {"this": "that"}, then passing a key of "this" would return the string "that," and no key would return array("this" =\> "that").

---
Tags: 8, database
---


# Question
Title: How to pass values to content creation page to set default values in form elements?
## Introduction *(not necessarily needed to be able to answer the question)*

I use Domain Access module to be able to manage different sites from one Drupal installation and a single shared database. I enabled Domain Content submodule that provides a content administration page for each subdomain.
Instead of having all contents of all domains displayed at `/admin/content`, this allows to display all contents of a given domain at `/admin/content/domain-content/mydomain`.

## What I'd like to do

I'd like to prefill a form element in ***Create Article*** page according to a given domain.

So I plan to add a ***Add content*** button at `/admin/content/domain-content/mydomain`, and pass the parameter `mydomain` from here until, for example, ***Create Article*** page.

Then I'll be able to prefill (tick) the right domain checkbox in the ***Create Article*** page according the passed argument.

## My question

How to pass parameters between the given admin pages to be able to prefill a form in ***Create Article*** page?

# Answer
### Altering the form

You should implement the hook\_form\_FORM\_ID\_alter. Then, read the parameters like this:

```
$name = \Drupal::request()->request->get('country'); // from param

```

Then alter the *form elements*, rewriting the `#defatult_value` conditionally, like this:

```
$form['field_country']'#default_value'] = 'my domain specific default';

```

In the case of a checkbox widget, the `#default_value` is an array (source):

$form\['countries'\]\['#default\_value'\] = \[1, 3\];

### Passing parameters in general

If your parameters are simple strings, like `country: denmark`, you could use GET parameters. This answer has the sample code:

How do I create a link?

### Passing parameters through the '/node/add' route

This is a special route, it is not so simple.

**Method 1: Implementing a subtheme**

If you are using the default admin theme ('seven') you would have to create a subtheme, and overwrite this hook, so that your custom parameters are passed:

```
   /**
     * Implements hook_preprocess_HOOK() for list of available node type templates.
     */
    function seven_preprocess_node_add_list(&$variables) {
      if (!empty($variables['content'])) {
        /** @var \Drupal\node\NodeTypeInterface $type */
        foreach ($variables['content'] as $type) {
          $variables['types'][$type->id()]['label'] = $type->label();
          $variables['types'][$type->id()]['url'] = \Drupal::url('node.add', ['node_type' => $type->id()]);
        }
      }
    }

```

**Method 2: Overwriting the twig template**

The links are ultimately rendered by the `core/themes/seven/templates/node-add-list.html.twig` template. To overwrite this output, you would: \- Implement a `hook_theme_suggestions_HOOK` \- Copy the `node-add-list.html.twig` to `node-add-list--custom.html.twig` and implement your custom changes here.

```
/**
 * Implements hook_theme_suggestions_HOOK()
 */
function hook_theme_suggestions_node_add_list(array $variables) {
  $suggestions = array();
  $suggestions[] = 'node_add_list__custom';
  return $suggestions;
}

```
> 2 votes

---
Tags: 8, forms, domain-access
---


# Question
Title: How do I map a path alias when migrating?
When migrating from Drupal 6 to 8 i can simply map path aliases with the mapping:

```
process:
  path: alias

```

I have the problem that the path alias is not set properly when pathauto is activated for a node-type. The alias always gets generated automatically instead of using the old alias. How can I override this behaviour?

# Answer
> 3 votes
You need to explicitly disable pathauto in your migration:

```
process:
  path/alias: alias
  path/pathauto:
    plugin: default_value
    default_value: false

```

# Answer
> 0 votes
For 8.5.6 Core is working fine. Another way for pathauto is:

```
path/alias: path_alias
path/pathauto:
    plugin: default_value
    default_value: 0

```

Regards! :D

---
Tags: 8, migrations, path-aliases
---


title: POST from external source

text:
# Question
Title: POST from external source
I have external site that needs to POST my drupal site (it basically shares data). I need to take the POST data parse it and create a node from it. Is this possible? I have created a PHP file `take_post.php` this file receives the POST request, parses it creates a node object and then sends it to `http://api/v1/node` this works fine, though it seems a little long winded?

My problem is that if a post is deleted from the external system a DELETE request is send via HTTP, however the external system has no idea of what the node ID is, and at the point of delete niether do. Is there a way to delete a node without knowing it's NID, maybe via a custom field value?

# Answer
The UUID field is what you are looking for. It stands for Universal Unique ID.

> The UUID is guaranteed to be unique and can be used to identify an entity across multiple systems.

-- from Entity::uuid
> 0 votes

---
Tags: nodes, services, http-request
---


# Question
Title: Users can post new node but ONLY Unpublished status
As the title says, users are able to create new node (type QUESTION), but they can not publish it. The node is saved when the user hits save, but the status is set to unpublished under Admin \> Content. I have checked a few permissions the authenticated user which has:

* Question: Create new content
* Question: Edit own content
* View published content
* View own unpublished content

This content is NOT using workflow moderation.

# Answer
> 1 votes
The obvious thing is that the "published" option is unticked on the content type. So if you go to "structure \> content types \> question" (/admin/structure/types/manage/question) and then click "Publishing option" is the published ticked? That controls the default status

If its not that then you must have some other module/code doing it. Without knowing your sites setup I dont think people can help much further

---
Tags: 8, theming, users
---


# Question
Title: How to retrieve all nodes for a taxonomy term using Services?
I want to retrieve all the nodes associated with a given taxonomy term (field\_term) using HTTP GET.

I have tried:

```
curl -v http://myserver/endpoint_path/node?parameters[field_term]=1

```

but I get an HTTP 406 Column not found.

Also later on I will need to use multiple taxonomy vocabularies to filter by more than one term.

I am using the Services 3 module in Drupal 7.

# Answer
> 6 votes
I found out how to do it, so I am posting it here in case it is helpful to somebody.
Feel free to post if you know a better way.

I assume you have created some content with fields corresponding to taxonomy vocabularies.

1. **Create a Services View**

* Install the Services View module, as suggested in my previous comment.
    * Go to Structure / Views / Add new view
    * Give your view a name and uncheck 'create a page' because we just want a service.
    * Click 'Continue & Edit', you should then be in the 'Displays' screen.
    * Click on the '+Add' displays button, select 'Services'.
    * Under 'Service Settings' click on the path and change it. e.g my\_view\_path.
2. **Create criteria for your view**

* Under 'Filter Criteria' click 'Add'. Do not use Advanced/Contextual Filters.
    * Search for your field, and click Apply'
    * 'Autocomplete' in the Selection Type, 'Apply and Continue'. It should not matter because we are going to call this from a URL, not a web page.
    * The 'Configure filter criterion' popover is shown.
    * Check 'Expose this filter to visitors'. If you don't do this, you will not be able to pass as an argument.
    * Scroll down to the bottom and click on 'More'.
    * Take note of the 'filter identifier'. This is the name of the argument you need to pass in the URL, e.g: field\_myterm\_tid
    * Click on Apply filter
    * Repeat for other filter criteria as needed.
    * Click on Save View
3. **Enable the Service Resource**

* One last step, go to Structure \> Services
    * You should see a list of endpoints, click 'Edit resources'
    * Check to enable the resource you just created.
4. **Finally, retrieve your info with HTTP GET**

`http: //myserver/my_endpoint_path/my_view_path?field_myterm_tid=XX&field_myterm2_tid=YY`

* XX and YY are the textual names of the terms

# Answer
> 0 votes
Services in itself doesn't provide such specific use-cases.

You need a new resource, possibly you can find a module that provides what you are looking for, or you'll need to create a new one on your own.

The Services views module appears like an excellent start for creating such resources.

# Answer
> 0 votes
In Drupal 8 this can be done using json API module.

Install the module

Create a taxonomy color

Add vocabulary red, green and blue

Now to get all the vocabularies associated with the taxonomy color using get need to perform get on the following URL

```
http://localhost/drupal/jsonapi/taxonomy_term/color?_format=hal_json

```

---
Tags: 7, taxonomy-terms, services
---


# Question
Title: Automatic Google translation when there is no real translation
I have a multilingual site.

I want it so that if a user has chosen French as they preferred language, but no French translation exists for a particular page, then an automatic Google Translation is displayed.

I have tried doing things like installing the Google website translation module: https://translate.google.com/manager/website/ but this of course cannot display the proper translation if one exists because it does not integrate with Drupal. I have also looked at options like GTranslate https://www.drupal.org/project/gtranslate, which has a Drupal module but that does not integrate properly with Drupal multilingual sites.

Any suggestions for a solution to this? The only way I can think of doing it is to The Translation Management Tool (TMGMT) module and to use Google translate all pages and have those Google translations as proper Drupal translations, although this has disadvantages as well in that it will be cumbersome to do with this hundreds of pages. Any ideas?

# Answer
I have an idea that we can achieve using gtranslate language dropdown (hidden) and drupal langauge dropdown

Steps in hook\_preprocess\_page check node has translation if yes make the page is not google translatable using class "notranslate" if it has not translation then pass the language code to javascript and call google translate function

For Exampel: /\** * Implements hook\_preprocess\_page(). \*/ function hook\_preprocess\_page(&$variables) { $variables\['attributes'\]\['class'\] = \[\]; $language = \Drupal::languageManager()-\>getCurrentLanguage()-\>getId();

```
$variables['attributes']['class'][] = 'node-' . $nid;

if(isset($variables['node'])) {
    $nid = $variables['node']->id();

    if($variables['node']->hasTranslation($language)) {
        $variables['attributes']['class'][] = 'notranslate';
    }
    else {
        $variables['#attached']['drupalSettings']['language'] = $language;
    }
}

```

}

In Custom.js

doGTranslate('en|' + drupalSettings.language);
> 1 votes

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


# Question
Title: How to remove the div surrounding the view block?
I created a view block that I added in the navigation bar.

When I inspect my page, I have a div around my block.

How can I delete this div ?

I want to have only :

```
<section class="views-element-container block block-views block-views-blockmenu-page-utilisateur-block-2 clearfix" id="block-views-block-menu-page-utilisateur-block-2">

```

# Answer
> 0 votes

---
Tags: views, 8
---


# Question
Title: Twig date function not working on custom field within node
Even if `content.field_my_date` contains a date like 2021-10-01, twigs date function outputs today's date when using `{{ content.field_my_date|date("M.d.Y") }}`. Simply printing `{{ content.field_my_date }}` to make sure the field isn't empty, outputs the correct date and label.

# Answer
> 0 votes
Before you need convert field `field_my_date` form `2021-10-01` to timestamp

You can use hook\_ENTITY\_TYPE\_view\_alter to be convert it to timestamp

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

/**
 * Implements hook_ENTITY_TYPE_view().
 */

function hook_ENTITY_TYPE_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
  if($display->bundle()=='node_type'){
    $field_date_timestamp = strtotime($entity->get('field_my_date')- >value);
    $build['field_my_date'] = \Drupal::service('date.formatter')->format(
    $field_date_timestamp, 'custom', 'M.d.Y');
  }
}

```

in file twig node tempalte `{{field_my_date}}`

---
Tags: 8, theming
---


# Question
Title: Commerce 2: Can a product buyer set the price they want to pay for a product during checkout?
I want to create a product where users can enter the price they'd like to pay for it. How can I do it?

Edit: Just changed the question to be a little more clear. I will be trying the solution posted by Ismail for now.

# Answer
This module https://github.com/bojanz/donation\_example can be a good start. There it is donation, but you can customize it to serve your purpose.
> 1 votes

---
Tags: 8, commerce
---


title: Two sites, same codebase mystery

text:
# Question
Title: Two sites, same codebase mystery
Ubunutu Server, two Drupal sites. One dev and one live. Both domain names take you to the same code and database, the ones correct for the live site. Checked apache virtual host files. Both the dev and live sites are pointing to different directories where they should go, one to the live code, and one to dev.

What setting, and where, could make the dev site point to the live one, instead of where apache's virtual host file says it's pointing?

\*I should add, this occurred after a server upgrade.

# Answer
The answer to this was that the dev site was being redirected to the live site, where the "https" was then crossed out, but the domain name remains, confusingly, the same.
> 0 votes

---
Tags: configuration
---


title: Two step media creation form?

text:
# Question
Title: Two step media creation form?
It would seem very logical to pick the media source first, and then have the field map mechanism fill in the fields based on the metadata the source entity provides via the media source plugin.

I am fairly certain we could write the necessary two step entity form, but I'd be surprised if it didn't exist already. Does it?

# Answer
> 1 votes
Currently there do not seem to be any modules improving the metadata mapping workflow for Media in Drupal core.

There are core issues to improve the metadata mapping and improving the metadata mapping is currently a high priority issue to deliver in Drupal 8.7:

---
Tags: 8, media
---


# Question
Title: HTML Purifier module and upload YouTube videos not working
I am using the HTML Purifier module https://www.drupal.org/project/htmlpurifier. And Drupal version 8.5.6. Most of the help I could find is for Drupal version 7. When I try to embed a YouTube video into the Ckeditor the iframe tag remains but the src url is stripped out. I am allowing every element and class like this, this is part of my GUI config for html purifier:

```
HTML:
 Allowed: null
 AllowedAttributes: null
 AllowedElements: null
 SafeEmbed: true
 SafeIframe: true
 SafeObject: true
 FlashCompat: false
 SafeIframeRegexp: null
 YouTube: true

```

And below is the full config file.

```
        Attr:
      AllowedClasses: null
      AllowedFrameTargets: _blank,_self,_target,_parent
      AllowedRel: {  }
      AllowedRev: {  }
      ClassUseCDATA: null
      DefaultImageAlt: null
      DefaultInvalidImage: ''
      DefaultInvalidImageAlt: 'Invalid image'
      DefaultTextDir: ltr
      EnableID: false
      ForbiddenClasses: myHeader2,myHeader3,mso*,mso-*
      ID.HTML5: null
      IDBlacklist: {  }
      IDBlacklistRegexp: null
      IDPrefix: ''
      IDPrefixLocal: ''
    AutoFormat:
      AutoParagraph: false
      Custom: {  }
      DisplayLinkURI: false
      Linkify: false
      PurifierLinkify.DocURL: '#%s'
      PurifierLinkify: false
      RemoveEmpty.Predicate:
        colgroup: {  }
        th: {  }
        td: {  }
        iframe:
          - src
      RemoveEmpty.RemoveNbsp.Exceptions:
        td: true
        th: true
      RemoveEmpty.RemoveNbsp: false
      RemoveEmpty: false
      RemoveSpansWithoutAttributes: false
    CSS:
      AllowDuplicates: true
      AllowImportant: true
      AllowTricky: false
      AllowedFonts: null
      AllowedProperties: null
      DefinitionRev: 1
      ForbiddenProperties: {  }
      MaxImgLength: 1200px
      Proprietary: true
      Trusted: true
    Cache:
      DefinitionImpl: Serializer
      SerializerPath: null
      SerializerPermissions: 493
    Core:
      AggressivelyFixLt: true
      AggressivelyRemoveScript: true
      AllowHostnameUnderscore: false
      CollectErrors: false
      ColorKeywords:
        maroon: '#800000'
        red: '#FF0000'
        orange: '#FFA500'
        yellow: '#FFFF00'
        olive: '#808000'
        purple: '#800080'
        fuchsia: '#FF00FF'
        white: '#FFFFFF'
        lime: '#00FF00'
        green: '#008000'
        navy: '#000080'
        blue: '#0000FF'
        aqua: '#00FFFF'
        teal: '#008080'
        black: '#000000'
        silver: '#C0C0C0'
        gray: '#808080'
      ConvertDocumentToFragment: true
      DirectLexLineNumberSyncInterval: 0
      DisableExcludes: false
      EnableIDNA: false
      Encoding: utf-8
      EscapeInvalidChildren: false
      EscapeInvalidTags: false
      EscapeNonASCIICharacters: false
      HiddenElements:
        script: true
        style: true
      Language: en
      LegacyEntityDecoder: false
      LexerImpl: null
      MaintainLineNumbers: null
      NormalizeNewlines: true
      RemoveInvalidImg: true
      RemoveProcessingInstructions: false
      RemoveScriptContents: null
    Filter:
      Custom: {  }
      ExtractStyleBlocks.Escaping: true
      ExtractStyleBlocks.Scope: null
      ExtractStyleBlocks.TidyImpl: null
      ExtractStyleBlocks: false
      YouTube: true
    HTML:
      Allowed: null
      AllowedAttributes: null
      AllowedComments: {  }
      AllowedCommentsRegexp: null
      AllowedElements: null
      AllowedModules: null
      Attr.Name.UseCDATA: false
      BlockWrapper: p
      CoreModules:
        Structure: true
        Text: true
        Hypertext: true
        List: true
        NonXMLCommonAttributes: true
        XMLCommonAttributes: true
        CommonAttributes: true
      CustomDoctype: null
      DefinitionID: null
      DefinitionRev: 1
      Doctype: null
      FlashAllowFullScreen: true
      ForbiddenAttributes: {  }
      ForbiddenElements: s,h2,h3
      MaxImgLength: 1200
      Nofollow: false
      Parent: div
      Proprietary: true
      SafeEmbed: true
      SafeIframe: true
      SafeObject: true
      SafeScripting: {  }
      Strict: false
      TargetBlank: true
      TargetNoopener: true
      TargetNoreferrer: true
      TidyAdd: {  }
      TidyLevel: medium
      TidyRemove: {  }
      Trusted: true
      XHTML: true
    Output:
      CommentScriptContents: true
      FixInnerHTML: false
      FlashCompat: false
      Newline: null
      SortAttr: false
      TidyFormat: false
    Test:
      ForceNoIconv: false
    URI:
      AllowedSchemes:
        http: true
        https: true
        mailto: true
        ftp: true
        nntp: true
        news: true
        tel: true
      Base: null
      DefaultScheme: http
      DefinitionID: null
      DefinitionRev: 1
      Disable: false
      DisableExternal: false
      DisableExternalResources: false
      DisableResources: false
      Host: null
      HostBlacklist: {  }
      MakeAbsolute: false
      Munge: null
      MungeResources: false
      MungeSecretKey: null
      OverrideAllowedSchemes: false
      SafeIframeRegexp: null

```

# Answer
> 1 votes
It works now after changing the last setting in the config file to this: SafeIframeRegexp: %(www.youtube.com/embed)%

---
Tags: 8, wysiwyg
---


# Question
Title: Add fields to image upload option in CKEditor
I make SVGs using LaTeX and would like to upload both the image and its LaTeX source code when I attach an imagine via CKEditor. I don't want the code to be displayed, just stored with the image so that I can change it later if I need to, or use it as a reference for making more images.

There are already some default fields for images in the upload widget, such as alt-text and caption, so this seems possible. I just want another field called "source" where I can dump the LaTeX.

# Answer
Caption and alt text are not a good example because they are stored where the image is used, not together with the file entity. What you are looking for is File Entity to store the source data in a field of the image file. For new projects you shouldn't use it anymore, because it is deprecated in favor of the Media entity. Media is now in core and when the module is enabled you can add fields directly to the media type `Image` (/admin/structure/media/manage/image/fields).

Out of the box CKeditor does only provide a button to add file images, which you want to replace with Media. To add media types you need the module Entity Embed until this feature is integrated into core.
> 0 votes

---
Tags: 8, media, wysiwyg
---


# Question
Title: Git workflow for Composer-based projects
I would like to install/manage Drupal with Git, Drush, and configuration synchronization.

Should I add `core/` and `vendor/` into the .gitignore so that instead of pushing/pulling core I simply update core on prod/dev and synchronize configuration only?

This way I could potentially manage a Drupal site with few repositories:

* Repository for configurations
* Repository for a custom theme
* Repository for custom modules

When updating a module, this would be my workflow.

### On development

1. `git pull`
2. `drush up`
3. `drush config-export to-prod`
4. `git push`

### On production

1. `git pull`
2. `drush up`
3. `drush config-import to-prod`

I ask because it doesn't seem to make sense that I have to push/pull all of Drupal 8 with every update.

# Answer
If your goal is to minimize the size of your repository, then you should use Composer, following the pattern described in the project drupal-composer/drupal-project.

One possible workflow would then be:

On dev:

1. git pull
2. composer install
3. drush config-export
4. git add / commit / push

On stage:

1. git pull
2. composer install
3. drush config-import

On live:

1. rsync from stage to live
2. drush config-import

The workflow you propose will not work. The command `drush pm-update` will not do anything if Drupal is already at the most recent version. `drush pm-download` is not a good alternative either, as it will overwrite portions of your code base. You could potentially repair this with a `git reset --hard` or some similar trick, but that would not be very clean.

If you do not wish to use Composer, your best option is to simply commit the core and vendor directories.
> 8 votes

# Answer
> I ask because it doesn't seem to make sense that I have to push/pull all of Drupal 8 with every update.

The whole point of Git is that it’s incremental. It only pulls and pushes what has changed, the differences.

If you modify a file, it only needs to send the differences. That’s what’s stored in a commit. Not the full file again.
> 2 votes

---
Tags: 8, drush
---


# Question
Title: Docker website running locally not loading CSS
I'm completely new to Drupal, and I'm running this multi-container Drupal-Docker app locally, and website is only loading HTML, no CSS.

These are the only error warnings I am getting.

> exception 'PDOException' with message 'SQLSTATE\[08006\] \[7\] could not translate host name "dbname=template1" to address: Name or service

Any help?

# Answer
> 0 votes
You forgot to link the db container. Look at the quickstart here https://hub.docker.com/r/feikede/drupal8-docker/ and take care for the "--link" to your database container.

---
Tags: 8
---


# Question
Title: How to fix missing php extensions problems in custom Docker image?
There are many excellent questions here about automating the initial setup process for Drupal but I haven't seen any pertaining specifically to Drupal containers in Docker.

Here's my setup. I've kept the images/builds as vanilla as possible; the only Dockerfile I have is for `composer`, inspired by the accepted answer to this question.

docker-compose.yml

```
version: '2'
services:

  drupal:
    image: drupal
    ports:
      - 8888:80

  mariadb:
    image: mariadb
    environment:
       MYSQL_DATABASE: drupal8
       MYSQL_USER: drupal8
       MYSQL_PASSWORD: drupal8
       MYSQL_ROOT_PASSWORD: drupal8
    restart: always
    depends_on:
      - drupal

  drush:
    image: drush/drush

  composer:
    image: composer
    build: composer_init
    depends_on:
      - drupal
      - drush

```

Dockerfile for `composer`:

```
FROM composer

RUN composer -vvv create-project drupal-composer/drupal-project /var/www/html --stability dev --no-interaction
RUN cd /var/www/html
RUN drush si -y \
  --db-url=mysql://root:drupal8@localhost/drupal8 \
  --site-name=drupal8 \
  --site-mail=drupal8@foo.com \
  --account-mail=drupal8@foo.com \
  --account-name=drupal8 \
  --account-pass=drupal8 >> /dev/null 2>&1

```

I spun up the build process by issuing `docker-compose up -d --build`. Now when the process reached the composer part, it blew up with the following message:

```
Resolving dependencies through SAT
Dependency resolution completed in 0.001 seconds
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - drupal/core 8.5.x-dev requires ext-gd * -> the requested PHP extension gd is missing from your system.
    - drupal/core 8.5.1 requires ext-gd * -> the requested PHP extension gd is missing from your system.
    - Installation request for drupal/core ~8.5.1 -> satisfiable by drupal/core[8.5.1, 8.5.x-dev].

  To enable extensions, verify that they are enabled in your .ini files:
    -
    - /usr/local/etc/php/conf.d/date_timezone.ini
    - /usr/local/etc/php/conf.d/docker-php-ext-sodium.ini
    - /usr/local/etc/php/conf.d/docker-php-ext-zip.ini
    - /usr/local/etc/php/conf.d/memory-limit.ini
  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.

```

Based on other answers/suggestions here, I added a Dockerfile to my drupal section and added `RUN apt-get install php7.0-gd` to the Dockerfile, but this now blows up with `E: Package 'php7.0-gd' has no installation candidate`.

I've ensured that the PHP version for this Docker image is PHP 7.

`php --ini` gives me:

```
# php --ini
Configuration File (php.ini) Path: /usr/local/etc/php
Loaded Configuration File:         (none)
Scan for additional .ini files in: /usr/local/etc/php/conf.d
Additional .ini files parsed:      /usr/local/etc/php/conf.d/docker-php-ext-gd.ini,
/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_pgsql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-zip.ini,
/usr/local/etc/php/conf.d/opcache-recommended.ini

```

How can I resolve this error now?

# Answer
I resolved this by removing the `drush` and `composer` services from the docker-compose file and updating my Dockerfile for drupal as follows:

```
FROM drupal

RUN apt-get update -y && apt-get install -y wget vim git mysql-client

RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \
    php composer-setup.php && \
    mv composer.phar /usr/local/bin/composer && \
    php -r "unlink('composer-setup.php');"

RUN wget -O drush.phar https://github.com/drush-ops/drush-launcher/releases/download/0.4.2/drush.phar && \
    chmod +x drush.phar && \
    mv drush.phar /usr/local/bin/drush

```
> 0 votes

# Answer
It's much more easy to install composer in your Drupal-Dockerfile and install Drupal, drush and console from that composer.

You could extend my Dockerfile here https://hub.docker.com/r/feikede/drupal8-docker/ with a "drush si" and your done.
> 0 votes

---
Tags: 8, installation
---


# Question
Title: Is there a way to export or import individual display views?
I am looking for a way to import and export individual Views displays and found this issue on drupal.org, Export/Import individual display views \[#1470318\].

Has such a functionality available been developed, even through a module?

# Answer
> 0 votes
Not that I know of.

An option. If they’re so similar that you can just do export and reimport to another view, you could keep them on the same view, clone the display, rename the display, override whatever field/filter you need to change and change it.

---
Tags: 7, views, importing-exporting
---


# Question
Title: Why do vertical images flip horizontal after upload?
I run into this issue once in a while and I am not sure what it is. For example I have an image that I get from a non Drupal site or directly from a camera. If I view the image via Preview on my Mac or on a browser from the site it displays vertically. As soon as upload to my Drupal site, it flips horizontally.

To go around this I just open the image on my Mac and just re-save.

I always thought that my computer somehow is rotating the images just for display (based on some logic) but really in the background it is still a horizontal image. But I don't understand why the image displays correctly in the browser from the non Drupal site?

# Answer
> 1 votes
Probably the program looks on your mac to the orientation of the recording itself. Most cameras place information in the photo or it is taken in portrait or landscape. The program that reads the picture can then look at it and put the picture correctly on the screen.

---
Tags: 7, media
---


# Question
Title: Create a view of the 'Recent Log Messages'
I would like to give an admin user (not User 1) permission to see the Recent Log Messages (/admin/reports/dblog), but I only want him to see 'User' logs. As it is a subscription website he could see who has been signing up and cancelling their accounts. But if I was to give them this permission, they will also be able to see all the other log messages, which I do not want them to see.

I have searched for a module that allows permissions by Log Type (access denied/cron/page not found/etc.) , but with no luck. My best idea is if there was a way to create a View of the recent log messages, I could then create a filter to only show User messages.

Is there a module or some hook where I can limit a users access to 'Recent log messages' by 'Type'?

# Answer
> 2 votes
In Drupal 8, you can simply create a view of "Log entries". Just make sure you add a "Type" filter and select "user" as the type.

Then under "Page settings", change the "Access: Permission" to "Role \> Administrator". However, if you don't want this user to view other log messages, perhaps that user shouldn't be an administrator? I recommend creating a new role for that type of user.

In Drupal 7, the Views module doesn't allow you to make a view of log entries out-of-the-box, however if you install the Views Watchdog module, you can do it just like the Drupal 8 method described above.

---
Tags: log-messages
---


# Question
Title: Swiftmailer module installation fails although the swiftmailer external library is installed
I am trying to install the Swiftmailer module on Drupal 8, but I get the following error.

> Swift Mailer requires the external Swift Mailer library. The recommended way of solving this dependency is using the Composer Manager module.

The steps I took are the following.

1. I installed the Libraries and Mail System modules
2. I installed the Swiftmailer external library, by running `composer require swiftmailer/swiftmailer:"~5.4.5"` from sites/all/libraries (inside the Drupal root directory)
3. I uploaded and uncompressed swiftmailer-8.x-1.0-beta2.tar.gz at $DRUPAL\_ROOT/modules/. The installation seemed to be successful, afterwards I got a vendor/swiftmailer/swiftmailer directory under sites/all/libraries.
4. I tried to install the Swiftmailer module with `drush en swiftmailer` and through the admin UI.

I have also tried the second step from other locations (for example $DRUPAL\_ROOT/libraries), with the same result. Note that the *Composer Manager* module seems to be obsolete and not needed, according to latest information found in Drupal forums/sites.

How do I install the Swiftmailer module?

# Answer
That's 7.x/outdated information unfortunately.

You should use composer to manage your Drupal 8 site, using the drupal-project starting point: https://github.com/drupal-composer/drupal-project. It will be a bit of work to switch an existing site to that but after that, installing swiftmailer including all its dependencies will be as easy as running `composer require drupal/swiftmailer`. That will automatically include all dependencies.
> 2 votes

---
Tags: 8, emails
---


# Question
Title: How to create a message when a new store is created?
I installed the Message module on my site :

https://www.drupal.org/project/message

And I created a custom module from the Message Example sub-module.

Here is the content of the `message_activity_stream.info.yml` file :

```
name: Message Activity Stream
type: module
description: "Message Activity Stream for working with the message module."
# core: 8.x
package: Message
dependencies:
 - message
 - token
 - group
 - node
 - commerce_store
 - commerce_product
 - comment

# Information added by Drupal.org packaging script on 2018-04-23
version: '8.x-1.0-rc2'
core: '8.x'
project: 'message'
datestamp: 1524519795

```

Here is the content of the `message_activity_stream.module` file :

```
<?php

/**
 * @file
 * Holds hook implementation for the Message Activity Stream module.
 */

use Drupal\Core\Entity\ContentEntityBase;
use Drupal\group\Entity\Group;
use Drupal\node\Entity\Node;
use Drupal\comment\Entity\Comment;
use Drupal\commerce_store\Entity\Store;
use Drupal\commerce_product\Entity\Product;
use Drupal\user\Entity\User;
use Drupal\profile\Entity\Profile;
use Drupal\message\Entity\Message;

/**
 * Implements hook_profile_insert().
 */
function message_activity_stream_profile_insert(Profile $profile) {
  $message = Message::create(['template' => 'mas_create_node', 'uid' => $profile->get('uid')]);
  $message->set('field_profile_reference', $profile);
  $message->set('field_published', $profile->isPublished());
  $message->save();
}

/**
 * Implements hook_commerce_store_insert().
 */
function message_activity_stream_commerce_store_insert(Store $commerce_store) {
  $message = Message::create(['template' => 'mas_create_store', 'uid' => $commerce_store->get('uid')]);
  $message->set('field_store_reference', $commerce_store);
  $message->save();
}

/**
 * Implements hook_commerce_product_insert().
 */
function message_activity_stream_commerce_product_insert(Product $commerce_product) {
  $message = Message::create(['template' => 'mas_create_product', 'uid' => $commerce_product->get('uid')]);
  $message->set('field_product_reference', $commerce_product);
  $message->set('field_published', $commerce_product->isPublished());
  $message->save();
}

/**
 * Implements hook_group_insert().
 */
function message_activity_stream_group_insert(Group $group) {
  $message = Message::create(['template' => 'mas_create_group', 'uid' => $group->get('uid')]);
  $message->set('field_group_reference', $group);
  $message->save();
}

/**
 * Implements hook_node_insert().
 */
function message_activity_stream_node_insert(Node $node) {
  $message = Message::create(['template' => 'mas_create_node', 'uid' => $node->get('uid')]);
  $message->set('field_node_reference', $node);
  $message->set('field_published', $node->isPublished());
  $message->save();
}

/**
 * Implements hook_comment_insert().
 */
function message_activity_stream_comment_insert(Comment $comment) {
  $message = Message::create(['template' => 'mas_create_comment', 'uid' => $comment->getOwnerId()]);
  $message->set('field_comment_reference', $comment);
  $message->set('field_published', $comment->isPublished());
  $message->save();
}

/**
 * Implements hook_user_insert().
 */
function message_activity_stream_user_insert(User $account) {
  Message::create(['template' => 'mas_user_register', 'uid' => $account->id()])->save();
}

/**
 * Implements hook_commerce_store_update().
 */
function message_activity_stream_commerce_store_update(Store $commerce_store) {
  if (empty($commerce_store->original)) {
    return;
  }

  message_activity_stream_update_message_status($commerce_store);
}

/**
 * Implements hook_commerce_product_update().
 */
function message_activity_stream_commerce_product_update(Product $commerce_product) {
  if (empty($commerce_product->original)) {
    return;
  }

  message_activity_stream_update_message_status($commerce_product);
}

/**
 * Implements hook_group_update().
 */
function message_activity_stream_group_update(Group $group) {
  if (empty($group->original)) {
    return;
  }

  message_activity_stream_update_message_status($group);
}

/**
 * Implements hook_node_update().
 */
function message_activity_stream_node_update(Node $node) {
  if (empty($node->original)) {
    return;
  }

  message_activity_stream_update_message_status($node);
}

/**
 * Implements hook_comment_update().
 */
function message_activity_stream_comment_update(Comment $comment) {
  if (empty($comment->original)) {
    return;
  }

  message_activity_stream_update_message_status($comment);
}

/**
 * Set message entity published field when it changes in the related entity.
 *
 * @param \Drupal\Core\Entity\ContentEntityBase $entity
 *   The entity object.
 */
function message_activity_stream_update_message_status(ContentEntityBase $entity) {
  if ($entity->isPublished() == $entity->original->isPublished()) {
    return;
  }

  $query = \Drupal::entityQuery('message');

  $field = 'field_' . $entity->getEntityType()->id() . '_reference';
  $query->condition($field . '.target_id', $entity->id());

  $results = $query->execute();

  if (empty($results)) {
    return;
  }

  $messages = Message::loadMultiple($results);

  foreach ($messages as $message) {
    $message->set('field_published', $entity->isPublished());
    $message->save();
  }
}

```

Here is the content of the `message_activity_stream.tokens.inc` file :

```
<?php

/**
 * @file
 * Place holder for the Message Activity Stream module.
 */

/**
 * Implements hook_token_info().
 *
 * We need this part until the token module will be exported to Drupal 8.
 */
function message_activity_stream_token_info() {
  $type = [
    'name' => t('Message Activity Stream'),
    'description' => t('Tokens for the Message Activity Stream module.'),
    'needs-data' => 'message',
  ];

  // User relate tokens.
  $message['user-name'] = [
    'name' => t("Author name"),
    'description' => t("The related author name."),
  ];

  $message['user-url'] = [
    'name' => t("Author url"),
    'description' => t("The related author URL."),
  ];

  // Comment relate tokens.
  $message['comment-url'] = [
    'name' => t("Comment url"),
    'description' => t("The comment url."),
  ];

  // Node related tokens.
  $message['node-render'] = [
    'name' => t("Rendered node"),
    'description' => t("The related node rendered to HTML."),
  ];

  $message['node-title'] = [
    'name' => t("Node title"),
    'description' => t("The related node title."),
  ];

  $message['node-url'] = [
    'name' => t("Node URL"),
    'description' => t("The related node URL."),
  ];

  return [
    'types' => ['message' => $type],
    'tokens' => [
      'message' => $message,
    ],
  ];
}

/**
 * Implements hook_tokens().
 */
function message_activity_stream_tokens($type, $tokens, array $data = [], array $options = []) {
  $token_service = \Drupal::token();

  $url_options = ['absolute' => TRUE];
  if (isset($options['langcode'])) {
    $url_options['language'] = \Drupal::languageManager()->getLanguage($options['langcode']);
    $langcode = $options['langcode'];
  }
  else {
    $langcode = NULL;
  }
  $sanitize = !empty($options['sanitize']);

  $replacements = [];

  if ($type == 'message' && !empty($data['message'])) {
    /** @var \Drupal\message\Entity\Message $message */
    $message = $data['message'];

    foreach ($tokens as $name => $original) {
      switch ($name) {
        // Simple key values on the comment.
        case 'user-name':
          $replacements[$original] = $message->getOwner()->label();
          break;

        case 'user-url':
          if ($message->getOwner()) {
            $replacements[$original] = $message->getOwner()->url();
          }
          break;

        case 'node-title':
          if ($message->bundle() == 'mas_create_comment') {
            $replacements[$original] = $message->field_comment_reference->entity->getCommentedEntity()->label();
          }
          else {
            $replacements[$original] = $message->field_node_reference->get(0)->entity->label();
          }
          break;

        case 'node-url':
          if ($message->bundle() == 'mas_create_comment') {
            $replacements[$original] = $message->field_comment_reference->entity->getCommentedEntity()->url();
          }
          else {
            $replacements[$original] = $message->field_node_reference->get(0)->entity->url();
          }
          break;

        case 'node-render':
          if ($message->bundle() == 'mas_create_comment') {
            $entity = $message->field_comment_reference->entity->getCommentedEntity();
          }
          else {
            $entity = $message->field_node_reference->get(0)->entity;
          }

          $view_builder = \Drupal::entityTypeManager()->getViewBuilder($entity->getEntityTypeId());
          $message_view = $view_builder->view($entity, 'teaser');
          $replacements[$original] = \Drupal::service('renderer')->renderRoot($message_view);
          break;

        case 'comment-url':
          $replacements[$original] = $message->field_comment_reference->entity->id();
          break;
      }
    }
  }

  return $replacements;
}

```

Drupal Commerce is installed on my site.

Here is my question :

Currently:

* a message is created when a new node is created.
* a message is created when a new comment is created.
* a message is created when a new user registers.

What I want to do :

* a message is created when a new store is created.
* a message is created when a new product is created.
* a message is created when a new group is created.

**How to create a message when a new store is created ?**

I created a message template "Message Activity Stream - Create store" with the machine name `mas_create_store`

I created a message template "Message Activity Stream - Create product" with the machine name `mas_create_product`

I created a message template "Message Activity Stream - Create group" with the machine name `mas_create_group`

# Answer
> 0 votes
What you are already doing is that you implement `hook_ENTITY_TYPE_insert()` for `ENTITY_TYPE` = `node`. See the documentation: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook\_ENTITY\_TYPE\_insert/8.6.x

In your module that's the `function message_activity_stream_node_insert(Node $node) {` line in the `message_activity_stream.module` file.

From what I read you want to implement it (also) for entity types: `commerce_store`, `commerce_product` and `group`. Remember to rebuild the cache after implementing hooks.

Then the only remaining part will be to adjust following part accordingly, depends on the template's machine name to use and fields you want to set:

```
$message = Message::create(['template' => 'TEMPLATE_MACHINE_NAME', 'uid' => $entity->get('uid')]);

// @todo: Set fields you want, ie. field_store_reference
$message->save()

```

---
Tags: 8, commerce, tokens, message-subscribe
---


# Question
Title: Child & Grand Child terms of Parent Term from URL
I am looking for a way to display both the Child and Grand Children of a taxonomy term (found on the URL) on the same page.

**Example** Taxonomy called Food. Top root term called GRAPE has children and grandchildren like this.

-Grape

--Red

---Small

---Medium

---Large

-- White

**How can we create a view (block in our case) that will always show the children and grandchildren of the parent term from URL?**

I am guessing one or two contextual filter where the filter takes the taxonomy term ID Raw from the URL.

Example: doamin.com/fruit/grape/,

therefore, parent will be second in path. The parent term in this case is Grape.

So in the block we will show children and grandchildren of Grape:

--Red

---Small

---Medium

---Large

-- White

Ideally grouped by RED, WHITE.

Apply the contextual filter to a second filter? Not sure, I am just guessing.

# Answer
> 1 votes
You can create a Block that displays Child and Grandchild terms (in terms of hierarchy within a Taxonomy Vocabulary) on a taxonomy term pages with the use of an additional module Views Contextual Filters OR to tell the Views to show children `OR` grandchildren.

Contextual filters always work with the `AND` operator, so this module is necessary to loosen that circumstance.

1. Create View of type `Taxonomy term`
2. Filter it to show only the Food Vocabulary
3. To show Children of a term on that term page we can use the **Parent term** Contextual filter with these options:
`When the filter value is NOT available`
**Provide default value**
**Taxonomy term ID from URL**
**Load default filter from term page**
`When the filter value IS available or a default is provided`
**Specify validation criteria**
**Taxonomy term ID**
**Food**

Now if you enter a term ID into Preview you will see the Child terms of that term. This takes care of the Parent-Child.
4. To filter Grandchildren we have to introduce that level of connections into View. Add the **Parent** Relationship
5. Add another **Parent** Relationship and make it use the first one, this is how we get Grandparent info
6. Add a new Contextual filter **Term ID** and make it use the **second** Parent Relationship and other options the same as above.

Now if you enter `all/[TID]` you will see the grandchildren terms of the \[TID\].
7. To make the Contextual work with `OR` go to **Query settings** and enable **Contextual filters OR** option.

To test enter the term ID twice into Preview `[TID]/[TID]`.
8. Add the Field **Name** from the Taxonomy term Category and make it use the first Parent Relationship (that is the Parent, not the Grandparent), you can `Exclude it from display` later
9. Under Format Settings set the **Grouping field Nr.1** set the Parent field (you might want to use the `HTML List` as the Format)

The results will show the grandparent first and its children, then grandchildren under their parents.

If the grandparent showing their children is not necessary for you, which it probably isn't, because it will be implied from circumstances by being on the grandparent page, you can edit the Filter from step 2 and make it use the second Parent Relationship, this will only show Grandchildren grouped by Parents.

Place the Block in a region and limit the **Pages** to `/taxonomy/term/*`.

Alternatively you'd have to use Views Field View to insert one view into another, which can be performance heavy. I'm not sure how the above compares, it does use some LEFT JOINs too which aren't so performance friendly.

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


# Question
Title: How to redirect to a edit node page with RedirectResponse?
From a hook (not form\_alter), I want redirect the user to a node edit page (like mywebsite/node/\[nid\]/edit) How can I do that with the `RedirectResponse` class?

After searches, I found the following code.

```
new RedirectResponse(\Drupal::url('route.name'));

```

How can I get/find the route.name for a node edit page?

**Update :**

According the cilefen's answer =) From my entity\_insert hook :

```
function article_entity_insert(EntityInterface $entity) {
  if ($entity->bundle() == "article"){
    Url::fromRoute('entity.node.edit_form',['node', $entity->id()]); //But when I create a new node, the "view" page is loaded and not the edit page
    dpm($entity->id()); //show the node id
  }
}

```

**Update 2 :**

The command

```
dpm(Url::fromRoute('entity.node.edit_form',['node', $entity->id()]));

```

return

```
Drupal\Core\Url Object
(
    [urlGenerator:protected] =>
    [urlAssembler:protected] =>
    [accessManager:protected] =>
    [routeName:protected] => entity.node.edit_form
    [routeParameters:protected] => Array
        (
            [0] => node
            [1] => 31
        )

    [options:protected] => Array
        (
        )

    [external:protected] =>
    [unrouted:protected] =>
    [uri:protected] =>
    [internalPath:protected] =>
    [_serviceIds:protected] => Array
        (
        )

)

```

But the command

```
dpm(Url::fromRoute('entity.node.edit_form',['node', $entity->id()])->toString());

```

Return this error :

> \[Mon Feb 15 01:38:30.081002 2016\] \[:error\] \[pid 10219\] \[client 192.168.1.48:49246\] Uncaught PHP Exception Drupal\Core\Entity\EntityStorageException: "Some mandatory parameters are missing ("node") to generate a URL for route "entity.node.edit\_form"." at /var/www/system/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php line 757, referer: http://192.168.1.44/system/node/add/article

# Answer
> 9 votes
Note that `\Drupal::url()` is deprecated. You should use the static methods of the `Url` class to create URLs from routes.

To find the route names, use the Drupal console `drupal router:debug`. From that I found:

```
 entity.node.edit_form  /node/{node}/edit

```

I think what you need is `Url::fromRoute('entity.node.edit_form', ['node' => 1])` where 1 is the node ID to be edited.

# Answer
> 4 votes
From your controller class, you can use the redirect() method like so :

```
return $this->redirect('entity.node.edit_form', ['node' => $node_id]);

```

For other ways of doing this, see drupal\_goto() has been removed.

There's no need to fiddle with Urls or string conversion as discussed in the other answer.

# Answer
> 1 votes
You have:

```
Url::fromRoute('entity.node.edit_form', ['node', $entity->id()])->toString()
                                               ^^

```

I think you want:

```
Url::fromRoute('entity.node.edit_form', ['node' => $entity->id()])->toString();
                                               ^^^^

```

The first has an *indexed* array as the second parameter to Url::fromRoute(), the second has a *named* array as the second parameter.

---
Tags: 8, redirection
---


title: How to call a block inside a view page?

text:
# Question
Title: How to call a block inside a view page?
I am working with Drupal 8. I have a view page and added a twig for that.

I want to call a block inside my view page. How can I do that?

# Answer
Here is some possible ways to do it:

# 1. using no extra modules

Click ADD next to header or footer area and look for `GLOBAL: Rendered entity - Block`. The configuration asks for `view mode` and `block id`

# 2. using Views block area module

You can use Views block area module that will allow you to insert a block as a field or in header or footer area.

# 3. using preprocess / twig

if you want to add the block using your twig template in your `THEMENAME.theme` file using a `preprocess` function

```
function THEMENAME_preprocess_XXX (&$variables) {
    $block = \Drupal\block\Entity\Block::load('id_block');
    $variables['myBlock'] = \Drupal::entityTypeManager()
        ->getViewBuilder('block')
        ->view($block);
}

```

and then inside your twig file use this

```
{{ myBlock }}

```

To find appropriate preprocess function look in your twig file comments.

For example if you want to use `views-view--unformatted.html.twig` you can see in the comments

```
* @see template_preprocess_views_view_unformatted()

```

which means include in your `.theme` file `THEMENAME_preprocess_views_view_unformatted()` function
> 2 votes

# Answer
You can use module Twig Tweak this module you can render view,block ... You can see document here

Render views

```
{{ drupal_view('who_s_new', 'block_1') }}

```

Render blocks

```
{{ drupal_block(plugin_id) }}

```
> 2 votes

---
Tags: views, 8
---