# Question
Title: How to transfer data from the program's created field to the standard text, while saving the node?
Using `hook_form_alter()`, I created 4 form fields. When saving a node, I want to extract data from them and transferred to a standard field.

Using `foreach()`, I can form a string and then transfer it to the standard field, but how do I get the data from the form input, while saving material?

I use `hook_node_presave($node)` but it already takes `$node` as argument, in which there are no custom fields. I do not know how to transfer them here and already work with `hook_node_presave()`.

```
$form['field_cadastral_num'] = array(
    '#type' => 'fieldset',
    '#title' => 'test',
    '#attributes' => array(
        'class' => array(
            'field-type-text',
            'field-name-property_node_form'
        ),
    ),
  '#weight' => $instance['widget']['weight'],
);
$form['field_cadastral_num']['cell'][] = array(
  '#type' => 'textfield',
  '#default_value' => '',
  '#size' => 3,
  '#maxlength' => 3,
  '#name' => 'kadastr[0]',
  '#value' => ''
);
$form['field_cadastral_num']['cell'][] = array(
  '#type' => 'textfield',
  '#default_value' => '',
  '#size' => 3,
  '#delta' => 3,
  '#maxlength' => 3,
  '#name' => 'kadastr[1]',
  '#value' => '',
  '#prefix' => ':'
);
$form['field_cadastral_num']['cell'][] = array(
  '#type' => 'textfield',
  '#default_value' => '',
  '#size' => 6,
  '#maxlength' => 6,
  '#name' => 'kadastr[2]',
  '#value' => '',
  '#prefix' => ':'
);
$form['field_cadastral_num']['cell'][] = array(
  '#type' => 'textfield',
  '#default_value' => '',
  '#size' => 3,
  '#maxlength' => 3,
  '#name' => 'kadastr[3]',
  '#value' => '',
  '#prefix' => ':'
);

```

# Answer
> 0 votes
I would suggest you create the 'cell' fields through the Drupal UI (admin/structure/types/manage/xxxx/fields) so they are registered correctly as part of the content type, then their values will be available in hook\_node\_presave().

---
Tags: entities
---


# Question
Title: change views global text field conditionally
I am trying to either show a text field or hide it depending on the date of another field in a view. I am trying to use the views\_pre\_render hook and so far have:

```
function MODULE_NAME_views_pre_render(&$view) {
if ($view->name == 'user_dashboards' && $view->current_display == 'my_tutorials')
{
    foreach ($view->result as $index => $value)
    {
        $tutorialtime = strtotime($value->field_field_tr_tutorial_start[0]['raw']['value']);
        if($tutorialtime < strtotime('now'))
        {
            $view->field['nothing']->options['alter']['text'] = '';

        }
    }
}

```

}

So I can successfully test whether to show the field or not, however I can't then change the field. Using the code above changes every global text field in the view. Is there a way to target just the row in the comparison?

# Answer
Ok so credit goes to https://www.webfoobar.com/index.php/node/65 which basically gave me the answer. The working code is as follows:

```
function MODULE_NAME_views_pre_render(&$view)
{
    if ($view->name == 'user_dashboards' && $view->current_display == 'my_tutorials')
    {
        foreach ($view->result as $index => $value)
        {
            $tutorialtime = strtotime($value->field_field_tr_tutorial_start[$index]['raw']['value']);
            if($tutorialtime < strtotime('now'))
            {
                $oldtutorials[] = $index;
            }
        }
        $view->style_plugin->render_fields($view->result);
        foreach ($view->style_plugin->rendered_fields as $index => &$rendered_result)
        {
            if(in_array($index, $oldtutorials))
            {
                $rendered_result['nothing'] = '';
            }
        }
    }
}

```
> 1 votes

# Answer
You should be changing $view-\>result\[$index\]... instead of $view-\>field. This will make sure you only change the result in question and not globally.
> 0 votes

---
Tags: views
---


# Question
Title: Is it possible to give to a specific user role the permission to create content only in a language?
I've a Drupal 8 site using 8 languages. The site is not a multi-domain.

The *Admin DE* role should have only the permission to create nodes or translate nodes in German, but can view all node in all languages.

I don't find a module that can implement this functionality.
Do you have any ideas?

# Answer
> 0 votes
Create a custom module for this. I'm including some code that may help get you started. The idea behind this code (below) is preventing a user without the role 'admin\_de' from editing content that has a different language than what the 'admin\_de' user has set for their account. So there are some obvious differences, but this should be a good start.

In MY\_MODULE.info.yml:

```
name: MY_MODULE
type: module
description: Allows user with particular role to edit content of particular
language.
core: 8.x

```

In a file called MY\_MODULE.permissions.yml, include:

```
edit same language:
  title: 'Edit Same Language Only'
  description: 'Allow user to edit only nodes matching their account language'

```

In a file called MY\_MODULE.module, include:

```
<?php

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

/**
 * Implements hook_form_alter().
 */
function MY_MODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $currentUser = Drupal::currentUser();
  $roles = $currentUser->getRoles();

  if (in_array('admin_de', $roles)) {
    switch ($form_id) {
      case 'node_CONTENT_TYPE_edit_form':
        $currentUserLanguages = getUserLanguage($currentUser->id());
        $submissionLanguage = getSubmissionLanguage($form_state);
        $status = (Drupal::currentUser()
        ->hasPermission('edit same language') && ($submissionLanguage == $currentUserLanguages));
        if (!$status) {
          throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
        }
        break;
    }
  }
}

/**
 * @param $userId
 * logged in user id
 *
 * @return string of language id logged in user is associated with.
 */
function getUserLanguage($userId) {
  $user = \Drupal\user\Entity\User::load($userId);
  $languageId = $user->language()->getId();

  return $languageId;
}

/**
 * @param FormStateInterface $form_state
 *
 * @return string language id of page
 */
function getSubmissionLanguage(FormStateInterface $form_state) {
  $language = '';
  $form_object = $form_state->getFormObject();
  if ($form_object instanceof EntityForm) {
    $entity = $form_object->getEntity();
    $language = $entity->langcode->value;
  }

  return $language;
}

```

Hope this helps!

---
Tags: users, i18n-l10n
---


# Question
Title: How to add variable using mytheme_preprocess_field and print using twig template?
We have a content type Article that has two custom fields: `field_header` and `field_link`. When `field_header` is not populated, we want to perform validation in twig template to add a CSS class. When we tried to set a custom variable using `$variables['myVariable'] = TRUE` and try to print the value in the twig template, it is returning a `NULL` value.

How can I create a custom variable using `mytheme_preprocess_field()` hook and use it in the twig template?

mytheme.theme

```
function mytheme_preprocess_field(&$variables) {
  $element = $variables['element'];
  if($element['#field_name'] == 'field_header') {
    if($element['#items']->first()->isEmpty()) {
      $variables['myVariable'] = TRUE;
    }
  }
}

```

node--article.html.twig

```
<div>
  {{ kint(myVariable) }} // Returns NULL everytime.

  {% if myVariable %}
    // If not empty, do something.
  {% else %}
    // If empty, do something else.
  {% endif %}
</div>

```

# Answer
> 3 votes
Variables in a template are scoped - what you add in `hook_preprocess_field` will only be available in *field.html.twig* and its derivatives, not *node.html.twig* etc.

You can implement the same logic in the node preprocess:

```
function mytheme_preprocess_node(&$variables) {
  if ($variables['node']->hasField('field_header') && $variables['node']->field_header->isEmpty()) {
    $variables['myVariable'] = TRUE;
  }
}

```

---
Tags: 8, theming, entities, hooks
---


# Question
Title: Increasing performance of cache_form on high traffic sites
I am noticing a significant performance increase in my load testing when this table is small, but due to a large traffic site this is growing very quickly.

I have read that it is not a good idea to move this into an "in memory" cache like redis or memcached but can this be moved to a noSQL database for example?

My issue is that even with frequent clearing of old records the performance is struggling and my main solution is to take the database offline and optimize the table to reduce the physical size of the table in MariaDB.

# Answer
Checkout https://www.drupal.org/project/apdqc if you're on D7; this is my config for it in the settings.php file.

```
$conf['apdqc_cache_default_compress'] = 2;
$conf['apdqc_cache_compression_level_cache_form'] = 3;

```
> 2 votes

---
Tags: database, performance
---


# Question
Title: View of nodes and all their taxonomy terms
There is a vocabulary which has an additional field 'field\_icon' I have a view that displays nodes of a certain content type.

I am looking to display all the term's field\_icon associated with each node.

I have then added the relationship of Content: Taxonomy terms on node and added the field\_icon using this relationship. But it is only displaying 1 icon. Not all.

When you look to configure that field, there is no MULTIPLE FIELD SETTINGS option.

How do I display all terms associated with a node in views.

EDIT
See screenshot attached
The vocabulary the field\_icon is in is call 'Key Elements'

# Answer
It would help if you could include a screenshot of your view. But based on your post (I am assuming each term only has one icon), it seems like you may need to aggregate your view. If this is a Drupal 7 site, I also recommend using the module Views Merge Rows, which allows you to choose a separator for when there are multiples after grouping.
> 1 votes

# Answer
Instead of adding the general `Content: Taxonomy terms` Relationship that can relate to all Vocabularies, you need to add the Relationship to the specific Field referencing your terms with icons: **Taxonomy term referenced from field\_whateverTermField** in the Content category. It will say `field_whateverTermField: Taxonomy term` after you add the Relationship.

Once you have the Relationship, you can add the Field `field_icon` and make it use the above Relationship. You will have the `Multiple field settings` options available this time so all icons will display together if you choose to show all in one row.
> 1 votes

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


# Question
Title: Which contextual filter should I use to make proximity filter get the URL param as center?
I am following How to create a nearest node view / Sorting by proximity, which at the fist point says:

> Under **Advanced**, add a contextual filter returning the center entity's ID. For example, if you want to show the view on a node, as a block, select the "Provide default value" radio button and underneath for **Type**, select "Content ID from URL".

Which contextual filter should I use? I tried *Global: Null*, but it doesn't seem to be the right one.

# Answer
The idea here is that you are creating a block to display on the node and need to add a contextual filter to return the nid to filter the results. You need to add the "Content: Nid" contextual filter.

You can do this by:

1. Add contextual filter
2. Select "Content: Nid"
3. Under "When the filter value is NOT in the URL" select "Provide default value"
4. Then under "Type" select "Content ID from URL"

This will automatically get the nid from the URL (node/nid) and apply the filter to the results.
> 2 votes

---
Tags: views
---


title: I cannot access the login page

text:
# Question
Title: I cannot access the login page
I have to change a website, but I cannot log in. The problem is, that the login page does not appears in any way. I get a 403 error when accessing /user. That should come from a change that I did in the past to deactivate the login page at all. Even I cannot remember what I did or (last conclusion), the database has an error and the login page does not appear.

I setup a new Drupal installation with the same version, but I cannot see any significant difference of the folders.

Is there a *hack* to activate for a moment to allow anonymous user act as an administrator?

I am using Drupal 6.19.

Querying the database, I get the following.

```
    drupal=> SELECT path FROM menu_router WHERE path LIKE '%user%';
     user/login
     user/password
     user/register
     user/autocomplete
     admin/user
     user/%
     user/%/view
     user/login/lightbox2
     user/login/thickbox
     admin/user/rules
     admin/help/user
     user/%/contact
     user/%/delete
     admin/user/permissions
     admin/user/roles
     admin/user/settings
     admin/user/user
     user/%/edit
     admin/user/rules/list
     admin/user/user/list
     user/%/edit/account
     admin/user/rules/add
     admin/user/user/create
     admin/user/rules/check
     admin/user/roles/edit
     admin/user/rules/edit
     admin/user/rules/delete
     admin/views/ajax/autocomplete/user
     user/reset/%/%/%
    (30 rows)

```

# Answer
Try accessing user/logout, and then log in the usual way.
> 1 votes

# Answer
There is hack to logged into site if you do not have admin details of the site. I I do not prefer this method but as you have disabled the login form, then it would be good solution for you.

There is `{sessions}` table in Drupal database which stored the sessions of the user into site. You can follow the below step:

* Empty the `{sessions}` table in your database.
* Visit the site as anonymous user
* Check `{sessions}` table in database and you will find the entry in table for the anonymous user. There is '0' value is saved in `uid` column of database table.
* Edit `uid` column and modify value from 0 to 1.

Kindly see that it's not standard solution to login into site.
> 1 votes

# Answer
You could :

* dump the DB + files on a local test server
* remove all non core modules
* reset the password of on of the user inside the user table

Don't do this on production if possible.

See http://drupal.org/node/44164
> 0 votes

# Answer
Since you followed answers to this Disable login at all ,may be you already set this FALSE! You checked this?

```
function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'user_login') {
    $form['#access'] = FALSE;
  }
}

```
> 0 votes

# Answer
Try and access the password reset page (/user/password), or, alternatively, use `drush uli` from the command line. Both will provide you with a reset link (the first by mail, so you should have functioning mail sending on the server), that will bypass the login page but get you a logged in session. Of course, whether this works completely depends on how thorough you were trying to prevent people from logging in.
> 0 votes

---
Tags: 6, users
---


# Question
Title: Adding a webform in a webform confirmation
I've been given a requirement to allow for a webform to be inserted into another webform's confirmation page.

At first I tried this with a token I could insert into the confirmation message, the form appears fine, but of course, the new webform is inside of the "parent" webform, which strips out the form tag.

So now I have overriden a few of the webform and webform submission entities handlers, so I can write my own custom *getCustomForm* function, I can get the new form appearing, but the submit behaviours are weird.

I've tried many things including:

```
return Webform::load(
    $webform->getThirdPartySetting('my_module', 'webform')
)->getSubmissionForm();

```

and

```
$form['confirmation'] = [
    '#type' => 'webform',
    '#webform' => $webform->getThirdPartySetting('wwf_fields', 'webform'),
    '#source_entity' => $webform,
    '#message' => [
        '#type' => 'inline_template',
        '#template' => $webform->getSetting('confirmation_message')
    ]
];

```

Is there some combination of code I'm missing, or am I trying to bend the system a little too much?

Thanks!

# Answer
> 0 votes
Could you not just redirect after a submission so it goes to a node page that has the other form on it? Rather than trying to put the webform into the message? As that message content could be in a drupal message rather than page content

---
Tags: 8, webforms
---


# Question
Title: Multiple AND/OR operators in contextual filters
I have created a page view that displays customer nodes. The result is filtered by a contextual filter based on a taxonomy term ID from url. To allow multiple filter values I'm using *OR (+)* and *AND (,)* operators in the URL. However, combining those operators doesn't work.

URLs like these work.

* /finder/220+300+121
* /finder/220,300,121

This doesn't work.

* /finder/220+300,121

I'm looking for a view setting or a module that allows multiple OR/AND operators. This is a screenshot of what I am trying to build.

>

Show me all customer nodes that are in industry3 OR industry5 AND are from Product1.

Do you have any idea?

# Answer
So I think you should remove your contextual filters and instead add exposed filters. In there you can make your industry filter multi select so the user can pick more than 1. Then you can also choose to make the filters an either AND or OR giving you that flexibility too.

If the exposed filters or the better exposed filters don't look as you wanted you could even hide the views filter form and created your own custom form that replicates it by passing the parameters into the url that views requires

Hope that helps!
> 0 votes

---
Tags: views
---


# Question
Title: Field configuration changes after clearing the cache
I have a content type with only an image field where users can put multiples images.

Sometimes, after clearing the cache, the configuration of the field resets by itself and it sets the cardinality to 1, not letting users to more than an image.

How can I prevent this problem?

# Answer
This is a strange problem which should not happen. I'm afraid you have some debugging to do.

First of all, try to reproduce the problem on a clean installation with just Drupal core, no additional themes or modules. If you can reproduce the problem, you probably found a bug in Drupal core. Search in the issue queue if it has already been reported. If not, report the problem in a new issue.

If you cannot reproduce the error with just Drupal core, it must be a problem in your site. Duplicate the site (so you're not destroying work you have already done) and turn off modules one by one. Once the problem goes away, you know you have roughly located the problem. Then you can either try to debug the module yourself, or go to the issue queue of that module and try to work with the module maintainer to figure it out.
> 0 votes

---
Tags: nodes, entities
---


# Question
Title: Views Infinite Scroll progress Indicator
I am using the Drupal 8 Views Infinite Scroll module on my website.

I have a button at the bottom of my view that when clicked, loads more nodes into the view.

How can I manipulate the view to show a progress indicator or loading icon whilst the Infinite Scroll Ajax is making the request?

Currently, there are no options in the pager settings, but I am confused by the documented project as the Animated gif shows the indicator at the top of the view appears once you've clicked the load more button.

Is this only in place for Drupal 7?

# Answer
> 3 votes
I was able to do this as below.

Add the below in your custom.js file

```
// Sets the fullscreen progress indicator.
(function ($) {
  'use strict';
  Drupal.behaviors.privacyPolicyLinked = {
    attach: function (context) {
      Drupal.Ajax.prototype.setProgressIndicatorFullscreen = function () {
        this.progress.element = $('<div class="ajax-progress ajax-progress-fullscreen"> </div>');
        $('body .pager').before(this.progress.element);
      };
    }
  };
})(jQuery);

```

And in your custom.css , add your styles as below

```
.ajax-progress-fullscreen {
  background: url($assetsPath + '/images/status-active.gif') no-repeat center center;
  min-height: 16px;
  opacity: .9;
  padding: 3px;
  vertical-align: middle;
  width: 16px;
  position: relative;
}

```

# Answer
> 1 votes
Here's what I did quickly to add a "throbber" as part of my custom theme when working with views infinite scroll module:

I copied /modules/views\_infinite\_scroll/templates/views-infinite-scroll-pager.html.twig to /themes/mytheme/templates/views\[ optional\]/views-infinite-scroll-pager.html.twig I customized the template, adding a throbber. In my case though, I showed a non-animated font awesome clock icon (you can do whatever you want).

```
{#
/**
 * @file
 * The views infinite scroll pager template.
 */
#}

{% if items.next %}
<ul{{ attributes }}>
  <li class="pager__item">
    <a class="button" href="{{ items.next.href }}" title="{{ 'Go to next page'|t }}" rel="next"><i class="fa fa-clock-o"></i> {{ options.button_text }}</a>
  </li>
</ul>
{% endif %}

None of the edits were visible yet because the module's js adds a .visually-hidden class to the pager when the page loads, if infinite scrolling with auto-load happening. I added this to my theme's css to override this:
/* infinate scroll module override (.visually-hidden styles added to infinate scroll pager) */

.js-pager__items {
  position: relative !important;
  clip: inherit;
  overflow: inherit;
  height: inherit;
  width: inherit;
  word-wrap: inherit;
  opacity: 0.5;
  animation: throb 0.5s 0.5s infinite;
}

@keyframes throb {
  0% { opacity: 0.5; }
  50% { opacity: 1; }
  100% { opacity: 0.5; }
}

```

To polish off the text a touch more, I changed "Load More" to "Loading More..." in the views pager settings. Cleared the cache... The result was that when I scroll down to the bottom of the page while/if being ahead of the ajax scroll page load, I see a button (or link, I'm using Bootstrap parent theme that shows a button) with a throbber inside with the text, "Loading More...". Once loaded, the button disappears and content replaces it. Since the button is linked, it would stay in place if JavaScript is not enabled, and one could click it to load the next page of results.

I'm sure more work could be done with this but it's a quick solution. I'm open to additional thoughts out there if steering in a bad direction.

proof https://www.drupal.org/project/views\_infinite\_scroll/issues/2829014#comment-11858073

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


title: Set value for custom field

text:
# Question
Title: Set value for custom field
I created a custom field but I don't know how to set a value. I can read values with

```
$entity->get('field_myfield')->getValue()[0]['data']

```

The field consists of several elements: `value`, `data`, `api_key`

I'm loading the entity and would like to set the values of the field programatically, I tried:

```
$entity->set('field_myfield', ['data' => 'some data'], 'value' => 'some value');

```

This doesn't work.

# Answer
You don't need to worry as the entity API should take care of the specific structure and just set it via:

```
$entity->set('field_myfield', 'some value');
$entity->save();

```
> 6 votes

---
Tags: 8, entities
---


title: Create order : how to set price?

text:
# Question
Title: Create order : how to set price?
In my module, on a `cron_job` function I need to create an order with specific `order_item` price. Here is my code :

```
        switch ($role[1]) {
            case 'biocoop':
                $role_price = $produit->get('field_prix_biocoop');
                break;
            case 'montagne':
                $role_price = $produit->get('field_prix_montagne');

                break;
            case 'vente_directe':
                $role_price = $produit->get('field_prix_vd');
                break;
              /* default:
              $role_price = $produit->getPrice();
              break; */
        }

        $order_item = \Drupal\commerce_order\Entity\OrderItem::create([
            'type' => 'default',
            'purchased_entity' => $produit,
            'quantity' => $quantite,
        ]);
        $unit_price = new \Drupal\commerce_price\Price($role_price->number, $role_price->currency_code);
        $order_item->setUnitPrice($unit_price);
        $order_item->save();
        \Drupal::logger('commande_et_paiement')->notice('Prix @role : @prix',
        array(
            '@prix' => $order_item->getUnitPrice(),
            '@role' => $role[1],

        ));

        $line_item[$i]=$order_item;
    }

    //creation de la commande
    $entity_type_manager = \Drupal::service('entity_type.manager');
    $order_storage = $entity_type_manager->getStorage('commerce_order');
    $new_order = Order::create([
      'type' => 'default',
      'store_id' => 1,
      'checkout_flow' => 'boulangerie',
      'uid' => $user,
      'billing_profile' =>$profile,
      'order_items' =>$line_item,
      //'state' => 'draft',
      'field_abonnement' => $nid,
      'placed' => time(),
      'field_date_livraison' =>$date_livraison->format('Y-m-d'),

    ]);

    $new_order->save();
    $new_order->set('order_number', $new_order->id());
    $new_order->save();

}

```

In the watchdog the price is good, but not in my order. If I try to set quantity of the `order_item` just after the `setPrice` function, the quantity is OK in my order too :

```
// Set the quantity with setQuantity.
    $order_item->setQuantity(50);

```

It seems that when the order is saved the `order_item` price has been updated?

Here is my resolver class :

```
class PrixRoleResolver implements PriceResolverInterface {
    public function resolve(PurchasableEntityInterface $entity, $quantity, Context $context) {
        //kint($context);
        $current_user_id = \Drupal::currentUser()->id();
        $account = User::load($current_user_id);

        if ($account->hasRole('biocoop')) {
            $role_price = $entity->get('field_prix_biocoop');
            return new Price($role_price->number, $role_price->currency_code);
        }

        if ($account->hasRole('montagne')) {
            $role_price = $entity->get('field_prix_montagne');
            return new Price($role_price->number, $role_price->currency_code);
        }

        if ($account->hasRole('vente_directe')) {
            $role_price = $entity->get('field_prix_vd');
            return new Price($role_price->number, $role_price->currency_code);
        }

        if ($account->hasRole('administrateur_boutique')) {
            //l'administrateur quand il créé une commande le site applique le prix lié au role du client

            $client=$context->getCustomer();
            $client_uid = $client->uid;
            if (!empty($client_uid))  {
                $uid = $client_uid->getString();
                //kint($uid);
                if (!empty($uid)) {
                    $client_user_id = $uid;
               ÷    $account = User::load($client_user_id);
                    if ($account->hasRole('biocoop')) {
                        $role_price = $entity->get('field_prix_biocoop');
                        return new Price($role_price->number, $role_price->currency_code);
                    }
                }
            }

        }

        return $entity->getPrice();
    }
}

```

# Answer
> 0 votes
Yes, the price of order items in unplaced orders (i.e. carts) is recalculated regularly in Drupal 8 similar to the product pricing process in Drupal 7. If you're trying to achieve a different base price for different user roles, you likely need to implement a custom price resolver to do so.

Unfortunately, we currently have documentation handy for that, but you can look at our work in the Drupal 8 version of Commerce Pricelist for an example. (This is actually one of the key features of that module, so perhaps you can eventually eliminate your custom code.)

---
Tags: 8, commerce
---


# Question
Title: [fixed]Trigger an ajax Submit Form button by clicking on a div
I've a form inside a custom template and I would like to trigger the submit button clicking on one div. Then the function submitForm sends the form-data to a webservices using Drupal httpClient.

The twig template is like:

```
<div class="Rectangle" id="rectangle-div" >
 This is the div containing some stuff that I want to click to submit the form.
</div>

<form id="form-id">
{{ form.elem }}
{{ form.actions.submit }}
</form>

```

I tried with a simple jQuery function like:

```
jQuery(function($) {
    $(document).ready(function () {
        $('#rectangle-div').on('click', function () {
            var wrapper = $('#form-id');
            $('.form-submit', wrapper).trigger( "click" );
        });
    });
});

```

I tried also to write a selector like:

```
$('button[id^="edit-mod-submit"]', wrapper).trigger( "click");

```

if I try with a simple submit like

```
$('form-id').submit();

```

the js code submits the form but refresh the page avoiding ajax and furthermore doesn't send data to the WS:

(if I use the submit button the data goes to the WS).

Any other ideas?

**UPDATE #1: FIXED**

I added inside the ajax option of my submit button the event 'click' and now, using jQuery, I am able to send the post request to the WS. The form is like:

```
 $form['actions']['submit'] = array(
            '#type' => 'submit',
            '#value' => $this->t('Save'),
            '#button_type' => 'primary',
            '#ajax' => [
                'callback' => '::setMessage',
                'event' => 'click',
            ],

        );

```

The jQuery function is:

```
jQuery(function($) {
        var wrapper = $('#form-id');
        $('.form-submit', wrapper).trigger( "click" );
    });

```

Now I should intercept the response coming from the webserver and then execute a JS script, but these are other questions :)

# Answer
> 0 votes
Your code is not triggering an AJAX call, it will just submit the form normally via JavaScript rather than pressing a button, etc. If you want submit the form via AJAX you will need something like:

```
  var url = $('#form-id').attr('action');
  $.getJSON(url, {
    field1: 'data1',
    field2: 'data2'
  }).done(function(data) {
    console.log(data);
  });

```

Place this inside `$('#rectangle-div').on('click', function () {`

---
Tags: forms, javascript, ajax
---


# Question
Title: Adding an input filter to automatically replace text with HTML via a script
I am using Drupal 8 on Pantheon.

This is a website for an ebook. The ebook HTML was generated using a Perl script that automatically replaces text like this:

* APPLE -\> HTML including an apple image
* ORANGE -\> HTML including an orange image

The list of these replacements is kept in a plain text file (there are about 200 replacements), and then there is a relatively short Perl script that does the actual replacing (for the ebook).

Now, I want to use these replacements in my Drupal site.

Following this lullabot tutorial, I created a custom input filter in a custom module.

But now I am wondering about how I should proceed.

In the future, the replacements for the ebook will be changed every month, so I need to make sure that it isn't too painful to keep the ebook replacements and Drupal replacements in sync (ideally, I would use the same files).

So,

* Should I try to find a way to call the Perl script from within Drupal, and share the exact same code between Drupal and the ebook?
* Or should I rewrite the Perl script in PHP and incorporate it into the custom input filter?
* Or should I do something else entirely?

# Answer
> 1 votes
I would rewrite the relatively short script. This shouldn't be a problem because you can re-use the Perl Regex in PHP, see http://php.net/manual/en/book.pcre.php

More Drupal specific would be caching. Add a cache tag to the filter result

```
  public function process($text, $langcode) {
    ...
    $result = new FilterProcessResult($text);
    $result->addCacheTags(['mymodule:filter']);
    return $result;
  }

```

so that you can invalidate the cached entities when the replacement text file gets updated:

```
\Drupal::service('cache_tags.invalidator')->invalidateTags(['mymodule:filter']);

```

---
Tags: 8, input-formats
---


# Question
Title: Full automation for upgrading everything
I have a Drupal 8.5.x site with the Redirect and the Metatag modules installed. I want to fully automate the process of upgrading Drupal including Drupal core, the translations, the themes, and any third-party module used on the site.
I want to upgrade the site from the Drupal UI, possibly without the need to create scripts.

Is it possible with Drupal?

# Answer
Is it *possible* to full upgrading with solely Drupal/PHP? In the sense that *anything* is possible given enough time/effort, yes.

Should you? Not unless you want to spend a lot of time building a bespoke, error-prone (especially if you're scoping in *any* modules, themes, etc.) process that will only work under the narrow scenario in which you developed it.

To get a sense of what you're asking, look at auto updates initiative. You're probably better off contributing/following the initiative instead of rolling your own.
> 3 votes

---
Tags: upgrading
---


# Question
Title: Setup voting/rating on content to require a "reason" field
Is there a way to setup content voting/rating on Drupal 7 in such way that the user **must** provide a *reason* for their vote/rating?

# Answer
There are probably many different ways to create a feature where a comment is required along with voting. I guess it all depends on which method you're using for the voting part.

You could use the Fivestar module to Set up fivestar widget for User/Author rating with comment on any content type. 7X. Here you use allow for rating to be available on each new comment. You can use the usual comment field permissions to require input on both the voting field and the comment text area.

There are more ways to create something similar with the Fivestar module, it all depends on your particular needs.

Another module that can be used for voting is Flag. You can add Fields to Flags just like you can on a Content type: Attaching fields to flags (Flag 3.x). This way Flags are used for the voting part, and the Text area field created on the Flag is used to type in the reason. You can configure both the Flag and the Text area field on the Flag to be required based on Roles and Permissions.

Basically it's all about attaching a Text field to your voting widget and setting up permissions to make it required so the form can't be saved if it's empty.
> 3 votes

---
Tags: rating
---


# Question
Title: Trying to add CSS to certain pages using a custom module in 7.x
I tried following the instructions here: How to override some admin theme CSS rules? and have spent a lot of time and energy googling and iterating this, so I'm turning to the stack exchange community for help.

What I'm trying to do is make some text fields larger when a user tries to edit a page. I'm attempting to do this by writing a custom module that checks if the page's url contains the string edit, and if so, enabling the custom css. The version is drupal 7, and I am working with Pantheon. So far, my module looks like this:

```
<?php

function admincss_preprocess_html(&$variables) {

$url_string = $_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];

if (strpos($url_string, 'edit') !== FALSE) {

  // reference your current admin theme
    $theme_path = drupal_get_path('theme', 'seven');

  // reference your own stylesheet
    drupal_add_css('sites/all/modules/admincss/css/admincss.css', array('weight' => CSS_THEME));
}

```

Why isn't my module being used by edit pages? And what, specifically, is the $variables variable referencing? Thank you in advance!

# Answer
To add CSS to node edit pages you can use hook\_form\_alter. Then check the $form\_id to localize changes to desired node form(s) and add your call to drupal\_add\_css().

Example:

```
function admincss_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == "xxx") {
    drupal_add_css(drupal_get_path('module', 'admincss') . '/css/admincss.css');
  }
}

```

hook\_preprocess\_html() Is used to preprocess variables for the html.tpl.php file.
> 0 votes

---
Tags: 7, theming
---


title: How do I move a site to a new server?

text:
# Question
Title: How do I move a site to a new server?
How do I move a site to a new server?

I have a backup file for the database content and all the files. I uploaded it using cPanel to the new server, imported the database, and updated the username and password as well.

For some reason, the website is just showing this message.

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

The content of the error log provided by my hosting provider is the following.

How can I fix this?

# Answer
It seems that you may forgot to move the *vendor* directory to the new location. Also you may need to run `composer dump-autoload` to update the autoloader with your new vendor's path. Though may be obvious to many, you need to clear the Drupal cache, in this case I prefer do a truncate over the cache bins (assuming you're using the default cache backend).

**Update**

Also worth checking the *autoload.php* file in your Drupal root, this file includes the actual autoloader generated by Composer.
> 4 votes

---
Tags: backups
---


# Question
Title: Setting exposed filter default value from query string
I have a view which show products and an exposed filter block (category, manufacturer, price).

I want to set category default value from URL, like this:

/browse-products/category-id

though, I wrote this module which take the parameter from URL and put it into exposed filter default value.

```
function mymodule_form_alter(&$form, &$form_state, $form_id) {
  global $request;

  if ($form_id == 'views_exposed_form') {
    $category_id = (int)($request->attributes->get('_raw_variables')->get('arg_0'));
    $form['category_id']['#default_value'][$category_id] = $category_id;
    dpm($form['category_id']);
  }
}

```

dpm output for /browse-products/5

```
Array
    (
        [#type] => checkboxes
        [#multiple] => 1
        [#options] => Array
            (
                [5] => Tablets
                [10] => -Ainovo
                [7] => -Galaxy Tab
                [6] => -IPad
                [1] => Smart Phones
                [4] => -Galaxy
                [3] => -IPhone
                [9] => --IPhone C
                [8] => --IPhone X
            )

        [#size] => 9
        [#default_value] => Array
            (
                [5] => 5
            )

        [#bef_nested] => 1
        [#theme] => bef_checkboxes
    )

```

**but it doesn't work?**

another thing, why dpm($form) prints the views exposed form data twice!

update 1: I tried something like this (but didn't work):

```
function mymodule_views_pre_build(Drupal\views\ViewExecutable $view) {
    $view_filters = $view->display_handler->getOption('filters');
    $view_filters['field_category_target_id']['value'][8] = 8;
    $view->display_handler->setOption('filters', $view_filters);
}

```

or this:

```
function mymodule_views_pre_build(Drupal\views\ViewExecutable $view) {
  $filters = $view->getExposedInput();
  $filters['field_category_target_id'] = 8;
  $view->setExposedInput($filters);
}

```

# Answer
The #default\_value parameter should be set to the key of the select list array.

Example:

```
$form['category_id']['#default_value'] = $category_id;

```
> 0 votes

---
Tags: commerce, views, http-request
---


title: 500 error without any error log entry

text:
# Question
Title: 500 error without any error log entry
Migrated a Drupal 8 site to another server running apache2 PHP 5.5.9 (should be supported). Apache returns 500 when index.php requested, but no errors are logged anywhere. I tested by forcing an intentional PHP error in index.php and the log contains PHP errors.

I also excluded database connection problems. Taking settings.php out redirects me correctly to /core/install.php and no error is thrown.

# Answer
> 0 votes
If domain name is changed for new server, you need to clean cache entries. Try using truncate commands for cache tables and confirm back. You need to have database backup before cleaning tables as well.

---
Tags: 8, debugging
---


title: .htaccess does not work?

text:
# Question
Title: .htaccess does not work?
I'm using Litespeed and clean-urls has been activated.

When I upload .htaccess file, my Drupal does not render links and all link/buttons/drop-down menus expands autttomatically. When I remove .htaccess, website Works without problem.

\*.htaccess is enabled from LiteSpeed configuration.

What is the problem? How can I use clean-urls?

# Answer
> ... essentially if your content just keeps getting cached by it \[litespeed\] you will have to keep the compression lines in your .htaccess commented out to prevent the javascript from breaking ...

Source

So essentially he's saying to comment these lines out:

```
<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>

```

I'm no expert in litespeed either, so I'm not sure if this is your problem.
> 0 votes

# Answer
Please follow the steps to debug- 1. check if mod\_rewrite is enabled on server 2. Check by concatenation if index.php in URL if render page properly. Concatenation of URL will be such as- http://YOUR-URL.COM/index.php/innerpageroute
> 0 votes

---
Tags: .htaccess, uri
---


# Question
Title: How to remove specific meta-tag from header section of page?
How to remove specific meta-tag from header section of page ?

I am trying to remove

```
<link rel="delete-form-edit" href="/node/11/delete" />

```

tag from header section of the page ,but no luck.

As there is no tag as shown above found on html.html.twig file header section ,its automatically generating.

# Answer
> 3 votes
I think you need hook\_page\_attachments\_alter, which Alter attachments (typically assets) to a page before it is rendered.

```
 /**
 * Implements hook_page_attachments_alter().
 * @param array $attachments
 */
function my_module_page_attachments_alter(array &$attachments) {
  if (!isset($attachments['#attached']['html_head_link'])) {
    return;
  }
  $unset_html_head_link = [
    'canonical',
    'shortlink',
    'delete-form',
    'edit-form',
    'version-history',
    'revision',
  ];
  foreach ($attachments['#attached']['html_head_link'] as $key => $value) {
    if (isset($value[0]['rel']) && in_array($value[0]['rel'], $unset_html_head_link)) {
      unset($attachments['#attached']['html_head_link'][$key]);
    }
  }
}

/**
 * Implements hook_module_implements_alter().
 */
function my_module_module_implements_alter(&$implementations, $hook) {
  if ($hook === 'page_attachments_alter') {
    $group = $implementations['my_module'];
    unset($implementations['my_module']);
    $implementations['my_module'] = $group;
  }
}

```

excerpt from : How to unset link rel: shortlink, edit-form, version-history and revision from ?

# Answer
> 1 votes
For nodes you have to use `hook_ENTITY_TYPE_view_alter`.

There you can alter node-specific values for `$build['#attached']['html_head_link']` and `$build['#attached']['html_head']`.

```
/**
 * Implements hook_ENTITY_TYPE_view_alter().
 */
function MYMODULE_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {

  if (empty($build['#attached']['html_head_link'])) {
    return;
  }

  $tags = [
    'canonical',
    'shortlink',
    'delete-form',
    'edit-form',
    'version-history',
    'revision',
  ];

  foreach ($build['#attached']['html_head_link'] as $key => $tag) {

    if (empty($tag[0]['rel'])) {
      continue;
    }
    if (!in_array($tag[0]['rel'], $tags)) {
      continue;
    }

    // Hide tag.
    unset($build['#attached']['html_head_link'][$key]);
  }
}

```

---

In `/core/modules/node/src/Controller/NodeViewController.php` from class `NodeViewController` method `view()` Drupal initially adds the canonical tag:

```
if ($rel == 'canonical') {
  // Set the non-aliased canonical path as a default shortlink.
  $build['#attached']['html_head_link'][] = [
    [
      'rel' => 'shortlink',
      'href' => $url->setOption('alias', TRUE)->toString(),
    ],
    TRUE,
  ];
}

```

---
Tags: 8
---


# Question
Title: How to use same database for two website but different panel?
Is this possible to use same database for two different domain? Example domain1.com and domain2.com but their views and designing are different for both site but content will be same .

If I change in one domain1.com it will reflect also in the domain2.com

# Answer
> 1 votes
You can using the Domain Access module.

> The Domain Access project is a suite of modules that provide tools for running a group of affiliated sites from one Drupal installation and a single shared database. **The module allows you to share users, content, and configurations across a group of sites** such as:
>
> example.com one.example.com two.example.com my.example.com thisexample.com \<-- can use any domain string example.com:3000 \<-- treats non-standard ports as unique By default, these sites share all tables in your Drupal installation.

# Answer
> 2 votes
You should start from https://www.drupal.org/docs/8/multisite Drupal supports multisite structure out of the box. You don't need Domain Access module to reach it. You may share some db tables among your websites, e. g. content but keep settings (Views, display settings unique). It depends of your purpose. Also you may have shared or unique modules and themes. The idea is that you specify the list of the sites in sites.php and have several subfulders under /sites folder. At least it worked with Drupal 7. I'm sure there is no drastic charge with Drupal 8. But be careful with cache. Mind which caches you want to keep shared or unique.

# Answer
> 0 votes
If I understand you want to change only the theme based on the domain. I have not made such changes in Drupal 8 but Switch Page Theme module can help you.

Here is a similar question: How can I change the active theme programmatically?

---
Tags: 8, nodes, database
---


# Question
Title: Apply a promition only on a product variation
I have a Drupal Commerce product with two variations.

* Variation A - 18 euro - SKU 123
* Variation B - 30 euro - SKU 234

Is it possible to apply a promotion only on *Variation B*?

I am using Drupal Commerce 8.x-2.4.

# Answer
> 1 votes
You need to implement you own promotion condition plugin. Theres a condition plugin defined in *commerce\_product* module in Commerce module since 2.0 release but I recommend you to use latest stable release. Check this class `Drupal\commerce_product\Plugin\Commerce\Condition\OrderItemVariationType` thus it only checks for variation type (aka bundle), you can easily write your own checking specific product variation instance. Also worth checking *OrderItemProduct* condition plugin I think you need a mix from both. This plugin is located in the same namespace than the first one.

**Update**

There's a feature request for that see this link. Thanks to @bojanz!

---
Tags: commerce
---


# Question
Title: How to apply js and css to ajax loaded content?
When content get loaded through ajax, neither theme.css or js get applied. Below is code snippet,

controller

```
    $twig = \Drupal::service('twig');
        $twigFilePath = drupal_get_path('module', 'mythemename') . '/templates/test.html.twig';
        $template =  $twig->loadTemplate($twigFilePath);
      $markup = $template->render(array('gainerList' => $gainerList, 'loseList' => $looserList));

        $build = array(
            '#type' => 'markup',
            '#markup' => $markup,
            '#attached' => array(
                'css' => array(
                    drupal_get_path('themes', 'mythemename') . '/css/theme.css'
                )
            )
        );
        return new Response(render($build));

```

Is there any issue with above code?

Also below testing code does not hide the second

.

```
 $build = array(
            '#type' => 'markup',
            '#markup' => '<p>Demo text content</p> <p style="display:none">Demo text content</p>',
        );
        return new Response(render($build));

```

Js file code snippet:

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

  Drupal.behaviors.company = {
    attach: function(context, settings) {
        $.ajax({
                url: "get-top-performing-fund",
                type: 'GET',
                success:function(data, error){
                    console.log(data);
                    $('#topPerforming').html();
                    $('#topPerforming').html(data);
                }
        });
    }
}
})(jQuery, Drupal);

```

# Answer
> 0 votes
> Is there any issue with above code?

Yes, you're using the D7 approach. In D8 it is different. You need to create a libraries.yml file where you will define your CSS and JS files.

See:

Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 module

Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 theme

Once you have a library you can attach it like this:

```
  '#attached' => array(
    'library' => array(
      'your_theme/library_name',
    ),

```

---
Tags: 8, theming, ajax
---


# Question
Title: How to update from Drupal core 8.5.0 to 8.5.5?
In the past (Drupal 7), security-only update via drush was simple as:

```
drush up --security-only

```

now, Drush 9.3 returns:

> Command "up" is ambiguous.
> Did you mean one of these? ...

`composer` does not help either:

```
composer outdated drupal/*

```

returns *nothing*.

In fact, my Drupal is outdated:

How can I update Drupal security updates via command line?

UPDATE (`composer prohibits`):

```
$ composer prohibits drupal/core:8.5.5
There is no installed package depending on "drupal/core" in versions not matching 8.5.5

```

# Answer
> 2 votes
It's all here Update core via Composer.

Short version, turn on maintenance mode

```
drush sset system.maintenance_mode 1

```

then run

```
composer update drupal/core --with-dependencies
drush updatedb
drush cr

```

Turn off maintenance mode

```
drush sset system.maintenance_mode 0

```

> If you run the `composer update` command above but drupal/core is not updated, there might be another dependency holding back the Drupal upgrade. You can check for blocking dependencies using the command `composer prohibits`. For example, if you are trying to upgrade from 8.4.5 to 8.5.0, you can run `composer prohibits drupal/core:8.5.0`, and it should give a list of dependencies blocking the upgrade. Update those dependencies along with drupal/core and it should work (e.g. `composer update drupal/core symfony/* --with-dependencies`).

---
Tags: 8, drush, updating, composer
---


# Question
Title: how do I get the depth of a MenuLinkContent?
I'm using the sitemap module and i need to get the menu link depth in my preprocess function (template\_sitemap\_menu\_link). I'm trying to do that by accessing the MenuLinkContent object with

```
    $menu_link_obj = $variables['element']['#original_link'];

```

There is a getParent() method I can access to check if this is a level zero item, but no way to check for depth. I could always loop trough getParent() until I get NULL and count the number of iterations, but that seems like a bad practise to me. Is there an alternative?

# Answer
Here is our approach:

```
$menu_link = $variables['element']['#original_link'];

$depth = 0;
$parent = $menu_link->getParent();
if ($parent) {
  while ($parent) {
    $parent_parts = explode(':', $parent);

    $parent_entity = \Drupal::service('entity.repository')->loadEntityByUuid($parent_parts[0], $parent_parts[1]);
    $parent = $parent_entity->get('parent')->get(0)->value;
    $depth ++;
  }
}

```

Hope to help
> 4 votes

---
Tags: 8, navigation
---


title: Config webform for read

text:
# Question
Title: Config webform for read
It is posible config webform for read but not submmit? I need that anonymous user see webform but only authenticated user can send.

# Answer
> 0 votes
If you customize your submit buttons, you can set up access controls that only allow authenticated users to see the submit buttons.

@see https://www.drupal.org/project/webform/issues/2983024

---
Tags: 8, webforms
---


title: Change views pager programmatically

text:
# Question
Title: Change views pager programmatically
I'm adding nodes to a view programmatically and i'm altering the pager 'x out of y' by setting the folowing in hook\_views\_pre\_render:

```
$view->query->pager->total_items = $count;
$view->query->pager->current_page = isset($params['page']) ? $params['page'] : 0;
$view->query->pager->options['total_pages'] = ceil( $count / $lim );
$view->total_rows = (string) $count;
$view->items_per_page = (string) $view->query->pager->options['items_per_page'];
$view->current_page =isset($params['page']) ? $params['page'] : 0;

```

Let's say there are 10 pages but even with this code nothing seems to happen, nothing get's altered. When on the second page, it doesn't display the next button. How can this achieved with code? What object, array should i alter to have this result? Any help would be appreciated.

Thanks

# Answer
> 9 votes
Try some thing like this and see if it helps

```
function views_pag_views_pre_build(&$view) {
    if ($view->name == "pagination") {
            $view->init_pager();
            $view->set_items_per_page('10');

    }
}

```

# Answer
> 3 votes
Thanks for all the great help. In hook\_views\_pre\_render i used this 2 lines of code:

```
if($view->name=='myview'){ ...
   $view->query->pager->total_items = $count;
   $view->query->pager->update_page_info();
...
}

```

And now the pager is working like a charm. :D The items per page value i have set it in the views ui, so i didn't have to change/set that programmatically.

# Answer
> 2 votes
For those using Drupal 8: If you're like me and made changes to your view in the 'hook\_views\_query\_pre\_render' hook then all you need to do to update the page is the following:

```
$view->result = $new_results; // Where $new_results is an array of new rows
$view->total_rows = count($new_results);
$view->pager->total_items = count($new_results);
$view->pager->updatePageInfo(); // After updating page variables then it's important to run this method!

```

Please note that the pager uses the variable 'total\_items' and the view object uses the variable 'total\_rows'...

Hope that helps someone!

# Answer
> -1 votes
I used the following code:

```
function yourmodule_views_pre_render(&$view) {
    $myview = views_get_view('view_id', TRUE);
    $myview->display['default']->display_options['pager']['options']['items_per_page'] = '5';
    views_save_view($myview);
}

```

Your view id is the machine name of your view.

The snippet was borrowed from Programmatically Change Pager "Items to Display" value?

In order to clear the pager, the solution in the above thread also leaves the following snippet on the end.

```
$cache = $myview . ':block:results:';
cache_clear_all($cache, 'cache_views_data', TRUE);

```

---
Tags: views, paging
---


title: Exposed form don't have class attribute

text:
# Question
Title: Exposed form don't have class attribute
In a `form_alter`, I simply want to add a class to an exposed form (this code works for a custom form) :

```
$form['#attributes']['class'][] = 'my_class';

```

But neither my class nor the default class (`views-exposed-form`, I can see it in `$form['#attributes']`) is printed in front in the `form` tag.

Any idea?

# Answer
I guess `hook_form_alter` is not the right place to set attributes. But I may be wrong. What surely works is to set attributes in a preprocess function.

The following snippet adds the form ID as CSS class to every form. You could easily wrap some if-request around this to only fire on certain forms checking for `$variables['element']['#form_id']`.

```
/**
 * Implements hook_preprocess_HOOK().
 */
function MYTHEME_preprocess_form(&$variables) {

  // Add form ID as class to form attributes.
  $variables['attributes']['class'][] = 'form';
  $variables['attributes']['class'][] = 'form-' . str_replace('_', '-', $variables['element']['#form_id']);
}

```
> 0 votes

---
Tags: 8, forms
---


title: Add variables in custom input template

text:
# Question
Title: Add variables in custom input template
In D8 I created a custom input twig file (based on input.html.twig) :

```
{{ icon }}

<input{{ attributes }} />{{ children }}

```

Then I created a new entry in hook\_theme() :

```
function my_module_theme() {
 return [
   'input_custom' => [
     'render element' => 'form',
     'variables' => [
       'icon' => NULL,
     ],
     'template' => 'input-custom',
   ],
 ];
}

```

Then I'm loaded the template in my form element :

```
$form['my_field'] = [
        '#type' => 'textfield',
        '#theme' => 'input_custom',
        '#icon' => 'my_icon',
        '#title' => $this->t('My title'),
      ];

```

My custom variable is sent to the template but I lost all html attributes on the input. If I remove `variables` from `my_module_theme()` all html attributes are back, but I'm losing my custom variable.

How can I send custom variables in custom input template ?

# Answer
Declare a #theme starting with the base hook of the input element and a double underscore:

```
  $form['my_field'] = [
    '#type' => 'textfield',
    '#theme' => 'input__custom',
    '#icon' => 'my_icon',
    '#title' => $this->t('My title'),
  ];

```

Prepare additional variables in a preprocess hook:

```
function mytheme/mymodule_preprocess_input(&$variables) {
  if ($variables['theme_hook_original'] == 'input__custom') {
    $variables['icon'] = $variables['element']['#icon'];
  }
}

```

Then you can use the added variables in the input template:

```
{{ icon }}

```
> 6 votes

# Answer
**Update** : this solution is not working because the form element becomes a theme element.

I just realize that I'm taking the problem in the wrong way... I should use a custom template where I will load my input and not the opposite.

Like this I don't need to override a core element.

Twig file :

```
{{ icon }}

{{ input }}

```

Hook\_theme :

```
function my_module_theme() {
  return [
    'input_custom' => [
      'variables' => [
        'icon' => null,
        'input' => null,
      ],
      'template' => 'input-custom',
    ],
  ];
}

```

My form element :

```
 $form['my_field'] = [
    '#theme' => 'input_custom',
    '#icon' => $labels['icon'],
    '#input' => [
      '#type' => 'textfield',
      '#title' => $this->t('My title'),
    ],
  ];

```

**Notice :** for this solution, I changed my point of view on the issue to make it easier to solve. Technically even if this is working, as @4k4 said this is not answering totally the beginning question.
> 0 votes

---
Tags: 8, theming
---


title: Alter Ajax callback on Webforms

text:
# Question
Title: Alter Ajax callback on Webforms
I'm loading a webform on a Ajax modal dialog. The form submission is also set to Ajax. I want to alter the Ajax submit callback so I can have more control over the form behaviour. I'm not being able to do that. The callback being executed is always submitAjaxForm, set on the WebformAjaxFormTrait trait.

# Answer
> 2 votes
Try using a

```
hook_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  ....
  if (isset($form['actions']['submit'])) {
    $form['actions']['submit']['#ajax'] = [
      'callback' => '/path/to/your/controller/or/webformhandler/submitModalFormAjax',
      'event' => 'click',
    ];
}

```

in your \*.module and then implement the callback function somewhere

```
public static function submitModalFormAjax(array &$form, FormStateInterface $form_state) {...}

```

---
Tags: 8, ajax, webforms
---


# Question
Title: Make node/field text input format available to Views
The standard *Content* list in Drupal 7 (displayed with the *Find content* menu item) gives me a table of nodes in the system with various attributes, such as the type. I want to add the *text* type (e.g. *Filtered HTML*).

How can I do this? Installing the *Administration views* module has made the table much more configurable, but there seems to be no way to include data from the `field_data_body` database table, which contains the information. The *Table Wizard* and *Data* modules apparently provide this functionality, but are not done for Drupal 7.

Is there a way to do this without coding?

If I have to code it, do you recommend creating a new module (with which I have no experience) or patching up an existing one until it works well enough, and if so, which one?

PS: this can be regarded as a special case of a (frequently asked) related question.

# Answer
It is possible to do this with Views 3 in Drupal 7:

1. Add the field you need the format of to the view (E.g. field\_body)
2. In the configuration form for that field tick the 'Rewrite the output of this field' box
3. Put the '\[*field\_name*-format\]' token into the box

It will render the raw name of the input format, instead of the value.
> 3 votes

# Answer
This is the third step when you want to achieve this in Drupal 8: 3. Put the '{{ body\__format }}' token into the box.

This is because the token format changed between Drupal 7 & 8.
> 0 votes

---
Tags: 7, views, input-formats
---


title: One site, two domains

text:
# Question
Title: One site, two domains
We have a single site that we'd like to have two different domains: `apply.school1.edu` and `apply.school2.edu`.

The site is at `apply.school1.edu` and we'd simply like to create a domain `apply.school2.edu` to point to `apply.school1.edu`. That way we can use the domain to determine what content to load on the page.

How can we do this?

# Answer
> 0 votes
If you'd like both sites to use the same code/modules and database (thus sharing users and some content), use the domain access module at https://www.drupal.org/project/domain

If you'd like both sites to have the same code/modules but not the database, check out Multisite at https://www.drupal.org/docs/7/multisite/multi-site-sharing-the-same-code-base

---
Tags: 7, redirection, domain-access
---


# Question
Title: Custom plugin modified results in WSOD PluginNotFoundException
I've created a module with a custom Plugin ("group\_user"). It all worked great until I modified the code and accidentally introduced an error. This resulted in a WSOD `Drupal\Component\Plugin\Exception\PluginNotFoundException</em>: The "group_user" plugin does not exist.` I cannot even uninstall the custom module since either drush or the WSOD show the same error. Even undoing the code changes in the code do not work. I've found this bug description which is discussed in the following issue. There does not seem to be a working solution yet. Is there any way I could manually "remove" the plugin or find the "location" it is still loaded?

# Answer
Plugin definition its a tandem between the plugin manager wich defines how your plugin type should be discovered and instantiated; and the plugin definition method itself that could be either using YAML files or annotations. Depending of which you used to define you new plugin type is how you must proceed in order Drupal find your plugin implementation. Said that if your plugin is used in a configuration entity you can find it querying your configuration table as follows:

`SELECT * FROM config WHERE name LIKE '%group_user%' OR data LIKE '%group_user%';`

In the other hand if your plugin is invoked directly in code by calling the plugin manager method `createInstance` you can then find where it is being used with a simple search in your custom code using your favorite editor or IDE. I emphasize on custom code as is a custom plugin type cannot be (yet) in contrib code.
> 2 votes

# Answer
> Is there any way I could manually "remove" the plugin or find the "location" it is still loaded?

The first step to find the "location" is to find the code trying to load the plugin. If you don't have an IDE with xdebug you can try to find it in a backtrace. Since you can't reach the admin UI anymore, add this line to settings.php:

`$config['system.logging']['error_level'] = 'verbose';`

I don't think the linked issue is connected, because it is about what happens after uninstalling a module containing a specific plugin type. You didn't even uninstall the module, you've tried this only after the error occured, which then is no longer possible because of the error.
> 1 votes

---
Tags: 8, plugins
---


# Question
Title: How to remove block from the page based on cookie value?
We have a block (`myblock`) that is only displayed on 4/5 content types. When a cookie, `mycookie`, is set and has a value of `allow`, I want to load the block on the page, but if the value is not set to `allow`, then I want to remove it from the page. The cookie is set through a third party Javascript library.

How to remove block based on cookie value?

Setup:

1. Under block layout, we load the block on 4/5 content types.
2. Using twig template (`myblock--name.html.twig`), we add some css to the `myblock`

# Answer
I'll assume this is not a block plugin, right (or at least you dont have access to modify it)? If it is or you can modify it, you should add the logic below to your `build()` method inside your block class.

Is the cookie you're looking for generated from Drupal? Assuming it is, you should be able to do something like this:

```
HOOK_preprocess_block__myblock__name(&variables) {
  if (!\Drupal::request()->cookies->get('mycookie') == 'allow') {
    $variables = [];
  }
  // Don't forget about cache context for cookie!
  $variables['#cache']['contexts'][] = 'cookies:mycookie'
}

```
> 2 votes

---
Tags: 8, theming, blocks, hooks
---


# Question
Title: Access Denied when I try to flush cache or change theme
This is a very odd issue. Logged in as admin. All permissions given to admin. But Access Denied page when I try to flush cache or change theme. I can flush the cache with drush. I tried switching theme to garland and back again. I tried creating a new admin user, didn't work. I tried disabling recently enabled boost module, to no avail.

# Answer
I have no idea why, but I disabled clean-urls and reenabled it and now I can flush cache and switch themes without access denied.

I had installed the Boost module which also involved putting some stuff in the .htaccess and turning on clean urls (although I was using it anyway).

This problem took me about 4 hours to solve and was completely unintuitive.
> 2 votes

# Answer
I experienced this issue and it turned out to be a problem with the admin-menu. Clearing caches worked when triggering from Performance admin workflow.

In my case this problem occurred after installing a custom permissions-related feature which included some permissions for the admin-module. I recreated the feature without these and then reinstalled the admin-menu module and the problem was resolved.

Hope this helps.
> 0 votes

---
Tags: users
---


# Question
Title: How to make sure that drupalSettings value gets updated on the JavaScript end?
Have an ajax callback function within which the data gets generated dynamically based on the custom input from form fields.

```
//ajax callback submit
$form['action'] = [
'#type' => 'button',
'#value' => $this->t('Submit'),
'#ajax' => [
'callback' => '::getData',
'wrapper' => 'table-data',
'method' => 'replaceWith',
'effect' => 'fade',
];

//ajax callback function
public function getData($form, FormStateInterface &$form_state) {
$table_data = $this->getTableData($form_state);  //getting the data dynamically
$form['section']['#attached']['drupalSettings']['table_data'] = $table_data; //assigning the data to drupalSettings
dpm($table_data); //to check if the assignment is updated
    return array($form['table_markup'],$form['section']);   //$form['table_markup'] is a markup used to display data in the table
   }

//javascript code
(function ($, Drupal, drupalSettings) {
    Drupal.behaviors.display_data = {
    attach: function (context, settings) {
        alert(drupalSettings.table_data);
        var table_data  = drupalSettings.table_data;  //inconsistency noticed in this assignment
    }
};

})(jQuery, Drupal, drupalSettings);

```

Now whenever I click on the submit button, the $table\_data gets updated and assigned to the drupalSettings dynamically, but passing its value to the javascript seems to be behaving inconsistent, meaning the drupalSettings.table\_data within javascript does not get updated but shows the previous set values.

For it to work correctly I have to reload the page, change the form inputs and submit.

I've realized it may have to do with the cache and tried to avoid it by setting the routing.yml file as below:

```
  options:
    no_cache: 'TRUE'

```

Not sure how to use cache tags here, as I do not have any tags defined Tried to rebuild the form within the callback which didn't work either. The form input fields does not get cleared even after reloading the page and I'm confused why this happens even after the no\_cache is set to true?

Tried using 'delete' on javascript end, which didn't work either

Is there a suitable approach to make sure that the variable from drupal php, received on the javascript is always an updated one?

# Answer
> 4 votes
In this case instead of returning HTML (aka the form render array) your AJAX callback method needs to return an AjaxResponse object (see API docs). The AjaxResponse object should contain at least 2 commands, one for updating your HTML (the processed form) and other to update the *drupalSettings* object. A possible response could be like

```
public static function ajaxCallback(array $form, FormStateInterface $form_state) {
  // Assuming the $form variable is either the updated render array or rendered output.
  $response = new AjaxResponse();
  $response->addCommand(new ReplaceCommand('#wrapper-id', $form));
  // The $data variable is an assoc array with he same keys you passed during the build under #attached key.
  // If you don't want to merge the settings but instead replace it, remove the second argument.
  $response->addCommand(new SettingsCommand ($data, TRUE));
  return $response;
}

```

---
Tags: 8, javascript, ajax, caching
---


# Question
Title: How to set a specific vocabulary in a taxonomy reference field during migration?
I am doing a D7 \> D8 migration (where the D7 site in question itself was migrated from D6 some years back) and most stuff just works fine. But I am stuck on the field (instance) settings for taxonomy reference fields.

When migrating the field instances, I am using a slightly changed version from the one provided by core (that's how I did it with most other stuff, too):

```
langcode: en
status: true
dependencies: {  }
id: my_fields
class: Drupal\migrate_drupal\Plugin\migrate\FieldMigration
field_plugin_method: processField
cck_plugin_method: null
migration_tags:
  - 'Drupal 7'
  - Configuration
migration_group: my
label: 'Field configuration'
source:
  plugin: d7_field
  constants:
    status: true
    langcode: und
process:
  entity_type: entity_type
  status: constants/status
  langcode: constants/langcode
  field_name:
    plugin: static_map
    source: field_name
    map:
      taxonomy_vocabulary_1: field_issues
      taxonomy_vocabulary_2: field_tags
    bypass: TRUE
  type:
    plugin: process_field
    source: type
    method: getFieldType
  cardinality: cardinality
  settings:
    plugin: d7_field_settings
destination:
  plugin: 'entity:field_storage_config'
migration_dependencies: null

```

When I run this via `drush mim my_fields` all field instances on all content types are created (wonderful!), the only thing missing is the restriction in taxonomy term reference fields regarding a specific vocabulary.

When I create such a field manually and export the configuration, there is a section in the yaml file describing that restriction:

```
settings:
  handler: 'default:taxonomy_term'
  handler_settings:
    target_bundles:
      issues: issues
    sort:
      field: name
      direction: asc
    auto_create: false
    auto_create_bundle: ''

```

I guess this needs to be in the process section of the migration configuration, but how do I set it correctly? If I read that right, the vocabulary name (issues) is both field name and value, which would probably pose a problem for multiple vocabularies. Also, how would I set this for taxonomy reference fields only?

Added note: In Drupal 7, the restriction was set within the field global settings (`allowed_values[vocabulary]`, could be found in the DB table field\_config) and not with the field instance.

In Drupal 8, it seems to be a field\_instance setting as the same field can be restricted to different vocabularies in different content types. May that be the reason, why this setting is not migrated?

By the way: I did try a simple migration first by using the Migrate Drupal module and while it got most configuration right by just using defaults, here also the restrictions on taxonomy reference fields was missing.

# Answer
> 0 votes
I needed to write a custom migration process plugin.

The default is called `d7_field_instance_settings` and already provides custom settings for entityreference fields. I am not sure, why they didn't include just similar code block for taxonomy\_term\_reference, though.

Thus, I wrote that block:

```
if ($row->getSourceProperty('type') == "taxonomy_term_reference") {
      if (array_key_exists('allowed_values', $field_settings)) {
          $vocabulary = $field_settings['allowed_values'][0]['vocabulary'];
          $instance_settings['handler_settings']['target_bundles'] = array(
              $voc => $voc,
          );
      }
  }

```

This code just looks, if the **field settings** (as the vocabulary is stored in the field settings in D7) contain a key `allowed_values` and if so set the associated vocabulary name as target bundle for the **field instance** in D8.

Note: In D7 it was only possible to add a single vocabulary which is why I am just using `[0]` in the code. Otherwise, this should be turned into a foreach loop in order to set multiple vocabularies (as allowed in D8).

# Answer
> 1 votes
The field settings are created in the process plugin, d7\_field\_settings, in this section of the process pipeline.

```
 settings:
    plugin: d7_field_settings

```

It seems that you will need to write a custom process plugin. You may want to preserve the settings created by d7\_field\_settings. I don't recall what d7\_field\_settings does. So you could put something like this after the settings property is set..

```
 'settings/handler_settings/target_bundles': my_custom_plugin

```

Edit: Glad got it working. Found the core issue for this today, https://www.drupal.org/project/drupal/issues/2763637.

---
Tags: 8, taxonomy-terms, migrations
---


title: How can I load entity form for comment?

text:
# Question
Title: How can I load entity form for comment?
I want to **load entity form for comment entity type**.

I can load entity form for node (entity type = node and bundle = article).

But the entity type = comment and bundle = comment.

Here is the code of loading entity:

```
  $values = [];
    $definition = \Drupal::entityManager()->getDefinition("node");
    $bundle_key = $definition->get('entity_keys')['bundle'];
    $values['entity_type'] = "node";
    $values[$bundle_key] = "article";
    $entity = \Drupal::entityManager()->getStorage($definition->get('id'))
      ->create($values);
   return \Drupal::service('entity.form_builder')->getForm($entity);

```

=\> This example works well.

But if i replace entity type with comment and bundle with comment, not work :(.

```
        $values = [];
        $definition = \Drupal::entityManager()->getDefinition("comment");
        $bundle_key = $definition->get('entity_keys')['bundle'];
        $values['entity_type'] = "comment";
        $values[$bundle_key] = "comment";
        $entity = \Drupal::entityManager()->getStorage($definition->get('id'))
          ->create($values);
       return \Drupal::service('entity.form_builder')->getForm($entity);

```

# Answer
> 0 votes
it also needs the field name I think, check CommentDefaultFormatter::viewElements

https://api.drupal.org/api/drupal/core%21modules%21comment%21src%21Plugin%21Field%21FieldFormatter%21CommentDefaultFormatter.php/class/CommentDefaultFormatter/8

It uses a lazy builder so it can be built after render caching

$output\['comment\_form'\] = \[ '#lazy\_builder' =\> \['comment.lazy\_builders:renderForm', \[ $entity-\>getEntityTypeId(), $entity-\>id(), $field\_name, $this-\>getFieldSetting('comment\_type'), \]\], '#create\_placeholder' =\> TRUE, \];

# Answer
> 0 votes
Yes, I found the answer to the question:

The entity type comment must be related to another entity and the other entity must have a field ( type = comment).

So here is the code for the entity form for comment related to the entity user:

```
$values = [];
$definition = \Drupal::entityTypeManager()->getDefinition("comment");
$bundle_key = $definition->get('entity_keys')['bundle'];
$values['entity_type'] = "user";
$values['field_name'] = "field_comments";
// comment type = comment_user(for entity type : user)
$values[$bundle_key] = "comment_user";
// user/1
$values['entity_id'] = array(
  'target_id' => 1,
);
$entity = \Drupal::entityTypeManager()->getStorage($definition->get('id'))
  ->create($values);

 return \Drupal::service('entity.form_builder')->getForm($entity);

```

# Answer
> 0 votes
I had the same problem. I got the solution.

For Node :

```
function d8_points_receipt_form_submit($form, FormStateInterface $form_state) {
    $user_input = $form_state->getUserInput();
    $selected = array_filter($user_input['node_bulk_form']);
    $connection = Database::getConnection();
      if($form_state->getValue('action') == "node_publish_action") {
        foreach ($selected as $bulk_form_key) {
          $key_json_value = base64_decode($bulk_form_key);
          $key_ids = json_decode($key_json_value);
          $node_ids = array_pop($key_ids);
          $node_storage = \Drupal::entityTypeManager()->getStorage('node');
          $node = $node_storage->load($node_ids);
          $node_creator_id = $node->getOwnerId();
          $result = $connection->insert('d8_points_new_table')
          ->fields([
          'uid' => $node_creator_id,
          'title' => $node->get('title')->value,
          'info_type' => 'receipt',
          'action_points' => $node->get('field_point_for_receipt_upload')->value,
          ])
            ->execute();
          }
        }
  }

```

For Comment :

```
function d8_points_comment_form_submit($form, FormStateInterface $form_state) {
    drupal_set_message('come on');
    $user_input = $form_state->getUserInput();
    $selected = array_filter($user_input['comment_bulk_form']);
    $connection = Database::getConnection();
      if($form_state->getValue('action') == "comment_publish_action") {
        drupal_set_message('cnd ok come on');
        foreach ($selected as $bulk_form_key) {
          $key_json_value = base64_decode($bulk_form_key);
          $key_ids = json_decode($key_json_value);
          $comment_ids = array_pop($key_ids);
          $comment = \Drupal::entityManager()->getStorage('comment')->load($comment_ids);
          $comment_creator_id = $comment->getOwnerId();
          $result = $connection->insert('d8_points_new_table')
          ->fields([
          'uid' => $comment_creator_id,
          'title' => $comment->get('subject')->value,
          'info_type' => 'comment',
          'action_points' => $comment->get('field_point_for_comment')->value,
          ])
            ->execute();
          }
        }
  }

```

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


title: How do I replace a plugin?

text:
# Question
Title: How do I replace a plugin?
Let's say that I want to replace the `block_content_type` plugin of the core `block_content` module to ad some features while not having to rewrite a whole module to achieve this.

It is very easy to replace a service by providing your own service definition with the same key as the to-be-replaced service. How do I replace a plugin with another one?

# Answer
To answer the general question how do you do that with plugins: Each plugin type is managed by a plugin manager. You can list all plugin manager classes with this console command:

```
drupal debug:plugin

```

Most plugin managers provide an alter hook to change the plugin definitions. Look in the plugin manager class method `__construct` for a line with `$this->alterInfo()`:

```
public function __construct(...) {
  ...
  $this->alterInfo('example_plugin_info');

```

In this alter hook you can replace the class of plugins managed by this plugin manager:

```
function mymodule_example_plugin_info_alter(array &$info) {
  if (isset($info['foo_plugin'])) {
    $info['foo_plugin']['class'] = '\Drupal\mymodule\Plugin\ExamplePlugin\MyCustomFooPlugin';
  }
}

```

You can check the result by executing the same console command, now providing the plugin type as parameter, to list the plugins of this type and their classes:

```
drupal debug:plugin example_plugin

```

---

**Entity type classes**

About your specific question, the plugin manager for entities is EntityTypeManager (not listed by the console command because it doesn't use the standard service name scheme). It provides an alter hook to alter entity types as well, so if you are referring to the bundle entity type class of Block Content, then you can change it here:

```
/**
 * Implements hook_entity_type_alter().
 */
function mymodule_entity_type_alter(array &$entity_types) {
  $entity_types['block_content_type']->setClass('...');
}

```

---

## Using Drush and Devel instead of Drupal Console to debug plugins

Devel adds some useful commands to Drush, one of them is to debug services, which you can filter to list only plugin managers:

```
drush devel:services plugin.manager.

```

After you've found the service ID of the plugin manager you can list the plugins discovered by this plugin manager:

```
\Drupal::service('plugin.manager.example')->getDefinitions();

```

Run this command from a `drush php` shell to get a nice output.

For the plugin manager class name look up the service ID in Devel UI (/devel/container/service).
> 13 votes

---
Tags: plugins
---


# Question
Title: How to disable modules using config split?
I have created different split for each environement (local, dev, test, prod) using the Configuration Split module. How can manage modules (enable/disable) in each environment?

Should I keep `core.extensions.yml` in each split and remove the module to be uninstalled from the list?

# Answer
> 10 votes
The `core.extension.yml` should only be put into the default, shared config. As it only holds those modules, that are enabled across all your different environments.

```
$config_directories['sync'] = '../config/sync/default/shared';

```

This default Drupal config sync directory also has the `config_split.config_split.local.yml` in it, which defines which modules apart from the ones in the `core.extension.yml` should be enabled additionally when the `local` split is active.

```
uuid: abc123456-7890-abcd-906d-abc123456
langcode: en
status: false
dependencies: {  }
id: local
label: Local
folder: ../config/sync/default/local
module:
  browsersync: 0
  devel: 0
  features_ui: 0
  field_ui: 0
  kint: 0
  link_css: 0
  masquerade: 0
  views_ui: 0
  webprofiler: 0
theme: {  }
blacklist: {  }
graylist: {  }
graylist_dependents: true
graylist_skip_equal: true
weight: 0

```

Then, inside each environment's `settings.local.php` you have to define which split in addition to the default, shared config should be active and which not. Here's how it may be configured on your local machine:

```
$config['config_split.config_split.local']['status'] = TRUE;
$config['config_split.config_split.dev']['status']   = FALSE;
$config['config_split.config_split.stage']['status'] = FALSE;
$config['config_split.config_split.prod']['status']  = FALSE;

```

---

The `core.extension.yml` only holds those modules that are shared among **all** your different environments.

---
Tags: 8, configuration
---


# Question
Title: How to add class to image tag in Twig template?
How can I add a CSS class to an `<img>` tag by using a template file if output looks like this:

```
<!-- BEGIN OUTPUT from 'themes/contrib/bootstrap/templates/system/image.html.twig' -->
<img class="media__image media__element b-lazy b-responsive img-responsive b-loaded" src="/sites/default/files/styles/media_image/public/2018-03/Trainer-Norbert-Sauer-auf-der-Rennbahn-Wambel-Am-Donnerstag-249903.jpg?h=c913b3c6&itok=sENPOWtc" alt="Trainer Norbert Sauer auf der Rennbahn Wambel">
<!-- END OUTPUT from 'themes/contrib/bootstrap/templates/system/image.html.twig' -->

```

# Answer
You can use `hook_preprocess_field` to add classes to the attributes array without modifying twig:

```
/**
 * Implements hook_preprocess_field().
 */
function mytheme_preprocess_field(&$variables) {
  if ($variables['entity_type'] == 'media' && $variables['field_name'] == 'image') {
    foreach ($variables['items'] as $key => $item) {
      $variables['items'][$key]['content']['#item_attributes']['class'][] = 'myclass';
    }
  }
}

```

Note that I am checking by both entity type (media) here along with the field name (image).

If you want to do this by image style, you can also use `hook_preprocess_image`:

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

```

In both cases you do not need to touch the Twig file because the image field will be rendered and as long as `attributes` is output on the img tag (coming from core, it will be), the class will be appended to any other existing classes.
> 3 votes

# Answer
Copy `image.html.twig` from `themes/contrib/bootstrap/templates/system/image.html.twig` to your theme's template folder

and modify the image tag adding `addClass("myClass")`

```
<img{{ attributes.addClass(classes).addClass("myClass") }} />

```

**Note:** this will apply the class to all images fields in the site
> 0 votes

# Answer
A less hacky option is to enable Display Suite field templates, which allows you to add classes to the immediately `<div>` wrapper of the `<img>` tag. This way, you can practically add different classes to different image fields.
> 0 votes

---
Tags: 8, theming
---


# Question
Title: Default entity ID for _entity_view in routing.yml
I've a custom content entity (created using Config pages module) which is used as a welcome screen / dashboard. Privileged super editors can edit those content entities, normal editors can only view it.

The config pages module itself does not provide routes to view modes (only to edit forms), so I used the core's generic `_entity_view` to create routes for the normal editors myself:

This is `my_module.routing.yml`

```
my_module.view_config_pages:
  path: '/admin/config_pages/{i_dont_want_no_parameter}'
  defaults:
    _entity_view: 'config_pages.full'
  requirements:
    _role: 'authenticated'
  options:
    _admin_route: true
    parameters:
        i_dont_want_no_parameter:
          type: 'entity:config_pages'

```

This works with URLs like `/admin/config_pages/1`, `/admin/config_pages/2` etc... But I want to create nice, parameter-less, named routes to specific entity IDs. Something similar to my dummy-code below

```
my_module.view_welcome:
  path: '/admin/welcome'
  defaults:
    _entity_view: 'config_pages.full'
  requirements:
    _role: 'authenticated'
  options:
    _admin_route: true
    parameters:
        yeah_no_parameter:
          type: 'entity:config_pages'
          id: 1
my_module.view_stats:
  path: '/admin/stats'
  defaults:
    _entity_view: 'config_pages.full'
  requirements:
    _role: 'authenticated'
  options:
    _admin_route: true
    parameters:
        yeah_no_parameter:
          type: 'entity:config_pages'
          id: 2

```

Can this be done with `_entity_view` in YAML files without coding a custom controller?

# Answer
The default ID can be set in the defaults section, here is an example:

```
my_module.view_dashboard:
  path: '/admin/dashboard/{my_entity_id}'
  defaults:
    _entity_view: 'my_custom_entity.full'
    my_entity_id: 123
  requirements:
    _role: 'authenticated'
    my_entity_id: ^[0-9]+
  options:
    _admin_route: true
    parameters:
      my_entity_id:
        type: 'entity:my_custom_entity'

my_module.view_stats:
  path: '/admin/stats/{my_entity_id}'
  defaults:
    _entity_view: 'my_custom_entity.full'
    my_entity_id: 456
  requirements:
    _role: 'authenticated'
    my_entity_id: ^[0-9]+
  options:
    _admin_route: true
    parameters:
      my_entity_id:
        type: 'entity:my_custom_entity'

```

This solution creates nice URLs without any controller.
> 2 votes

---
Tags: 8, routes
---


# Question
Title: Error - External URLs do not have an internal route name
I can't access to my site because of this error:

> UnexpectedValueException: External URLs do not have an internal route name. in Drupal\Core\Url-\>getRouteName() (line 554 of C:\Users\user\Documents\Sites\camp\core\lib\Drupal\Core\Url.php).
>
> This is the function that I have in line 552 to 558.

```
public function getRouteName() {
if ($this->unrouted) {
  throw new \UnexpectedValueException('External URLs do not have an internal route name.');
}

return $this->routeName;
}

```

The last thing I have done it was update 2 nodes that I have created and a View of that content type.

The nodes I have changed the text (just text, didn't put URL or so) and added a photo storage locally

That content type has 2 fields, body and image

On view I deleted the field body and then added again

I have deleted the view, nodes and content type and I still having that error

I don't know if this help but I have installed these modules:

video embed field, views infinite scroll, superfish, pathauto, libraries, flexslider and entity reference revision.

Today I installed the module paragraphs but I uninstalled after the error

Any ideas?

This is the second time that happened to me with this site, the first time I lost some work because I have backed up an older version, but I don't want to lose some work again.

# Answer
> 2 votes
Hi

After a lot of research and try and error attempts I have found what was doing that.

My problem starts when I delete some view page that I have created, it seems the path of that page is still "alive".

If I create another page with them same path the site works fine

So to fix this problem:

\- Delete the page view with some path, eg "contacts" (at this point I have that error)

\- Create a new content and set the same URL name, in this case "contacts" (at this point the site is working 100%)

\- Then delete the content created in the step above (site is still working 100%)

This seems the URL path its no deleted by drupal on the first step and thats why I have that error.

# Answer
> 1 votes
This is a known issue with the superfish-8.x-1.0-rc3 module. Also the rc4 and rc5 versions.

I fixed the problem on Drupal 8.2.1 + superfish-8.x-1.0-rc4 by applying a patch (#15) to superfish.theme.inc

Just upgraded to Drupal 8.2.3 + superfish-8.x-1.0-rc5 and it is still broken, so I reverted back to superfish-8.x-1.0-rc4 + patch 15.

# Answer
> 0 votes
The error also can appear for other reasons. In my case I had disabled a view, but there was still a manually created menu link pointing to the path of the disabled view. Deleting / disabling the orphaned menu link solved the problem. What was weird is it did not throw the error on every page the menu was on, only the front page in my case.

So check if you changed any paths / menu paths that are still in use.

---
Tags: 8, debugging
---


# Question
Title: node.getRevisionCreationTime equivalent in views
This question is somewhat related to Comparing node creation and modification dates in twig I asked earlier.

For the website in question, we agreed to the following semantics of the various dates related to a node (in our case, blog posts):

* **Creation date**: The date the note was created.
* **Changed date**: The date when any of the node's modifiable settings were changed.
* **First publication**: The date the node was first published (using Drupal module Publication Date).
* **Publication date**: The date a new revision of the node has been created - in other words, the *current revision's date*.

In rendering the content, all is well when using `node.getRevisionCreationTime` for the publication date in the relevant twig templates and display modes.

However, I what certain blocks and views to order the blog posts by publication date as defined above.

I fail to find the right settings when defining the view - I find the Views user interface incredibly complicated and not intuitive at all. In my (perhaps naive) assumption, using the Content Revision field `Changed` or `Authored on` as sufficient, but I suspect that that doesn't always relates to the *current* revision.

See the attached screenshot on how I have defined the view:

**UPDATE: An example:**

The above view (with some filtering on example name) gives the following result:

Taking a screenshot when editing the node I get this:

So far, so good: Node creation, publication and changed times all match. But look at the "Revision created" and "Revision changed" dates - they match the corresponding node times!

Checking the node's revisions, I see that the current revision's date (which date exactly? Created? Changed? Something else?) is 12 June 2018 - but nowhere to be found in my view - see screenshot:

The revision date 12 June 2018 is the date I want to fetch as the "Publication date" explained above.

How do I do that in a view?

Please help!

TIA, Michel

# Answer
> 0 votes
I found the answer eventually:

The crucial thing to do was to built the query starting with content revisions rather content. Rather unintuitively - creating a relationship the other way around does NOT get you to where you need to get in this situation!

To create a view listing the node's title, creation date, changed date, first publication, and publication date (the creation date of the *current* revision, follow these steps, and then add/remove as required:

1. **Create a view showing** content revisions of type all as follows, creating a page for easier review:
2. **Remove the field** "Content revision: Changed (Changed)" as this is not what we are interested in.
3. **Add a relationship** to Content as seen in the screenshot below:  This is one of the #DrupalWTF moments - where's the crucial documentation that allows me to select the correct relationship!? There are apparently two RDBMS foreign key relationships you can use to join revisions and content:

a. Via content revision foreign key to the id of the node this revision belongs to - this is the *first* content relationship, and

b. Via revision id referenced as foreign key from the content table as current node - this is the *second* content relationship shown above in the screenshot.

For whatever reason you **cannot** reach the creation date of a revision when joining via the first content relationship, #Drupal, #WTF?

Require the relationship for all results, and change the administrative title if you wish:

4. **Add a filter criterion to show only blog posts** The relationship shows revisions for all content types, so we need to filter for content type blog post (Yours may be different). This is pretty straightforward, see the following screenshots:

a. Select the filter criterion:

b. Configure the filter:
5. **Add the various date related fields** This is repetitive; to add the fields select them all in the "Add field" form, and configure them all the same way:

* (Content) Authored on,
    * (Content) Changed,
    * (Content) Published on,
    * (Content revision) Revision create time

Here are the screenshots:  and

Et voila, all fields present as required.

Now you (I) can go to town for formatting and sorting.

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


# Question
Title: Content Moderation: Remove transition from select list programmatically
How do I alter this select list programmatically in my module?

Permissions won't work here since all the roles can use the 'Request publish' transition, but the roles that can also use the 'Published' transition don't need to see 'Request publish'. I think the easiest way to make this change is to remove 'Request publish' from the dropdown list.

I'm working with hook\_field\_widget\_form\_alter()

The code that I'm trying to override is from formElement() in ModerationStateWidget.php.

Thanks.

# Answer
> 1 votes
Thanks @No Sssweat. You put me on the right track.

Since this is the node form, I opted to use hook\_form\_BASE\_FORM\_ID\_alter().

```
/**
 * Implements hook_form_BASE_FORM_ID_alter() for node_form().
 */
function MY_MODULE_form_node_form_alter(&$form, FormStateInterface $form_state) {
  $roles = \Drupal::currentUser()->getRoles();
  if (array_intersect(['role_1', 'role_2', 'role_3'], $roles)) {
    $options = isset($form['moderation_state']['widget']) ? $form['moderation_state']['widget'][0]['state']['#options'] : [];
    $options = array_diff_key($options, [
      'request_publish' => 'Request Publish',
      'request_unpublish' => 'Request unpublish',
      'request_delete' => 'Request Delete'
    ]);
    $form['moderation_state']['widget'][0]['state']['#options'] = $options;
  }
}

```

---
Tags: 8, hooks
---