# Question
Title: How to set programmatically Line Item Price?
I just managed to add programmatically a line item (type: product) to my order.

I struggle to set the price for this item now. How can I set the price at the same time when adding such an item (and having the total calculated accordingly)?

This is how I can successfully add a product:

```
 $product_id = XXX;

// Load whatever product represents the item the customer will be
// paying for and create a line item for it.
$product = commerce_product_load($product_id);
commerce_product_save( $product );

$line_item = commerce_product_line_item_new($product, 1, $order->order_id);

// Save the line item to get its ID.
commerce_line_item_save($line_item);

// Add the line item to the order
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$order_wrapper->commerce_line_items[] = $line_item;

// Save the order again to update its line item reference field.
commerce_order_save($order);

```

# Answer
> 1 votes
I have struggled a bit with this, as have others apparently, but i found the solution in another thread.

Every time an order object is loaded the following function is fired:

commerce\_cart\_line\_item\_refresh()

In this function the unit price of the Line Item is set to the current price of the original product, so even if you change the unit price, when you create the line item, its changed back to the original price the next time you load the order object.

So rather than setting the unit price of a line item, when you create it, you have to do it every time it's refreshed - For this Drupal Commerce offers the following hook:

HOOK\_commerce\_cart\_line\_item\_refresh($line\_item, $order\_wrapper)

Heres a coding example:

```
function YOUR_MODULE_commerce_cart_line_item_refresh($line_item, $order_wrapper){

$line_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);

$label = $line_wrapper->line_item_label->value();

//Only alter price for a specific product type (you could choose other selection critirias here)
if ( $label == 'YOUR PRODUCT TYPE'){
    $new_price = calculate_new_price(); //I use a function to calculate a price, you could set a static price instead

    if(!empty($new_price)){
        $line_wrapper->commerce_unit_price->amount->set($new_price);
        $line_item->commerce_unit_price['und'][0]['data']['components'][0]['price']['amount'] = $new_price;
        $line_wrapper->save();
    }

}

```

}

```
function calculate_new_price(){

//Do what ever pricing logic you need here

//Here a static price of one dollor
$price = 100;

return $price;

```

}

# Answer
> 0 votes
Once you've added it to the order, the standard product pricing system takes over to derive the price of the line item from the price of the product (well, depending on the order status). So if this order is a cart order, it should get its price automatically on the subsequent order load that triggers price calculation.

If you're wanting to set it to something other than the calculated sell price, you'll need some strategy that involves storing the price directly on the line item object (either in the data array or a custom field) and then setting the unit price of the line item to that stored price during the sell price calculation process.

# Answer
> 0 votes
try to following code.. //update line\_item amount

```
  $amount = XXXX;
  $order_id = XXX;

  $line_item_id = db_select('commerce_line_item', 'li')
            ->fields('li',array('line_item_id'))
            ->condition('li.order_id', $order_id, '=')
            ->execute()->fetchField();
  $line_item = commerce_line_item_load($line_item_id);

  $line_item->commerce_unit_price[LANGUAGE_NONE][0]['amount'] = $amount;
  $line_item->commerce_unit_price[LANGUAGE_NONE][0]['data']['components'][0]['price']['amount'] = $amount;
  commerce_line_item_save($line_item);

```

Thank You

---
Tags: commerce, payment-gateways
---


# Question
Title: how to optimize setting theme suggestion for different languages?
I've been trying to look for a way on how to optimize theme suggestions for different languages. The code below is a snippet of what I have been working on.

One is for english and one is for Spanish. Is there a way I can minimize this into a single code instead of breaking it down for multiple languages?

```
// Template based on current url
// News Press Room

if ($current_url == '/iom/news-press-room') {
    $suggestions[] = 'page__news_press_room';
}

// News Press Room(Spanish)

if ($current_url == '/iom/es/news-press-room') {
    $suggestions[] = 'page__news_press_room';
}

```

# Answer
> 1 votes
Check the example in hook\_theme\_suggestions\_alter() for language (second one below)
You can add more specific suggestions by appending the content type.

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


# Question
Title: Filter product displays by parent taxonomy term
I'm running a music store and have a taxonomy term field on products that that is used for the product's format. We tag the products from the following vocabulary.

* Vinyl
    + 140g vinyl
    + 180g vinyl
* CD
    + Jewelcase
    + Digipack
* Digital
    + Mp3
    + FLAC

I'd like create an exposed filter on the product catalog using the parent terms, *Vinyl*, *CD*, *Digital*. When one of taxonomy terms is selected, the filter should display all products tagged with the child terms.

The *Content: Has taxonomy terms (with depth)* filter doesn't seem to work with referenced products. I'm not seeing a solution in the Taxonomy Entity Index module either (but I might be wrong).

# Answer
> 0 votes
With a view using Products as base\_table:

1. Add a relationship using the taxonomy reference field you're using and do not require the relationship
2. Add an exposed filter \`Content: Has taxonomy terms (with depth)
3. In the settings, set the depth to the level you want
4. In the exposed filter itself, you can configure whether multiple values can be selected or not.

But before all that, you need to make sure that only the child terms are selected on the products.

---
Tags: 7, views, commerce
---


title: Filter criteria date and granularity

text:
# Question
Title: Filter criteria date and granularity
In my view I filtered for date "greater than now" and in the settings I put granularity "day".

I can see the 3 events correctly, but they are grouped by "month" and not in chronological order though.

Is there any option I can't find by myself to view the events in chronological order?

I sorted by date ASC

This is the export display: https://kopy.io/DRwkf

This is the export of all the view: https://kopy.io/KJsM0

# Answer
In your views sort settings, make sure your Date sort is the first one, because it seems that there is another sort by entity title applied first

---

# UPDATE

After checking the view export:

```
/* Sort criterion: Content: Post date */
$handler->display->display_options['sorts']['created']['id'] = 'created';
$handler->display->display_options['sorts']['created']['table'] = 'node';
$handler->display->display_options['sorts']['created']['field'] = 'created';
$handler->display->display_options['sorts']['created']['granularity'] = 'month';

```

You are sorting the results using "Post Date" of the node, not the date field, you should remove this and add the date field instead
> 0 votes

---
Tags: 7, views
---


# Question
Title: How to use url alias in views for taxonomy terms?
On a Drupal 7 site with pathauto installed I'm using a view to show all taxonomy terms of a given node. The terms are linked to the term's page. The problem is, that the path of those terms does not use the url alias' that are set for the terms. Is there a way (without programmatically rewrite the view) to use alias in a view?

I know about the globalredirect module, but a redirect is not a clean solution here, in my opinion. And I do not understand why the pathes aren't replaced by there aliases in a view, can someone explain please?

# Answer
This is a kind of workaround but I thinks the simplest solution for you would be to use the module: TVI: Taxonomy View Integrator

Then when when you modify the terms vocabulary you can use a view to replace the default page default view: the url alias of the term alias would call your view.
> 0 votes

---
Tags: 7, views, taxonomy-terms, path-aliases
---


# Question
Title: How to enforce a one-to-one relationship
I want to store data about students and the books they read. Each student can read only one book, and each book can be read by only one student.

I have created a Student content type, and a Book content type, and I have created a reference field in the Student content type to reference the Book content type, and I have made the reference field to only accept one value:

So this way when I am entering data for a student, I can only enter one book value for the student (so the constraint that a student can only read one book is enforced).

But I can still enter the same book for more than one student, for example I can enter book1 for student1 and and I can also enter book1 for student2. How can I prevent this (remember that I want each book to be read by only one student)? The way I can do that if I am creating a database is to make the book foreign key in the Student table unique, but I don't think there is a way to make a field unique in Drupal.

# Answer
I think you will need to use an entity reference view to enforce your restriction. In the settings for your reference type you can select Default or Views: Filter by an entity reference view

You will need to create your View first, instead of adding a Page or Block you need to add Entity Reference but this isn't available as part of the Views Wizard.

Part of the filter criteria will be to hide books which have already been assigned to a student. Hope this helps you get to your solution
> 2 votes

# Answer
Colin Shipton's solution is perfect (however if I write my post request on my own to a book ID that's already assigned, I can still assign it). Mine is just an other way to solve things: You can also inherit from the default EntityReference widget and just adding an extra validation to it: When the user submits the request you can check whether the chosen book ID is already assigned to another student or not. In case the answer is TRUE you just need to throw a validation error.
> 1 votes

---
Tags: 8
---


# Question
Title: How to add constrain validation on entity_create
So in my BaseFieldDefinition I have this below

```
 $fields['name'] = BaseFieldDefinition::create('string')
  ->setLabel(t('Name'))
  ->setDescription(t('The name of the Crypto entity.'))
  ->addConstraint('UniqueField')

```

And I was hoping this would make this "name" field unique when creating new enteties. It does when I try to do that in UI, but when programmatically making new entities it is just ignored.

```
 $crypto = entity_create('crypto', array(
  'name' => "Dai",
  'status' => '1',
));
$crypto->save();

```

So should I use some other method for creating entities or do I need to add some manual validation here?

Also extra question, how do I find list of "addConstraint" values that are present in core?

# Answer
Entities aren't validated automatically when saved via the API. (I'd be interested in knowing more about why not.) See the validation API docs for examples of validating a field and a whole entity:

```
$violations = $entity->field_text->validate(); // single field
$violations = $entity->validate();             // whole entity

if ($violations->count() > 0) {
  // Validation failed.
}

```

To find all possible constraints, look for anything extending (possibly indirectly) `\Symfony\Component\Validator\Constraint`.
> 2 votes

---
Tags: 8, entities
---


# Question
Title: How do you add validation (constraints?) on a paragraph? Compare two fields
How does one go about adding validation (contraints?) on a paragraph?

I need to compare two entity reference fields on submission. If one field has a certain entity referenced, the other cannot have certain entity references.

I'd be interested in restricting the autocomplete options as well, but that simply won't be enough as I need to ensure that they user doesn't manually enter another entity value.

# Answer
You simply inherit from the the default EntityReferenceWidget and you will call it like MyParagraphEntityReference widget. You can here both change the way how the autocomplation works and also how you validate the entered data.

This is page may help you.
> -1 votes

---
Tags: 8, forms, paragraphs
---


# Question
Title: Plugin Derivatives For Queue and Migration Plugins
I've created a custom Content Entity and a custom Content Entity Type, basically I'm mirroring the Node module but the purpose of this is to have external data to be synced with this setup(not using node and the content types because I want the content not to have any canonical pages, and at the same time, I am supposed to have content with landing pages).

Content Sync \- this link provides a good example of setting up a sync process using the Migrate module. I would need a set of plugins to define the migration process for a custom entity, but since I have multiple types of my custom entity, can it be possible to use derivatives for any types of plugins(Migrate module - source, process, destination and Queue plugins like QueueWorker) to handle each type of custom entity dynamically?

This might be a huge question to dig into, but I'm more interested in a yes/no type of answer, because I can do the investigation myself afterwards, just need to know if it's worth it.

# Answer
> 0 votes
The annotation cannot be derviated, but the class itself yes.

---
Tags: 8, entities, migrations, queue
---


title: Finding the host node of a paragraph

text:
# Question
Title: Finding the host node of a paragraph
I'm trying to find all the absolute URLs in a site (in wysiwyg content, url fields, config) to convert them into relative URLs later via manual administration. All the URLs in question are within the same Drupal site. I've managed to use PHPMyAdmin to find and record readily-accessible entities that contain absolute urls (nodes - `/node/NID/edit`, menu items - `/admin/structure/menu/item/MLID/edit`, etc.). However, I'm having a difficult time with Paragraphs.

* The id of a paragraph field row is for a specific instance of the paragraph.
* Without knowledge of the field hosting the paragraph, the instance could be *anywhere*.
* The paragraph could be nested in another paragraph.

How would one go about solving this issue? How do I find the host node of paragraphs containing an absolute link?

# Answer
> 2 votes
It might be a bit easier to use the API rather than SQL for this. I'd be tempted to load all nodes, loop through all their fields and check values that way. If you hit a paragraph field, recurse and check its fields too.

This is a very rough example function, but it should get you going:

```
function entityHasFieldWithAbsUrl(\Drupal\Core\Entity\ContentEntityInterface $entity, array $types) {
  foreach ($entity->getFields() as $key => $field) {
    $field_type = $field->getFieldDefinition()->getType();
    $field_settings = $field->getSettings();
    if ($field_type == 'entity_reference_revisions' && $field_settings['target_type'] == 'paragraph') {
      foreach ($field as $item) {
        if ($item->entity instanceof \Drupal\paragraphs\ParagraphInterface) {
          if (entityHasFieldWithAbsUrl($item->entity, $types)) {
            return TRUE;
          }
        }
      }
    }
    elseif (in_array($field_type, $types)) {
      foreach ($field as $item) {
        // Change this to something better...
        if (strpos($item->value, 'https://www.example.com/') !== FALSE) {
          return TRUE;
        }
      }
    }
  }

  return FALSE;
}

```

And you'd use it something like this:

```
$nodes_with_abs_urls = [];
$nodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple();
$types = ['text', 'text_long', 'text_with_summary', 'string'];
foreach ($nodes as $node) {
  if (entityHasFieldWithAbsUrl($node, $types)) {
    $nodes_with_abs_urls[] = $node->id();
  }
}

```

You probably need to tweak the types to suit your installation, but it should work at a basic level.

# Answer
> 1 votes
So what I ended up doing was searching for the URLs in PHPMyAdmin, picked out all the tables that belong to paragraph fields (they were prefixed `paragraph__`) and gathered all their `entity_id`s. Then using a temporary Drush command, I loaded all of these paragraphs and for each, recursively loaded `$paragraph->getParentEntity()` until it hit a desired entity type (in this case, nodes). Then I recorded the node ids.

```
function mymodule_drush_command() {
  $items = [];
  $items['mycommand'] = [
    'description' => 'Find the nids of the pids',
    'arguments' => [],
    'drupal dependencies' => ['mymodule'],
    'aliases' => [],
  ];
  return $items;
}

function drush_mymodule_mycommand() {
  // Could be improved by retrieving ids via query.
  $pids = [/* paragraph entity_ids */];

  // For each, recursively search ancestors.
  $nids = array_unique(array_filter(array_map(function($pid) {
    return _mymodule_find_node(\Drupal\paragraphs\Entity\Paragraph::load($pid));
  }, $pids)));

  // Print results
  drush_print_r(array_map(function($nid) {
    return '/node/' . $nid . '/edit';
  }, $nids));
}

function _mymodule_find_node($entity){
  // Could be improved by handling more than just nodes
  if ($entity instanceof \Drupal\node\NodeInterface) return $entity->id();
  // If still a paragraph, climb
  if ($entity instanceof \Drupal\paragraphs\ParagraphInterface) return _mymodule_find_node($entity->getParentEntity());
  // Otherwise, this is an entity we didn't want.
  return null;
}

```

Bulk of this operation could have been automated. It could have been improved to grab the entity ids via a query instead of PHPMyAdmin and handle different root types like blocks, terms, etc. It could also be more performant by not loading every single paragraph. But the above did what I needed at the moment, so I left it as is.

---
Tags: entities, uri, paragraphs
---


title: How to make conditional path aliases?

text:
# Question
Title: How to make conditional path aliases?
In Drupal 8 you can create path aliases by going to: admin/config/search/path/patterns/add

Which allows me to, for example, say that all content of type "blog\_post" can have something like this:

```
/blog/[category]/[title]

```

The problem is, I want the TOP path to be different, depending on the category. Specifically, I want any blog post that has the category = Competition, to have:

```
/competitions/[title]

```

While still being able to have

```
/blog/[category]/[title]

```

I can't seem to get this going. Is there a way to do this? I tried creating another aliases but I don't think there is any path I can specify that will give me this?

# Answer
## Solution 1: Without code

* Configure a taxonomy vocabulary named *Blog category* to manage blog categories.
* Configure *Blog category* aliases to `/blog/[term:name]`.
* For the *Competitions* term, override the URL alias to `/competitions`.
* Configure a taxonomy term reference field (preferably single value) on the *Article* content type. Say, the field name is `field_category`.
* Configure the *Article* path pattern as `/[field_category:entity:url:path]/[node:title]`.

This is somewhat like what gapple has mentioned above.

## Solution 2: With code

* Configure a taxonomy vocabulary named *Blog category* to manage blog categories.
* Configure a taxonomy term reference field (preferably single value) on the *Article* content type. Say, the field name is `field_category`.
* Configure the *Article* path pattern as `/blog/[field_category:entity:name]/[node:title]`
* Use `hook_pathauto_pattern_alter()` or `hook_pathauto_alias_alter()` to change the path pattern depending on the `$context`.

This is what I did for my problem. This way, you can choose whatever alias you want for your taxonomy term.
> 3 votes

# Answer
A solution I've implemented for a potentially similar problem in the past, however it only works if the Category taxonomy is exclusive to the blog content type:

1. Set the pattern for 'category' taxonomy terms to `/blog/[name]`
2. Override the alias for the Competition term to be `/competitions`
3. Set the pattern for the blog nodes to reference their category's path.
This should be something like `[test_term_reference:entity:url:path]/[title]` (or `[test_term_reference:entity:0:url:path]/[title]` if category is multi-value)

---

See https://www.drupal.org/node/2493559 for where Token module implemented tokens for referenced entities.
> 2 votes

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


title: Disallow HTML in comments

text:
# Question
Title: Disallow HTML in comments
I'd like to disallow all HTML and only allow plain text in comments across the site for all users, authenticated or not, but I still want to use other HTML filters for other content types. How can I achieve that in Drupal 8?

I've created a custom text format called "No HTML" and set it as the default format for comment bodies at `admin/structure/comment/manage/comment/fields/comment.comment.comment_body`. But instead of disallowing all HTML, it gives the option to change the text format to any other format available to the user.

How can I get comments to only use my "No HTML" text format for all users without disabling the other text formats for other content types?

# Answer
The Allowed Formats projects allows you to control the available text formats per field, so you can limit it to plain text. Better Formats is a similar module.

You could do the same with a form alter and set #allowed\_formats on the form element. Or you could remove the default comment body field and replace it with a plain text field. Although there might be some code relying on the name/existence of the default body field.
> 5 votes

# Answer
Berdir provided the key to figuring this out in his answer, so I marked it as the answer, but I'll post how I finally resolved this issue. Since I only need this for the comment forms, I decided to just write a small module to take care of the problem. Here's how I implemented hook\_form\_FORM\_ID\_alter():

```
function MY_MODULE_form_comment_comment_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  $form['comment_body']['widget']['0']['#allowed_formats'] = array('plain_text');
}

```

But I've also confirmed that the Allowed Formats module also does the job quite nicely. It gives me the option to limit the comment body field at `admin/structure/comment/manage/comment/fields/comment.comment.comment_body` without needing to touch code.
> 2 votes

# Answer
If go to Permissions (admin/people/permissions) you can set which user roles are allowed to use filter types, so you can uncheck basic HTML, Full HTML and Restricted HTML for authenticated users, then they wont have the option to change the text format.

EDIT:

Some other options to disable the filter input form for comments only:

1. Use the Simplify Module

2: Hide the filter form with CSS (Not my advised choice) so it doesn't display.

```
div.edit-comment-body-0-format {display:none; visibilty:hidden;}

```

3: Manipulate the the comment form output with PHP using hook\_form\_FORM\_ID\_alter() and unset the filter options. This would be my preferred choice. I can't provide a snippet for this just yet, but I will edit and add it as soon as I can.
> 0 votes

# Answer
Another Solution Is To Use --- `fields.field_article_type.content|render|striptags`
> 0 votes

---
Tags: entities, 8, comments
---


# Question
Title: How do I correctly setup caching for my custom API routing?
I have custom module with some routes which return JSON, for instance terms of a vocabulary.

routing.yml

```
mymodule.terms:
  path: '/api/terms/{vid}'
  defaults:
    _controller: '\Drupal\mymodule\Controller\MyModuleController::getTerms'
    _title: 'Terms'
  requirements:
    _permission: 'access content'
    vid: '^(foobar|barfoo)$'

```

Controller:

```
public function getTerms($vid) {
  $response = $this->jsonifyVocabulary($vid);
  return $response;
}

private function jsonifyVocabulary($vid) {
  $request = \Drupal::request();
  $lang = $request->query->get('lang', 'en');
  $output = [];
  $taxonomyManager = \Drupal::entityManager()->getStorage('taxonomy_term');
  $terms = $taxonomyManager->loadTree($vid, 0, 1, false);
  $response = CacheableJsonResponse::create($output);

  debug(1);

  foreach ($terms as $term) {
    $term = Term::load($term->tid);
    if ($term->hasTranslation($lang) && $lang !== $term->language()) {
      $term = $term->getTranslation($lang);
    }
    $entry = [
      'tid' => (int) $term->id(),
      'label' => $term->getName(),
    ];

    // $response->addCacheableDependency($term);
    $output[$vid][] = $entry;
  }

  $response->setData($output);

  $cacheMeta = (new CacheableMetadata())->addCacheContexts(['url.query_args:lang']);
  $response->addCacheableDependency($cacheMeta);

  return $response;
}

```

Thanks to this answer I know how to actually add the URL params as a cache context, but the

```
debug(1);

```

always gets called, I guess I just somehow have to tell Drupal that this JSON response's cache should relate to that route...

I don't use the core's REST module on purpose since I find it hard to configure to output exactly what I need.

# Answer
> 14 votes
This is all you need to set up caching for a response:

```
  $response = CacheableJsonResponse::create($output);
  return $response;

```

If you use a response that implements the CacheableResponseInterface it will be cached indefinitely.

**Cache tags**

When you add a list of taxonomy terms you have to add these tags:

```
  $list_tags = $this->entityTypeManager()->getDefinition('taxonomy_term')->getListCacheTags();
  $cache_metadata->addCacheTags($list_tags);

  foreach ($terms as $term) {
    $cache_metadata->addCacheableDependency($term);
  }

```

This will invalidated the cache entry when the terms are modified in the database.

**Cache contexts**

When you use a query parameter add this context:

```
  $lang = $request->query->get('lang', 'en');
  $cache_metadata->addCacheContexts(['url.query_args:lang']);

```

This will vary the cache by the query arguments.

**Cacheable metadata in a response**

To put all this together create at the beginning of the controller an empty CacheableMetadata object:

```
  $cache_metadata = new CacheableMetadata();

```

While building the content collect the cache metadata for all dependencies you use as described in the two examples before and then add the metadata to the response at the end of the controller:

```
$response->addCacheableDependency($cache_metadata);

```

# Answer
> 1 votes
> ..I guess I just somehow have to tell Drupal that this json response's cache should relate to that route...

Looking at the "Cache contexts" documentation under "Debugging":

> *"All of the above is helpful information when debugging something that is being cached. But, there's one more thing: let's say something is being cached with the cache keys \['foo', 'bar'\] and the cache contexts \['languages:language\_interface', 'user.permissions', 'route'\]. Then the corresponding cache item will be cached in a particular cache bin with a CID (cache ID) of:*
>
> > *`foo:bar:[languages:language_interface]=en:[user.permissions]=A_QUITE_LONG_HASH:[route]=myroute.ROUTE_PARAMS_HASH`"*

It looks like if you're defining the cache contexts in the response, it should cache in the cache bin that has a CID for that route & cache context.

> I dont use the core's rest module on purpose since I find it hard to configure to output exactly what I need.

Drupal core REST includes a "Taxonomy vocabulary" REST resource that takes in the vocabulary ID as an argument:

By default, it returns the vocabulary's information like:

```
{
  "uuid": "46fb0c72-4570-4c7f-b90d-faa69f2c5e7a",
  "langcode": "en",
  "status": true,
  "dependencies": [],
  "name": "Vocabulary Name",
  "vid": "vocabulary_vid",
  "description": "Some vocabulary description.",
  "hierarchy": 0,
  "weight": 0
}

```

However, to get the terms for a particular vocabulary to show up in the JSON response, you can create a custom normalizer that can alter the output of this REST resource to your liking.

See:

# Answer
> 1 votes
Not sure if you have already found an answer for your question. I have spent literally half a day trying to find out what is wrong... Well - the answer is very simple: make sure you have the Internal Dynamic Page Cache module enabled. (This simplest way: `drush en -y dynamic_page_cache`)

When the module is disabled than NOTHING is being taken from cache. The module itself has an EventSubscriber, triggered on route match (see dynamic\_page\_cache/src/EventSubscriber/DynamicPageCacheSubscriber.php):

```
/**
 * Sets a response in case of a Dynamic Page Cache hit.
 *
 * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
 *   The event to process.
 */
public function onRouteMatch(GetResponseEvent $event) {
  // Don't cache the response if the Dynamic Page Cache request policies are
  // not met. Store the result in a static keyed by current request, so that
  // onResponse() does not have to redo the request policy check.
  $request = $event->getRequest();
  $request_policy_result = $this->requestPolicy->check($request);
  $this->requestPolicyResults[$request] = $request_policy_result;
  if ($request_policy_result === RequestPolicyInterface::DENY) {
    return;
  }

  // Sets the response for the current route, if cached.
  $cached = $this->renderCache->get($this->dynamicPageCacheRedirectRenderArray);
  if ($cached) {
    $response = $this->renderArrayToResponse($cached);
    $response->headers->set(self::HEADER, 'HIT');
    $event->setResponse($response);
  }
}

```

which actually takes care of the whole cache reading and returning a cached json response. Without the module the whole CachedJsonResponse is useless.

NOTE: I would like to give full credit for this answer to Monika From the Forests near Rzeszów. It was her dedication and commitment to finding this problem, that has given me this splendid opportunity to work on the challenge. Thank you. God bless you.

---
Tags: routes, caching, 8
---


title: Style of User login Page

text:
# Question
Title: Style of User login Page
I started to create my own homepage with a theme. Now i want to customize the user login-page. I can't find the user/login, user/register and user/edit pages in the context area of the administration menu.

I just want to change one block of the page and some css-type stuff. Is there an easy way to do this? I really don't want to create a whole new template just for some adjustments.

To be more specific, there is one style-element i want to be shown on the user-pages. I also want to change the URL's you are forwarded to after clicking the buttons.

# Answer
> 2 votes
Here is a module I have been messing around with to theme those login related pages.

slimlogin.module

```
/**
 * @file
 * Contains slimlogin.module.
 */

use Drupal\Core\Routing\RouteMatchInterface;

/**
 * Implements hook_theme().
 */
function slimlogin_theme($existing, $type, $theme, $path) {
  return array(
    'slimlogin_page' => array(
      'render element' => 'page',
    ),
  );
}

/**
 *
 */
function slimlogin_preprocess_html(&$variables) {
  $route_name = \Drupal::routeMatch()->getRouteName();

  if (in_array($route_name, ['user.login', 'user.pass', 'user.register'])) {
    $variables['html_attributes']->addClass('slimlogin-html');
    $variables['attributes']['class'][] = 'slimlogin-body';
  }
}

/**
 * Implements template_preprocess_slimlogin_page().
 */
function template_preprocess_slimlogin_page(&$variables) { }

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function slimlogin_theme_suggestions_page_alter(array &$suggestions, array $variables) {

  $route_name = \Drupal::routeMatch()->getRouteName();

  if (in_array($route_name, ['user.login', 'user.pass', 'user.register'])) {
    $suggestions = array('slimlogin_page');
    if ($route_name == 'user.login') {
      $suggestions[] = 'slimlogin_page__login';
    } elseif ($route_name == 'user.pass') {
      $suggestions[] = 'slimlogin_page__pass';
    } elseif ($route_name == 'user.regisiter') {
      $suggestions[] = 'slimlogin_page__register';
    }
  }

}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function slimlogin_form_user_login_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) { }

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function slimlogin_form_user_pass_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) { }

```

templates/slinglogin-page.html.twig

```
{#
/**
 * @file
 * Default theme implementation to display a single Drupal page while offline.
 *
 * All available variables are mirrored in page.html.twig.
 * Some may be blank but they are provided for consistency.
 *
 * @see template_preprocess_slimlogin_page()
 *
 * @ingroup themeable
 */
#}
{%
  set classes = [
    'slimlogin-main'
  ]
%}
{{ attach_library('slimlogin/base') }}
{{ page.messages }}

<main{{ attributes.addClass(classes) }}>
  {{ page.help }}
  {{ page.content }}
</main>

```

css/slimlogin.css

```
.slimlogin-body {
  background-color: #fff;
  color: #000;
  margin: 0;
}

@media all and (min-width: 460px) {
  .slimlogin-html {
    display: table;
    height: 100%;
    width: 100%;
  }
  .slimlogin-body {
    display: table-cell;
    height: 100%;
    vertical-align: middle;
    width: 100%;
  }
}

.slimlogin-main {
  background-color: transparent;
  margin-right: auto;
  margin-left: auto;
  width: 300px;
}
@media all and (min-width: 460px) {
  .slimlogin-main {
    width: 440px;
  }
}

```

slimlogin.install

```
/**
 * @file
 * Install, update, and uninstall functions for the SlimLogin module.
 */

/**
 * Implements hook_install().
 */
function slimlogin_install() {
  module_set_weight('slimlogin', 99);
}

```

slimlogin.libraries.yml

```
base:
  version: VERSION
  css:
    theme:
      css/slimlogin.css: {}

```

slimlogin.info.yml

```
name: SlimLogin
type: module
description: My Awesome Module
core: 8.x
package: Custom

```

A quick summary of the workings of this. `hook_theme()` give you a new template for the page. This page template is managed/customized into ways: the function `template_preprocess_slimlogin_page()` and the template file `templates/slinglogin-page.html.twig`.

`hook_theme_suggestions_HOOK_alter()` use the Route names to add the new page template to the list of suggestions for the user login, user password reset, and user request pages.

The preprocess and alter functions are there for you to made customization. for example `slimlogin_preprocess_html` adds some classes to the HTML and Body tags to help with your styling. you also have: `template_preprocess_slimlogin_page()`, `slimlogin_form_user_login_form_alter()`, and `slimlogin_form_user_pass_alter()`.

And I think the other file are rather straight forward as to what they do. But if you need more info on those, ask in with a comment.

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


# Question
Title: \Drupal::currentUser() returns admin account info instead of logged in user
The following function resides in a .module file:

```
function user_menu_avatar_menu_links_discovered_alter(&$links) {

    $user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
    $name = $user->get('name')->value;
    $userMenuAvatar = $user->get('user_picture')->entity->url();

    $links['user.page']['title'] = $name;

}

```

When logged in as another user, I am only getting the account info from the Admin user account. User name, email, etc..

What am I missing?

# Answer
`hook_menu_links_discovered_alter()` is not invoked right before the links are shown, but when the links need to be rebuilt. Using the code you are showing, you are getting values from the user who is currently logged-in when the links are rebuilt; until the next rebuilt, that is the value shown for every user. (This means this is not the right method to dynamically change the menu link.)
If the links rebuilt is caused from a action you take when logged-in as administrator user, that explains why the name shown is taken from the administrator user.

If you need to alter the title used for a page, you need to alter the route and set its *\_title\_callback* property. The title callback is invoked right before the title is shown, so accessing there the object for the currently logged-in user would be correct.
> 3 votes

---
Tags: 8, users
---


title: Debugging Module Show PHP Errors

text:
# Question
Title: Debugging Module Show PHP Errors
I saw in a YouTube video someone had made a configuration where if there was a PHP bug in their module, upon cache rebuild it would show the error underneath the "The Website Encountered an Unexpected Error" screen.

I've been running dual screens monitoring the php error log - but would actually prefer to consolidate it into that one screen. Where is that configuration option found?

# Answer
> 2 votes
You need add `$config['system.logging']['error_level'] = 'verbose';`

in file

```
sites/default/settings.php

```

or in `{example}.com/admin/config/development/logging` you checked in `All messages` after click to `Save configuration`

---
Tags: 8, debugging
---


title: Custom attributes for a menu item

text:
# Question
Title: Custom attributes for a menu item
I have to create a menu that includes items in a variety of languages including Arabic and Farsi.

Something like this:

```
-LTR item
-LTR item
 RTL item -
-LTR item
 RTL item -

```

Is there a way to add the dir='rtl' to specific menu items?

And more importantly, is there a way for me to make this accessible to non-technical users that will be maintaining the site after I have created it?

The site is being built in Drupal 8

Ideas?

# Answer
Maybe starting from https://www.drupal.org/project/link\_attributes and contributing a dir attribute patch (this way you have a UI for non tech users that will maintain the site)
> 1 votes

# Answer
You can use hook\_preprocess\_HOOK

```
/**
 * Implements hook_preprocess_HOOK().
 */
function hook_preprocess_menu(&$variables) {
  $variables['attributes']['class'][] = 'clearfix';
  if($variables['menu_name'] =='main'){
    foreach($variables['items'] as $item){
      if($item['title'] =='Home'){
        $item['attributes']['dir']='rtl';
      }
    }
  }
}

```
> 1 votes

---
Tags: 8
---


# Question
Title: How do I bulk update the alt and title tags of images
Is there a way to bulk update image title and alt tags? Where do alt and title tags are saved in the database?

# Answer
> 2 votes
Rewriting the D7 code of How to bulk update image alt and title?

```
$nodes = \Drupal::entityTypeManager()
  ->getStorage('node')
  ->loadByProperties(['type' => 'article']);

foreach ($nodes as $node) {
  $node->field_image->alt = $alt;
  $node->field_image->title = $title;

  $node->save();
}

```

---
Tags: 8, media
---


# Question
Title: Unable to pass the value from .module file to JS using the implementation given below
.module file

```
function taxonomy_fancybox_menu(){
     $items['fetch-popup-markup-data/%'] = array(
  'title' => 'Store markup',
  'page callback' => 'ajax_fetch_markup_popup_data',
  'page arguments' => array(2),
  'access arguments' => array('access content'),
  'type' => MENU_CALLBACK,
);
return $items;
}

function ajax_store_markup_popup_data($fieldname){

  $field = $_POST['field'];

  // $html = $_POST['html'];
     $output = theme('taxonomy_fancybox_term_field_display_template',array(
     'rows' => $_SESSION['taxonomy_fancybox'][$field]['rows'],
     'field'=>$field
    )
   );
     drupal_set_message($field);
   drupal_set_message($output);
   watchdog('taxonomy_fancybox','<pre> OUTPUT:'. $output . '</pre>');
   drupal_json_output(array('output'=>$output));
  // $_SESSION['taxonomy_fancybox'][$field]['html'] = $html;
  // drupal_json_output($html);
}

```

JS Implementation:

```
$('.popup-data').each(function(){
           var field = $(this).attr('field');
           var html  = $(this).html();
           $.ajax({
             type: 'POST',
              dataType: 'json',
             data: {field: field},
             url: '/fetch-popup-markup-data/'+field+'/',
             success: function(ht) {
              alert(ht);
              alert('got the html if not check in the console');
              console.log(ht);
              if (ht !=''){
                $('#'+field+'-popup-data').html(ht);
              }
             }
            // Change site name to current user name.
           });
        });

```

Whatever data I am passing in `drupal_json_output()` does not pass to JS and when I try to check the value in `watchdog`, I see the data, also see it in `drupal_set_message()` but when I check the html on the success function of the POST by sending `alert()` it returns empty value,even the `console.log()` returns empty value, what can be the reason for the empty value ?

# Answer
> 1 votes
Router:

```
$.ajax{{
...
 url: '/fetch-popup-markup-data/'+field+'/'

```

vs router

```
$items['store-popup-markup-data/%'] = array(..

```

not dissimilarity. change dataType `dataType: 'json'` to `dataType: 'html'`

You can try code below:

```
$('.popup-data').each(function(){
  var field = $(this).attr('field');
  var html  = $(this).html();
  $.ajax({
     type: 'POST',
     dataType: 'json',
     data: {field: field},
     url: '/store-popup-markup-data/'+field+'/',
     success: function(ht) {
       alert(ht);
       alert('got the html if not check in the console');
       console.log(ht);
       var jsonHt = $.parseJSON(ht);
       if (jsonHt.output !=''){
         $('#'+field+'-popup-data').html(jsonHt.output);
       }
     }

   });
 });

```

---
Tags: 7, javascript, ajax
---


# Question
Title: What is the difference between getValue() and referencedEntities() to fetch paragraphs?
What is the difference between using `getValue()` and `referencedEntities()` in order to get the paragraph on a node?

See example below. Both examples are used in a node template such as `node--page--full.html.twig` and `mymodule_preprocess_node()` hook.

**Using `getValue()`**

```
$paragraph = $node->field_paragraph->getValue();
foreach ( $paragraph as $pr ) {
  // Get the entity using Paragraph::load(entity_id).
  $pr_item = \Drupal\paragraphs\Entity\Paragraph::load($pr['target_id']);

  // Now use $pr_item to get any field.
  $pr_item_img = $pr_item->field_image;
}

```

**Using `referencedEntities()`**

```
$pr_field = $node->field_paragraph->referencedEntities();
foreach($pr_field as $pr) {
  $item_image = $pr->get('field_image');
}

```

I am mainly concerned with the following:

1. What is more performant?
2. What is the best practice since both work?
3. Is either method considered a magic method? I ask because you can use `$node->field_paragraph` as opposed to `$node->get('field_paragraph')`

# Answer
**Performance**

EntityReferenceFieldItemList::referencedEntities performs better because it uses loadMultiple() instead of loading the entities separately.

**Best practice**

You use static code to load the entity which should be avoided when possible. You could make proper OOP code out of it, but it is also best practice to not reinvent the wheel.

Edit: You've added the info this is in node preprocess. Then best practice would be to render the paragraph field in the node template `{{ content.field_paragraph }}`. Configure the field in UI, for example add a custom view mode. Theme the output in field and paragraph templates for this specific field or view mode.

**Magic method**

No, this doesn't involve a magic method, the method is called directly. A magic method is involved in getting entity fields as if they were object properties, like the example you've mentioned `$node->field_paragraph`.

**Translation**

You need to translate the entities for both methods before you can output translated field values directly:

```
$paragraph = \Drupal::service('entity.repository')
  ->getTranslationFromContext($paragraph, $langcode);

```

By the way core translates the entities later when building the rendered output using the entity reference field formatter. This works for core because it usually doesn't output field values directly, so this could be considered as bad practice as well, see for example this question from today How to display Paragraph bundles fields links inside a page.html.twig file that are within a paragraph bundle in Twig?.

**Revisions**

Paragraphs are stored in an EntityReferenceRevisions field. Your example code ignores the revision data and so you might load the wrong version. One more reason to use the methods provided by the field, `referencedEntities()` or `$item->entity` in case you need to load a single entity.
> 2 votes

---
Tags: 8, entities, hooks, paragraphs
---


# Question
Title: htaccess in files folder breaks displaying of images
I installed media module and all files in /file directory became unreachable - browser gives 500 internal server error. I can confirm files exist there. After removing htaccess from files directory, everything works ok. Could be that toot htaccess is not properly configured? (images located in root directory display ok)

```
# Turn off all options we don't need.
Options None
Options +FollowSymLinks

# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
  # Override the handler again if we're run later in the evaluation list.
  SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>

# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
  php_flag engine off
</IfModule>

RewriteEngine On

# cele domeny (aliasy)
RewriteCond %{REQUEST_URI} !^domains/
RewriteCond %{REQUEST_URI} !^/domains/
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$
RewriteCond %{DOCUMENT_ROOT}/domains/%2 -d
RewriteRule (.*) domains/%2/$1 [DPI]

# subdomeny (s nebo bez www na zacatku)
RewriteCond %{REQUEST_URI} !^subdom/
RewriteCond %{REQUEST_URI} !^/subdom/
RewriteCond %{HTTP_HOST} ^(www\.)?(.*)\.([^\.]*)\.([^\.]*)$
RewriteCond %{DOCUMENT_ROOT}/subdom/%2 -d
RewriteRule (.*) subdom/%2/$1 [DPI]

# aliasy - spravne presmerovani pri chybejicim /
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^domains/[^/]+/(.+[^/])$ /$1/ [R]

# subdomeny - spravne presmerovani pri chybejicim /
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^subdom/[^/]+/(.+[^/])$ /$1/ [R]

#fix for infinite loops - Request exceeded the limit of 10 internal redirects due to probable configuration error
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]

#
# Apache/PHP/Drupal settings:
#

# Protect files and directories from prying eyes.
<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl|svn-base)$|^(code-style\.pl|Entries.*|Repository|Root|Tag|Template|all-wcprops|entries|format)$">
  Order allow,deny
</FilesMatch>

# Don't show directory listings for URLs which map to a directory.
Options -Indexes

# Follow symbolic links in this directory.
#Options +FollowSymLinks

# Make Drupal handle any 404 errors.
ErrorDocument 404 /index.php

# Force simple error message for requests for non-existent favicon.ico.
<Files favicon.ico>
  # There is no end quote below, for compatibility with Apache 1.3.
  ErrorDocument 404 "The requested file favicon.ico was not found.
</Files>

# Set the default handler.
DirectoryIndex index.php

# Override PHP settings that cannot be changed at runtime. See
# sites/default/default.settings.php and drupal_environment_initialize() in
# includes/bootstrap.inc for settings that can be changed at runtime.

# PHP 5, Apache 1 and 2.
<IfModule mod_php5.c>
  php_flag magic_quotes_gpc                 off
  php_flag magic_quotes_sybase              off
  php_flag register_globals                 off
  php_flag session.auto_start               off
  php_value mbstring.http_input             pass
  php_value mbstring.http_output            pass
  php_flag mbstring.encoding_translation    off
</IfModule>

# Requires mod_expires to be enabled.
<IfModule mod_expires.c>
  # Enable expirations.
  ExpiresActive On

  # Cache all files for 2 weeks after access (A).
  ExpiresDefault A1209600

  <FilesMatch \.php$>
    # Do not allow PHP scripts to be cached unless they explicitly send cache
    # headers themselves. Otherwise all scripts would have to overwrite the
    # headers set by mod_expires if they want another caching behavior. This may
    # fail if an error occurs early in the bootstrap process, and it may cause
    # problems if a non-Drupal PHP file is installed in a subdirectory.
    ExpiresActive Off
  </FilesMatch>
</IfModule>

# Various rewrite rules.
<IfModule mod_rewrite.c>
  RewriteEngine on

  # Block access to "hidden" directories whose names begin with a period. This
  # includes directories used by version control systems such as Subversion or
  # Git to store control files. Files whose names begin with a period, as well
  # as the control files used by CVS, are protected by the FilesMatch directive
  # above.
  #
  # NOTE: This only works when mod_rewrite is loaded. Without mod_rewrite, it is
  # not possible to block access to entire directories from .htaccess, because
  # <DirectoryMatch> is not allowed here.
  #
  # If you do not have mod_rewrite installed, you should remove these
  # directories from your webroot or otherwise protect them from being
  # downloaded.
  RewriteRule "(^|/)\." - [F]

  # If your site can be accessed both with and without the 'www.' prefix, you
  # can use one of the following settings to redirect users to your preferred
  # URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option:
  #
  # To redirect all users to access the site WITH the 'www.' prefix,
  # (http://example.com/... will be redirected to http://www.example.com/...)
  # uncomment the following:
   RewriteCond %{HTTP_HOST} !^www\. [NC]
   RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
  #
  # To redirect all users to access the site WITHOUT the 'www.' prefix,
  # (http://www.example.com/... will be redirected to http://example.com/...)
  # uncomment the following:
  # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
  # RewriteRule ^ http://%1%{REQUEST_URI} [L,R=301]

  # Modify the RewriteBase if you are using Drupal in a subdirectory or in a
  # VirtualDocumentRoot and the rewrite rules are not working properly.
  # For example if your site is at http://example.com/drupal uncomment and
  # modify the following line:
  # RewriteBase /drupal
  #
  # If your site is running in a VirtualDocumentRoot at http://example.com/,
  # uncomment the following line:
  # RewriteBase /

  # Pass all requests not referring directly to files in the filesystem to
  # index.php. Clean URLs are handled in drupal_environment_initialize().
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^ index.php [L]

  # Rules to correctly serve gzip compressed CSS and JS files.
  # Requires both mod_rewrite and mod_headers to be enabled.
  <IfModule mod_headers.c>
    # Serve gzip compressed CSS files if they exist and the client accepts gzip.
    RewriteCond %{HTTP:Accept-encoding} gzip
    RewriteCond %{REQUEST_FILENAME}\.gz -s
    RewriteRule ^(.*)\.css $1\.css\.gz [QSA]

    # Serve gzip compressed JS files if they exist and the client accepts gzip.
    RewriteCond %{HTTP:Accept-encoding} gzip
    RewriteCond %{REQUEST_FILENAME}\.gz -s
    RewriteRule ^(.*)\.js $1\.js\.gz [QSA]

    # Serve correct content types, and prevent mod_deflate double gzip.
    RewriteRule \.css\.gz$ - [T=text/css,E=no-gzip:1]
    RewriteRule \.js\.gz$ - [T=text/javascript,E=no-gzip:1]

    <FilesMatch "(\.js\.gz|\.css\.gz)$">
      # Serve correct encoding type.
      Header set Content-Encoding gzip
      # Force proxies to cache gzipped & non-gzipped css/js files separately.
      Header append Vary Accept-Encoding
    </FilesMatch>
  </IfModule>
</IfModule>

```

# Answer
This isn't a Drupal specific question. However, enough Drupal users have this Apache problem that it makes sense to answer.

1. Whenever you get a `500 internal server error` you should check the webserver error log. (Any decent hoster gives you access to that file.) The error log normal contain a rather clear message about what is wrongly configured.
2. If removing the .htaccess file fixes the problem, you know that one of Apache directives in the file causes the error. Finding the directive if you don't have access to the error log can be a lot of work. However, reading the AllowOverride directive documentation will help by pointing to the most likely problem directives - unless it's just wrong syntax ... Often the problem is the "Options" directive as tenken already replied.
> 1 votes

# Answer
no i had the same issue the other day. It's more likely the `.htaccess` file in your `files` directory has directives not allowed by your webhost or just improper directives.

My files .htaccess in it was an upgrade from Drupal6 -\> Drupal7 and had: `Options None` in it and this broke my logo file, and 2 CSS files -- but everything else was ok.

Htaccess files `nest` so it's most likely the nearest `.htaccess` file to the affected files is causing the problems.

**EDIT**

This line is missing closing quotations in your root .htaccess file:

> ErrorDocument 404 "The requested file favicon.ico was not found.

But thats likely not the issue, i guess it could be.

Other than that assure these are the only .htaccess files on your site and examine them thoroughly.
> 0 votes

---
Tags: 7, files, media, .htaccess
---


title: Alias / to /lang_code

text:
# Question
Title: Alias / to /lang_code
I got a multilanguage configuration with language detection based on URL(/en /fr). Drupal behavior redirects everything to so it would have those two prefixes or, if setup, it will ignore the prefix for a language while keeping for the other.

In my situation I need to keep the prefix for both language except for root page.

Ex:

* example.com/en -\> will load english homepage
* example.com/fr -\> will load french homepage
* example.com/ -\> has to load english homepage but without redirect to /en

So, how can this be achieved?

# Answer
Drupal core doesn't redirect everything. Do you have the Redirect module installed? Then disable the route normalizer in the module settings, which is by default enabled:

*/admin/config/search/redirect/settings*

> **GLOBAL REDIRECTS**
>
> \[x\] Enforce clean and canonical URLs

If you want to keep the global redirect try this module specifically for the language prefix Disable Route Normalizer.
> 1 votes

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


# Question
Title: Custom node migration for multi-value imagefield
I'm working on a custom migration module to "link" images to the imagefield. It's work well for an unique value image field like this:

```
field_illus_vdl:
  -
    plugin: d6_field_file
    source: field_illus_vdl
    migration: upgrade_d6_file
  -
    plugin: skip_on_empty
    method: process

```

But not for a multivalue imagefield after different tests:

```
field_galerie_image_vdl:
  -
    plugin: skip_on_empty
    method: process
  -
    plugin: sub_process
    source: field_galerie_image_vdl
    process:
      target_id:
        plugin: migration_lookup
        migration: d6_file (upgrade_d6_file doesn't change result)
        source: fid
      alt: alt
      title: title
      description: description

```

I try with `iterator` plugin, but no change.What is missing or wrong ? Do order is important between for chained processes ?

thanks

EDIT: I see there that `sub_process` replace `iterator` plugin.But I don't find infos about a `cckfield` plugin.

Devel data example:

```
field_galerie_image_vdl (Array, 6 elements)
0 (Array, 10 elements)
1 (Array, 10 elements)
fid (String, 4 characters ) 2006
uid (String, 1 characters ) 8
filename (String, 11 characters ) niger_3.jpg
filepath (String, 48 characters ) sites/all/media/galerie/actu/2018/20/niger_3.jpg
filemime (String, 10 characters ) image/jpeg
filesize (String, 6 characters ) 113504
status (String, 1 characters ) 1
timestamp (String, 10 characters ) 1526837277
list (String, 1 characters ) 1
data (Array, 3 elements)
description (String, 0 characters )
alt (String, 0 characters )
title (String, 0 characters )

```

Extract of a value for a filefield from var\_dump:

```
[field_illus_vdl] => Array
    (
        [0] => Array
            (
                [fid] => 2004
                [uid] => 8
                [filename] => niger4.jpg
                [filepath] => sites/all/media/illustration_vdl/2018/20/niger4.jpg
                [filemime] => image/jpeg
                [filesize] => 181770
                [status] => 1
                [timestamp] => 1526837126
                [list] => 1
                [data] => Array
                    (
                        [alt] => Lycée Célony - Aix en provence
                        [title] => Lycée Célony
                    )

                [nid] => 471
                [view] => Lycée Célony - Aix en provence
            )

    )

```

This source could be the right way,but I can't it work actually.

EDIT2: an format error in my YML file break the process, so after reorder the file, files are migrated.With a more simple code too:

```
 field_galerie_image_vdl:
  -
    plugin: d6_field_file
    source: field_galerie_image_vdl
    migration: upgrade_d6_file
  -
    plugin: skip_on_empty
    method: process

```

# Answer
I think your problem come from source migrate. When you using process **sub\_process** source data must be an array like this:

```
[
    'fid' => 1,
    'another_key' => '...'
],
[
    'fid' => 2,
    'another_key' => '...'
],
[
    'fid' => 23,
    'another_key' => '...'
]

```

**Note: fid is old fid of database need to migrate.**

I'll show you a example migrate field image with multilple value. I have a content type with machine name **galary**. This content type have body and field images (machine\_name: field\_images) ullimited value.

I'll migrate data to this content. Create migration group **galary** with file name **migrate\_plus.migration\_group.galary.yml** and content

```
id: galary
label: Import galary images
description: Import field images has multilple values.

```

Create migration **file\_images** with file name **migrate\_plus.migration.file\_images.yml**

```
id: file_images
label: 'Migrate images files'
migration_group: galary
source:
  constants:
    file_destination: 'public://galary/'
  plugin: embedded_data
  data_rows:
    -
      fid: 1
      alt: 'Bootstrap'
      src: 'https://www.drupal.org/files/styles/grid-3/public/project-images/bootstrap_project_1.png'
      filename: 'bootstrap_project_1.png'
    -
      fid: 2
      alt: 'Adminimal - Responsive Administration Theme'
      src: 'https://www.drupal.org/files/adminimal-logo-slogan.png'
      filename: 'adminimal-logo-slogan.png'
    -
      fid: 3
      alt: 'AdaptiveTheme'
      src: 'https://www.drupal.org/files/styles/grid-3/public/project-images/Adaptivethemes_220.png'
      filename: 'Adaptivethemes_220.png'
    -
      fid: 4
      alt: 'Drupal8 Zymphonies Theme'
      src: 'https://www.drupal.org/files/styles/grid-3/public/project-images/desktop_8.png'
      filename: 'desktop_8.png'
  ids:
    fid:
      type: integer
process:
  public_path:
    -
      plugin: concat
      delimiter: ''
      source:
        - constants/file_destination
        - filename
    -
      plugin: urlencode
  uri:
    plugin: file_copy
    source:
      - src
      - '@public_path'
destination:
  plugin: entity:file

```

Create migration **node\_images** with file name **migrate\_plus.migration.node\_images.yml** and content

```
id: node_images
label: Node galaryy
migration_group: galary
source:
  plugin: embedded_data
  data_rows:
    -
      nid: 1
      title: 'Bootstrap'
      body: 'Body Bootstrap'
      images: 1|3
    -
      nid: 2
      title: 'Adminimal - Responsive Administration Theme'
      body: 'Body Adminimal - Responsive Administration Theme'
      images: 2|4
  ids:
    nid:
      type: integer
destination:
  plugin: entity:node
  default_bundle: galary
process:
  title: title
  'body/0/value': body
  'body/0/format':
    plugin: default_value
    default_value: basic_html
  field_images:
    plugin: sub_process
    source: images
    process:
      target_id:
        plugin: migration_lookup
        migration: file_images
        source: fid
migration_dependencies:
  required:
    - file_images

```

In my case, two source **file\_images** and **node\_images** I use the embedded\_data source plugin for the sake of simplicity so that this example can be copy-pasted as a working example.

Let see **images: 2|4** or **images: 1|3** in data\_rows. I'll use **source: images** for process **sub\_process** plugin but data is not like data example. So I need use hook\_migrate\_prepare\_row or method **prepareRow** in your source plugin to prepare soure.

```
/**
 * Implements hook_migrate_MIGRATION_ID_prepare_row().
 */
function MODULE_NAME_migrate_node_images_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration) {
  $images = $row->getSourceProperty('images');
  $images = explode('|', $images);
  $data = [];
  foreach ($images as $index => $fid) {
    $data[$index] = ['fid' => $fid];
  }
  $row->setSourceProperty('images', $data);
}

```

Now, you can import data to this content have multiple field images with

```
drush mim file_images && drush mim node_images

```
> 1 votes

---
Tags: 8, migrations, entities
---


# Question
Title: How to get the distinct number of the nodes?
In my task I need to get the distinct number of the nodes of some content type. How can I do it?

```
$query = $this->connection->select('node', 'node')->condition('node.type', $type);
$query->addExpression('COUNT(*)');
$query->innerJoin('taxonomy_index', $id,  "$id.nid = node.nid  AND $id.status = 1");
$count = intval($query->execute()->fetchField());

```

As the node may have multiple values for the field, in the end it counts all nodes and produces the wrong output. Therefore I need to get distinct number of nodes.

Just adding $query-\>distinct(); doesn't bring anything. Could you please help me how can I solve the issue?

# Answer
If you want to retrieve distinct number of the nodes of content type `$type`.
Try this.

```

use Drupal\Core\Database\Database;

//- Retrieves a \Drupal\Core\Database\Connection which is a PDO instance
  $connection = Database::getConnection();
    $query = $connection->select('node', 'node')
        ->fields('node', array('nid'))
        ->condition('node.type', $type, '=')
        //- Force filtering of duplicate records in the result set.
         ->distinct()
        ->countQuery()
        ->execute();

    $count = $query->fetch(\PDO::FETCH_NUM);

```

Ps: you still have to add Your desired `innerJoin` to the query take a look to Select::innerJoin .
> 1 votes

# Answer
You can use Drupal EntityQuery class like this:

```
$count = \Drupal::entityQuery('node')
    ->condition('status', 1)
    ->condition('type', $type)
    ->count()->execute();

```
> 0 votes

---
Tags: 8, database
---


# Question
Title: User Login: login failed: 400 Bad Request
I am trying the log in rest API with Drupal 8.4

For that, I am using **angular 5**

I have all the configurations working.

This is how I get the data from the form and send it to the UserServices. The UserServices will do the post method with the correct header, the user, and the password.

**onSubmit() getting the data from the form:**

```
onSubmit(name: string, pass:string): void {
    name = name.trim();
    if (!name) { return; }
    let user: any = {
     name: null,
     pass: null
    };
    user.name = {value: name};
    user.pass = { "": pass};
    console.log('Json from the form ' +JSON.stringify(user));
    this.UserService.login(user)
      .subscribe(user => {
        console.log('subscribed to login function' + JSON.stringify(this.user));
       });
}

```

**this is the login() function, that send the post method**

```
login (user: User): Observable<User> {
  const url = `${this.mainUrl}/user/login?_format=json`;
  const postReturn = this.http.post(url, user, httpHaljson);
console.log('Login return from the user service' + JSON.stringify(postReturn));
return postReturn
}

```

**This is my header** i have tested with aplication json and haplication hal json

```
const httpHaljson = {
  headers: new HttpHeaders({
  "X-CSRF-Token": "Qfnczb1SUnvOAsEy0A_xuGp_rkompgO2oTkCBOSEItM",
  "Authorization": "Basic Qfnczb1SUnvOAsEy0A_xuGp_rkompgO2oTkCBOSEItM", // encoded user/pass - this is admin/123qwe
  // "Content-Type": "application/hal+json"
  "Content-Type": "application/json"
  })
};

```

**Now, this is what i get from the console:** User Login: login failed: Http failure response for http://drupal.dd:8083/user/login?\_format=json: 403 Forbidden

This is how I send the data from the form: Json from the form {"name":{"value":"asd"},"pass":{"":"123"}}

Login return from the user service

```
{"_isScalar":false,"source":{"_isScalar":false,"source":

{"_isScalar":false,"source":{"_isScalar":true,"value":

{"url":"http://drupal.dd:8083/user/login?_format=json","body":{"name":

{"value":"asd"},"pass":

{"":"123"}},"reportProgress":false,"withCredentials":false,"responseType":"

json","method":"POST","headers":{"normalizedNames":

{},"lazyUpdate":null},"params":{"updates":null,"cloneFrom":null,"encoder":

{},"map":null},"urlWithParams":"http://drupal.dd:8083/user/login?

_format=json"},"scheduler":null},"operator":{"concurrent":1}},"operator":

{}},"operator":{}}

```

Any idea what am i doing wrong? thanks!

# Answer
> 0 votes
try

```
const headers= new Headers({
  'Content-Type': 'application/json',
  'X-CSRF-Token': 'Qfnczb1SUnvOAsEy0A_xuGp_rkompgO2oTkCBOSEItM',
  'Authorization': 'Basic Qfnczb1SUnvOAsEy0A_xuGp_rkompgO2oTkCBOSEItM'
})

let options = new RequestOptions({ headers: headers });

login (user: User): Observable<User> {
  const url = `${this.mainUrl}/user/login?_format=json`;
  return this.http.post(url, user, options ).map((res)=>{console.log(res)});
}

```

---
Tags: users, 8
---


# Question
Title: Force redirect back to password form until password got set after one-time-login
When my users click on a one-time-password-reset link then I log them in and then show them a page where they can choose their new password. Problem is that there are two additional links on that page (one for dashboard and some other one) and they can click on them and visit the linked pages.

I want that until they change their password they cannot navigate to other pages. For now I managed to set a custom value in `$_SESSION`, but I can't figure out how I can intercept their further request (once they land on password change page). How can I check for such a session value and redirect them back to password-reset page (if they haven't changed their password yet) and allow them to navigate to other pages only after they changed their password?

# Answer
You should be able to use `hook_init` to check for your custom `$_SESSION` variable (along with other conditions), and then leverage `drupal_goto()` to send the user back to the password change page.

Rough example:

```
function MODULE_NAME_init() {
  // Check that the session key exists.
  if (!empty($_SESSION['my_special_session_key'])) {
    // Check to verify the path the user is currently visiting is not the
    // password change form, or related path.
    // This needs to be customized according to your needs.
    if (arg(0) != 'user' || arg(1) != $GLOBALS['user']->uid || arg(2) != 'edit') {
      drupal_goto("user/{$GLOBALS['user']->uid}/edit");
    }
  }
}

```

You'll also need to unset that `$_SESSION` key after the user successfully changes their password. You'll likely want to do this using another hook related to the password change form.

Using`hook_form_FORM_ID_alter` to add a custom submit callback to the form is a reasonable choice.

Here is an example that adds the submit callback to the user's edit form if the `$_SESSION` key exists.

```
/**
 * Implements hook_form_FORM_ID_alter().
 */
function MODULE_NAME_form_user_profile_form_alter(&$form, &$form_state) {
  if (!empty($_SESSION['my_special_session_key'])) {
    $form['#submit'][] = '_MODULE_NAME_unset_session_key';
  }
}

/**
 * Custom callback for removing the special session key.
 */
function _MODULE_NAME_unset_session_key() {
  unset($_SESSION['my_special_session_key']);
}

```

Hope this helps.
> 0 votes

# Answer
I did similar years ago in 7 using rules + roles although obviously you could do it in code too. Once they've done what you want them to do then you assign them a different role, until then they will always get redirected back to the page you want.

I'm only answering from vague memories, so initial thoughts are you may need to store the password hash before and check to ensure it's changed after.
> -2 votes

---
Tags: 7, redirection, sessions
---


# Question
Title: Inserting search term within "No results behavior"
Within the 'NO RESULTS BEHAVIOR' section of Views in Drupal 8 how do I output the search term along with some custom text using the "Unfiltered text" option?

My desired output is "No results found for ***search term***, please..."

Can anyone suggest a solution?

# Answer
you can use template\_preprocess\_views\_view

```
 function template_preprocess_views_view(&$variables) {
  $view = $variables['view'];
  $variables['view_total_count'] = $view->total_rows;

  if ($view->total_rows === 0) {
    $exposed_input = $view->getExposedInput();
    $search_term = $exposed_input['your search input'];
    $variables['empty'] = 'No results found for'.$search_term.', please ...';
  }
}

```

then in your twig template, you print the empty variable.
> 2 votes

# Answer
Maybe you could use JS.

Put a placeholder in place of "search term", maybe `<span id="search-term">search term</span>`, so that it still functional when JS is disabled.

Then store the search term in a variable, let's call it `var searchTerm`, and replace text by `document.getElementById("search-term") = searchTerm`.

Now all we got to do is store the search term.

* If the search term is in URL, follow this tutorial to extract it.
* If it isn't, please provide more detail and I'll update my solution.
> 0 votes

# Answer
Looks to be fairly old, but I will post the solution here. You can use the D8 port of search\_api\_spellcheck, here - https://github.com/nuvoleweb/search\_api\_spellcheck. It is not official release, but works well.
> 0 votes

---
Tags: 8, search, views
---


title: Missing Menu Links generating a Feature

text:
# Question
Title: Missing Menu Links generating a Feature
I am using Features that includes several basic site features such as the main menu and another custom navigation menu. Both are two level menus. I have included the menus in the Feature, but when I select the menu links, only a few of the menu link items are included in the selection list. The balance are missing.

What I have done:

* I have searched for other issues on Drupal.org, but not found a similar one.
* I have also examined the links and cannot find a difference between those that are included and those that are not.
* I have flushed the menu cache.

Has anyone else seen anything like this or have any insights as to how I might fix this?

# Answer
> 3 votes
It could be an issue that can be fixed by UUIDs for Menu Links, opened for the UUID Features Integration module. In that issue, one of the project maintainers suggested the feature should instead be implemented in a separated project. UUID Features - Menu, a sandbox project, has been then created by ioskevich.

Something to be aware of: Menu links don't show up in the administrative UI, nor get added to the database, if they are not for existing nodes.

# Answer
> 0 votes
For future visitors, another possibility I found is link role filtering. I was trying to feature the User-menu | Log in menu-item which is filtered to only display for anonymous users. I verified there were no duplicates and tried uuid-menu-feature patch and it still would not show as an export option. However, once I disabled the anonymous role filtering it showed up.

---
Tags: features
---


# Question
Title: Can't save any changes on the Content Language & Translation page
I'm using Drupal 8 and when I go to /admin/config/regional/content-language and try to turn on "Custom menu link", it doesn't save, and it just reloads unchecked.

I saw here that you need to check the actual items, as well, to get it to save, but that doesn't work either: https://www.drupal.org/forum/support/translations/2016-09-07/i-cant-save...

Then I realized that I can't save ANY changes to this page.

I see the warning "(\* unsupported) Paragraphs fields do not support translation. See the online documentation.", which was red before I turned off translation for all Paragraph fields, and then the warning turned orange but remained. I had to go to the actual Content Type edit page to turn off translation from paragraph fields to get those changes to save.

Nothing is saving and I'm not seeing anything in the dblog. It just reloads as it was. I'm not even sure where to start on this. Any help would be greatly appreciated.

# Answer
> 2 votes
I tried the max\_input\_vars fix and that didnt work. I had to check the entity, pretend it was called MyCustomEntity in 'Custom language settings' at the top... but also scroll down to the individual MyCustomEntity settings further down on the page, and also check that checkbox. When I saved, now it worked

# Answer
> 0 votes
I don't know if I can help after all this time, but in my case the problem was the server php settings max\_input\_vars that was set to 1000 by default. After have increased that value to 5000, system returned to work.

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


title: Define Access Control based on URL Path

text:
# Question
Title: Define Access Control based on URL Path
Is there a contrib module that can define access control based on the url path of content? So if an anonymous user goes to www.mysite.com/pages/test they can reach it, but if they go to www.mysite.com/hidden/stuff they can't get to it since it is in the /hidden/ path and they don't have an authenticated role.

I've already looked into controlling it based on content types, workbench groups, etc. Don't want to go with Workspaces since it is experimental and requires a whole other suite of modules to function.

Ideally, I'd like to be able to allow and block users with certain roles access to content that follows a specific path. Hoping there's something that already exists to handle this.

# Answer
What we ended up using was an existing module that we have already installed (Context) along with a custom block.

We created a new context for hidden sections of our site using the condition of the request path and the user role anonymous. From there our two reactions were to hide all sections within our theme except ones for help messages to our users, and to add a custom block to that help section.

Works like a charm and is fairly straightforward to change and keep track of in config.
> 0 votes

---
Tags: 8, users
---


# Question
Title: How to use trusted contacts as a selection rule for user panel page, drupal commons
In Drupal Commons, using Panels, I'd like to change the behavior of the user page.

One variant for users to view their own page, and another for viewing other user pages. Also, I'd like to limit it so that only the trusted contacts of a user can view his/her page.

It is set up using panels, so first I added a variant with a selection `rule: user: compare - User being viewed is not Logged in user`. This works fine.

But how to configure it to limited to trusted contacts of a user. The context for user: user\_trusted\_contacts is already listed as an option, but I can't use it as a selection rule. There's no option there for "..user is one of".

I'm sure it can be done within panels, thanks for any help. D

commons-7.x-3.46

# Answer
I couldn't find a direct solution for this.

So as a workaround, I'm using Flags and Rules. Trusted contacts are flagged (explained in "How to create a rule to flag users when they're approved as a Trusted Contact?").

Once the flag is there you can then use it as a selection rule in panels.
> 1 votes

---
Tags: panels
---


# Question
Title: How to create a node with mulitple field-collection items?
I've a content type having filed collection item (3 fields of 5 sets). Created a custom module form, when user submits that form, it should create a node with all 5 set field collection items.

So far tried the following code. it's working for 1st set but not for all.

```
$values = array(
  'type' => 'ct_machine_name', // Content Type machine name
  'uid' => $uid,
  'status' => 1,
  'promote' => 0,
  'title' => 'xxxx',
);
$entity = entity_create('node', $values);
$ewrapper = entity_metadata_wrapper('node', $entity);
$ewrapper->save();
$node = node_load($entity->nid);

$fc_val= entity_create('field_collection_item', array('field_name' => 'field_fc_mcnename'));
// Attach to the node
$fc_val->setHostEntity('node', $node);
$fc_val->field_field1[LANGUAGE_NONE][0]['value'] = $val1;
$fc_val->field_field2[LANGUAGE_NONE][0]['value'] = $val2;
$fc_val->field_field3[LANGUAGE_NONE][0]['value'] = $val3;

// Save field-collection item.
$fc_val->save();

```

The above code working. But I need to loop through it and save all field collection items in an user submitted order.

I tired as follows, but doesn't work. (example)

```
for ($i=0; $i<=4; $i++) {
$fc_val->field_field1[LANGUAGE_NONE][$i]['value'] = $val1;
$fc_val->field_field2[LANGUAGE_NONE][$i]['value'] = $val2;
$fc_val->field_field3[LANGUAGE_NONE][$i]['value'] = $val3;
}
$fc_val->save();

```

Also tried

```
for ($i=0; $i<=4; $i++) {
$fc_val->field_field1[LANGUAGE_NONE][0]['value'] = $val1;
$fc_val->field_field2[LANGUAGE_NONE][0]['value'] = $val2;
$fc_val->field_field3[LANGUAGE_NONE][0]['value'] = $val3;
$fc_val->save();
}

```

Any inputs or suggestions would be much appreciated.

# Answer
> 0 votes
Try This:
Example for field1 and repeat it with other fields.

```

$entity_fc_val = entity_metadata_wrapper('field_collection_item', $fc_val);
$entity_fc_val->field_field1->set(array('value' => $val1));

```

---
Tags: 7, entities
---


# Question
Title: How to get the id of a group when using the Group module?
I'm using the Group module.

How can I get the id of a group whose a user is a member (I have the user id)?

# Answer
> 0 votes
I would just start with creating a view (using Views) of all "***Group memberships***", and include all available colums of that specific base table. It should include things like "user id" and "group id".

If you then add a contextual filter to limit it to some selected user id, you'll get 1 views result (row) for each group that the selected user is member of, or is invited for, revoked from, etc (membership status for each group is one of the available columns to include in your view). For each group you'll have its group id available also, so if needed you can add a relationship to the group itself to have access to additional data about the group itself (eg: the group title, or any of its custom fields you added).

After you have such view created, you have a prototype of anything else you want to do with that, e.g use whatever you want in your custom module to invoke the Group's API functions.

PS: refer to my answer to "How to add a column to the list of group members or create a Views equivalent of it?" for getting started with creating such view (even though it's for D7, for D8 you can use a similar one).

# Answer
> 0 votes
Assuming you mean how to do this programmatically.

One thing to understand is that there are mid level entities between a user account and groups called GroupMembership entities.

There is a service called group.membership\_loader that provides the utility functions for retrieving the membership entities:

```
  $group_memberships = \Drupal::service('group.membership_loader').loadByUser($account);

```

With a list of memberships, you can then load the groups:

```
  $groups = [];
  foreach ($group_memberships as $group_membership) {
    $groups[] = $group_membership->getGroup();
  }

```

---
Tags: 8, group
---


title: Hide error and warning in admin panel

text:
# Question
Title: Hide error and warning in admin panel
I want to hide error and warning message from admin panel. I have checked the option None in admin panel for error reporting and still it showing error and warning messages in admin panel. let me how it can removed.

# Answer
The code suggested by indrock would remove all the messages shown by the modules, not just error messages, and warnings.

What you can do is implement `THEME_preprocess_HOOK()` using the following code.

```
function mytheme_preprocess_page(&$variables) {
  if (path_is_admin(current_path())) {
    unset($_SESSION['messages']['warning']);
    unset($_SESSION['messages']['error']);
  }
}

```

current\_path() currently returns the value of `$_GET['q']`; I am using it for compatibility with Drupal 8, as for that version current\_path() is not simply returning the value of `$_GET['q']`.
Instead of `unset($_SESSION['messages'][$type])`, you can use `drupal_get_messages($type, TRUE)`. Using `drupal_get_messages()`, you are sure your code works even when the messages are stored in a different session variable, or a variable that is a session variable. So far, it doesn't seem necessary, as Drupal 8 uses the same session variables used from Drupal 7, for the messages.

The settings in admin/config/development/logging are for error messages caused by PHP code. They don't influence the error messages shown by modules.
> 2 votes

# Answer
Although it is not a good idea to hide the errors (you may want to solve it; by watching the error log, debugging etc.), there is a way you can do it.

You can do it at theme level in `template_process_page()` function, in your theme's template.php file. (It should be placed in your admin theme's template.php)
Code: Edited according to @Chapabu 's comments :)
Used `path_is_admin()` and `current_path()`.

```
<?php

function MYTHEME_process_page(&$variables) {
  if (path_is_admin(current_path())) {
    unset($variables['messages']);
  }
}

?>

```
> 4 votes

# Answer
To hide Error and Warnings using Admin panel goto

**admin/config/development/logging**

Select **None** to hide errors.
> 3 votes

# Answer
You can only make it so that the error shows on certain usernames, because sometimes they do give out helpful information like "Module Update reminder" etc.

```
function MYTHEME_process_page(&$variables) {
  global $user;
  if (path_is_admin(current_path()) == TRUE) {
    if(!in_array($user->name,array('username1','username2'))) {
       $variables['show_messages'] = FALSE;
  }
}

```

You can replace/add to array username1 and username2 with whatever usernames you would wish to show the error messages to.
> 0 votes

---
Tags: 7
---


# Question
Title: Delete "permanent" file when it has 0 uses
Files that are "used in 0 places" (viewable at /admin/content/files) are not being deleted automatically by cron. They also show a status of permanent. How do I allow these files to be deleted by cron, or if not possible is there another way?

# Answer
Prior to 8.4.x this was the default behavior, but a number of issues with file reference counting meant it was possible for files to get deleted prematurely (and possibly also for stale files to linger, though that's not so important). In 8.4.x the default behavior was changed. See Files that have no remaining usages are no longer deleted by default.

For completion, to answer the question it's possible to change back to the old behaviour by setting `make_unused_managed_files_temporary` to true in `file.settings`. **It's clearly not recommended** (that's why core doesn't use it anymore). See Dealing with unexpected file deletion due to incorrect file usage to track progress on file reference tracking.
> 10 votes

---
Tags: 8, files
---


title: Unpublished file still downloadable

text:
# Question
Title: Unpublished file still downloadable
I have a file attached to a node via a link. The node is published but the file is unpublished. The link on the node points to the file /sites/default/files/file.txt

The file is still downloadable by anonymous users.

I would assume the file, being unpublished, would be unavailable to download. This is not the case.

The anonymous permissions are set to view published content.

Is this expected behaviour? What would be the best way to not allow the file to be downloaded once it's unpublished?

# Answer
You need to setup a private file system in settings.php:

```
/**
 * Private file path:
 *
 * A local file system path where private files will be stored. This directory
 * must be absolute, outside of the Drupal installation directory and not
 * accessible over the web.
 *
 * Note: Caches need to be cleared when this value is changed to make the
 * private:// stream wrapper available to the system.
 *
 * See https://www.drupal.org/documentation/modules/file for more information
 * about securing private files.
 */
# $settings['file_private_path'] = '';

```

Files stored in the private file system will be served by Drupal and you can control which users are allowed to access the files.
> 3 votes

---
Tags: nodes, users, files
---


# Question
Title: How can I get uploaded files sent to webforms to be attached to an email?
In Drupal 8, uploaded image files sent to a Webform are uploaded to a private area. The image files are referenced in the email that is sent to the administrator for that form, but unless they are logged in and access the email through the webforms results interface, they cannot see the file. It appears as a broken image in the HTML email.

I've installed SwiftMailer and Mail System modules per https://www.drupal.org/node/2837024 but installing and enabling the modules has not solved the problem.

# Answer
The steps to get uploaded files to be sent as attachments to be included in emails from Webforms go as follows:

1. Install SwiftMailer and Mail System Modules
2. In Mail System Module Configuration, add Webform Module and set Handler and Mailer to Swift Mailer
3. In Swift Mailer Configuration, Messages tab, set to HTML (may not be necessary, but it worked for me.
4. In Structure..Webforms..\[your webform name\]..Settings..Email/Handler..Edit..Advanced Tab set the check box for include files as attachments

The body of the email still has a broken image, but the files are attached. I believe I can modify the body of the email to just include the fields that I want by expliciting naming each one, however, if you uncheck the fields that are "broken" in Included Email Values (hoping to continue to use \[webform\_submission:values\] in the body template) the email does not show the broken connection but it also no longer includes the attached file(s)
> 0 votes

---
Tags: 8, webforms
---


# Question
Title: How to add twig template for OwlCarousel format?
I am working with drupal8. I have created a views with owlCarousel format.I want to add twig template for this carousel views.How to name this twig template?

# Answer
You need to rename it like this: **owlcarousel-views--expert-talk.html.twig**
> 2 votes

---
Tags: views, 8
---


# Question
Title: How to implement per user caching when restricting display of comments by author
I have threaded comments on a site where there are two roles, reviewers and administrators.

Comments are shown in a view block added to the node (in this case a webform). The view format is set to 'content' and it's using tag based caching.

* Admins are allowed to see all comments
* Reviewers can write comments and only seen their own, or replies to them

This is all ok and I've implemented it with `hook_ENTITY_TYPE_view_alter` (simplified example below).

**The problem is caching - the view for one reviewer is being cached and shown when the other logs on.**

Scenario:

* Alice and Bob are reviewers
* Alice leaves a comment on a node. Logs out.
* Bob logs on. If the cache hasn't been cleared in the meantime, he'll see Alice's comments even though he shouldn't. (And then, were I then to clear the cache, his view would be correct, but should he logged off and Alice logs back in, she'll now see the view intended for Bob.)

**Can I give each user their own cache, or failing that, not cache the view at all?** (setting caching of the *view block* to 'none' doesn't appear to change anything, would be useful to know why in answer.)

```
function mymodule_comment_view_alter(
    &$build,
    Drupal\Core\Entity\EntityInterface $entity,
    \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display ) {

    // ... some logic that deals with admins (omitted)

    $comment_uid    = $entity->getOwnerId();
    $parent_comment = $entity->getParentComment();

    if ( $comment_uid === $current_user->id() ) {
        // current user's own comment? Show it
    } elseif ( isset( $parent_comment ) &&
               $parent_comment->getOwnerId() == $current_user->id() ) {
        // a comment in  reply to current user's comment? Show it
    } else {
        // otherwise, don't show it
        $build['#access'] = false;
    }

    return;
}

```

# Answer
As Clive said in the comments, all I needed was the following.
I won't mind if people down vote the question for being too stupid…

```
// was user.permissions, but that means there will only be a single
// cache shared by all reviewers, and we must cache according to authorship
$build['#cache']['contexts'] = ['user'];

```

**Caveat:** the view block cache setting also needs to be 'none'.

Drupal docs - cacheability of render arrays
> 3 votes

---
Tags: 8, caching, comments
---


title: Two forms on one page break submit

text:
# Question
Title: Two forms on one page break submit
I have two forms on a node page (the comment one + a custom form). Ajax is not enabled for both of them but still, when submitting the custom form form\_set\_error or durpal\_set\_message are not displayed but displayed when you load a new page (if you submit the form again, if you reload a page or if you change the page). It's like I have a hidden ajax behavior messing the submit up.

```
function my_module_quote_request_form($form, &$form_state) {
  global $user;
  $account = user_load($user->uid);

  $user_phone_number = $account->field_user_address[LANGUAGE_NONE][0]['phone_number'] ? $account->field_user_address[LANGUAGE_NONE][0]['phone_number'] : '';

  $form = array();

  $form['phone_number'] = array(
    '#type' => 'textfield',
    '#title' => t('Phone number'),
    '#default_value' => $user_phone_number,
    '#size' => 30,
    '#maxlength' => 10,
    '#required' => TRUE,
  );

  $form['actions'] = array('#type' => 'actions');
  $form['actions']['submit'] = array(
    '#title' => t('Submit'),
    '#type' => 'submit',
    '#value' => t('Request'),

  );
  $form['actions']['cancel'] = array(
    '#title' => t('Cancel'),
    '#markup' => l(t('Cancel'), '/market'),
  );

  return $form;
}

function my_module_quote_request_form_validate($form, &$form_state) {
  if (blabla) {
   form_set_error($phone_number, $message);
  }
}

```

If you trigger blabla, then the message is not displayed but displayed on page reload.

Any idea what it can due to?

# Answer
> 0 votes
I have finally found what was the issue. It's absolutely not related to the fact I have two forms but that I was implementing my theme variable in a node preprocess function.

Errors messages are prepared in upper function so the result is that you alter a variable after it's actually called. The result is the message is displayed on reload.

See here : form\_set\_error message delayed one page refresh

---
Tags: 7, forms, ajax
---


# Question
Title: Where can I alter the labels used on the login form?
This must be configurable somewhere, surely, but I just can't find where. I'm sure I'm doing something silly. Apologies for such a simple question.

# Answer
Try this way by implementing hook\_form\_alter.

```

/**
 * Implements hook_form_alter().
 */
function YourCustomModuleName_form_alter(&$form, Drupal\Core\Form\FormStateInterface $form_state, $form_id){
    if ($form_id == 'user_login_form') {
        //- change label for username input
        $form['name']['#title'] = t('Your New UserName Label');
        //- change label for password input
        $form['pass']['#title'] = t('Your New Password Label');
    }
}

```
> 2 votes

---
Tags: 8, forms
---


# Question
Title: Why does my kernel test error with "Install profile will be a mandatory parameter in Drupal 9.0."?
I've test classes based on `KernelTestBase`.

Previously everything was working smoothly, now I came back to the project and I'm hit by this error:

> Install profile will be a mandatory parameter in Drupal 9.0.

Drupal version: 8.3.5 PHPUnit version: 4.8.35

phpunit.xml:

```
<phpunit bootstrap="web/core/tests/bootstrap.php" colors="true"
         beStrictAboutTestsThatDoNotTestAnything="true"
         beStrictAboutOutputDuringTests="true"
         beStrictAboutChangesToGlobalState="true"
         checkForUnintentionallyCoveredCode="false">
<!-- TODO set printerClass="\Drupal\Tests\Listeners\HtmlOutputPrinter" once
 https://youtrack.jetbrains.com/issue/WI-24808 is resolved. Drupal provides a
 result printer that links to the html output results for functional tests.
 Unfortunately, this breaks the output of PHPStorm's PHPUnit runner. However, if
 using the command line you can add
 - -printer="\Drupal\Tests\Listeners\HtmlOutputPrinter" to use it (note there
 should be no spaces between the hyphens).
-->
  <php>
    <!-- Set error reporting to E_ALL. -->
    <ini name="error_reporting" value="32767"/>
    <!-- Do not limit the amount of memory tests take to run. -->
    <ini name="memory_limit" value="-1"/>
    <!-- Example SIMPLETEST_BASE_URL value: http://localhost -->
    <env name="SIMPLETEST_BASE_URL" value=""/>
    <!-- Example SIMPLETEST_DB value: mysql://username:password@localhost/databasename#table_prefix -->
    <env name="SIMPLETEST_DB" value="mysql://vagrant:vagrant@localhost/vagrant"/>
    <!-- Example BROWSERTEST_OUTPUT_DIRECTORY value: /path/to/webroot/sites/simpletest/browser_output -->
    <env name="BROWSERTEST_OUTPUT_DIRECTORY" value=""/>
  </php>
  <testsuites>
    <testsuite name="mymod">
      <file>web/modules/custom/mymod/tests/src/Kernel/FooTest.php</file>
    </testsuite>
    <!-- etc -->
  </testsuites>
  <listeners>
    <listener class="\Drupal\Tests\Listeners\DrupalStandardsListener">
    </listener>
  </listeners>
  <!-- Filter for coverage reports. -->
  <filter>
    <whitelist>
      <directory>./web/core/includes</directory>
      <directory>./web/core/lib</directory>
      <directory>./web/core/modules</directory>
      <directory>./web/core/modules</directory>
      <directory>./web/core/sites</directory>
      <!-- By definition test classes have no tests. -->
      <exclude>
        <directory suffix="Test.php">./</directory>
        <directory suffix="TestBase.php">./</directory>
      </exclude>
     </whitelist>
  </filter>
</phpunit>

```

Test class:

```
class FooTest extends KernelTestBase {

  protected static $modules = ['foo'];

  public function testFoo() {
    self::assertEquals(2, 2);
  }

}

```

I'm launching it from PHPStorm via:

> vagrant:///Users/drupality/Develop/drupal/myproj/usr/bin/php /home/vagrant/.phpstorm\_helpers/phpunit.php --group foo --configuration /var/www/myproj/site/phpunit.xml --filter "/::testFoo( .\*)?$/" Drupal\Tests\foo\Kernel\FooTest /var/www/myproj/site/web/modules/custom/myproj/tests/src/Kernel/FooTest.php

**UPDATE**

I've updated PHPUnit to 5.7.21 (newest supported by PHPStorm) but still no success.

# Answer
> 2 votes
Your problem is that your test and/or code is relying on a deprecated feature.

In Drupal 8.3, there was a push to have deprecated featured generate `E_USER_DEPRECATED` messages, eg in `Drupal\Core\Config\ExtensionInstallStorage`:

```
  public function __construct(StorageInterface $config_storage, $directory = self::CONFIG_INSTALL_DIRECTORY, $collection = StorageInterface::DEFAULT_COLLECTION, $include_profile = TRUE, $profile = NULL) {
    parent::__construct($directory, $collection);
    $this->configStorage = $config_storage;
    $this->includeProfile = $include_profile;
    if (is_null($profile)) {
      @trigger_error('Install profile will be a mandatory parameter in Drupal 9.0.', E_USER_DEPRECATED);
    }
    $this->installProfile = $profile ?: \Drupal::installProfile();
  }

```

This is to provide early warning to developers to update their code.

If the code is hit in a phpunit test (which includes unit tests, kernel tests, and functional tests using BrowserTestBase), anything from `trigger_error` will generate a fail.

So, you either need to fix your code, or you can cause the test to not fail by using the `@expectedDeprecation` annotation on the test method until you can fix it.

# Answer
> 0 votes
I had this issue. To get rid of some I could just do this in my setUp method:

```
 $this->setInstallProfile('testing');

```

In others though I had to override the register method of the parent class:

```
  /**
   * {@inheritdoc}
   */
  public function register(ContainerBuilder $container) {
    parent::register($container);
    $this->container->setParameter('install_profile', 'testing');
  }

```

Obviously, like much of Drupal 8, it would be nice if this were documented somewhere.

---
Tags: 8, testing
---