# Question
Title: How do I add inline JavaScript to the footer?
I want to add third-party JavaScript code at bottom of the every page. I build an module and I am able to add the JavaScript on the head tag, instead of footer.

I am using the following code.

```
function ur_optin_monster_preprocess_html(&$variables) {
  $config = \Drupal::config('ur_form.admin_settings');
  $variables['#attached']['html_head'][] = [
    [
      '#tag' => 'script',
      '#value' => $config->get('my_js'),
      '#weight' => 400,
    ],
    'ur_form_js',
  ];
}

```

I also tried changing `'html_head'` to `'html_scripts'`, but it doesn't help. I tried with the *batrik.theme* file, but it gives the following error.

> Error: Call to undefined function drupal\_add\_js() in bartik\_preprocess\_html() (line 95 of core/themes/bartik/bartik.theme).

```
function bartik_preprocess_html(&$variables) {
  $config = \Drupal::config('ur_form.admin_settings');
  if ($config->get('my_js')) {
    drupal_add_js($config->get('my_js'), array('scope'=>'footer'));
  }
}

```

Can you suggest me the correct way to add JavaScript code at the footer of every page?

# Answer
> 2 votes
Until Add support for inline JS/CSS with #attached is resolved, you should add a JavaScript file normally as a library defined in a MYMODULE.libraries.yml and then pass your module's config as Drupal settings from PHP to this JavaScript file.

```
foobar:
  version: VERSION
  js:
    js/myscript.js: {}
  dependencies:
    - core/jquery
    - core/jquery.once
    - core/drupal
    - core/drupalSettings

```

Then in MYMODULE.module add the JS file and pass the config over to JS.

```
/**
 * Implements hook_page_attachments().
 */
function MYMODULE_page_attachments(array &$attachments) {

  $attachments['#attached']['library'][] = 'MYMODULE/foobar';

  // Pass values from PHP to JS.
  $attachments['#attached']['drupalSettings']['MYMODULE']['lorem'] = \Drupal::config('MYMODULE.settings')->get('lorem');
  $attachments['#attached']['drupalSettings']['MYMODULE']['ipsum'] = \Drupal::config('MYMODULE.settings')->get('ipsum');
}

```

Then in the JS file access them like following.

```
(function($, Drupal) {
  'use strict';
  Drupal.behaviors.MyBehavior = {
    attach: function(context, settings) {

      $('html').once('MyBehavior').each(function() {

        var lorem = settings.MYMODULE.lorem;
        var ipsum = settings.MYMODULE.ipsum;

        // Do whatever you need to do.
        // ...

      });
    }
  };
})(jQuery, Drupal);

```

---

I just found Inline JavaScript that is in an integration module in the docs. But it also says

> **Using any inline JavaScript is highly discouraged**. If you can use one of the examples above, please consider those before attempting to do this.

---
Tags: 8, javascript
---


# Question
Title: How do you rename the machine name of a content type?
I have this content-type that i created titled: "Engineering".

1500 hundred nodes later management wants me to rename it : "Staff". I can easily rename the label but how do i rename the machine name? Does anyone have any success renaming a content-type machine name that is loaded with content/revision and relationships?

It is sometimes impossible to predict these kind of changes. How do we rename the machine name a a content-type.

i have tried the instructions from this article below : https://medium.com/@philw\_/how-to-change-a-content-type-s-machine-name-in-drupal-8-33fc3c0520dc with no success.

> Error: bundle name cannot be changed.

I will be trying the following:

export the database out. find and replace the old content-type machine name with the new name I will also rename any tables named after the content type in the process re-import the db I will see how that works out.

# Answer
I disagree with most of the comments above simply stating: don't change the bundle machine name. These don't answer the poster's question.

This was a simple task in Drupal 7; but due to the added complexities in Drupal 8 it was decided to attempt to remove this ability. See this issue for history:

#2172843 Remove ability to update entity bundle machine names.

That being said, if you do a database search/replace on the machine name this should do what you are looking for - BUT beware, some of those machine names are embedded in serialized data (e.g. key\_value table) and you will need to modify the json string size if the machine name you are replacing is a different length than the new name.
> 4 votes

# Answer
1. Leave the machine\_name intact
2. Create path alias wherever outdated machine\_name is exposed to the end user via the URL.
3. Define custom const in a custom module - name it after "new" machine\_name and set the value to the old machine\_name. Use new const in the code as a replacement for old, incorrect machine\_name.
> -1 votes

---
Tags: 8, nodes
---


# Question
Title: How to allow users to cancel their own account?
I gave the permission `cancel own user account` to authenticated users.

Now they can see a `Cancel account` button on their profile edit.

But when they click on that button, a confirmation form opens. That is fine.

On the confirmation form, when they click on the `Cancel account`, they are redirected to their profile page with a message

`A confirmation request to cancel your account has been sent to your email address.`

I want to change this functionality. When they click on cancel account, they should not receive a confirmation cancellation email. Their account should be deleted immediately and they should be gets logged out.

I tried with this code but it is not working.

`$form['user_cancel_confirm']['#default_value'] = FALSE;`

Is this possible? How can I do this?

# Answer
Seems the Cancel Account Separate Form module does exactly what you want. It provides a form that finally calls `user_cancel` with the current user's UID as parameter.

> This is a very simple, lightweight module that provides cancel user account separate form and adds it to user edit form by default if user has cancel account permissions and edits his own account.
> 0 votes

---
Tags: 8, users
---


# Question
Title: Content tab takes a very long time to load
I have about 350 000 records in node table and about 600 000 in node\_access and domain\_access tables.

When I try to open content tab it takes about a minute to load.

As I found out with Devel module this query takes about 32 seconds to execute:

```
SELECT DISTINCT node.nid          AS nid,
                node.title        AS node_title,
                node.language     AS node_language,
                history.timestamp AS history_timestamp,
                node.created      AS node_created,
                node.changed      AS node_changed,
                node.type         AS node_type,
                users_node.name   AS users_node_name,
                users_node.uid    AS users_node_uid,
                node.status       AS node_status
FROM node node
         LEFT JOIN users users_node ON node.uid = users_node.uid
         LEFT JOIN taxonomy_index taxonomy_index ON node.nid = taxonomy_index.nid
         LEFT JOIN taxonomy_term_data taxonomy_term_data_node ON taxonomy_index.tid = taxonomy_term_data_node.tid
         LEFT JOIN history history ON node.nid = history.nid AND history.uid = :views_join_condition_
ORDER BY node_changed DESC
LIMIT 50 OFFSET 0

```

And this one takes 20 seconds:

```
SELECT COUNT(*) AS expression
FROM (SELECT DISTINCT node.nid          AS nid,
                      node.title        AS node_title,
                      node.language     AS node_language,
                      history.timestamp AS history_timestamp,
                      node.created      AS node_created,
                      node.changed      AS node_changed,
                      node.type         AS node_type,
                      users_node.name   AS users_node_name,
                      users_node.uid    AS users_node_uid,
                      node.status       AS node_status,
                      1                 AS expression
      FROM node node
               LEFT JOIN users users_node ON node.uid = users_node.uid
               LEFT JOIN taxonomy_index taxonomy_index ON node.nid = taxonomy_index.nid
               LEFT JOIN taxonomy_term_data taxonomy_term_data_node ON taxonomy_index.tid = taxonomy_term_data_node.tid
               LEFT JOIN history history ON node.nid = history.nid AND history.uid = :views_join_condition_1) subquery

```

I tested the first query and found out that the ORDER\_BY causes the slowness.

Is there any way to make it fast?

# Answer
I am not exactly sure if it is the best solution but it works for me. I changed default nodes view to use GROUP BY (without any aggregation function) instead of DISTINCT and it works 40 times faster in my case.
> 0 votes

---
Tags: 7
---


title: Updating Drush with Composer

text:
# Question
Title: Updating Drush with Composer
I've been using Drupal for several years, but only just dipping a toe in with Drush - I've bought an ebook tutorial and working my way through. I've installed Composer, and used it to install Drush. The tutorial book specified a particular build of Drush to install (7.0.0-alpha5). I've navigated to a drupal folder and run

```
drush st

```

to get installation info which works fine. The tutorial explains that you don't have to navigate into the drupal folder to do this, instead using

```
drush --root=PATH-TO-DRUPAL-SITE st

```

however this brings an error:

```
Fatal error: Call to undefined function conf_path()

```

Googling this error suggests this a problem with the version of Drush and to upgrade.

SO I've navigated into the .composer/vendor/drush/drush folder and run composer global update but composer says nothing to update, confirming the version as 7.0.0-alpha5 - I assume this is not the latest 7.x version, so do I need something changing in the composer.json file?

# Answer
> 12 votes
If you want to update your global installations of any package under composer, you can just do this:

`composer global update`

You don't need to navigate to `.composer/vendor/drush/drush`

However: There are a couple of things:

1) Your global composer.json file might have a version constraint.

Check out drush's packagist page: https://packagist.org/packages/drush/drush

That will show you the available release versions of drush.

Edit `~/.composer/composer.json` so that the version constraint for `drush/drush` is higher than the one you have. Probably something like `"~8"`.

Do `composer global update`.

2) It's best practice to install drush per project.

The reasons why are a little complex and might not answer the question here, so I'll just link to an article: https://pantheon.io/blog/composer-vs-drush-make-which-should-you-use

# Answer
> 3 votes
I would add that, depending upon your needs, `composer global update` may not bring you up to the version you need. I had run it, and was only getting to version 8.1.8.

For my needs, I needed 8.1.14, at minimum. Since the latest stable version was 8.1.15 as of now, I simply ran this: `composer require drush/drush:8.1.15`. This ran fine, and then checking by `drush --version`, which registered the proper version then.

# Answer
> 1 votes
To update Drush using composer, navigate to your *project root*, then use

```
composer update drush/drush

```

Note that the method for installing and running Drush has changed pretty significantly (I believe as of the release of Drush 9). Fortunately managing Drush is now much less unique to Drush and much more like what you do with other software.

See the official docs: Install a site-local Drush and Drush Launcher

---
Tags: drush, composer
---


title: How do I modify the breadcrumb?

text:
# Question
Title: How do I modify the breadcrumb?
I want to modify my bread crumb ( remove one link from bread crumb and add one link to bread drumb).

I tried,

```
/**
 * Implements hook_system_breadcrumb_alter().
 */
function modulename_system_breadcrumb_alter(\Drupal\Core\Breadcrumb\Breadcrumb &$breadcrumb, \Drupal\Core\Routing\RouteMatchInterface $route_match, array $context) {
// to get current path and alias
  $current_path = \Drupal::service('path.current')->getPath();
  $result = \Drupal::service('path.alias_manager')->getAliasByPath($current_path);

// get current route name
  $route_name = \Drupal::service('current_route_match')->getRouteName();
// check route is an quickinfo content create in group
  if ($breadcrumb && $route_name == 'entity.group_content.group_node__quickinfo.create_form') {
// get bread crumb links
    $breadcrumb_links = $breadcrumb->getLinks();
// fetch titile of the current path
    $title = \Drupal::service('title_resolver')->getTitle(\Drupal::request(), $route_match->getRouteObject());
    if (!empty($title)) {
// change third link of a breadcrumb
     $breadcrumb_links['2'] = Link::createFromRoute(t('RZ-schnellinfo'), '<none>');
    }
//    set links again
   $breadcrumb->setLinks($breadcrumb_links);
  }
}

```

SetLinks() ==\> work when only bread crumb links doesn't exist, i.e.. we can create new links by using addLinks(). Since we need to remove a link we can use this function .

Then I followed https://www.drupal.org/node/2026025 but I am getting below error.

> exception 'Symfony\Component\DependencyInjection\Exception\LogicException' with message 'Service \[error\] 'xxxxx.breadcrumb\_xxxx\_create' for consumer 'breadcrumb' does not implement Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface.' in

# Answer
As comment said above, you have to implement `Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface`. Here is a working snippet that I use to implement those Breadcrumbs :

It appends a custom routename to all 'Nodes' pages :

```

<?php

namespace Drupal\Your_Module_Namespace\Breadcrumb;

use Drupal;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;

class Your_Module_NamespaceBreadCrumbBuilder implements BreadcrumbBuilderInterface {

  /**
   * {@inheritdoc}
   */
  public function applies(RouteMatchInterface $attributes) {
    $parameters = $attributes->getParameters()->all();
    // I need my breadcrumbs for a few node types ONLY,
    // so it should be applied on node page ONLY.
    if (isset($parameters['node']) && !empty($parameters['node'])) {
      return TRUE;
    }
  }

  /**
   * {@inheritdoc}
   */
  public function build(RouteMatchInterface $route_match) {
    $breadcrumb = new Breadcrumb();
    $breadcrumb->addLink(Link::createFromRoute('Home', '<front>'));

    $node = Drupal::routeMatch()->getParameter('node');
    $node_type = $node->bundle();

    // Put the needed logic here

    // addLink example
    $breadcrumb->addLink(Link::createFromRoute('My Page Name', 'drupal_internal.routename'));
    $breadcrumb->addCacheContexts(['route']);

    return $breadcrumb;
  }
}

```
> 1 votes

# Answer
Above in the start you should use this class .

use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
> 0 votes

---
Tags: breadcrumbs
---


# Question
Title: How to get rid of an extra space in a twig date field template?
I have a twig date field template that has a mysterious extra blank space that I want to remove.

In my twig template, `field--comerce-product--field-ppromotion-enddate.html.twig`, I have the following line:

```
  <div{{ item.attributes.addClass('field--item') }}><span class="green">{{ item.content }}{{ 'TEXT'|trans }}</span></div>

```

Unfortunately, the printed output looks like this:

`2017-12-25 TEXT`

I don't know where the space is coming from.

I am using a similar template for an integer field that has this line:

```
  <div{{ item.attributes.addClass('field--item') }}><span class="discount">{{ item.content }}{{ 'OFF!'|trans }}</span></div>

```

This prints the discount percentage (integer field) and then the word "off" (example: `20%off`)-- there is no space between the percentage and off, which is what I want.

(Why no space? My site actually uses an Asian language that doesn't use spaces.)

So where is this space coming from on the date field? When the date field content is printed, it uses the template `time.html.twig`, but the content of that template is this single line (skipping the comments):

```
<time{{ attributes }}>{{ text }}</time>

```

**EDIT:** Based on the suggested answers, I have tried `{{- foo -}}` to remove the whitespace around the date and text, as well as `{%spaceless%}` to remove other whitespace, but the extra space is still there between the date and the text):

```
  {% spaceless %}
    <div{{ item.attributes.addClass('field--item') }}><span class="green">{{- item.content -}}{{- 'TEXT'|trans -}}</span></div>
  {% endspaceless %}

```

Actual output of this code: `2017年12月25日 TEXT`

Output should be: `2017年12月25日TEXT`

# Answer
> 1 votes
You can also use Trim, if doesn't work please check this answer.

# Answer
> 0 votes
Surround your code in spaceless tags.

```
{% spaceless %}

....

{% endspaceless %}

```

https://twig.symfony.com/doc/2.x/tags/spaceless.html

---
Tags: 8, theming
---


# Question
Title: How do I override the $message value of the UniqueFieldConstraint class?
I am new to Drupal 8 and I have added Core Constraint called "UniqueField" on my custom field "Customer\_no" which is attached user to Entity. Below is that code which I am trying to override error Message but its not working:

```
  function devel_reg_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {

      if ($entity_type->id() == 'user' && isset($fields['field_customer_number_reseller_i'])) {

        $fields['field_custome_no']->addConstraint('UniqueField', []);
        //The below code not setting Custom Error Message
        UniqueFieldConstraint::$message = "Custom Error Message";
      }
    }

```

# Answer
> 4 votes
The message is hard-coded into `UniqueFieldConstraint`. It's a public property, so there may be a way to set it that I don't know about. However, another way to go about it is to extend `UniqueFieldConstraint`, set your own message, and tell the system to use your class instead of the original.

1. Extend the class:

```
namespace Drupal\[MODULE]\Plugin\Validation\Constraint;

use Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldConstraint;

class [MODULE]UniqueFieldConstraint extends UniqueFieldConstraint {
  public $message = 'Something about an @entity_type with a @field_name and value of %value.';
}

```
2. Implement hook\_validation\_constraint\_alter() to swap out the existing constraint for yours:

```
function [MODULE]_validation_constraint_alter(array &$definitions) {
  $definitions['UniqueField']['class'] = '\\Drupal\\[MODULE]\\Validator\\Constraints\\[MODULE]UniqueFieldConstraint';
}

```

Note that `[MODULE]` should be swapped out with the appropriate value, and the class should be placed in the appropriate folder for the given namespace.

**Update:** Or, as 4k4 mentioned, you can add `@Constraint` annotation to the constraint above, creating a new constraint. This new constraint can then be explicitly attached to whatever it is that needs constraining.

Which method to use will depend on whether you want to override the `UniqueFieldConstraint` message any time it is called (the original method I outlined) or whether you want to explicitly attach the constraint to specific items (4k4's method).

---
Tags: users
---


title: How to show only my content?

text:
# Question
Title: How to show only my content?
I want to make a view that only show the content that is made by the user itself. For example, I have a library and it contains all content that I flagged, but I also want to show all content that I made (even if I have not flagged it).

# Answer
Use views **CONTEXTUAL FILTERS**, filter by content author is the current user.

Example:
> 1 votes

---
Tags: views
---


# Question
Title: How to create a role without some permissions an "Authenticated User" has?
I have created a custom role. It automatically receives any permissions given to authenticated users. Is there a way to prevent this from happening?

What I would like to achieve is:

Authenticated user: has permission to edit email address and password

Custom role: doesn't have permission to edit email address and password

Currently on my site, users all have the permission "Authenticated user". I would like some new users to have the "Custom role".

The answer to this question: How can i create a user without role authenticated user role suggests to instead edit the "Authenticated user role" and swap the "Custom role" to being the one with more permissions.

So instead I would have to have:

"Authenticated user": doesn't have permission to edit email address and password.

"Custom role": has permission to edit email address and password.

BUT if I do this then all of the current users will no longer be able to edit their email address and password, as they will still be "Authenticated Users", and updating each user to the new role would require entering their password (which I can't do).

Note: I would still like all users to be able to edit other fields such as "First Name".

# Answer
> 1 votes
I don't think you can do that. The authenticated is the mimialist role with the lowest permissions.

You give it the Minimal permissions then make other roles with added permissions to the authenticated.

---
Tags: 8, users
---


# Question
Title: How to add library to Paragraph bundle using hook_preprocess_theme?
I wanted to add a library to a specific paragraph bundle. I know I can do `{{ attach_library('my_theme/my-library-name') }}` using twig, but that means I have to create a file for each bundle. The goal is to be able to use just the `my_theme.theme` file to add the library.

**Question**

How to add library to Paragraph bundle using hook\_preprocess\_theme?

Here is what we tried, but it didn't work even after cache clear.

```
function mytheme_preprocess_paragraphs(&$variables) {
  $elements = $variables['elements'];
  $paragraph = $elements['#paragraph'];
  if(isset($paragraph) {
    $paragraph_bundle = $paragraph->getParagraphType()->id();
    switch($paragraph_bundle) {
      case 'my_bundle':
        $variables['elements']['#attached']['library'][] = 'my_theme/my-library-name';
        break;
    }
  }
}

```

# Answer
> 7 votes
You need to set `$variables['#attached']['library']` instead of `$variables['elements']['#attached']['library']`.

The code shown in the question becomes the following one.

```
function mytheme_preprocess_paragraphs(&$variables) {
  $elements = $variables['elements'];
  $paragraph = $elements['#paragraph'];

  if (isset($paragraph)) {
    $paragraph_bundle = $paragraph->getParagraphType()->id();
    switch($paragraph_bundle) {
      case 'my_bundle':
        $variables['#attached']['library'][] = 'my_theme/my-library-name';
        break;
    }
  }
}

```

---
Tags: 8, theming, hooks, paragraphs
---


# Question
Title: Is Entity Translation module compatible with Internationalization and can they be used to translate menus?
I installed the `entity translation` module for Drupal 7 and it works fine.

However, I also want to translate menus and I found that `Internationalization` module can do that.

The question is: are they compatible at all? If I install `internationalization` module will it not break the `entity translation` one?

# Answer
Yes, they are compatible.

Entity Translation deals with entity translations, and menus in Drupal 7 are not entities, there's no clash between Entity Translation and Internationalization modules.
> 0 votes

---
Tags: 7, i18n-l10n
---


# Question
Title: What hook to alter the result of a view?
In a custom module, I have a custom entity for which a view shows the following values:

*Contact* is the ID of another entity (Person) containing some fields, such as *Email*. *Adresse courriel* is a *Custom text* field defined in the view.

What hook should I use to achieve the following task?

1. Query the *Person* entity with the *Contact* value to retrieve the *Email* field value
2. Update *Adresse courriel* in the view output

# Answer
I added this to `MemberViewsData.php`:

```
class MemberViewsData extends EntityViewsData
{
  /**
   * {@inheritdoc}
   */
  public function getViewsData()
  {
    $data = parent::getViewsData();

    // Additional information for Views integration, such as table joins, can be
    // put here.
    $data['member']['contact_id'] = array(
      'title' => t('Contact Id'),
      'relationship' => array(
        'base' => 'person',
        'base field' => 'id',
        'handler' => 'views_handler_relationship',
        'label' => t('Member to Person (Contact)'),
        'title' => t('Person (Contact)'),
        'id' => 'standard',
      ),
    );
    return $data;
  }
}

```

Then I could use Views UI, adding a 'Relation' from Member (main entity of my view) to Person. And here it is:
> 1 votes

# Answer
1- Firstly you need to add a relationship to the Person entity to have the fields available.

2- then use `hook_views_query_alter()` to change the fields values.
> 1 votes

---
Tags: views, 8
---


title: drupalSettings value is undefined

text:
# Question
Title: drupalSettings value is undefined
I am trying to call a JavaScript function when I click on a button in a form. I have multiple buttons in a for loop and I have attached the library to all those buttons. (Not sure whether this is a correct way or not) I also need to pass some values to the JavaScript function depending on the button pressed, which I am passing using drupalSettings. **The issue is for the first button the value is passed and I can print it. For the second button, it is not passed. I guess the JavaScript is not called for the second form element.**

buildForm Code:

```
$levels = 2;
$level_labels_array = ['chapter', 'sloka'];
for ($l = 1; $l <= $levels; $l++) {
  $levelName = strtolower($level_labels_array[$l-1]);
  $textOnButton = '';
  for ($k = 1; $k <= $l; $k++) {
    $textOnButton = $textOnButton . '>';
  }
  $label = $levelName . '_next_navigation';

  $wrapper = $levelName . '_wrapper';
  $form[$label] = [
    '#type' => 'html_tag',
    '#tag' => 'input',
    '#attributes' => [
      'type' => 'button',
      'value' => $this->t($textOnButton),
      'class' => 'button',
      'name' => $this->t($label),
    ],
    '#attached' => [
      'library' => [
        'heritage_ui/heritage_ui_library',
      ],
    ],
  ];
  $form[$label]['#attached']['drupalSettings']['nav'] = $label;
  $form[$label]['#attached']['drupalSettings']['navLevel'] = $levelName;
}

```

JavaScript function:

```
(function($, Drupal, drupalSettings) {
Drupal.behaviors.navigation_levels = {
  attach: function (context, settings) {
    var navLabel = drupalSettings.nav;
    var navLevel = drupalSettings.navLevel;
    console.log(navLevel);
    // Attach a click listener to the nav button.
    var navBtn = document.getElementsByName(navLabel);
    if (navBtn.length != 0) {
        for (i = 0; i < navBtn.length; i++) {
            navBtn[i].addEventListener('click', function() {
                console.log("entered");
                var navLevelElement = document.getElementsByName(navLevel);
                if(navLevelElement.length != 0) {
                    $(navLevelElement[0]).trigger('change');
                }
                // Do something!
                console.log('Nav button clicked!');
            }, false);
        }
    }
  }
};})(jQuery, Drupal, drupalSettings);

```

**Question edited for better clarification**

# Answer
I am guessing that you need to set your `heritage_ui/heritage_ui_library` library to have a dependency on `core/drupalSettings`.

Note that looking at your code, you should also add a dependency upon `core/jquery.once`, and spend a bit of time learning how to use $.once(). This is because Drupal.behaviors is called often, so your code will be run multiple times unnecessarily (and potentially with problems). You can read more here: https://www.drupal.org/docs/8/api/javascript-api/javascript-api-overview
> 3 votes

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


# Question
Title: How do I set a redirect to custom 403 and 404 pages?
What I am trying to do is redirecting users to a custom page, instead of showing the standard error message, when a 403 or 404 error happens.

I tried to use /error/404 on the *Base site settings* page and create a node with that path alias, but it didn’t work. When I try to access some random URL, it still shows a standard error message, not the /error/404 node.

Did I misunderstand how the feature work? Should I try another approach?

# Answer
> 2 votes
This is build in to Drupal and the simple way to do this is to create separate pages for both error codes and add your own wording as necessary.

Then go to the error pages section of site settings at /admin/config/system/site-information and add the path of your custom error pages.

---
Tags: 8
---


# Question
Title: How do I programmatically add a "Load More" button?
I am trying to add the "Load More" button in the block view programmatically.

Initially, I am loading the 9 contents but when clicking on the button next 9 contents should load from view.

How can I achieve this?

# Answer
> 4 votes
You can try one of these two modules:

* Views infinite scroll
> Views infinite scroll allows you to load and display pages of any view inline, using AJAX (this has been called infinite scrolling, load more, autopaging, endless pages and more). The pager can be triggered with the press of a button or automatically as the user scrolls to the bottom of the view's content.
* Views load more

> Yes, this is indeed, Yet another load more pager for views.
>
> This module has some very key differences then the other load more module.
>
> + Provide ajax/no-ajax views load more
>     + Works with views default ajax implementation, no hacks (check/uncheck ajax)
>     + Supports the Waypoints module for loading on various points, Such as when the scroller is visable on the page.
>     + Supports the Fade effect when loading new content

---
Tags: 7, views
---


# Question
Title: 'Edit' tab does not appear on user's account page?
On my site when a user navigates to their account page there is no 'Edit' button for them to be able to edit their details. From the documentation online it seems this should appear automatically.

Is there any way this could have been disabled by accident or are there any modules that could have interfered with it?

A user is able to edit their profile if they add /edit to the link to their profile page, so it is not that they don't have the 'edit' permission - they definitely do and are able to edit their details successfully if they go to this link.

# Answer
> 3 votes
Oceanescence, some times people have disabled or moved the tabs block. If you are using a custom theme try switching to Bartik and see if it pops up.

If not try digging into the permissions. Just log in as Admin 1 and see if the tabs show up.

---
Tags: 8, users
---


title: PostgreSQL unbuffered query

text:
# Question
Title: PostgreSQL unbuffered query
I am producing large query results that can exceed a sizable PHP memory limit (128 Mb). I've been trying to address this and came across unbuffered queries. Unfortunately, these only seem to be supported by MYSQL while I'm using PostgreSQL. There does seem to be a similar process for PostgreSQL involving cursors, but I'm unsure how to implement them within the Drupal framework using db\_query(). Demo implementation with plain PHP can be found here.

My alternative solution would be to call a query multiple times with restrictions to LIMIT and OFFSET. Query performance is reasonably good, so this may be a viable solution as well. With this method I have yet to figure out how to divide queries into chunks by memory size. Instead, I would have to use a fixed row range. This could be a problematic approach given rows can significantly differ in size.

# Answer
There are certain cases where `db_query` may not be able to do certain things, and this very well could be one of those cases.

That said, nothing is stopping you from leveraging PDO just like that blog post you linked to.

Here is an example from a project of mine in 2015 in Drupal 7 that performs a function using PDO:

```
/**
 * This takes the provided uploaded file and imports it directly into a temporary table in the database.
 * Drupal has some issues executing the statement, so the PDO class is leveraged with some different options to allow it without error.
 *
 * @param $table_name
 * @param $uri
 */
function populate_mysql_table_with_infile($table_name, $uri) {
  $database = Database::getConnectionInfo()['default'];

  $data_source = 'mysql:host=' . $database['host'] . ';dbname=' . $database['database'];
  $db_user = $database['username'];
  $db_password = $database['password'];

  $connection = new PDO($data_source, $db_user, $db_password,
    array(
      PDO::ATTR_EMULATE_PREPARES => TRUE,
      PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_PERSISTENT
    )
  );

  $statement = $connection->prepare("LOAD DATA LOCAL INFILE '" . drupal_realpath($uri) . "' INTO TABLE " . $table_name . "
    FIELDS TERMINATED BY ','
    LINES TERMINATED BY '\r\n'
    IGNORE 1 LINES");
  $statement->execute();
  $statement->closeCursor();
}

```
> 2 votes

# Answer
If you need a `PDO` object, the object returned from `Database::getConnection()` (the method called from `db_query()`) is an instance of a class that extends the `PDO` class. See the documentation for the `DatabaseConnection` class.

```
abstract class DatabaseConnection extends PDO {
 // ...
}

```

Instead of calling `db_query()`, calls `Database::getConnection('default')`. On the object you get, you can call `setAttribute()` and `prepare()` as described in PostgreSQL unbuffered queries and PHP (cursors).
> 0 votes

---
Tags: 7, database
---


# Question
Title: Custom content entity: can't hide translation details in edit form
I've created a multi-lingual custom content entity using Drupal Console. The basic stuff with editing/viewing works fine, also multi-lingual. But for some reason, I can't hide the "Translation" details form element (the one with the translation meta data) in the entity's edit form.

Screenshot of form display settings:

Screenshot of edit form:

In the config export `core.entity_form_display.chunk.weather_daswetter.default.yml` the translation also is listed correctly in the `hidden` section:

```
id: chunk.weather_daswetter.default
targetEntityType: chunk
bundle: weather_daswetter
mode: default
third_party_settings:
  stuff_from_field_group_module_here: nothing_with_translation
content:
  all_visible_fields_listed_correctly
hidden:
  changed: true
  created: true
  langcode: true
  translation: true
  uid: true

```

Into the blue I've tried relisting the fields from core's ContentTranslationHandler in my own `src/Entity/Chunk.php->baseFieldDefinitions()` and explicitly set them configurable, but this did not help either:

```
/**
 * @ContentEntityType(
 *   id = "chunk",
 *    ...
 *   translatable = TRUE,
 *   ...
 * )
 */
class Chunk extends ContentEntityBase implements ChunkInterface {
  use EntityOwnerTrait;
  use EntityChangedTrait;
  use EntityPublishedTrait;

  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);
    $fields += static::ownerBaseFieldDefinitions($entity_type);
    $fields += static::publishedBaseFieldDefinitions($entity_type);

    // tried adding this, did not help
    if ($fields['content_translation_status']) {
      $fields['content_translation_status']->setDisplayConfigurable('form', TRUE);
    }

    if ($fields['content_translation_outdated']) {
      $fields['content_translation_outdated']->setDisplayConfigurable('form', TRUE);
    }

    if ($fields['content_translation_uid']) {
      $fields['content_translation_uid']->setDisplayConfigurable('form', TRUE);
    }

    if ($fields['content_translation_created']) {
      $fields['content_translation_created']->setDisplayConfigurable('form', TRUE);
    }
  }
}

```

Why doesn't the form display mode control for "Translation" work?

I really want to keep this visible and configurable in the UI and therefore want to avoid using `hook_form_alter`.

UPDATE:
I've tried using hook\_form\_alter, but this doesn't work either:

```

function wt_chunks_form_alter(&$form, $form_state, $form_id) {
  if ($form['#entity_type'] == 'chunk') {
    /** @var $formMode \Drupal\Core\Entity\Entity\EntityFormDisplay */
    $formMode = $form_state->getStorage()['form_display'];
    $hiddenFields = $formMode->get('hidden');
    if (in_array('translation', $hiddenFields)) {
      //code goes into here, but the key 'content_translation'
      //does not exist in the $form array
      $form['content_translation']['#access'] = FALSE;
    }
  }
}

```

# Answer
The `translation` field that you try to disable is not the one containing the metadata.

The translation metadata is generated in `Drupal\content_translation\ContentTranslationHandler` and is automatically applied if following access check is true:

```
'#access' => $this->getTranslationAccess($entity, $new_translation ? 'create' : 'update')->isAllowed(),

```

To solve this problem you can add a checkbox to your entity settings form that allows you to disable the translation.

You will also need to create a custom `TranslationHandler` for you entity.

In the annotations of your entity add this under `handlers`:

```
"translation" = "Drupal\MY_MODULE\MyEntityTranslationHandler",

```

Your custom translation handler can then be something like this:

```
namespace Drupal\MY_MODULE;

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

class MyEntityTranslationHandler extends ContentTranslationHandler {

  public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
    $form = parent::entityFormAlter($form, $form_state, $entity);
    if (// Some condition...) {
      $form['content_translation']['#access'] = FALSE;
    }
  }

}

```

Hope it makes sense.
> 2 votes

# Answer
Just for completeness, here is the working code I acutally use to make the hiding via form display mode functional:

(My custom entity's name is `chunk`)

file `src/Entity/Chunk.php`

```
namespace Drupal\MY_MODULE\Entity;

use ...

/**
 * Defines the Chunk entity.
 *
 * @ContentEntityType(
 *   id = "chunk",
 *   label = @Translation("Chunk"),
 *   ...
 *   handlers = {
 *     ...
 *     "translation" = "Drupal\MY_MODULE\ChunkTranslationHandler",
 *     ...
 *   },
 *   translatable = TRUE,
 *   ...
 * )
 */
class Chunk extends ContentEntityBase implements ChunkInterface {
  ...
  // no special code required here, just notice the translation handler annotation above
  ...

```

file `src/ChunkTranslationHandler.php`

```
namespace Drupal\MY_MODULE;

use Drupal\content_translation\ContentTranslationHandler;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * Defines the translation handler for chunk.
 */
class ChunkTranslationHandler extends ContentTranslationHandler {

  public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
    parent::entityFormAlter($form, $form_state, $entity);
    /** @var $formMode \Drupal\Core\Entity\Entity\EntityFormDisplay */
    $formMode = $form_state->getStorage()['form_display'];
    $hiddenFields = $formMode->get('hidden');
    if (in_array('translation', $hiddenFields) && array_key_exists('content_translation', $form)) {
      $form['content_translation']['#access'] = FALSE;
    }
  }
}

```

This is the same @JDrupal's solution above, but actually uses the form display config of the `Translation` field (i.e. if you move it to the disabled section in the UI, all translation meta data fields are hidden).

If you use Drupal console's `drupal generate:entity:content` you just need to write the custom `entityFormAlter()` function.
> 1 votes

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


title: Hashing function for session

text:
# Question
Title: Hashing function for session
I need to verify the users session of Drupal on a Node.js server. The session ID has been hashed and it is stored in the Drupal 8 database. How can I hash the browsers session ID to compare it with the one stored in the database?

# Answer
> 1 votes
I see that no one has put up an answer for quite a while, so I will put it up here. This has been correctly answered by RaisinBrainCrunch above.

Drupal 8 hashes its session ID before it puts it in the database. The hash function used is `hashBase64($sid)` under `Drupal\Component\Utility\Crypt`.

Therefore, I am guessing you will have to write the same function in Node. This is the full function:

```
public static function hashBase64($data) {
  $hash = base64_encode(hash('sha256', $data, TRUE));
  // Modify the hash so it's safe to use in URLs.
  return str_replace(['+', '/', '='], ['-', '_', ''], $hash);
}

```

---
Tags: 8, sessions
---


# Question
Title: What is the purpose of Translation field in form display mode?
When editing the form display mode of a translatable content entity, there is a field called `Translation` in the UI. I thought this field would manage the weight/visibility of translation meta data fields (like `content_translation_uid` or `content_translation_outdated`) in the entity's edit form.

But moving that field around doesn't have any effect, it neither reorders the position, nore does it hide the Translation `<details>` element when I move it into the disabled section.

So, what is the real purpose of the field `Translation` in `/admin/structure/ENTITY/manage/BUNDLE/form-display` ?

(This is a follow-up of my question Custom content entity: can't hide translation details in edit form)

# Answer
This is an extra field (Drupal term for a pseudo field not stored in the database you can move around in UI), which is added when *Content Translation* is enabled: content\_translation\_entity\_extra\_field\_info()

See this issue:

> **content\_translation\_entity\_extra\_field\_info is obsolete**
>
> **Problem/Motivation**
>
> content\_translation\_entity\_extra\_field\_info is adding the extra field "Translation" but it is not used by content\_translation in the form alter hooks and it only confuses when we are on the form display configuring the fields and reordering it doesn't change anything on the edit page.
>
> **Proposed resolution**
>
> Remove content\_translation\_entity\_extra\_field\_info and remove the "translation" component from all saved form display configs.

https://www.drupal.org/project/drupal/issues/2856551
> 2 votes

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


# Question
Title: I can't get the correct current language in node URLs
In D8, I have a website set up with 5 languages, using file path, like so:

```
 website.com/en/link
 website.com/en-us/link
 website.com/fr-ca/link
 etcetera.

```

I've made a view of blogs and resources. It includes a filter to **current language selected for page** and **Not Specified**-- this is to include articles that are intentionally set to Not Specified, so they show up for ALL languages. ( I don't want to have to turn 1000 blog posts into 4000 duplicates)

Problem is, the view is showing the link to items ONLY in the default language (EN) Regardless of what language I view the website in.

I'm using a hidden "Link to Content" field within a custom field for each item. I've UNchecked 'use absolute url'. I'm not sure what else to do. It doesn't make sense to me that it would be ignoring the site's current language.

If it's relevant, the link within the custom field is written like this:

```
 <a href="{{ view_node }}?title={{ field_file_name }}&type={{field_resource_type}}">{{ title }}</a>

```

I also added in a "Content: Translation language" field, to verify I was looking at the correctly filtered language. the URL uses default language regardless of whether the item's language is specified or not.

Update: I've also ensured the bottom middle column in Views is set like this:

```
 Rendering Language:Content language selected for page

```

This did not solve the problem. As a further test, I've also unchecked 'not defined' in my filter. While filtering to only nodes of the current language selected for page, I Still get URLs to the default language.

Also, the view has been translated into all relevant languages. Not sure how to change how the {{ view\_node }} renders though. I assume it should be programmically pulling the current language when generating a URL. This {{ view\_node }} is where the language is appearing. It seems like it should not be, though. The node alias shouldn't contain the language, I thought.

# Answer
After narrowing down the issue, I think I've stumbled into an actual existing, known issue: Entity Links fields does not have translation support.

https://www.drupal.org/project/drupal/issues/2877994

I still need to figure out how to apply a patch, but I suspect this is actually a duplicate of the above issue.
> 0 votes

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


# Question
Title: Webform Module Email - Module Specific Configuration
We've built a custom web form module to handle the capturing of contact information on our website. We recently came across the Webform module and are thrilled that it has so many different customization options that we're looking to transitioning over to using it across our entire site.

Before making this move we'd like to test it out using a single form on our site that captures some user data and sends it via an email submission. This data would not be stored within the Drupal database.

Our custom form module uses the Mail System and Swift Mailer modules to handle the sending of confirmation emails and we'd like to leverage the same modules when using the Webform module.

Within the Module Specific Configuration section of the Mail System module we've defined the following:

MODULE: Webform KEY: ccpa\_email\_handler FORMATTER: Webform PHP Mailer SENDER: Webform PHP Mailer

I assume that the KEY value needs to be associated with the ID of the Email Handler that was defined for the Webform we've put built.

Unfortunately, when using the Test feature to see what the email looks doesn't seem to be working. When I submit the form I see the inline confirmation message but the email never makes it to my inbox.

I'm sure I've got something misconfigured here but I'm grasping at what it could be. I assume it has to be something with the Mail System and Swiftmailer setup so I'm hoping someone is also using this particular type of setup and could offer some insight as far as the setup and configuration.

# Answer
You say that you use Swift Mailer for your current setup, but for your test setup with Webform, it seems like you use Webform PHP Mailer.

Try to use Swift Mailer instead and see if that works.
> 1 votes

---
Tags: webforms
---


# Question
Title: How to return the whole entity referenced by a entity reference field with views
I have content type A with a entity reference field that references a user (let's name it `field_user_reference`). The user has `field_b` and `field_c` field. I've created a rest export view to return all nodes of type A with it's field which includes `field_user_reference`. My problem now is that the `field_user_reference` exported by views only contains the user's name. How do i also include the user's id, `field_b` and `field_c`?

The view returning something like this would be optimal:

```
[{"nid":"1","title":"title","field_user_reference":[{"uid":"1","name":"username","field_b":"valueb","field_c":"valuec"}]}]

```

# Answer
You have to add a views relationship to the user.

The relationship is usually called something like, `Entity referenced from FIELD_NAME` in your case `User referenced from field_user_reference`.

When you have added the relationship, the user's fields will then appear in the fields list.

For more information about views relationships, look here add a relationship to a view.
> 0 votes

---
Tags: views
---


title: Webform hook field text element

text:
# Question
Title: Webform hook field text element
I Use Drupal 8.8 with Webform 8.x, in a simple webform with a select list element and a text field element, I need to update a text field element with values resulting from database queries when the user chooses an option from the listbox.

I would like to accomplish this with a PHP code in a custom mymodule. How can I intercept the user's action when selecting a value from the select list?

Besides intercepting the event I also need to know the content of the choice that the user has made on the select list.

How can it be done? Can anyone give me an example?

# Answer
> 0 votes
There are more than one way to do what you are asking note both these will require you to create a custom module. (I assume you know how to do this or can google it)

here need to change to your form id, and your field names..

```
function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
    // change to your form id
  if ($form_id == 'webform_submission_contact_add_form') {
    //dump($form['elements']);
    $form['elements']['select_me']['#ajax'] = [
      'callback' => 'MYMODULE_callback_ajax',
      'event' => 'change',
      'wrapper' => 'changethis',
      'method' => 'replace',
    ];

   $form['elements']['TEXTFIELDNAME']['#prefix'] = '<div id="changethis">';
   $form['elements']['TEXTFIELDNAME']['#suffix'] = '</div>';
 }
}
// ajax call back
function MYMODULE_callback_ajax(&$form, FormStateInterface $form_state) {
  $value_selected = $form_state->getValue('select_me');
  if (!empty($value_selected)) {
    // Here do queries then set the value of your text field.

    $form['elements']'TEXTFIELDNAME']['#value'] = $value_selected;
    return $form['elements']'subject'];
  }
}

```

# Answer
> 0 votes
I tried to implement the function but I didn't have much luck. Ok something works, when I go to select the select list and change an option we see that ajax updates but the text field does not change, I get an HTTP 200 error in the browser console.

Initially nothing worked because having the webform a series of multi-step-wizards. Then I realized that I had to modify the access to the array in the hook\_form\_alter, in practice like this:

```
$form['elements']['PAGE_STEP_NAME']['select_list_name']['#ajax'] = [
  'callback' => 'mymodule_callback_ajax',
  'event' => 'change',
  'wrapper' => 'edit-microchip',
  'method' => 'replace',
];
$form['elements']['PAGE_STEP_NAME']['microchip']['#prefix'] = '<div id="edit-microchip">';
$form['elements']['PAGE_STEP_NAME']['microchip']['#suffix'] = '</div>';

```

And the same in the callback function:

```
$form['elements']['PAGE_STEP_NAME']['microchip']['#value'] = $value_selected;
return $form['elements']['PAGE_STEP_NAME']['subject'];

```

link

in this link from the official website of drupal, it is very well explained how to exploit this technology. In particular, it is written that the WRAPPER must be equal to the ID of the object to be modified with the callback. I noticed that the WRAPPER ID in the HTML code is not the same as the one I set in the hook\_form\_alter `edit-microchip`but this id is the same in the first part then there is a random code, maybe it doesn't work for this?

# Answer
> 0 votes
**BINGO SUCCESSFUL :-)**

First thing I found this post LINK where thanks to this user I copied this concept:

> Drupal changes DOM IDs on every submit. You can, however, fix them by adding an attribute specification to your element:

I modified the hook\_alter\_form function code in the following way inserting this line before the last two

```
$form['elements']['PAGE_STEP_NAME']['microchip']['#attributes']['id'] = 'edit-microchip';

```

After this I was surprised to see that the ID in HTML view was no longer the same as before with the name and random number, but exactly as I wanted!

Then I modified the last line of the callback function with this line:

```
return $form['elements']['PAGE_STEP_NAME']['microchip'];

```

Now it works great. I am very satisfied and I thank you @TaggartJensen for showing me the way.

---
Tags: webforms
---


# Question
Title: How do I create a template for custom display mode of user registration form?
I have multiple registration pages, each with corresponding to a form display under admin/config/people/accounts/form-display. I added this to Mytheme.theme

```
function Mytheme_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {

  if ($hook == 'form' & !empty($variables['element']['#id'])) {
    $suggestions[] = 'form__' . str_replace('-', '_', $variables['element']['#id']);
  }
}

```

Then I can create a template form--user-register-form.html.twig but that will affect all the form display modes. Is it a way to create a template for each display mode? For instance for a form display "Allied" something like form--user-registration-form---allied.html.twig ?

# Answer
> 2 votes
If you want to add template by Form mode try the following:

```
/**
 * Implements theme_theme_suggestions_alter().
 */
function YOURTHEME_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if ($hook == 'form' & !empty($variables['element']['#id'])) {
    /** @var \Drupal\Core\Entity\Entity\EntityFormDisplay $form_display */
    $form_display = $variables['element']['#process'][1][0] ?? NULL;
    if ($form_display) {
      $suggestions[] = 'form__' . str_replace('-', '_', $form_display->getMode());
    }
  }
}

```

---
Tags: 8, theming
---


# Question
Title: In views, how do I show posts from this calendar day, ten years ago?
I have a view in which I want to display posts that I made on this *date* 10 years ago. I can get close but not exactly what I want by setting the view's filter to the following:

"Authored On is between: (offset) `-10 year` and `-10 year +1 day`"

My problem is that if it's currently 1pm on Dec. 17, 2019, I want to see all posts from the Dec. 17, 2009, regardless of hour posted. Instead I am seeing posts from Dec. 16, 2009 1pm to Dec. 17, 2009 1pm. I don't care what time the post was authored at, I just want it to show if the **calendar day** from 10 years ago is the same.

How can I set up my filter to do this?

# Answer
> 3 votes
Like you did, create two filters for the date range and then use the following values

```
-10 years midnight
-10 years +1 day midnight

```

Remember to select

```
An offset from the current time such as "+1 day" or "-2 hours -30 minutes"

```

If you want to do this programmatically you can create a date filter and set the actual date values from code for the filter range.

You can create the date filter and set the filter value programmatically like the following

How do I programmatically render a view that has exposed filters?

---
Tags: views, 8, datetime
---


# Question
Title: How to query for a list of tables in a secondary database
I'm working on some Functional tests on a secondary database. Part of the tear down process is to drop tables in the secondary database. How do a make a query like 'show tables' where I can iterate through them and conditionally drop a table when I want to? I've got a connection to the database, like this:

```
$conn = Database::getConnection('default', 'civicrm_test');
$database = $conn->getConnectionOptions()['database'];

```

I was looking at Connection-\>query() but it doesn't seem to return the results? Is there a different way to get the list of tables so I can return them and act on them individually?

# Answer
> 0 votes
```
$conn = Database::getConnection('default', 'civicrm_test');
$database = $conn->getConnectionOptions()['database'];
$conn->query("SET FOREIGN_KEY_CHECKS = 0");
$tables = $conn->query('SHOW TABLES')->fetchAll();
foreach ($tables as $table_result) {
  $table = $table_result->{"Tables_in_$database"};
  $conn->query("DROP TABLE $table");
}
$conn->query("SET FOREIGN_KEY_CHECKS = 1");
$conn->destroy();

```

I only needed to disable/enable foreign key checks, because I needed to. Others may not need to.

---
Tags: 8, database
---


# Question
Title: How to Allowed Options for BaseFieldDefinition on Custom Entity
I'm trying to access the allowed options on a custom entity's field that I created. (see code below) Is there a way to access this?

One field I would like to access, for example, is...
`$fields['category'] = BaseFieldDefinition::create('list_string')`

Is there a way to get this information without loading a particular entity instance?

```
<?php

namespace Drupal\customers\Entity;

use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityChangedTrait;
use Drupal\Core\Entity\EntityPublishedTrait;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\user\UserInterface;

/**
 * Defines the Customer entity.
 *
 * @ingroup customers
 *
 * @ContentEntityType(
 *   id = "customer_entity",
 *   label = @Translation("Customer"),
 *   handlers = {
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "list_builder" = "Drupal\customers\CustomerEntityListBuilder",
 *     "views_data" = "Drupal\customers\Entity\CustomerEntityViewsData",
 *
 *     "form" = {
 *       "default" = "Drupal\customers\Form\CustomerEntityForm",
 *       "add" = "Drupal\customers\Form\CustomerEntityForm",
 *       "edit" = "Drupal\customers\Form\CustomerEntityForm",
 *       "delete" = "Drupal\customers\Form\CustomerEntityDeleteForm",
 *     },
 *     "route_provider" = {
 *       "html" = "Drupal\customers\CustomerEntityHtmlRouteProvider",
 *     },
 *     "access" = "Drupal\customers\CustomerEntityAccessControlHandler",
 *   },
 *   base_table = "customer_entity",
 *   translatable = FALSE,
 *   admin_permission = "administer customer entities",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "name",
 *     "uuid" = "uuid",
 *     "uid" = "user_id",
 *     "langcode" = "langcode",
 *     "published" = "status",
 *   },
 *   links = {
 *     "canonical" = "/admin/content/customer_entity/{customer_entity}",
 *     "add-form" = "/admin/content/customer_entity/add",
 *     "edit-form" = "/admin/content/customer_entity/{customer_entity}/edit",
 *     "delete-form" = "/admin/content/customer_entity/{customer_entity}/delete",
 *     "collection" = "/admin/content/customer_entity",
 *   },
 *   field_ui_base_route = "customer_entity.settings"
 * )
 */
class CustomerEntity extends ContentEntityBase implements CustomerEntityInterface {

  use EntityChangedTrait;
  use EntityPublishedTrait;

  /**
   * {@inheritdoc}
   */
  public static function preCreate(EntityStorageInterface $storage_controller, array &$values) {
    parent::preCreate($storage_controller, $values);
    $values += [
      'user_id' => \Drupal::currentUser()->id(),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getName() {
    return $this->get('name')->value;
  }

  /**
   * {@inheritdoc}
   */
  public function setName($name) {
    $this->set('name', $name);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getCreatedTime() {
    return $this->get('created')->value;
  }

  /**
   * {@inheritdoc}
   */
  public function setCreatedTime($timestamp) {
    $this->set('created', $timestamp);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getOwner() {
    return $this->get('user_id')->entity;
  }

  /**
   * {@inheritdoc}
   */
  public function getOwnerId() {
    return $this->get('user_id')->target_id;
  }

  /**
   * {@inheritdoc}
   */
  public function setOwnerId($uid) {
    $this->set('user_id', $uid);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setOwner(UserInterface $account) {
    $this->set('user_id', $account->id());
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);

    // Add the published field.
    $fields += static::publishedBaseFieldDefinitions($entity_type);

    $fields['user_id'] = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('Authored by'))
      ->setDescription(t('The user ID of author of the Customer entity.'))
      ->setRevisionable(TRUE)
      ->setSetting('target_type', 'user')
      ->setSetting('handler', 'default')
      ->setDisplayOptions('view', [
        'label' => 'hidden',
        'type' => 'author',
        'weight' => 0,
      ])
      ->setDisplayOptions('form', [
        'type' => 'entity_reference_autocomplete',
        'weight' => 5,
        'settings' => [
          'match_operator' => 'CONTAINS',
          'size' => '60',
          'autocomplete_type' => 'tags',
          'placeholder' => '',
        ],
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields['name'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Name'))
      ->setSettings([
        'max_length' => 50,
        'text_processing' => 0,
      ])
      ->setDefaultValue('')
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -4,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setRequired(TRUE);

    $fields['email'] = BaseFieldDefinition::create('email')
      ->setLabel(t('Email'))
      ->setSettings([
        'max_length' => 50,
        'text_processing' => 0,
      ])
      ->setDefaultValue('')
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -4,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setRequired(TRUE);

    $fields['phone'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Phone'))
      ->setSettings([
        'max_length' => 50,
        'text_processing' => 0,
      ])
      ->setDefaultValue('')
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -4,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setRequired(TRUE);

    $fields['state'] = BaseFieldDefinition::create('list_string')
      ->setSettings([
        'allowed_values' => [
          'AL' => 'Alabama',
          'AK' => 'Alaska',
          'AZ' => 'Arizona',
          'AR' => 'Arkansas',
          'CA' => 'California',
          'CO' => 'Colorado',
          'CT' => 'Connecticut',
          'DE' => 'Delaware',
          'DC' => 'District of Columbia',
          'FL' => 'Florida',
          'GA' => 'Georgia',
          'HI' => 'Hawaii',
          'ID' => 'Idaho',
          'IL' => 'Illinois',
          'IN' => 'Indiana',
          'IA' => 'Iowa',
          'KS' => 'Kansas',
          'KY' => 'Kentucky',
          'LA' => 'Louisiana',
          'ME' => 'Maine',
          'MD' => 'Maryland',
          'MA' => 'Massachusetts',
          'MI' => 'Michigan',
          'MN' => 'Minnesota',
          'MS' => 'Mississippi',
          'MO' => 'Missouri',
          'MT' => 'Montana',
          'NE' => 'Nebraska',
          'NV' => 'Nevada',
          'NH' => 'New Hampshire',
          'NJ' => 'New Jersey',
          'NM' => 'New Mexico',
          'NY' => 'New York',
          'NC' => 'North Carolina',
          'ND' => 'North Dakota',
          'OH' => 'Ohio',
          'OK' => 'Oklahoma',
          'OR' => 'Oregon',
          'PA' => 'Pennsylvania',
          'RI' => 'Rhode Island',
          'SC' => 'South Carolina',
          'SD' => 'South Dakota',
          'TN' => 'Tennessee',
          'TX' => 'Texas',
          'UT' => 'Utah',
          'VT' => 'Vermont',
          'VA' => 'Virginia',
          'WA' => 'Washington',
          'WV' => 'West Virginia',
          'WI' => 'Wisconsin',
          'WY' => 'Wyoming',
        ]
      ])
      ->setLabel('State')
      ->setRequired(TRUE)
      ->setCardinality(-1)
      ->setDisplayOptions('form', array(
        'type' => 'options_buttons',
        'weight' => -4,
      ))
      ->setDisplayConfigurable('form', TRUE);

    $fields['territory'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Territory'))
      ->setDescription(t('If applicable, which part of the state does this customer serve?<br/>(e.g., North Louisiana, Middle and E Tennessee, Mississippi - South, etc.)'))
      ->setSettings([
        'max_length' => 50,
        'text_processing' => 0,
      ])
      ->setDefaultValue('')
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -4,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setRequired(FALSE);

    $fields['category'] = BaseFieldDefinition::create('list_string')
      ->setSettings([
        'allowed_values' => [
          'stairtreads_risers' => 'Stairtreads & Risers',
          'exterior_door_sills_frames' => 'Exterior Door Sills & Frames',
        ]
      ])
      ->setLabel(t('Product Category'))
      ->setSettings([
        'max_length' => 50,
        'text_processing' => 0,
      ])
      ->setDefaultValue('')
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -4,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setRequired(TRUE)
      ->setCardinality(-1)
      ->setDisplayOptions('form', array(
        'type' => 'options_buttons',
        'weight' => -4,
      ))
      ->setDisplayConfigurable('form', TRUE);

    $fields['type'] = BaseFieldDefinition::create('list_string')
      ->setSettings([
        'allowed_values' => [
          'homeowner' => 'I am a Homeowner',
          'contractor' => 'I am a Contractor',
          'retail_dealer' => 'I am a Retail Dealer',
          'distributor' => 'I am a Distributor',
        ]
      ])
      ->setLabel(t('Customer Type'))
      ->setSettings([
        'max_length' => 50,
        'text_processing' => 0,
      ])
      ->setDefaultValue('')
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ])
      ->setDisplayOptions('form', [
        'type' => 'string_textfield',
        'weight' => -4,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE)
      ->setRequired(TRUE)
      ->setCardinality(-1)
      ->setDisplayOptions('form', array(
        'type' => 'options_buttons',
        'weight' => -4,
      ))
      ->setDisplayConfigurable('form', TRUE);

    $fields['status']->setDescription(t('A boolean indicating whether the Customer is published.'))
      ->setDisplayOptions('form', [
        'type' => 'boolean_checkbox',
        'weight' => 51,
      ]);

    $fields['created'] = BaseFieldDefinition::create('created')
      ->setLabel(t('Created'))
      ->setDescription(t('The time that the entity was created.'));

    $fields['changed'] = BaseFieldDefinition::create('changed')
      ->setLabel(t('Changed'))
      ->setDescription(t('The time that the entity was last edited.'));

    return $fields;
  }

}

```

# Answer
> 0 votes
You can do this:

```
$allowed_states = \Drupal::service('entity_field.manager')
   ->getBaseFieldDefinitions('customer_entity')['state']
   ->getSetting('allowed_values');

```

# Answer
> 2 votes
Base fields can be added or modified by hooks. To get the active base field definitions use EntityFieldManager::getBaseFieldDefinitions:

```
$base_fields = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions('customer_entity');

```

---
Tags: 8, entities
---


# Question
Title: Is there a way to mock a procedural function from common.inc in a test without an external library?
I am trying to mock the `render()` function from `common.inc` in a test.

I am aware that `render()` could be substituted with a `renderer` service, but in this specific case I can't/couldn't refactor the code itself. Nor can I use an external lib for it.

Is there a way to do this in a native way, using PHPUnit only?

# Answer
I have found a solution on this page: https://www.drupal.org/docs/8/phpunit/unit-testing-more-complicated-drupal-classes

> You can mock a global function by adding fixtures in your test module. Let's say that you need to mock base\_path().
>
> 1. Simple go add a fixture in your testing src
> 2. Add a mock for function, for example, you can define like above:
> 3. Simply use `require_once` on your setup and you get your mocked function available and replaceable only in the test you are requiring. Make sure to use `function_exists()` to check if the function you need to test isn't already available.

```
 /**
  * Overrides global function if not exists.
  *
  * @return string
  *   Base path mocked.
  */
  function base_path() {
    if (!function_exists('base_path')) {
      return '/';
    }
  }

```

In my case, I have used fixtures, as refactoring the code was out of question.

As the documentation says, I've created a mocked function in `tests/fixtures/function_name.php` and included the file into the `setUp()` method of the test with `require_once`. This way, I've had my own global function in the test's scope.
> 2 votes

# Answer
Yes, this is possible and done in a handful of places in core. One example is `TimeTest`. I am not 100% sure it is official, but I call it a shadow function.

The trick is to declare the procedural function in the same namespace as the caller. As an example the `Drupal\Component\Datetime\Time` class has a method

```
public function getCurrentTime() {
  return time();
}

```

this calls out the PHP internal function `time()`. `TimeTest` sets up

namespace Drupal\Component\Datetime;

```
/**
 * Shadow time() system call.
 *
 * @returns int
 */
function time() {
  return 12345678;
}

```

When PHP chases the scope for resolving a reference, it will check the current namespace first. By declaring the namespace, the procedural function declaration ends up that namespace instead of the global one (`\`). And since the test class only gets loaded during tests, you don't end up polluting the namespace with a bad function.
> 2 votes

---
Tags: 8, testing
---


# Question
Title: How do you add help text to a form item?
I would like to change the help text for an input field. My form ID is `views-exposed-form-events-page-1`. I have a text field that I want the helpful hint to appear below. The field ID is `edit-field-event-date-value2`, I think, based on the HTML.

```
<div id="edit-field-event-date-value2-wrapper" class="views-exposed-widget views-widget-filter-field_event_date_value2">
<label for="edit-field-event-date-value2">
From </label>
<div class="views-widget">
<div id="edit-field-event-date-value2-value-wrapper">
<div id="edit-field-event-date-value2-value-inside-wrapper">
<div  class="container-inline-date"><div class="form-item form-item-field-event-date-value2-value form-type-date-popup form-group">
<div id="edit-field-event-date-value2-value"  class="date-padding"><div class="form-item form-item-field-event-date-value2-value-date form-type-textfield form-group">
<input class="form-control form-text" type="text" id="edit-field-event-date-value2-value-datepicker-popup-0" name="field_event_date_value2[value][date]" value="18/12/2019" size="20" maxlength="30" />
<label class="control-label element-invisible" for="edit-field-event-date-value2-value-datepicker-popup-0">Date</label>
<div class="help-block"> E.g., 18/12/2019</div>

```

I thought that this would work, but I'm not seeing any help text appearing under the form field.

```
function mytheme_form_views_exposed_form_events_page_1_alter(&$form, &$form_state, $form_id) {
  $form['edit-field-event-date-value2']['#attributes']['description'] = 'DD/MM/YYYY';
}

```

What am I doing wrong?

# Answer
> 1 votes
The description doesn't live under `#attributes`, but under the element directly.

So you must do something like this to get it to work:

```
$form['field_event_date_value2']['#description'] = 'DD/MM/YYYY';

```

The HTML class is not the fieldname, but rather something like `field_event_date_value2` in your case.

If that is not the correct fieldname, you can try to `print_r(array_keys($form))` to see if you can see what the correct name is.

---
Tags: 7, forms
---


# Question
Title: Add a Radio-button with other option in comment type
I have the following requirement in Drupal 8:

I have to create a comment type with options. In options there will be a Other option on whose click a text field will be opened.

something like below image:

How can i achieve the showing of text box on other option selection in comment type?

# Answer
I think you need to do this in a `hook_form_alter`.

I have written some example code that you can use. The code is probably not 100% correct, but it's intended to help you, to get an idea of how to solve the problem.

```
function MY_MODULE_form_alter(&$form, \Drupal\Core\Form\FormStateInterface  $form_state, $form_id) {
  $form['radios_field']['#ajax'] = [
    'callback' => 'MY_MODULE_radios_field_callback',
    'event' => 'change',
    'wrapper' => 'radio-field-wrapper',
  ];

  if ($form_state->getValue('radiois_field') == 'other') {
    // Field to show when options is "Other".
    $form['textfield'] = [
      '#type' => 'textfield',
      '#attributes' => [
        'id' => 'radio-field-wrapper',
      ],
    ];
  }
}

function MY_MODULE_radios_field_callback(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  $form_state->setRebuild();
  return $form['radios_field'];
}

```
> 0 votes

---
Tags: 8, comments
---


# Question
Title: How to discard unsaved changes to a view when editing it leads to a WSOD?
This is one of those times when I tried to add something and realized that I've got it applied to all displays. This time it was a vocabulary filter, so I clicked cancel and it didn't register so I clicked back to site.

After that I tried to edit and it returned

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

The log shows this:

> Exception: No entity type for field vid on view VIEW in Drupal\views\Plugin\views\HandlerBase-\>getEntityType() (line 712 of /PATH/core/modules/views/src/Plugin/views/HandlerBase.php).

I checked the active config and couldn't find anything with a vid. Clearing cache and reimporting the view config didn't fix it. So, is there a way?

# Answer
> 15 votes
A quick fix would be to delete the data from the expirable key/value store:

```
\Drupal::keyValueExpirable('tempstore.shared.views')
  ->delete('view_id');

```

Alternatively you could wait a week until it expires itself - probably not practical :)

# Answer
> 0 votes
Agree with @Clive answer here, you can delete that particular row in the table 'key\_value\_expire'. Here is the sample:

* viewName: homepage\_slider
* Then first check if that view exists in the table anywhere using the SQL command:
* select * from key\_value\_expire where name='homepage\_quote\_slider';
* if it shows the data then run the below command:
* delete from key\_value\_expire where name='homepage\_quote\_slider';
* Go back to your view and refresh it couple of times if it's still showing an error.

---
Tags: views, 8
---


title: How do I programmatically empty a cart?

text:
# Question
Title: How do I programmatically empty a cart?
I want to empty the cart before a product in the code. I tried

`$this->cartProvider->emptyCart($cart);`

But this did not work and gave an error. I am doing this in Drupal 8. I am adding products in the controller code.

This is how I am fetching the cart.

```
$destination = \Drupal::service('path.current')->getPath();
   $productObj = Product::load($productId);

   $product_variation_id = $productObj->get('variations')
     ->getValue()[0]['target_id'];
   $storeId = $productObj->get('stores')->getValue()[0]['target_id'];
   $variationobj = \Drupal::entityTypeManager()
     ->getStorage('commerce_product_variation')
     ->load($product_variation_id);
   $store = \Drupal::entityTypeManager()
     ->getStorage('commerce_store')
     ->load($storeId);

     $cart = $this->cartProvider->getCart('default', $store);

     $this->cartManager->emptyCart($cart);

   if (!$cart) {
    $cart = $this->cartProvider->createCart('default', $store);

   }

   $line_item_type_storage = \Drupal::entityTypeManager()
     ->getStorage('commerce_order_item_type');
// Process to place order programatically.
   $cart_manager = \Drupal::service('commerce_cart.cart_manager');
   $line_item = $cart_manager->addEntity($cart, $variationobj);

    $response = new RedirectResponse(Url::fromRoute('commerce_cart.page')->toString());
    return $response;

```

# Answer
> 4 votes
You must use the `commerce_cart.cart_manager` service instead.

So `$this->cartManager->emptyCart($cart);` should do the trick.

**Update:** The reason why you get an error is because you try to call `emptyCart` on `$cart` then it's NULL.

You must wrap the line where you empty the cart in an if statement, like this:

```
if (!empty($cart)) {
  $this->cartManager->emptyCart($cart);
}

```

---
Tags: 8, commerce
---


# Question
Title: How do I compare fields in a database query?
Given the query fragment:

```
$query = $connection->select('mytable', 't');
$query->addField('t', 'myfield1', 'myfield1');
$query->addField('t', 'myfield2', 'myfield2');

```

I need to add a condition like this:

```
$query->condition('t.myfield1', 't.myfield2', '=');

```

But it doesn't seem to work. For comparison, I can use:

```
$query->condition('t.myfield1', 'banana', '=');

```

... and that works. But it seems comparing two fields to see if they match does not work? I can write this out in straight SQL code and properly query the database in a console, but can't duplicate in Drupal's database API.

What am I doing wrong?

# Answer
You must use `where()`, like this:

```
$query = \Drupal::database()->select('mytable', 't')
  ->addField('t', 'myfield1', 'myfield1')
  ->addField('t', 'myfield2', 'myfield2')
  ->where('t.myfield1 = t.myfield2');

```
> 5 votes

---
Tags: 8, database
---


# Question
Title: Sort the products by SKU when seeing order details
I have an Ubercart commerce website in Drupal 7.

I'm trying to sort the products listed inside a given completed order by the SKU value.

This is the link: /admin/store/orders/1 or /admin/store/orders/300

I tried to edit uc-order--admin.tpl.php but it did not work. I tried everything but nothing works. Maybe I'm doing it wrong.

I'm new to theming and templating so the code I wrote or the place I did might have been wrong also.

Any ideas on how to sort the products by the values in the SKU field in an order that was already placed?

Inside `uc-order--admin.tpl.php` I added the following code:

```
$order_output = array();
$order_info = new stdClass();
$order_id = '';

$array_key_modifier = 0;
foreach ($products as $product) {
    // organize products by sku
    // make an array with stuff I need
    // sku => array(item,model,price,quantity,subtotal)
    // then sort keys by alphabetical value, output to table
    $array_key = '';
    if (!isset($order_output[$product->model])) {
        $array_key = $product->model;
    } else {
        $array_key = $product->model . $array_key_modifier;
        $array_key_modifier++;
    }

    $order_output[$array_key] = array("title" => $product->title, "model" => $product->model,
        "price" => $product->price, "quantity" => $product->qty, "subtotal" => $product->total_price);
    //  "price");
    $order_info = $product->order; // each product has complete built in order info. Maintain a reference to it
    $order_id = $product->order_id;

    if (!empty($product->data['attributes'])):
        $order_output[$array_key]["attributes"] = $product->data['attributes'];
    endif;
}

ksort($order_output);
```

# Answer
`uc-order--admin.tpl.php` is the "default admin notification template". In other words, the email sent to admins to notify them about a new order.

You can change the order of the products listed in the order view page by implementing `hook_tapir_table_alter()`

**I have not used this code in production, and do not know what effect it will have on other pages/processes, so test it thoroughly:**

```
function YOUR_MODULE_NAME_tapir_table_alter(&$table, $table_id) {
  if ($table_id == 'uc_op_products_view_table') {
    $sorted_rows = array();
    foreach ($table['#rows'] as $key => $row) {
      if (!empty($row['#entity']->model)) {
        $sku = $row['#entity']->model;
        $new_key = $sku . '_' . $key;
      }
      else {
        $new_key = $key;
      }
      $sorted_rows[$new_key] = $row;
    }
    if ($sorted_rows && ksort($sorted_rows)) {
      $table['#rows'] = $sorted_rows;
    }
  }
}

```
> 2 votes

---
Tags: 7, ubercart
---


# Question
Title: Media Title appearing in View when HTML is stripped
I've run into an issue with media in a view. I have a view using bootstrap grid to display body field content. The view field content being displayed is setup to strip out HTML, but the word "Image" is inserted where a media entity was. Not sure if the word "Image" is a leftover from media or the entity embed module.

example:

Any ideas on how to get rid of this unnecessary word?

# Answer
> 0 votes
This ended up being a media field label and not the media type name, like I originally thought it to be.

This was happening due to the media label being set to "Visually Hidden" instead of "Hidden"

This setting can be found at Administration \> Structure \> Media types \> \[your media type\] \> Manage Display

Now that it's set to "Hidden" it no longer shows in the label in the view or the WYSIWYG

---
Tags: views, media
---


# Question
Title: How can I remove the "This translation is published" checkbox?
In my custom entity module I have already defined a status checkbox to determine the entities status. What I noticed is when I enable show\_revisions\_ui in the annotation and have the entity setup to support multiple languages there are two check boxes at the bottom of the page.

One of them is to publish this entities language copy and as a result the published checkbox I created is being ignored. How can I disable the multilingual published checkbox?

# Answer
So it turns out I needed to define a translation handler for my entity.

inside of MyEntityTranslationHandler that extends the ContentTranslationHandler I override the entityFormAlter function and add this:

`$form['content_translation']['status']['#access'] = FALSE;`
> 2 votes

---
Tags: 8, entities
---


# Question
Title: Views data export user role field value missing from exported csv file
I'm using views\_data\_export to export data from the views displays. I added a **Data Export** option to the user account list views. When I use the **batch** in export settings, user role field is missing in the exported CSV file. While not using batch, role field is there.

Thanks

# Answer
> 1 votes
I found this is a bug in the module itself, and the following patch will solve the issue.

Discussion: https://www.drupal.org/project/views\_data\_export/issues/2789531#comment-13345278

Patch: https://www.drupal.org/files/issues/2019-11-08/views\_data\_export\_batch\_empty\_fields.patch

---
Tags: views, 8, importing-exporting, batch-operations
---


# Question
Title: What rule to use to redirect users, unless already redirected?
I'd like users with certain roles to be redirected to the page /civicrm when they login, unless they've already been redirected elsewhere. For example, an email might have a link that directs them to the page /elsewhere.

When I tried the module 'login destination' I can only achieve one or the other, never both - either the redirect works but a regular login doesn't redirect to /civicrm or the other way round.

From browsing in Drupal Answers, I'm pretty sure that Rules could do this, but I've tried and failed so far. The rule needs 2 conditions to be satisfied - user is one of the roles, and they are not already being redirected - then they should be directed to /civicrm.

Can anyone please suggest how a rule might achieve this?

# Answer
Make a flag on users: 'flag\_user\_has\_logged\_out', you will need more than one rule, first rule: react on: user has logged out, and flag the user with this new flag, on another rule: react on logged\_in: first validate your roles, then validate if user is 'flagged' if so, redirect to /whatever, and unflag user has logged out. if not, the other redirect will take control. This kind of rules i use a lot, i make many calculations on user has logged-out and i do not need to recalculate things again when user loggs in, it work both ways, maybe user just clossed browser and did not made a logged-out, so a evalutate that when loggs in and i do not duplicate my calculations. i hope you understood me and help you. is just a pointing directions on what you can do. Examples how your rules will look like:
> 1 votes

# Answer
You should be able to get this to work, using the Rules module, using the "**Drupal is initializing**" event. That will ensure that the rule gets triggered BEFORE the actual content is shown. Using Rules event " *Content is viewed* " is typically 'too late'. Refer to 'How to specify a Rules event like "Content is 'going to be' viewed"?' for more details on that. Adapt your rule to use this event, combine that with the relevant Rules conditions (like roles, etc) and, just for temporary unit testing, add a Rules Action (as the very first Rules Action) to "Show a message on a site", e.g to say '*Bingo, let the Rules party begin (we did find a Rules Event to continue building on)*'.
> 1 votes

---
Tags: 7, rules, redirection
---


# Question
Title: How do I limit a normalizer to a given class or interface?
I'm creating a custom normalizer for node entities.

I want to restrict the normalizer to normalize Node entities only. It seems like there are two ways this can be done:

1. `protected $supportedInterfaceOrClass = NodeInterface::class;`
2. ```
public function supportsNormalization($data, $format = NULL) {
  return (bool) $data instanceof NodeInterface;
}

```

Is there a difference between the two? Do I need both, or only one of them?

It seems like I don't need the `$supportedInterfaceOrClass`, but what is it used for? Can I just remove it and only use `supportsNormalization()`?

**UPDATE:** My class extends the `NormalizerBase` class.

# Answer
You didn't explicitly state that your class is extending NormalizerBase, but I assume that's the case. My reply is based on that assumption.

If you look in the code for NormalizerBase, there are two spots where $supportedInterfaceOrClass is accessed, in supportsNormalization() and supportsDenormalization(). If you override supportsNormalization() as option #2 from the original post suggests, your normalizer will be restricted to nodes. However, it overrides the base method, bypassing a check to see if the given normalization format is even supported, which is not good. If someone were to try to normalize an unsupported format, the overridden method would incorrectly return `TRUE`. Therefore, it is better to set supportedInterfaceOrClass according option #1 from the original post, as that will also cover the denormalization option, as well as allow the base API to do its work.

Verdict: Do NOT use method #2. Do use method #1. I would implement `__construct()` and set the node class upon instantiation:

```
public function __construct() {
  this->supportedInterfaceOrClass = NodeInterface::class;
}

```
> 1 votes

---
Tags: 8, entities
---


title: Add extra text input for file field

text:
# Question
Title: Add extra text input for file field
For Drupal 7, in page content type there is a multiple file upload section. Description is enabled for the file upload, but I need to add one more text input for each images to ask user enter the year file belongs to.

I am not very good at Drupal. So if I can find a clear solution it will save my day. Thank you from now.

# Answer
I would recommend using the field collection module instead. Create a field collection with a file upload field, description field and file owner field (can be a text field or user reference field. Set the field collection to unlimited. Then add the field collection to your page content type. It will allow you to do more custom things moving forward.

https://www.drupal.org/project/field\_collection https://www.drupal.org/project/references
> -1 votes

---
Tags: files
---


title: How do I alter the login form?

text:
# Question
Title: How do I alter the login form?
I have used `custom_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)`; I get the form ID of other forms, but I don't get the login form `$form_id` inside the hook.

# Answer
Try clearing cache and then visiting login page again, that should show Form ID. It will be hidden again when you refresh login page.

```
use \Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_form_alter().
 */
function [MODULE_NAME]_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  echo $form_id;
  switch ($form_id) {
    case 'user_login_form':
      // Do your code here to alter login form.
      break;
  }
}

```
> 8 votes

# Answer
```
function MYMODULE_form_user_login_form_alter(&$form, &$form_state, $form_id) {
  // you code here
}

```
> 1 votes

---
Tags: 8, forms
---


title: How to hide a specific user profile?

text:
# Question
Title: How to hide a specific user profile?
I would like to be able to hide a specific user profile.

I want to completely hide it from Drupal and search engines. How can I achieve this?

# Answer
To hide the page from Google and search engines, you can add the `robots` metatag.

Add this code to a custom module to add the metatag to the specefic profile page.

```
function MY_MODULE_preprocess_html(&$variables) {
  $user_id = 'ID of the user to hide profile page for';

  if (\Drupal::routeMatch()->getRouteName() == 'entity.user.canonical') {
    $user = \Drupal::routeMatch()->getParameter('user');
    if ($user instanceof \Drupal\user\UserInterface && $user->id() == $user_id) {
      $robots_none = [
        '#tag' => 'meta',
        '#attributes' => [
          'name' => 'robots',
          'content' => 'none',
        ],
      ];

      $variables['page']['#attached']['html_head'][] = [$robots_none, 'robots-none'];
    }
  }
}

```

If you want to hide the page in Drupal too, you can create a redirect from the specific user profile page to the `/system/403` page.
> 2 votes

# Answer
To avoid users can access a user profile, I would implement `hook_ENTITY_TYPE_access()`.
For the search engines, it would be sufficient to check the logged-in user isn't anonymous. For any Drupal user and the search engines, it's sufficient to check the permission the logged-in user has. (I would not hide the user profile to users who have the permission to administer users.)

In the first case, I would use code similar to the following one.

```
function mymodule_user_access(EntityInterface $entity, $operation, AccountInterface $account) {
  if ($operation == 'view' && $entity->id() == USER_ID && $account->isAnonymous()) {
    return AccessResult::forbidden()->cachePerUser();
  }
}

```

In the second case, I would use code similar to the following one.

```
function mymodule_user_access(EntityInterface $entity, $operation, AccountInterface $account) {
  if ($operation == 'view' && $entity->id() == USER_ID && !$account->hasPermission('administer users')) {
    return AccessResult::forbidden()->cachePerPermissions();
  }
}

```

(In both the cases, replace `USER_ID` with the actual user ID of the user profile you need to hide.)

The code checks the value of the operation, and forbids it only when it's *view*. In this way, the code is simpler, as it doesn't need to check users are trying to edit their own accounts, for example (which I assume it's not an operation you want to forbid).

`hook_ENTITY_TYPE_access()` is not invoked for pages listing more than one entity, for example a view page. In the case of user accounts, `hook_ENTITY_TYPE_access()` should be sufficient, but if you want to avoid that user account is listed also in a view output, the alternative is `hook_query_TAG_alter()` which is more complicated to implement, but it works in every case.
> 3 votes

---
Tags: 8, users
---


# Question
Title: Set parent service when registering a service in a ServiceProvider
I want to create dynamic services, therefore I added a `ServiceProvider` class to my module.

I have created a base service that my other services will have as parent.

When doing this in `my_module.services.yml`, I can just use:

```
parent: service_name

```

But I can't find out how to do in the `ServiceProvider` class.

My class looks like this:

```
class MyModuleServiceProvider extends ServiceProviderBase {

  /**
   * {@inheritDoc}
   */
  public function register(ContainerBuilder $container) {
    // Create services for our base normalizer classes.
    $container->register('MY_MODULE_rest.entity_normalizer_base', EntityNormalizerBase::class)
      ->addArgument(new Reference('entity_type.manager'));

    // Create node normalizer service.
    $container->register('MY_MODULE_rest.node_normalizer', NodeNormalizer::class)
      ->addTag('normalizer', ['priority' => 1])
      // How can I set "MY_MODULE_rest.entity_normalizer_base" as the parent for this one?
      ->addArgument(new Reference('path_alias.manager'))
      ->addArgument(new Reference('language_manager'));
  }
}

```

# Answer
You can find your answer in the symfony docs, How to Manage Common Dependencies with Parent Services. In the third snippet we see:

```
use AppBundle\Repository\BaseDoctrineRepository;
use AppBundle\Repository\DoctrinePostRepository;
use AppBundle\Repository\DoctrineUserRepository;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Reference;

$container->register(BaseDoctrineRepository::class)
    ->setAbstract(true)
    ->addArgument(new Reference('doctrine.orm.entity_manager'))
    ->addMethodCall('setLogger', [new Reference('logger')]);

// extend the AppBundle\Repository\BaseDoctrineRepository service
$definition = new ChildDefinition(BaseDoctrineRepository::class);
$definition->setClass(DoctrineUserRepository::class);
$container->setDefinition(DoctrineUserRepository::class, $definition);

```

Looking at the docs and your code, my understanding is you'd do something like:

```
use Symfony\Component\DependencyInjection\ChildDefinition;

class MyModuleServiceProvider extends ServiceProviderBase {

  /**
   * {@inheritDoc}
   */
  public function register(ContainerBuilder $container) {
    // Create services for our base normalizer classes.
    $container->register('MY_MODULE_rest.entity_normalizer_base', EntityNormalizerBase::class)
      ->addArgument(new Reference('entity_type.manager'));

    $node_definition = new ChildDefinition('MY_MODULE_rest.entity_normalizer_base');
    $node_definition->setClass(NodeNormalizer::class);
    $node_definition->addTag('normalizer', ['priority' => 1]);
    $node_definition->addArgument(new Reference('path_alias.manager'));
    $node_definition->addArgument(new Reference('language_manager'));

    // Create node normalizer service.
    $container->setDefinition('MY_MODULE_rest.node_normalizer', $node_definition)

  }
}

```
> 2 votes

---
Tags: 8, symfony-services
---


# Question
Title: How can I upgrade from Drupal 8.0.x to Drupal 8.1.x?
How can I upgrade from Drupal 8.0.x to Drupal 8.1.x?

Do I have to copy the core files in the project folder and then run update.php as usual, or do I have to do something more complicated like when migrating from older versio

# Answer
if your site installed with composer and want to upgrade to version 8.8.1 you can follow the steps below.

1)cd your\_install\_dir

2)rm composer.lock

3)rm -rf vendor

4)composer remove webflo/drupal-core-strict --no-update

5)composer remove drupal/core --no-update

6)composer require --dev drupal/core-dev

7)browse yourdomain.com/update.php

8)clear cache if drush installed

congratulations upgradation successful in my case.lets try and please let me know whether it works or not.
> 0 votes

# Answer
Yes, replace the core and vendor directories and run update.php.

**Note:**

> Also please follow the instructions from upgrade.txt. There are several other necessary instruction so that you can recover from any mishappening.

Drupal treats 8.0.x and 8.1.x as 8.x.x.
> 4 votes

---
Tags: 8, migrations, upgrading
---


# Question
Title: How can I detect if the current viewed page is administrative?
How do I detect whether the user the page is currently viewing, is considered administrative? An administrative page can be recognized when the administration theme is activated.

In my case I would like to print a notice if this condition is met, and if the user can 'administer modules'.

# Answer
This can be done with `path_is_admin(current_path())`.

For example, the following hook implementation can be used.

```
function mymodule_init() {
  if (user_access('administer modules') && path_is_admin(current_path())) {
      drupal_set_message(t('Message'));
  }
}

```
> 31 votes

# Answer
Daniel's answer is correct for determining if the current path is "administrative," but if you want to more directly check if the administration theme is being used (your question seems a bit vague as to which you're looking for), you can do…

```
global $theme;
if ($theme === variable_get('admin_theme', 'seven')) {
  // …
}

```

…though this is likely to fail if you try to run it too early in the bootstrap process, namely before `$theme` is defined.
> 11 votes

# Answer
For those looking for the Drupal 8 method:

```
if (\Drupal::service('router.admin_context')->isAdminRoute()) {
  // …
}

```

(Tested with a preprocess function in 8.7.5 and used in a core-patch in 8.0)
> 4 votes

# Answer
To check if the administration theme is being used (for Drupal 8) you can use

```
$theme_name = \Drupal::service('theme.manager')->getActiveTheme()->getName();

```

to get the theme name.
> 0 votes

---
Tags: 7
---