# Question
Title: Change values of nested fields with entity_metadata_wrapper
The background of this question is that I'm trying to migrate data from Drupal 6 Imagefield Extended to Drupal 7 File Entity (with File Entity Inline). See also https://www.drupal.org/node/974888

First I tried to understand how entities work and how they can be extracted and manipulated using Entity Metadata Wrappers. That seems to work ok, for example, I can get the values of my imagefield like this:

```
$nid = 103025;
$node_wrapper = entity_metadata_wrapper('node', $nid);
$images = $node_wrapper->field_image->value();

```

And it seems that I could change the values of the images with something like this:

```
// Do something with $images
$node_wrapper->field_image->set($images);
$node_wrapper->revision->set(1);
$node_wrapper->save();

```

(For some reason it's not saving the values for the node in my case, but that's another question.)

My problem now is that I have nested fields, i.e. the imagefield has "subfields" for the source and license (that I had added in Drupal 6 using Imagefield Extended). I do get the values of those nested fields in $images - but only in the typical array with `$images[und][0]['value']` and `$images[und][0]['safe_value']`. But there seems to be no way to get those values through the wrapper, for example like

```
$node_wrapper->field_image->field_source->value();
$node_wrapper->field_image->value()->field_source->value();

```

Now I have been trying for hours to figure out how I can change (or populate) those (sub) fields and then save the entire node, but to no avail.

I'm also wondering if it's necessary to do this on a node level as files are also entities, but it seems that there is nothing like `entity_metadata_wrapper('file', $fid);`.

I'd appreciate any hint that could point me in the right direction because the search has been kind of exhausting.

# Answer
Using what Clive mentioned and with the hint eikes provided, this seems to be a way to accomplish what I want:

```
$nid = 108501;
$node_wrapper = entity_metadata_wrapper('node', $nid);

for ($i = 0; $i < count($node_wrapper->field_image->value()); $i++) {
  $node_wrapper->field_image[$i]->file->field_source->set('NEW SOURCE');
  $node_wrapper->field_image[$i]->file->field_license->set('NEW LICENSE');
  $node_wrapper->field_image[$i]->file->save();
}

// Just for dev: Check if the values have been saved
$node_wrapper = entity_metadata_wrapper('node', $nid);
dsm($node_wrapper->field_bild->value());

```

Erroneously I used the `save()` call on the whole node wrapper, but as files are their own entities, the call needs to be on the file, as eikes suggested.

Additionally, I noticed that calling `$node_wrapper = entity_metadata_wrapper('node', $nid);` after the above code doesn't reflect the changes (for checking). It seems I need to reload the entity first.

Thanks a lot to both of you!
> 1 votes

# Answer
This is my solution to access and update 2 nested levels deep on unlimited values on field collections fields

```
  function set_descuentos_pagos_action($nid) {
  // $raw_node = node_load($nid);  AVOID THIS
  $node = entity_metadata_wrapper('node', $nid);
  // dpm($node->getPropertyInfo());
  // dpm($node);
  $raw_ana = $node->field_ana->value();
  // dpm($raw_ana);
  $num_cotizaciones = count($raw_ana);

  // $i ES EL ITEM DE  CADA COTIZACION
  for ($i=0 ; $i < $num_cotizaciones  ; $i++ ) {

    $ana[$i] = entity_metadata_wrapper('field_collection_item', $raw_ana[$i]);
    $fp = $ana[$i]->field_m_fc_pago_texto->value();
    if($fp == 'Trimestral'){
      // get values from parent field collection
      $prima_descuento[$i] = $ana[$i]->field_m_fc_prima_neta_descuento->value();
      $prima_original[$i] = $ana[$i]->field_m_fc_prima_neta->value();
      $factor[$i] = $prima_descuento[$i] / $prima_original[$i];

      // get child field collection
      $raw_recibos = $ana[$i]->field_m_fc_recibo->value();
      $num_recibos[$i] = count($raw_recibos);

      // $j SON LOS PAGOS DE LA ITERACION $i
      for ($j=0; $j < $num_recibos[$i]; $j++) {

        // get current child field collection object
        $value[$j] = $ana[$i]->field_m_fc_recibo[$j]->value();

        // $pago[$j] ES EL PAGO OBJETO
        $pago[$j] = entity_metadata_wrapper('field_collection_item', $value[$j]);
         // dpm($pago[$j]->value());
         // get field value, set value on other field
         $prima = $pago[$j]->field_m_fc_prima_total->value();
         $nuevo_valor = $prima * $factor[$i];
         $pago[$j]->field_m_fc_prima_total_descuento->set($nuevo_valor);
         $pago[$j]->save();
      }

    }
  }

} // end  set_descuento_pagos_cotizacion

```
> 0 votes

---
Tags: 7, entities, files
---


title: Disable login at all

text:
# Question
Title: Disable login at all
I want to disable login at all on my drupal site, even better also hide the form. If i need login i will enable it from a ssh session and after working disable again.

I will prefer to do this with rewrite rules in .htaccess but i cannot figure out the right rule.

**Update** (as this seems to be a popular question)

I ended up with .htaccess like this:

```
 # disable well known Drupal user login endpoints
  RewriteCond %{QUERY_STRING} q=user
  RewriteRule ^/?$ http://%{HTTP_HOST}/? [R=307,L]
  RewriteRule ^user$ http://%{HTTP_HOST}/ [R=307,L]
  RewriteRule ^user/register$ http://%{HTTP_HOST}/ [R=307,L]

  # goto user login with that "secret" URL
  RewriteRule ^op9__P87? /user [NC]

```

# Answer
> 10 votes
Another way is set the access to false to the login form. Whenever you want to re-enable the login, just comment out the hook.

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

```

# Answer
> 7 votes
Maybe the Login Disable module will help?

> Prevent users from logging in to your Drupal site unless they know the secret key to add to the end of the ?q=user login form page. If a user does find out about the secret key they will still have their user account role checked during authentication .If they do not have the 'bypass disabled login' granted they will be refused access and displayed a customisable "denied" message.

# Answer
> 2 votes
The problem is more of a Apache config issue, rather than a Drupal issue. It also relies on the user login form just being on one page.

```
# Pass all requests not referring directly to files in the filesystem to
# index.php. Clean URLs are handled in drupal_environment_initialize().

RewriteRule ^user$ - [G,L]
RewriteRule ^q=user$ - [G,L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]

```

The `q=user` rule may require some tweaking, as an artificial URL with `q=user` in it will end up at the login page.

Note, that there are a few modules that disable user login (such as @Jonathan Rowny suggests), which may be a better option, depending on your scenario.

# Answer
> 0 votes
You can use Disable Login module to disable the login page, and secure it with secret key.

Ref: https://www.drupal.org/project/disable\_login

---
Tags: 6, users
---


# Question
Title: How can I get a list of all languages translation that a node has?
I'm trying to get a list of language translations that a node has in `theme_preprocess_node()`. I have the node object and can check for a translation on a one-by-one basis, if I have the list of languages. What I need is a list of all the translations for the node.

# Answer
Use getTranslationLanguages():

```
$languages = $node->getTranslationLanguages();

foreach ($languages as $id => $language) {
  print $node->getTranslation($id)->label();
}

```
> 4 votes

---
Tags: i18n-l10n, 9
---


# Question
Title: AJAX Form using a sub-class of ContentEntityForm fires/invokes/calls the WidgetBase::massageFormValues() twice
I'm using a AJAX form. This form I build from a sub-class of `ContentEntityForm`. The Entity edited by this form has a field **MyField**. To bring all the field values in a appropriate structure I'm using `massageFormValues()` in `MyFieldWidget` class (sub-class of `WidgetBase`).

The little problem is: the method `massageFormValues()` is called twice on every submit. The are no other problems with the form. I can properly edit values on this form.

So it's just the question of understanding: why Drupal does call `massageFormValues()` twice on every submit.

The mentioned and my (very simplified) code:

My ajax controller

```
class AjaxController extends ControllerBase {
  ...
  ...

  public function myController($eid) {

    $myEntity = $this->entityTypeManager()->getStorage('my_entity')->load($eid);
    $form = $this->entityFormBuilder()->getForm($myEntity, 'my_mode');
    $renderer = \Drupal::service('renderer');
    $output = $renderer->renderRoot($form);

    $response = new AjaxResponse();
    $response->addCommand(new OpenModalDialogCommand($title, $output));

    return $response;
  }
  ...
  ...
}

```

`MyForm` is a sub-class of the ContentEntityForm and it's a **mode form** for the **mode** `my_mode` of the Entity `my_entity`:

```
class MyForm extends ContentEntityForm {

 ...
 ...
  protected function actions(array $form, FormStateInterface $form_state) {
    $actions = parent::actions($form, $form_state);

    $actions['submit'] = [
      '#type' => 'submit',
      '#value' => t('Save'),
      '#ajax' => [
        'callback' => '::ajaxCallback',
        'event' => 'mousedown',
      ],
    ];

  return $actions;
  }
  ...
  ...
}

```

My field widget class:

```
class MyFieldWidget extends WidgetBase implements ContainerFactoryPluginInterface {
...
...

  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {

    // THIS CODE IS CALLED TWICE ON EVERY SUBMIT OF MY SUBMIT BUTTON DEFINED ABOVE
    // BUT WHY TWICE?

    return $rightStructureValues;
  }

...
...
}

```

# Answer
In an Ajax request the form is rebuilt from scratch. This was often asked here why the form build method is called two or even three times. It seems like the entity is rebuilt as well when the form is submitted via Ajax:

*Drupal\Core\Entity\EntityForm::afterBuild*

```
  /**
   * Form element #after_build callback: Updates the entity with submitted data.
   *
   * Updates the internal $this->entity object with submitted values when the
   * form is being rebuilt (e.g. submitted via AJAX), so that subsequent
   * processing (e.g. AJAX callbacks) can rely on it.
   */
  public function afterBuild(array $element, FormStateInterface $form_state) {
    // Rebuild the entity if #after_build is being called as part of a form
    // rebuild, i.e. if we are processing input.
    if ($form_state->isProcessingInput()) {
      $this->entity = $this->buildEntity($element, $form_state);
    }

    return $element;
  }

```

This will trigger the mentioned method in the field widgets.
> 4 votes

# Answer
My workaround/solution. massageFormValues() is still called twice by Drupal, but my logic in it will be executed just once, after the form validation is complete:

*MyFieldWidgetClass.php:*

```
class MyFieldWidget extends WidgetBase implements ContainerFactoryPluginInterface {
...
...

  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {

    // massageFormValues() is called twice: on validateForm and on submitForm
    // we just need massageFormValues once, after $form_state->isValidationComplete() is TRUE
    if(!$form_state->isValidationComplete()) {
      return [];
    }
    ...
    ...
    return $rightStructureValues;
  }

...
...
}

```
> 2 votes

---
Tags: entities, forms
---


# Question
Title: Can I use the session service directly instead of via the request?
The Drupal documentation on sessions mentions that sessions can be accessed via the Request object:

> Session data is accessed via the `\Symfony\Component\HttpFoundation\Request::getSession()` method, which returns an instance of `\Symfony\Component\HttpFoundation\Session\SessionInterface`. The most important methods on SessionInterface are set(), get(), and remove().

However I've also dicovered there is a session service.

In a class where I need to use dependency injection and I do not by default have access to the Request object, do I still need to access the session via the request, or can I use it directy? Loading the Request instead and then accessing the session feels like adding overhead.

I have tried below code, which seems to be working fine. So then why do most examples and even the documentation still demonstrate the Request way? Am I missing something, or is there a risk in this approach?

```
class MyForm extends FormBase {

  /**
   * The session.
   *
   * @var \Symfony\Component\HttpFoundation\Session\Session
   */
  protected $session;

  /**
   *
   * @param \Symfony\Component\HttpFoundation\Session\Session $session
   *   The session.
   */
  public function __construct($session) {
    $this->session = $session;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('session')
    );
  }

  function somefunction() {
    $this->session->get('value');
    $this->session->set('value', 'somevalue');
  }

}

```

# Answer
*... is there a risk in this approach?*

If you have multiple requests you could get the wrong session object. Drupal moved a lot of things out of the request object, like routing and even the path info, but they didn't implemented a stacked session service and instead kept the session object in the request stack.

If you want to inject this service there is already a property in FormBase with getter and setter methods.

This works injected or not (see the comments at the top of the class):

```
$session = $this->getRequest()->getSession();

```
> 0 votes

---
Tags: sessions, http-request, dependency-injection
---


# Question
Title: How do I add classes to main menu ul and li?
I want to generate the html elements and their classes to fit my styling of the main menu.

I'm confused by all the near-possibilities offered in the api documentation and by looking at core themes etc. and still can't quite see what I have to do, or where I have to do it.
I would be very grateful for clear pointers to:

1. which php functions I have to write;
2. which variables I need to add / update;
3. in which files the functions will go.

Presumably, in `MYTHEME.theme` I will need a preprocess function of some sort to add to the `attributes` and `item.attributes` variables that `links.html.twig` uses to print the menu `ul` and the menu item `li`'s.

\[Update\] So far I have discovered one way to place classes on the Main Menu's `ul` but ideally I would like to add a class to each submenu's `ul` indicating the depth of the sub-menu.
And I cannot locate any documentation or examples from which I can understand the generation / modifying of the main menu's individual `li`nk items.

This function goes into the file `MYTHEME.theme`.

```
function MYTHEME_preprocess_page(&$variables) {

  // Pass the main menu and secondary menu to the template as render arrays.
  if (!empty($variables['main_menu'])) {
    $variables['main_menu']['#attributes']['id'] = 'main-menu-links';
    $variables['main_menu']['#attributes']['class'] = array('links', 'clearfix', 'MYNEW_class');
  }

}

```

# Answer
> 14 votes
Override the twig file for the main menu by saving *menu--main.html.twig* in your theme. Copy the original *menu.html.twig* from *core/modules/system/templates/menu.html.twig*, or *core/themes/classy/templates/navigation/menu.html.twig* if your theme extends Classy.

You can then modify the macro used to generate the menu output. To get a class on the `<ul>`'s to indicate level, you could do this.

```
{% if menu_level == 0 %}
  <ul{{ attributes.addClass('menu', 'menu-level--' ~ menu_level) }}>
{% else %}
  <ul class="menu {{ 'menu-level--' ~ menu_level }}">
{% endif %}

```

You could do similar manipulations to the `<li>`'s.

```
<li{{ item.attributes }}>

```

Use `.addClass('class-name')` to add more CSS classes.

```
<li{{ item.attributes.addClass('class-name') }}>

```

If you're a HTML/class name snob like myself you can also remove classes.

```
{{ item.attributes.removeClass('menu-item') }}

```

# Answer
> 2 votes
The way to get the main menu with items in all levels has been resolved in Drupal 8 - "Implement menu links as plugins", trying to build a menu tree

To add class to ul and li, we got 3 options:

A. Override menuTree service:

1. create new MenulinkTree in your module MyprojectMenuLinkTree that extends core's MenuLinkTree
2. Override MenulinkTree::build by adding MyprojectMenuLinkTree::build
3. Update your level specifi class in logic like this https://gist.github.com/vijaycs85/308d2d0287a9ab1cd168
4. ovrride defult menu.link\_tree at sites/default/services.yml https://gist.github.com/vijaycs85/1179c6009c6932405f10

P.S: Not very sure, if you need to do these whole override for adding class.

B. Override just tree build on theme layer:

1. Add the code in mytheme.theme file: https://gist.github.com/vijaycs85/61f2b2757f83aaa5260e

C. Using Drupal.behaviors.MYTHEME in JavaScript (from https://www.drupal.org/project/gratis)

1. Create MYTHEME/script.js
2. Add MYTHEME.behaviour.menuTree
3. Update this code: https://gist.github.com/vijaycs85/346c14aedffcafe8945e

# Answer
> 0 votes
In Drupal8 - if you want to use **Macros** & add levels etc to the menu, you need to pass the variables that you need to extend/include accordingly:

Base Template Screen Shot:

Base Template Code:

```
{% import _self as menus %}

{{ menus.menu_links(items, attributes, 0, list_add_class, item_add_class) }}

{% macro menu_links(items, attributes, menu_level, list_add_class, item_add_class) %}
  {% import _self as menus %}
  {% if items %}
    {% if menu_level == 0 %}
      <ul{{ attributes.addClass(list_add_class) }}>
    {% else %}
      <ul>
    {% endif %}
    {% for item in items %}
      <li{{ item.attributes.addClass(item_add_class) }}>
        {{ link(item.title, item.url) }}
        {% if item.below %}
          {{ menus.menu_links(item.below, attributes, menu_level + 1, list_add_class, item_add_class) }}
        {% endif %}
      </li>
    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %}

```

Child template code:

```
{% include "@drupalastic/navigation/menu_base.html.twig" with {
    item_add_class: ['my-custom-item-class', 'my-another-custom-item-class'],
    list_add_class: ['my-custom-list-class']
  }
%}

```

End Result:

---
Tags: 8, theming, navigation
---


# Question
Title: Change workflow state with particular payment method
Right now i have a payment method called "Transferência Bancária" and I need it to change to the workflow state "Awaiting Transferencia" automatically when that payment method is selected.

Is it possible to do programmatically?

I'm stuck at:  `$order = $event->getEntity(); if(($order->getPaymentGateway()) == ('transferencia')) { $order->set('state', 'aguardando_transferencia'); }`

on my /modules/workflowtkn/src/EventSubscriber/WorkflowTknProcessSubscriber.php

```
Error: Call to undefined method Drupal\commerce_order\Entity\Order::getPaymentGateway()

```

EDIT: I'm having troubles calling the function "getPaymentGateway()" because is in another module, can somebody help, please :) It has to be corresponded to the order.

I've tried `$gateway = \Drupal::service('plugin.manager.commerce_payment_method_type');` but it says can't convert to string... This:

$payment = $order-\>get('payment\_gateway')-\>first()-\>entity

Gives me:

> Warning: htmlspecialchars() expects parameter 1 to be string, object given in Drupal\Component\Utility\Html::escape() .

I've looked at How do I get information about the payment method from the order object programmatically? but can't figure it out.

I guess i'm failing to convert to string?

EDIT: When I use json\_encode: `json_encode($order->get('payment_gateway')->first()->entity)` it only returns "{}"

# Answer
> 1 votes
After much head bashing and pure luck i found out the solution. In order.php:

```
function getPay()
{
    return $this->get('payment_gateway')->entity->get('label');
}

```

---
Tags: commerce
---


title: How to build core test database?

text:
# Question
Title: How to build core test database?
Fifteen years writing Drupal code and yet I have never written unit tests. I have recently posted a couple core patches which require tests to be written for them - so good time to learn how to write PHPUnit tests.

I have a test environmnet set up and am able to successfully run core unit tests. I need to extend these tests which I can see is not very difficult; but I need to run against the "test db". I can see core Views test modules like views\_test\_config and views\_test\_data which have everything I need - but I cannot enable them (manually so I can verify what my test content is).

Is there a way to get a copy of the D9 default test database that is used for running core (kernel) tests against? Or, alternatively, some way to enable these modules?

# Answer
I'm not sure if I understand your question correctly, but there is no "test db" as such other than what your test creates. The core test system installs a minimal Drupal site from scratch (the database URL for this can be set in the `phpunit.xml` file, a default template of which is in `core/phpunit.xml.dist`). This is independent of any existing sites, uses the "simpletest" installation profile and is created from scratch every time the test runs.

Your test's ::setUp() method then creates things like test users, content etc in this site.

If you extend the KernelTestBase or the BrowserTestBase class, you will see there is a class property named `$requiredModules`. If you set this to an array of module names, they will automatically be enabled as part of the setup process.
> 1 votes

# Answer
To allow installing test modules you need to set this in your $settings.php:

```
$settings['extension_discovery_scan_tests'] = TRUE;

```

\[EDIT\] - this does allow seeing all the test modules and i can now enabled them - but the test data and view is still not run.. ughh!!
> 0 votes

---
Tags: 9, testing
---


# Question
Title: Using #states on an inline paragraph form
I have a field on a custom content type which is a reference to a paragraph type, using the Paragraph (EXPERIMENTAL) widget. I'm trying to modify that widget to show and hide a field based on another field on the paragraph. Here is my widget alter code:

```
$field = 'field_supporter_form_fields';
$id_field = 'field_primary_custom';
$delta = $element['#delta'];
$id = sprintf('select[name="%s[%d][subform][%s]"]', $field, $delta, $id_field);
$element['subform']['field_field_type']['widget']['#states'] = [
  'visible' => [
    $id => ['value' => 'custom'],
  ],
];
$element['subform']['field_field_type']['widget']['#title'] = 'Blah!';

```

I know that I'm targeting the correct widget because I see the field title change to "Blah!", but the visibility of the field doesn't change.

Here's what the relevant part of the $element array looks like after the alter:

```
[#parents] => Array
    (
        [0] => field_supporter_form_fields
        [1] => 0
        [2] => subform
        [3] => field_field_type
    )

[#states] => Array
    (
        [visible] => Array
            (
                [select[name="field_supporter_form_fields[0][subform][field_primary_custom]"]] => Array
                    (
                        [value] => custom
                    )

            )

    )

```

The dependant field `field_primary_custom` is a pair of radio buttons with values of either primary or custom. The name of the element on the page is `field_supporter_form_fields[0][subform][field_primary_custom]` which matches what I have in my identifier.

Why isn't the visibility changing?

# Answer
Turns out I needed to use input instead of select. Not entirely sure why, but it works!
> 1 votes

---
Tags: 9
---


title: Route restrict access for current user

text:
# Question
Title: Route restrict access for current user
How do I restrict access to the route by current user in Drupal 8?

I want to create a new tab in user profile `path: '/user/{user}/my-cool-tab'`, which should be accessible by current user only. For example:

* path `/user/5/my-cool-tab` should be available only for UID=5
* path `/user/7/my-cool-tab` should be available only for UID=7
* etc.

Which way is the simplest and correct for that?

# Answer
You need an access check where you compare the passed user id with the current user, here's an example from simplenews:

```
public function checkAccess(UserInterface $user) {
  $account = $this->currentUser();

  return AccessResult::allowedIfHasPermission($account, 'administer simplenews subscriptions')
    ->orIf(AccessResult::allowedIfHasPermission($account, 'subscribe to newsletters')
      ->andIf(AccessResult::allowedIf($user->id() == $account->id())));
}

```

Note that this includes and admin permission check, for admins that can actually see the page for other users.

If you do not need that, you could also just make your route /my-cool-page and use the current user for whatever you are doing. With D8's routing system, you can even make local task appear on the user page if you want to.
> 2 votes

# Answer
If anyone wants to see full details how to achieve such case.

Route Path with custom access checking function

```
path: '/user/{user}/my-cool-tab'
...
requirements:
    _custom_access: '\Drupal\mymodule\Controller\AccessCheck::myRoutePermission'

```

Create new controller which specifically check the accesses.

```
mymodule/src/Controller/AccessCheck.php
<?php

namespace Drupal\mymodule\Controller;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Drupal\Core\Session\AccountInterface;

/**
 * Access Checks controller.
 */
class AccessCheck extends ControllerBase {

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * The controller constructor.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   */
  public function __construct(RequestStack $request_stack, EntityTypeManagerInterface $entity_type_manager, AccountInterface $current_user) {
    $this->requestStack = $request_stack->getCurrentRequest();
    $this->entityTypeManager = $entity_type_manager;
    $this->currentUser = $this->entityTypeManager->getStorage('user')->load($current_user->id());
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('request_stack'),
      $container->get('entity_type.manager'),
      $container->get('current_user')
    );
  }

  /**
   * Checks access for __ route.
   */
  public function myRoutePermission() {
    $uid = $this->requestStack->attributes->get('user_id');
    if ($this->currentUser->hasPermission('administer users')) {
      return AccessResult::allowed();
    }
    elseif ($uid != $this->currentUser->id()) {
      // Return 403 Access Denied page.
      return AccessResult::forbidden();
    }
    return AccessResult::allowed();
  }

}

```

This way you can add any number of access checking function with any type of checks.
> 0 votes

---
Tags: 8, routes, users
---


# Question
Title: How do you display a version number on a footer file?
When I deploy my Drupal code, I build an artifact with BLT. I would like to write a file of some kind with the version number (tag provided to the artifact) that could then be read and displayed in the footer.

Where is the best place to write this file in a Drupal directory?

What is the best method to read from the file and display on the page safely?

Is there a different/better method altogether that I'm not thinking of?

# Answer
> 3 votes
One way I do it is to commit a text file and then check that live. This can be done while building the project in CI. Here is an example (note your CI variables may vary):

In one of the final steps before the artifact deploys to the server, you can do:

```
deploy:
    - echo $CI_COMMIT_TAG > path/to/drupal/docroot/themes/custom/yourtheme/version.txt
    - git add/commit steps...
    - git push ...

```

Then visiting that URL in the browser will tell you what 'version' that is, made from your CI variable.

---
Tags: deployment
---


title: Migrate node with paragraph

text:
# Question
Title: Migrate node with paragraph
I'm trying to figure out how migrating content from a Drupal 7 site to a Drupal 8 site works. I managed to understand how to create a custom module to migrate nodes with regular fields to my new D8 site.

But I also have one content type where I use paragraphs. And I can't seem to find a well documented example on how to do this. I found some examples but they all seem to use different methods. This one seems like the most up to date. But how to make the code from #9 work?

```
field_paragraphs:
plugin: sub_process
source: field_source_paragraphs
process:
  target_id:
    -
      plugin: migration_lookup
      migration:
        - paragraph_box
        - paragraph_grid
        - paragraph_text_embedded
      source: value
    -
      plugin: extract
      index:
        - 0
  target_revision_id:
    -
      plugin: migration_lookup
      migration:
        - paragraph_box
        - paragraph_grid
        - paragraph_text_embedded
      source: value
    -
      plugin: extract
      index:
        - 0

```

So the `field_paragraphs` and `field_source_paragraphs` I understand. But what are these `paragraph_` items under migration? Is this where I set the paragraph bundles? And if not where do I set the paragraph bundles and there fields? So where do I begin? What are the right steps to take?

Thanks in advance

# Answer
> 0 votes
You'll need to create a plugin within your custom module in order to migrate paragraph fields properly. I just finished this process on a large site. I'm paring down the module to make it a bit easier to understand and making it available in a public repository, along with an explanatory video:

https://www.arsnova.cc/drupal-7-drupal-8-paragraph-migration

---
Tags: 8, migrations, paragraphs
---


# Question
Title: Translate taxonomy term programmatically
How can I translate a taxonomy term programmatically in drupal 8? I found how to get the translated taxonomy term programmatically? but this is only related to d7.

# Answer
> 7 votes
In D8 you can translate entities with `addTranslation()`.

This is an example for a taxonomy term:

```
$term->addTranslation($langcode, [
  'name' => 'translated term',
])->save();

```

You can provide values for all translatable fields in the array.

# Answer
> 0 votes
Based on using the i18n API from other modules, the code should be the following one.

```
$term = taxonomy_term_load($tid);
$translated = i18n_string_translate("taxonomy:term:$tid:name", $term->name);

```

---
Tags: 8, taxonomy-terms, i18n-l10n
---


# Question
Title: Create migration stubs of entities for a multiple value reference field?
I need to import a set of authors as part of a content entity. It is an array in a JSON object of id/name. I have a field in Drupal on the content type to be a user reference that accepts unlimited cardinality.

First of all, I don't know these users ahead of time, no way to query it, so I cannot just create a migration dependency and do that first. This seems to be a popular answer, but doesn't fit any of my use cases.

Second, I think you should be able to take the source data and loop each one, and create a user stub if they do not exist already. How do you do that? If the user does not exist yet they should be created, if they do exist, just look up the uid and put it into the target id per row.

This won't be the only spot I run into this, I will have content related to content that I will need to stub too. I won't know the latter content until I run their migrations later.

Is this even possible in D8?

# Answer
Yes. This use scenario is covered by `migration_lookup` plugin with its `stub_id` property and making sure it's referenced migration (in your case, a user migration sourced from the JSON array) has defined all the required fields via the `default_value` plugin such that `migration_lookup` can rely on it to stub out a user before the `stub_id` migration can be run on its own to fill in fields for each referenced entity.
> 3 votes

# Answer
Hey @Kevin here is complex example of looking/stubbing entities which involves creating custom source/process plugins:

```
  field_background_media:
    - plugin: sub_process
      source: field_background_media
      include_source: true # not required for this example
      source_key: root # not required for this example
      process:
        _migration:
          plugin: static_map
          source: bundle
          map:
            image: migrate_media__image
            video: migrate_media__video
        target_id:
          plugin: dynamic_migration_lookup
          migration: '@_migration'
          source: target_id
          source_ids: # not required for this example
            migrate_media__image:
              - target_id
              - root/langcode
            migrate_media__video:
              - target_id
              - root/langcode

```

The context.

I have an entity reference field that references two media types. The `migration_lookup` plugin can't get migration id from source/destination properties, it operates on static migration id.

The key idea to get somehow media type and map it with specific migration id.

You can find I'm using `bundle` source property to build up `_migration` property.

I'm populating bundle property in my custom source plugin:

```
  public function prepareRow(Row $row) {
    $result = parent::prepareRow($row);

    if (!$result) {
      return $result;
    }

    $media_references = $row->getSourceProperty('field_background_media');
    if (!empty($media_references)) {
      foreach ($media_references as &$value) {
        // Find media type by target_id
        $bundle = $this->getReferencedMediaType($value['target_id']);
        if (!$bundle) {
          continue;
        }
        $changed = TRUE;
        $value['bundle'] = $bundle;
      }
    }

    if ($changed) {
      $row->setSourceProperty('field_background_media', $media_references);
    }
    return $result;
  }

  protected function getReferencedMediaType(int $media_id): ?string {
    $query = $this
      ->select('media', 'm')
      ->condition('mid', $media_id);
    $query->addField('m', 'bundle');
    return $query->execute()->fetchField();
  }

```

Then after `static_map` plugin has filled up `_migration` property I can tell which migration exactly should be used for the lookup/stub process.

In order to use value from `_migration` property as lookup\_migration\_id in `migration_lookup` plugin I've created sub-class for it:

```
use Drupal\migrate\Plugin\migrate\process\MigrationLookup;

/**
 * @MigrateProcessPlugin(
 *   id = "dynamic_migration_lookup"
 * )
 */
class DynamicMigrationLookup extends MigrationLookup {

  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $lookup_migration_id = $row->get($this->configuration['migration']);
    $this->configuration['migration'] = $lookup_migration_id;
    return parent::transform($value, $migrate_executable, $row, $destination_property);
  }

}

```
> -1 votes

---
Tags: 8, migrations
---


# Question
Title: Programmatically append multiple paragraphs to entity reference field on node
I have a paragraph type that contains a text field and a text format field. I also have a content type that takes an unlimited number of paragraphs of this type.

The paragraph type is called 'questions\_and\_answers' and the two fields are 'field\_question' and 'field\_answer'. I'd like to be able to programmatically append 'questions\_and\_answers' paragraphs to a content type.

In the example below I'm grabbing the content from a 'double' field and importing them into the paragraph reference field. Here's my code so far.

```
    $nids = \Drupal::entityQuery('node')
        ->condition('type', 'faq')
        ->execute();
    foreach ($nids as $nid) {
        $node      = \Drupal\node\Entity\NODE::load($nid);
        $questions = $node->field_questions_and_answers->getValue();
        foreach ($questions as $question) {
            $q         = $question['first'];
            $a         = $question['second'];
            $paragraph = Paragraph::create([
                    'title'          => $q,
                    'type'           => 'questions_and_answers',
                    'field_question' => $q,
                    'field_answer'   => $a,
                ]);
            $paragraph->save();
            $node->field_qs_and_as[] = $paragraph->id();
        }
        $node->save();
    }

```

However when I perform this action the node gets a number of question paragraphs added but they're completely empty and they can't even be deleted. What am I missing? How do you append multiple paragraphs you created to an entity reference field on a node?

# Answer
> 14 votes
When you add a paragraph you also need to pass the revision id:

```
  $node->field_qs_and_as[] = [
    'target_id' => $paragraph->id(),
    'target_revision_id' => $paragraph->getRevisionId(),
  ];

```

# Answer
> 4 votes
I've found it preferable to pass the entity object instead of manually setting the IDs yourself:

```
$node->field_qs_and_as[] = $paragraph;
$node->save();

```

Only make one call to $node-\>save() of course, after you've added/edited all the paragraph entities you want.

The primary reason for this is that when I set the reference array values instead, at least in the case of a newly created paragraph, the paragraph does not end up with a parent entity set. If you later need to call $paragraph-\>getParentEntity() or otherwise make use of Paragraphs' ability to trace the relationship in the reverse direction, that will be a problem.

I haven't looked at the code paths but it makes sense that if you call -\>save() on the Paragraph it will not be able to detect a parent on its own. I would imagine the Entity Reference Revisions code handling array values then assumes that the relationship must already established on the child entity, if it's being passed existing IDs instead of an object.

# Answer
> 0 votes
I spent hours make it work, the problem was when adding a paragraph to my multivalues node field, the existing values were lost. I finally came to this working solution (retrieving existing paragraphs and adding them back together with the new paragraph), but I feel I'm missing something...

```
$currentUser = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
$product = Node::load($form_state->getValue('product_id'));

//create new ordered_item paragraph
$order = Paragraph::create(['type' =>'item_ordered']);
$order->field_item_ordered_number = $form_state->getValue('quantity');
$order->field_item_ordered_product = $product->id();
$order->uid = $currentUser->id();
$order->save();

$order_items[] = [
'target_id' => $order->id(),
'target_revision_id' => $order->getRevisionId(),
];

//check if user has already a cart
$cart=\Drupal::service('dpnews_home.get_user_infos')->getUserCart($currentUser);

foreach ($cart->field_ordered_item as $item) {
  $existing_order=$item->entity;
  $order_items[] = [
  'target_id' => $existing_order->id(),
  'target_revision_id' => $existing_order->getRevisionId(),
  ];
}
//if not create new cart for user
if(!isset($cart)){
  $cart = Node::create(['type' => 'panier']);
  $cart->uid = $currentUser->id();
  $cart->title= 'Panier en cours - utilisateur '.$currentUser->id();
  $cart->save();
}

//add ordered item to cart
$cart->set('field_ordered_item',$order_items);
$cart->save();

```

---
Tags: 8, nodes, entities, paragraphs
---


title: Pager element not showing on form

text:
# Question
Title: Pager element not showing on form
I have a simple tableselect element inside my form and the tableselect rows are populated using a pager as follows:

```
$pagerLimit = 10; //default value if nothing is passed in
$query = $this->jobSkillStorage->getQuery();
$query->condition('type', $skillType);
$query->pager($pagerLimit)
$ids = $query->execute();
$jobSkills = $this->jobSkillStorage->loadMultiple($ids);

return $jobSkills;

```

The pagination limit functions well and only 10 results are returned, however the pagination controls do not show after the tableselect. Please see the full code of how the tableselect was generated.

```
public function buildForm(array $form, FormStateInterface $form_state) {

  $form['vtabs'] = [
    '#type' => 'vertical_tabs',
  ];

  $form['tech_skills' = [
    '#type' => 'details',
    '#title' => $this->t('Tech Skills'),
    '#group' => 'vtabs',
    'tech_skills_table' => [
      '#type' => 'tableselect',
      '#empty' => $this->t('Your search for tech skills did not return '
          . 'any results.'),
      '#header' => [
        'name' => $this->t('SKILL NAME'),
        'description' => $this->t('DESCRIPTION'),
        'status' => $this->t('STATUS'),
        'changed' => $this->t('LAST UPDATED'),
        'actions' => $this->t('ACTIONS')
      ],
      '#options' => $this->getTableOptions(),
    ],
    'tech_skills_pager' => [
      '#theme' => 'pager',
    ],
  ];

  return $form;

```

Most examples of paging I see use $build\['pager'\] rather than $form\['pager'\]. I'm just wondering if pager isn't a form renderable element? Could that be the reason its not showing? Kinda lost on this. Any thoughts please?

Thanks

# Answer
I believe you need to use `#theme` rather than `#type`. `#type` is for form elements, `#theme` is for themeable elements, that are outside (and also sometimes inside) forms.

As another example, `table` is a `#theme`, whereas `tableselect`, which is a table with form elements, is a `#type`.
> 0 votes

---
Tags: 8, forms
---


title: Sorting Custom Content Type

text:
# Question
Title: Sorting Custom Content Type
Apologies if this question has been asked but I can't seem to find an answer anywhere. I am looking to sort a content type called biography. My understanding is that this is likely a custom entity and does not come with Drupal Core.

We currently use it to add leadership information such as (ceo, assistant, admin) position. Currently, the sorting function in views is standard (ascending -authored on) so new biography content is added to the bottom of a page block.

I do not have permission to download any new modules but want to create a custom sort in a hierarchy format (the highest job title first - i.e. ceo).

Can someone share how I might be able to do this? I assume it would be the same as sorting article nodes

# Answer
> 0 votes
First, go to the edit page for the view.

There, under **Sort criteria**, you will find an **Add** button.

If you click the **Add** button, a window will appear that lists all the fields you can use to sort the view. If **Job title** is a field, you can add it as a sort criteria and then sort by that field.

How you can sort by that field depends on what type of field it is. For a standard text field, you will only be able to sort ascending/descending; this is because Drupal has no way to tell what the order is.

If you want to set the order of the fields such as

1. CEO
2. Executive Assistant
3. CFO

then this will not work if you are using a text field.

**How to do it with taxonomy**

One good way to do this is:

1. Create a taxonomy vocabulary, **Job title**.

* Assign weights to the taxonomy terms in the order you want them to be sorted.

3. Add the taxonomy vocabulary as an entity reference field to the **Biography** content type.
4. Add a relationship to the referenced taxonomy vocabulary to the view.
5. As the sort criteria, use the referenced taxonomy term weight.

**A simpler way**

Another way to do this that is faster to set up but that will be harder to maintain down the line is to give up on sorting by the text field and add a custom weight field to the content type.

Specifically:

1. On the **Biography** content type "manage fields" page, add a new **Integer** field. Call it something like **weight** or **sort**.
2. On "Manage display" for the **Biography** content type, hide the **weight** field. (because we do not want to show this field)
3. Now the annoying part-- you have to edit all **Biography** content and assign the weight manually.
4. Then, in your view, as the sort criteria, sort by weight (ascending or descending, whichever makes sense for the way you assigned weights).

Obviously, when assigning weights manually like this it is easy to make a mistake, so I don't recommend this way, but it is probably the fastest way to get what you want.

---
Tags: views
---


# Question
Title: substitute for \Drupal\file\Entity\File::load($fid) in Drupal 8.9
My goal is to load a file and get its properties.

The method 'Load' does not exist any more in Drupal 8.9 (in the File.php file)

`\Drupal\file\Entity\File::load($fid);`

What would be the substitute for this function?

I'm using \<theme\_name\>*preprocess\_views*\<field\_name\> hook to override the output of a view. From here I'm able to retrieve the file id by using

`$fid = $variables['field']->getValue($variables['row'])[0];`

With the file id, my plan is to load the file and retrieve all its properties, such as label, uri, etc.

Searched the web and all recommendations are to use `\Drupal\file\Entity\File::load($fid);`

however, this method no longer exists Drupal 8.9

How would I go to load this file and get its properties??

Thanks!

# Answer
All entity types, of which `\Drupal\file\Entity\File` is one, have a static `load()` method. This comes from `EntityBase::load()`, and is present throughout all versions of Drupal 8 and 9.

You can keep using that method, it's not going anywhere, but alternatively you can use the entity type manager service, e.g.

```
$storage = \Drupal::entityTypeManager()->getStorage('file');
$file = $storage->load($fid);

```

Note that the service should be injected if your code is in a context which allows it.
> 4 votes

---
Tags: 8
---


# Question
Title: Menu item extras field in page.html.twig
I need a background image per menu item. For this I'm using menu\_item\_extras. I added an image field to menu items. This field I'd like to use in page.html.twig.

How can I use this field in this template?

# Answer
I got it with a views block. I use a contextual filter for the menu link entity id and filter by active menu item id. It works as expected.
> 0 votes

---
Tags: theming, navigation
---


title: Check minimum checked Checkboxes

text:
# Question
Title: Check minimum checked Checkboxes
i am new to the drupal world.

I have created a web form, there are several checkboxes there. like:

```
[1]
[2]
[3]
[4]

```

I would like to check whether at least X of the checkboxes are selected before sending. I have no idea how to set it up.

I would be very happy to hear from you.

Thanks very much

# Answer
If you really only need one item to be checked, setting the field as required would be the only thing you need to do. When you are in build mode of the webform and you click the element that needs this setting, there is a section called "FORM VALIDATION." If you click to expand this, there is a checkbox to make it required.

Update: the Webform documentation shows how to add custom validation to a Webform.
> 0 votes

---
Tags: 8, webforms
---


# Question
Title: Possible to add end points using REST UI module?
I'm using the REST UI module with Drupal 9 with a view. Right now I have my default path which is /api/directory, and this has the fields I want in the API, for example title.

Is it possible to create an endpoint such as /api/directory?title=""

So that way instead of loading all the data on my site, I can only load what is necessary?

# Answer
Yes, you can create custom REST endpoints, but not with the REST UI module; you need to write your own code and put it in a custom module.
> 0 votes

---
Tags: 9
---


title: How do I add a field to a node form?

text:
# Question
Title: How do I add a field to a node form?
The goal is to set a default counter, but let people override it. The counter should be the biggest value of the field plus 1.

Using an event subscriber, FORM ALTER event.

```
public static function getSubscribedEvents(): array {
  return [
    HookEventDispatcherInterface::FORM_ALTER => 'setDefaultCbid',
    HookEventDispatcherInterface::ENTITY_PRE_SAVE => 'checkCbiRaceCondition'
  ];
}

public function setDefaultCbid(FormAlterEvent $event) {

  $form_id = $event->getFormId();
  if ($form_id !== 'node_bond_edit_form') {
    return;
  }

  $result = \Drupal::database()
    ->query('select max(field_bond_cbid_value) from {node__field_bond_cbid}')
    ->fetchField();

  if ($result) {
    $cbid = $result + 1;
  }
  else {
    $cbid = 1;
  }

  $form = &$event->getForm();
  $form_already_alterered = false;
  if (array_key_exists('field_bond_cbid_default', $form)) {
    $form_already_alterered = TRUE;
  }
  $form['field_bond_cbid_default'] = [
    '#title' => $this->t('default cbid'),
    '#type' => 'number',
    '#value' => $cbid,
  ];

  if (!$form_already_alterered) {
    $form['field_bond_cbid']['widget'][0]['value']['#default_value'] = $cbid;
  }
}

```

This works fine. The value is set and the "default" field visible in the adjusted form

What happens if a second person edits another node and increments the counter whINCORRECTCODEile the form is displayed? This is where *field\_bond\_cbid\_default* is not available on the entity

```
public function checkCbiRaceCondition(EntityPresaveEvent $event) {

  $bond = $event->getEntity();
  if ($bond->bundle() !== 'bond') {
  return;
}

$enteredValue = $bond->get('field_bond_cbid')->getString();
$defaultCbid = $bond->get('field_bond_cbid_default')->getString();
if ($enteredValue != $defaultCbid) {

```

How do I access the default value?

# Answer
The form alter event is the wrong event for checking data. Instead of trying to deal with the form, use the backing entity.

On form alter event add a submit handler

```
$form['actions']['submit']['#submit'][]  = [$this, 'checkCbid'];

```

Check that the value is the latest on submit

```
public function checkCbiRaceCondition(&$form, FormState &$form_state) {
  $enteredValue = $form_state->getValue('field_bond_cbid')[0]['value'];
  $defaultCbid = $form['field_bond_cbid']['widget'][0]['value']['#default_value'];
  if (intval($enteredValue) != $defaultCbid) {
    return;
  }

  $result = \Drupal::database()
    ->query('select max(field_bond_cbid_value) from {node__field_bond_cbid}')
    ->fetchField();

  if ($result) {
    $cbid = $result +1;
  } else {
    $cbid = 1;
  }

  $form_state->set('field_bond_cbid', $cbid);
}

```
> 2 votes

---
Tags: forms, webforms
---


# Question
Title: How to override a class method that is not a service?
Usually we override services using RouteSubscribers, but i need to override a method of a class that is not a service. I need to alter the module of the core "views", the general structure of this module is:

```
> views
  > src
    > Entity
      > Render
        - ConfigurableLanguageRenderer.php
        - EntityTranslationRenderTrait.php

```

I need to override one method of one of those files.

In ConfigurableLanguageRenderer.php i need to override "getLanguage()" method or in EntityTranslationRenderTrait.php i need to override "getEntityTranslation()" method, but i don't know how override a trait or a class that is not a service, is that possible? Thanks.

**--- More context ---**

A hook\_language\_fallback\_candidates\_OPERATION\_alter() was implemented and we have a custom priority candidates to return the content translated, but one validation in the views module broke my custom fallback candidates.

**E.G:** if the content was written in English(en), and you send in the view rest the parameter lang=en, the view will be skip to search the translation in the candidates and the hook\_language\_fallback... doesn't be executed because if you looking for a node in english and this article has english as default is not necessary to search translation and this return the original language of the content.

Then i need to alter the langcode that return `$this->getEntityTranslationRenderer()->getLangcode($row)`

* ConfigurableLanguageRenderer.php

```
public function getEntityTranslation(EntityInterface $entity, ResultRow $row) {
  // We assume the same language should be used for all entity fields
  // belonging to a single row, even if they are attached to different entity
  // types. Below we apply language fallback to ensure a valid value is always
  // picked.
  $translation = $entity;
  if ($entity instanceof TranslatableInterface && count($entity->getTranslationLanguages()) > 1) {
    $langcode = $this->getEntityTranslationRenderer()->getLangcode($row);
    $translation = $this->getEntityRepository()->getTranslationFromContext($entity, $langcode);
  }
  return $translation;
}

```

So i need to alter those methods or alter the default language of the node, or if it's possible alter "context" to enter to the following validation: `($entity->language()->getId() != $langcode)`

```
public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = []) {
    $translation = $entity;

    if ($entity instanceof TranslatableDataInterface && count($entity->getTranslationLanguages()) > 1) {
      if (empty($langcode)) {
        $langcode = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
        $entity->addCacheContexts(['languages:' . LanguageInterface::TYPE_CONTENT]);
      }

      // Retrieve language fallback candidates to perform the entity language
      // negotiation, unless the current translation is already the desired one.
      if ($entity->language()->getId() != $langcode) {
        $context['data'] = $entity;
        $context += ['operation' => 'entity_view', 'langcode' => $langcode];
        $candidates = $this->languageManager->getFallbackCandidates($context);

        // Ensure the default language has the proper language code.
        $default_language = $entity->getUntranslated()->language();
        $candidates[$default_language->getId()] = LanguageInterface::LANGCODE_DEFAULT;

        // Return the most fitting entity translation.
        foreach ($candidates as $candidate) {
          if ($entity->hasTranslation($candidate)) {
            $translation = $entity->getTranslation($candidate);
            break;
          }
        }
      }
    }

    return $translation;
  }

```

**-- Update --**

as @4k4 mentioned i overwritten the service EntityRepository.php and that solved my problem

```
class GlobalizationServiceProvider extends ServiceProviderBase {

  /**
  * {@inheritdoc}
  */
  public function alter(ContainerBuilder $container) {
    if ($container->hasDefinition('entity.repository')) {
      $definition = $container->getDefinition('entity.repository');
      $definition->setClass('Drupal\Globalization\CustomEntityRepository');
    }
  }
}

```

# Answer
The first class is hard coded in the second class and the second class is a trait used in different field and row plugins. So you need to target one of those plugins. There are several ways. The preferred one is to assign a custom plugin ID to the extended plugin class and configure it in your custom View. If you want to override the plugin class in general see How do I replace a plugin?

---

The last method you've added in **more context** is in a service and you can implement `MyEntityRepository::getTranslationFromContext()` and then swap the class in a ServiceProvider (not RouteSubcriber): See altering existing services.
> 1 votes

---
Tags: 8, views
---


# Question
Title: How do I create a breadcrumb with the taxonomy terms used by the node?
I created a vocabulary for the nodes.

>

I installed the Easy Breadcrumb module.

When a node is tagged, for example, with *Crypto* and *ICO*, the breadcrumb should be the following one.

> Accueil \>\> Crypto \>\> ICO \>\> Node Title

> Home \>\> Term \>\> Sub-term \>\> Node Title

Nodes will only have a single term or a term and a sub-term.

Currently it does not work.

>

I also installed the Taxonomy Menu module.

The structure of the taxonomy is therefore exactly the same as that of the main menu, but nodes aren't attached to menus.

Does anyone have a solution?

# Answer
> 0 votes
I think you want Menu Breadcrumb instead of Easy Breadcrumb. This way, your breadcrumb trail is based on a menu, not the URL path. Then, use it in conjunction with Taxonomy Menu.

---
Tags: taxonomy-terms, 9, breadcrumbs
---


title: Redirect Anonymous user to login page

text:
# Question
Title: Redirect Anonymous user to login page
I want if user not logged in and visit any page of my website **except my REST VIEWS routers** I redirect him/her to login page in drupal 8, I found this solutions for drupal 7 but didn't find any solution for Drupal 8,

# Answer
You can test a user's status very early with event subscriber in a custom module that subscribes to KernelEvents::REQUEST.

First, you register the event subscriber in `mymodule.services.yml` in your module folder:

```
services:
  mymodule.event_subscriber:
    class: Drupal\mymodule\EventSubscriber\RedirectAnonymousSubscriber
    arguments: []
    tags:
      - {name: event_subscriber}

```

Then add `RedirectAnonymousSubscriber.php` for your custom event subscriber in your module in the `/src/EventSubscriber/` folder.

```
namespace Drupal\mymodule\EventSubscriber;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Event subscriber subscribing to KernelEvents::REQUEST.
 */
class RedirectAnonymousSubscriber implements EventSubscriberInterface {

  public function __construct() {
    $this->account = \Drupal::currentUser();
  }

  public function checkAuthStatus(GetResponseEvent $event) {

    if ($this->account->isAnonymous() && \Drupal::routeMatch()->getRouteName() != 'user.login') {

      // add logic to check other routes you want available to anonymous users,
      // otherwise, redirect to login page.
      $route_name = \Drupal::routeMatch()->getRouteName();
      if (strpos($route_name, 'view') === 0 && strpos($route_name, 'rest_') !== FALSE) {
        return;
      }

      $response = new RedirectResponse('/user/login', 301);
      $event->setResponse($response);
      $event->stopPropagation();
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkAuthStatus');
    return $events;
  }

}

```
> 24 votes

# Answer
First, create a service for your event subscriber in `module-name.services.yml`

**Code** -

```
services:
    [MODULE-NAME]_event_subscriber:
        class: Drupal\MODULE-NAME\EventSubscriber\[Event-Subscriber-class]
        tags:
        - {name: event_subscriber}

```

Create your own eventsubscriber class inside `modules/module-name/src/EventSubscriber` directory:

```
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class Event-Subscriber-class implements EventSubscriberInterface {

  private $redirectCode = 301;

  public function checkForRedirection2(GetResponseEvent $event) {
    $account = \Drupal::currentUser();
    if (empty($account->id()) {
      $response = new RedirectResponse('/', $this->redirectCode);
      $response->send();
      exit(0);
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkForRedirection2');
    return $events;
  }
}

```
> 9 votes

# Answer
On Drupal 8.3.3, this code causes an endless redirection. I've fixed that by adding that instead.

```
..
$response = new RedirectResponse('/user/login', 301);
$response->send();
..

```
> 8 votes

# Answer
This answer is compatible for Drupal 8, and 9.

First, you register the event subscriber in `redirect_anonymous_users.services.yml` in your module folder (taken from **@oknate**'s answer):

```
services:
  redirect_anonymous_users.event_subscriber:
    class: Drupal\redirect_anonymous_users\EventSubscriber\RedirectAnonymousSubscriber
    arguments: []
    tags:
      - {name: event_subscriber}

```

Then add RedirectAnonymousSubscriber.php for your custom event subscriber in your module in the `/src/EventSubscriber/` folder.

```
namespace Drupal\redirect_anonymous_users\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

/**
 * Event subscriber subscribing to KernelEvents::REQUEST.
 */
class RedirectAnonymousSubscriber implements EventSubscriberInterface {

  public function checkAuthStatus(GetResponseEvent $event) {
    if (
      \Drupal::currentUser()->isAnonymous() &&
      \Drupal::routeMatch()->getRouteName() != 'user.login'
    ) {
      $response = new RedirectResponse('/user/login', 302);
      $response->send();
    }
  }

  /**
   * {@inheritDoc}
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkAuthStatus');

    return $events;
  }

}

```
> 2 votes

---
Tags: 8, routes, redirection, event-subscribers
---


# Question
Title: How to use custom HTML code for a front page
I want to use custom HTML code for a front page in drupal 8 but I am a bit lost of how to do it. Is it possible to just insert a piece of HTML code in a basic page content? Or what is the best way to do it? I have full access to the server and I can modify any file if needed. Thank you.

# Answer
> 1 votes
You can make any node be the front page. So, if you have a basic page with a body field, you can place your html there. Then, go to admin \> configuration \> system (basic site settings) and set the path to your node as the front page such as /node/6.

---
Tags: 8
---


title: Drush script memory problem

text:
# Question
Title: Drush script memory problem
I'm running a long drush script and its causing memory problems.

Then I tried debbuging it and I have this very simple code:

```
$query = \Drupal::entityTypeManager()->getStorage('user');

foreach ($emails as $i => $email) {
    $users = $query->loadByProperties(['mail' => $email]);
    $user = reset($users);

    unset($user);
    unset($users);
}

```

When I ran the script I noticed that the memory increases dramatically as the script is running. What is causing this memory issue?

# Answer
The memory issue is caused by the internal entity cache which you can release by using $storage-\>resetCache().

You've named the user storage $query, so replace the unset() commands with:

```
$query->resetCache([$user->id()]);
$query->resetCache(array_keys($users));

```

Recently core added the advice to use the entity.memory\_cache service instead, to only clear the in-memory cache and not invalidate the entities in the database:

```
\Drupal::service('entity.memory_cache')->deleteAll();

```

This is more efficient, in your script and also for subsequent loads of the entities.

Reference: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21ContentEntityStorageBase.php/function/ContentEntityStorageBase%3A%3AresetCache/9.2.x
> 7 votes

---
Tags: 8, drush
---


# Question
Title: How can I fix this query error with drush sql-sync?
I crafted my drush/sites/self.site.yml like below\* and verified that `drush rsync @prod:%files @self:%files` worked. However, `drush sql-sync @prod @self` results in the following error:

```
  The command "/usr/local/bin/drush sql-query --strict=0 --file=/tmp/termitral_db_20211011_110905.sql.gz --file-delete --uri=drupal --root=/var/www/drupalvm/drupal/web" failed.

  Exit Code: 1(General error)

  Working directory:

  Output:
  ================

  Error Output:
  ================

  In SqlCommands.php line 199:

    Query failed.

  sql:query [--result-file [RESULT-FILE]] [--file FILE] [--file-delete] [--extra EXTRA] [--db-prefix] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-d|--debug] [-y|--yes] [--no] [--remote-host REMOTE-HOST] [--remote-user REMOTE-USER] [-r|--root ROOT] [-l|--uri URI] [--simulate] [--pipe] [-D|--define DEFINE] [--database [DATABASE]] [--target [TARGET]] [--db-url DB-URL] [--notify [NOTIFY]] [--druplicon] [--xh-link XH-LINK] [--] <command> [<query>]

```

On closer look (aka verbose), I noticed this\** and I was told on Drupal Slack that `--file` only takes an uncompressed SQL file (I later verified this). So my question is, how can I fix this dreadful error?

*

```
prod:
  host: example.com
  user: user
  root: /data/web/public_html/web
  uri: default
  paths:
   - files: sites/default/files

```

\**

```
// Copy new and override existing files at
// /tmp/termitral_db_20211011_103342.sql.gz. The source is
// termitral@termitral.com:/data/web/drush-backups/termitral_db/20211011103342/
// termitral_db_20211011_103342.sql.gz?: yes.

and

The command "/usr/local/bin/drush sql-query --strict=0 --file=/tmp/termitral_db_20211011_103342.sql.gz --file-delete --uri=drupal --root=/var/www/drupalvm/drupal/web" failed.

```

# Answer
> 1 votes
More information about others with the same problem (https://github.com/drush-ops/drush/issues/4319#issuecomment-790558557)

---

There are two ways to solve this:

* Upgrade drush to v10 (better even would be 11)
(https://www.drush.org/latest/install/#drupal-compatibility)
* Or, patch your current drush using something like the following:

```
diff --git a/includes/drush.inc b/includes/drush.inc
index a8f356ff8..85d56f617 100644
--- a/includes/drush.inc
+++ b/includes/drush.inc
@@ -352,6 +352,7 @@ function drush_file_is_tarball($path) {
   $supported = [
     'application/x-bzip2',
     'application/x-gzip',
+    'application/gzip',
     'application/x-tar',
     'application/x-zip',
     'application/zip',

```

Good luck!

---
Tags: drush
---


# Question
Title: Redirecting Anonymous Users to external URL on Drupal 8 site
I am attempting to create a custom module that redirects anonymous/unauthenticated users away from the site. This site is only supposed to be used by admins, so in order to access it, they must type `/user/login` at the end of the url to be taken to a log in page.

I have my `mymodule.info.yml` file created as well as my `mymodule.module` file.

Then in `mymodule.services.yml` file I have:

```
services:
  redirect_unauthenticated_user.event_subscriber:
    class: Drupal\redirect_unauthenticated_user\EventSubscriber\RedirectAnonymousSubscriber
    tags:
      - {name: event_subscriber}

```

In my `/src/EventSubscriber` folder I have a `RedirectAnonymousSubscriber.php` file:

```
<?php

namespace Drupal\hid_redirect_unauthenticated_user\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Event subscriber subscribing to KernelEvents::REQUEST.
 */
class RedirectAnonymousSubscriber implements EventSubscriberInterface {
  public function checkAuthStatus() {

    if (\Drupal::currentUser()->isAnonymous() && \Drupal::routeMatch()->getRouteName() !== 'user/login') {

      $response = new RedirectResponse('google.com', 301);
      $response->send();
      return;
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkAuthStatus');
    return $events;
  }
}

```

Here, I am trying to check if the user is anonymous/unauthenticated and are not on the user/login page, redirect them to an external url (google.com for example here).

Finally, I have a `mymodule.routing.yml` file (which I'm not even sure if I need):

```
hid_redirect_unauthenticated_user.content:
  path: '/hid_redirect_unauthenticated_user'
  defaults:
    _controller: '\Drupal\hid_redirect_unauthenticated_user\EventSubscriber\RedirectAnonymousSubscriber::getSubscribedEvents'
  requirements:
    _access: 'TRUE'

```

Currently my site redirects even when I type /user/login at the end of my url. I apologize if this is all over the place but I've been playing with it for a while and feel like I'm confusing myself. Any help appreciated. Thanks!

# Answer
I know this question is old, and I might not help the OP, but I will leave a solution here for future reference.

The status code needs to be 302 instead of 301 since 301 is meant for permanent redirects which will cause bugs on your site. (meaning no matter what conditions and "if statements" you have, it will redirect. Even if you are logged in). You can read more about HTTP status codes here.

So you change this code: `$response = new RedirectResponse('google.com', 301);`

to this: `$response = new RedirectResponse('google.com', 302);` and everything should be good.
> 3 votes

# Answer
Your route name is incorrect. You are making a comparison of the path, rather than the route name:

```
\Drupal::routeMatch()->getRouteName() !== 'user/login'

```

The route name of the user login page is user.login, so you should use that:

```
\Drupal::routeMatch()->getRouteName() !== 'user.login'

```
> 1 votes

---
Tags: 8, users, redirection, event-subscribers
---


# Question
Title: redirect an old url that no longer exists related to a file to a new one
I have 2 urls: www.example.com/somefile.pdf www.example.com/somefileNew.pdf

the first one no longer exists, i want to redirect this url to the new one. I tried to use the redirect module to no avail as the module adds the site language to the url (ex: www.example.com/\**en\**) since the website is multilingual.

how can i achieve this? i tried https://www.drupal.org/project/media\_entity\_file\_redirect but cant seem to make it work.

# Answer
Ok somehow submodule Redirect 404 fixed this, you search for the old url that no longer exists, the submodule logs it, and from there you can redirect it to a new url.
> 0 votes

# Answer
Try a .htaccess or other web server redirect. If that won't work make sure to delete the old file and then try using the redirect module rule. You should be able to enter a redirect without specifying the language (leave as "All languages"
> 0 votes

---
Tags: files, redirection
---


# Question
Title: Is there a way to synchronize a webpage from another website into Drupal?
A restaurant has its menu database in Foodpanda.

The owner wants that menu to appear in the website.

* We can manually duplicate all menu courses from FoodPanda to Drupal, upload the same images, etc. each menu course as a standalone node of a *menu* content type and then add some module for purchasing courses from the website (as delivery).
* We might also be able to move the database from FoodPanda to a more "agnostic" menu as a service app such as *Delivery Hero* or *Deliverect* and then synchronize both Foodpanda and Drupal from there

But, it might be much better to somehow embed the menu webpage from Foodpanda into the website; the user would visit a node "menu" but the content of that node would be the menu webpage in Foodpanda, for example, embedding this entire webpage as is, in the "menu" webpage in Drupal; can this be done elegantly somehow?

# Answer
You have a few options here.

1. You can use a standard `<iframe>`. To use the `<iframe>` tag, you may need to adjust the text forms and editor settings at `/admin/config/content/formats`.
2. You can use the Iframe module. This creates a field that you can add to your node content type, and then you can add iFrames to each piece of content by entering a value for this field. In your case, since it's only one page, using a module like this is probably overkill, but it provides some nice options in the UI like how big to make the iframe, so your client may want this feature.
3. You can just add a Drupal menu link directly to Foodpanda; Drupal allows you to put off-site menu links in menus.
> 0 votes

---
Tags: nodes, javascript, 9
---


# Question
Title: How to override node add template for custom content type?
I have a custom content type named called "circular". For Admin user the "circular" node add form is opening using administration theme (i.e. Seven). But for Authenticated user the node add form is opening using my custom theme. I want to override template of the node add/edit form the custom theme.

I created page--node--add.html.twig in the template folder of the custom theme and used {{ form }} to render the form. But blank page is coming.

How do I fix this?

# Answer
This template will be used when a node edit form specifies 'node\_edit\_form' as its #theme callback. Otherwise, by default, node add/edit forms will be themed by form.html.twig.

Try this on your theme:

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

function YOURTHEME_form_node_form_alter(&$form, FormStateInterface $form_state) {
  $form['#theme'] = ['node_edit_form'];
}

```

After this your theme can read template node-edit-form.html.twig.

https://api.drupal.org/api/drupal/core%21themes%21classy%21templates%21content-edit%21node-edit-form.html.twig/8.2.x
> 2 votes

# Answer
Great tip, and what about the same but but a specific content type ? I don't want all content types node forms templates to be overwritten. (I'm on Drupal 9)
> -1 votes

---
Tags: 8, nodes
---


# Question
Title: Multi-lingual Webform, not entire website
Our client does not need their entire website to be translated into multiple languages. However, they have a webform that provides a number of different languages in a dropdown, and would like the form labels to be displayed in the chosen language.

Creating multiple versions of the form would be a maintenance headache. Is there a way to tap into Webform and Drupal's localization facilities without the complexity of introducing it to the entire website, so just in the scope of the form?

# Answer
You probably need to enable configuration translation to be able to easily translate webforms.
> 2 votes

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


# Question
Title: How to access the value of a Drupal\Core\StringTranslation\TranslatableMarkup object within a form?
I tried this : `dpm($button['#value']->string` but got this error: access protected property Drupal\Core\StringTranslation\TranslatableMarkup::$string

Within a form object I need to be able to read that value and also change it. how can I access it? thanks

# Answer
> 1 votes
By casting the object to a (string), you will get the value.

Example:

```
$op = (string) $form_state->getValue('op');

```

# Answer
> 3 votes
You can get the string value by calling the magic function `->__tostring()` or casting the object to a `(string)`. But most time you don't need to do this, because if you use the translation object in a string context it will return the translated string automatically.

You can't change the original string in the translation object. You have to generate a new one with the t-function:

```
$button['#value'] = $this->t('new text');

```

# Answer
> 2 votes
You can get the string value by using the following method.

```
getUntranslatedString()

```

So if you get the object as $link\_object then accessing the string would be done using

```
$link_object->getUntranslatedString();

```

# Answer
> 0 votes
Actually it is a combiantion of the answers of @yash-khandelwal and @binny.

`$form_state->getValue('op')->getUntranslatedString();`

---
Tags: forms, 8
---


# Question
Title: How can I have Behat create content with an address field properly filled?
I'm writting a Behat test, where I'm triying to create a content that uses a field address, generated by Address Module. I'm using Drupal 9.0.7, Address Module 1.9.0 and behat 3.8.1. My goal is to create this type of content in my scenario; I'm using a behat table for this, and a *Given* statement like the following.

```
Given place content:

  | title   | field_address:country_code |field_address:address_line1 | status |
  |<<title>>| es                         | Behat test street          | 1      |

```

field\_address:country\_code and field address:address\_line1 are sub-fields of the address field.

This way of naming the sub-fields doesn't seeem to work.

How should I have to name the table headers, in order to make Behat create content with a field address properly filled?

# Answer
> 0 votes
I'm a bit late to the party but here is the proper way of doing it.

```
And "CONTENT_TYPE" content:
  | title          | field_address                    |
  | Bert and Ernie | address_line1: Sesame Street 123 |

```

The supported options are:

```
$addressFields = [
  'given_name',
  'additional_name',
  'family_name',
  'organization',
  'address_line1',
  'address_line2',
  'postal_code',
  'sorting_code',
  'locality',
  'administrative_area',
  'country_code',
];

```

Which can be found in `\Drupal\Driver\Fields\Drupal8\AddressHandler::expand`

Currently there is a bug in `drupal/drupal-driver` so if you are using composer (which you should) you can apply the following patch. Otherwise you will get an error like "Notice: Undefined offset: 0"

```
"drupal/drupal-driver" : {
    "Issue #206: Address field in Drupal 8 (PR: 236/240)": "https://patch-diff.githubusercontent.com/raw/jhedstrom/DrupalDriver/pull/240.diff"
}

```

---
Tags: testing, 9
---


# Question
Title: Programmatically update an entity reference field
I know I can update (or set a value for) an entity reference field in Drupal 7 with code similar to the following.

```
 $node['field_code_used_by'][LANGUAGE_NONE][0]['target_id'] = $id;

```

I want to programmatically set a value for my user entity reference field in Drupal 8.

I tried with `$node->field_code_used_by->setValue(1);` and `$node->field_code_used_by->entity->value = 1;` but neither of them worked.

How can I set the value for an entity reference field?

# Answer
> 56 votes
You need to use code similar to the following.

```
    $node = Node::load($nid);
    $node->field_code_used_by->target_id = $user_id;
    $node->save();

```

For a multiple-value field, to add the value to the end of the list, use the following code.

```
$node->field_code_used_by[] = ['target_id' => $user_id];

```

Another way is setting the `entity` property with the entity object, as in the following code.

```
    $node = Node::load($nid);
    $user = \Drupal\user\Entity\User::load(1);
    $node->field_code_used_by->entity = $user;
    $node->save();

```

# Answer
> 19 votes
Like in D7 the main property of a reference field in D8 is still the `target id`:

```
$node->field_code_used_by->target_id = $user_id;

```

The `entity` property is a computed value. If you put an object in this value, drupal will convert it back to the id before saving it to the dababase.

**Multivalue fields**

Add an item to a multivalue field:

```
$node->field_code_used_by[] = ['target_id' => $user_id];

```

The property `target_id` is not necessary, because it is the main property and used by default. So for most fields you can add a value like in a simple php array, which is easy to remember:

```
$node->field_code_used_by[] = $user_id;

```

# Answer
> 8 votes
You should be aware of the difference between a single value field and a multiple value field. Code below shows how. Source: https://stefvanlooveren.me/blog/how-programmatically-update-entity-reference-field-drupal-8

```
$imageIds = [
  '3',
  '32',
  '50'
];
foreach($imageIds as $index => $fid) {
  if($index == 0) {
    $node->set('field_article_images', $fid);
  } else {
    $node->get('field_article_images')->appendItem([
      'target_id' => $fid,
    ]);
  }
}

```

# Answer
> 2 votes
For multi value fields you can use:

```
$node = Node::load(212);
$multi_value = $node->get('field_NAME')->getValue();
$multi_value[] =['target_id' => 101];
$node->set('field_NAME', $multi_value);
$node->save();

```

For single value fields you can use:

```
$node->set('field_NAME',['target_id' => 101]);

```

---
Tags: 8, entities
---


# Question
Title: How to use entityQuery with custom field type?
I am working on building a query for nodes that have a few custom fields (field types). The fields are custom build in a custom module with a custom schema. When I execute the query:

```
 $query = \Drupal::entityQuery('node')
    ->condition('type', 'place');
 $query->condition('my_custom_field', '', '<>');

```

It fails with a message indicating that: `node__my_custom_field.my_custom_field_value` does not exist (NOT found). This is correct the table has a custom schema for this field `_value` does not exist:

```
 drush sqlq "describe node__my_custom_field"

bundle  varchar(128)    NO  MUL
deleted tinyint(4)  NO  PRI 0
entity_id   int(10) unsigned    NO  PRI NULL
revision_id int(10) unsigned    NO  MUL NULL
langcode    varchar(32) NO  PRI
delta   int(10) unsigned    NO  PRI NULL
my_custom_field_title   text    YES     NULL
my_custom_field_description text    YES     NULL

```

How do I make my entity field query work with this field custom schema?

# Answer
> 3 votes
It looks like your custom field type has `title` and `description` columns rather than `value` (the default Drupal assumes if you don't tell it otherwise).

You can specify the field column to use with `.` notation like this:

```
$query->condition('my_custom_field.title', '', '<>');
$query->condition('my_custom_field.description', '', '<>');

```

If you want the system to consider, for example, the `title` property as the default instead of `value`, you can implement `FieldItemBase::mainPropertyName()` in your field class:

```
public static function mainPropertyName() {
  return 'title';
}

```

That would make your original line work for the `title` column:

```
$query->condition('my_custom_field', '', '<>');

```

---
Tags: entities, 9
---


# Question
Title: Anonymous user redirected to core/install.php while admin does not
As an admin I've built a large table on Drupal 8 (php, mysql). It runs without issues for Admin, but trying as Anonymous user it redirects me to core/install.php

Since it's ONLY affecting Anonymous users, I suspect it's DRUPAL 8 that's setting the limit. I want to find where Drupal does that. Anyone can give tips to the specific Drupal 8 files I can look into?

(Resist trying the max\_allowed\_packet = 64M for my.cnf) for the only reason that everything works flawlessly for the Admin side.

...when I shorten the table I've built, Anonymous users can see it an no redirects occur...

# Answer
> 0 votes
Solved. max\_allowed\_packet indeed. Just raised to 8M and it was enough.

In my case steps taken as follows:

* Log in to PHPmyAdmin
* Go to tab "Variables"
* locate "max allowed packet"
* Click Edit
* Replace the current value with "8388608" (that's 8M)
* Click "Save"
* No need to restart - works immediately.

---
Tags: 8, database, redirection
---


# Question
Title: Is it possible to set up Amazon advertising with the Media module?
I have a Drupal 9 site with the Media module enabled.

I have subscribed to the Amazon partner program.

Is there a solution to display Amazon iframe in Drupal? I am thinking of the Media module.

Many websites display the product name with the updated price in real time. I did not find anything to fire this.

My question :

Is it possible to set up Amazon advertising with Drupal 9 and the Media module?

# Answer
> 1 votes
I wouldn't use the media module for this because eventually your needs may get more complex and you'll want access to the Amazon Product Advertising SDK.

Thankfully there's a module that supports this already, Amazon Product Advertising.

It does not yet have a stable release for D9, but it's in active development (new beta released last week).

---
Tags: media, 9
---


# Question
Title: ('text/plain') is not a supported stylesheet MIME type
We just upgraded from Drupal 8 to Drupal 9, and now we have some css files not working in Chrome due to the below error.

> Refused to apply style from '' because its MIME type ('text/plain') is not a supported stylesheet MIME type, and strict MIME checking is enabled.

These css files are in the private files directory for the site. I've verified that the mime\_module is loaded as I can see this in the apache logs

> module mime\_module is already loaded, skipping

I also have `.htaccess` files enabled using `AllowOverride All` in the `httpd.conf`

I've tried putting the following in the `.htaccess` file in the parent directory of the css files, in our `/etc/httpd/conf.d/drupal.conf`, and in `/etc/httpd/conf/httpd.conf` but nothing fixes the error

```
AddType text/css .css
AddHandler text/css .css

```

and

`AddType 'text/css; charset=UTF-8' css`

and

```
<FilesMatch "(\.css)$">
    AddType text/css .css
    Header set Content-Type text/css
</FilesMatch>

```

Why won't apache set the correct `content-type`?

# Answer
> 2 votes
If the CSS files are in the private files directory this is not an Apache issue. Drupal controls access and serves the files via PHP. Normally files stored in the private directory are managed and the MIME type is specified in the database table file\_managed. If not, you can use hook\_file\_download to manage them on your own:

```
use Drupal\Core\StreamWrapper\StreamWrapperManager;

/**
 * Implements hook_file_download().
 */
function mymodule_file_download($uri) {
  $scheme = StreamWrapperManager::getScheme($uri);
  $target = StreamWrapperManager::getTarget($uri);
  if ($scheme == 'private' && substr($target, -4) == '.css') {
    return [
      'Content-Type' => 'text/css',
    ];
  }
}

```

This allows anybody to access CSS files in the private directory and also sets the MIME type.

---
Tags: .htaccess
---


# Question
Title: Use ajax to save modal / dialog form instead of page reload
I'm looking for a way to save modal & dialog forms through ajax instead of redirecting the user after the form submit. Ajax is quite unknown territory to me.

I've found several interesting topics here already:

jQuery UI Dialog attempt to submit a form using AJAX redirects me to the actual form page instead of AJAX submitting

How to close modal after form submit?

I tried all answers shown there, but without luck. I'm using Drupal 9 and it seems that the code can be slightly different between 8 & 9 versions. I tried digging in the documentation pages on drupal.org but can't seem to find anything useful to my case.

# Answer
> 0 votes
For anyone who cares, I got it working with following code in my custom 'cs\_modals' module:

```
 /**
 * Implements hook_form_alter().
 */
function cs_modals_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
    $request = \Drupal::request();
    // Check if Ajax request.
    if ($request->isXmlHttpRequest()) {
      $form['actions']['submit']['#ajax']['callback'] = '_cs_modals_id_submit_ajax_callback';
    }
}

/**
 * Custom Ajax callback.
 */
function _cs_modals_id_submit_ajax_callback(array &$form, FormStateInterface $form_state) {
  // If form is valid then close the dialog.
  if (!$form_state->hasAnyErrors()) {
    $response = new \Drupal\Core\Ajax\AjaxResponse();
    $response->addCommand(new \Drupal\Core\Ajax\CloseDialogCommand());
    return $response;
  }
  // Otherwise call the default #ajax callback.
  $form_object = $form_state->getFormObject();
  $response = $form_object->submitAjaxForm($form, $form_state) ;
  return $response;
}

```

Now, every form in a modal is submitted through Ajax. Now I'm looking for a way to automatically close the modal when the form is submitted succesfully or display an error message through Ajax when one or more required fields have no value. Any help on that would be appreciated!

---
Tags: forms, ajax, 9, modal-dialogs
---


# Question
Title: How to add link to translated content in text field
I need some help on a multilingual D9 site, trying to add links to translated node in text field. In German version should be a link to the English and French version of this node, as part of the node content.
And I need them absolute, because the nodes are used as newsletter content: https://example.de/en/node/123
I created link with language part in url, but when I view the node, the links are rendered without translation. The en/ and fr/ part in the url are stripped.
I'm using CKEditor for content creation.
Any help appreciated, thanks.

# Answer
I solved this problem by using an extra field without CKEditor to add translation links. The links are working and no language part is stripped from URL.
> 0 votes

---
Tags: i18n-l10n
---


# Question
Title: How to access url of Remote Video, Document and Image inside twig template?
I have a field called **Media** (machine name: field\_media) inside of a content type. This field Media takes the media types of Remote video, Image, and Documents. **I am currently trying to render this media inside my twig template as a link to whatever media type it is**. For example, if it's a remote youtube video, the link would take you to the video or if it's a pdf document, the link would take you to the internal page to display that document. Examples:

Document:  Remote video:

So inside my field twig template, grab the above values and for each item, place it inside an `href` attribute like so:

```
<div{{ item.attributes.addClass('field__item') }}><a href={{ url_of_internal_document_image_or_remote_video }}>{{ item.content }}</a></div>

```

Inside the `href` value I've tried values such as `node.field_media.entity.field_media_oembed_video.value` (for remote video) but that didn't work.

My twig template is displaying like this:  Which looks how I want but I can't get the link to take me to the remote vid or internal pdf.

Side note: In the Manage Display menu of my content type, I have this configuration for the field.

# Answer
After quite an extensive search and with help of https://www.drupal.org/project/twig\_vardumper this worked for me in a Paragraphs Twig template, to print out the remote URL of a youtube video; managed in the Drupal core Media module.

```
{{ paragraph.field_media_1.entity.field_media_oembed_video.entity.field_media_oembed_video.value }}

```

Replace `field_media_1` with the system name of your defined field.
> 3 votes

# Answer
The name of our field is `field_images` and we have this to display a thumbnail of our video. That if statement may be the key.

```
{% if content.field_images[0]["#media"].field_media_video_embed_field.0.value %}
  {{ drupal_image(content.field_images[0]["#media"].thumbnail.entity.uri.value, 'ourimagestyle') }}
{% else %}
  {{ content.field_images[0] }}
{% endif %}

```
> 1 votes

---
Tags: theming, media, 9
---


# Question
Title: How can I debug a Twig error that occurs after migrating from Drupal 8.9 to Drupal 9+
I am trying migrate my Drupal 8.9 site to Drupal 9+ and I am stuck with an error its cause I am not able to hunt down. On almost every page I get the following PHP exception:

```
Twig\Error\RuntimeError: The "replace" filter expects an array or

"Traversable" as replace values, got "string" in "__string_template__faabd18c7a37a1e54d0ef10115b24022e72bc201187fff502de48bf58589321f" at line 2. in twig_replace_filter() (line 554 of /var/customers/webs/freigeist/www9/vendor/twig/twig/src/Extension/CoreExtension.php).

__TwigTemplate_75ee113db094d36d71f294529e9d7055b2065bf116719e9a04b7e4795be3121d->doDisplay() (Line: 405)
Twig\Template->displayWithErrorHandling() (Line: 378)
Twig\Template->display() (Line: 390)
Twig\Template->render() (Line: 45)
Twig\TemplateWrapper->render() (Line: 235)
Drupal\Core\Template\TwigEnvironment->renderInline() (Line: 52)
Drupal\Core\Render\Element\InlineTemplate::preRenderInlineTemplate()
call_user_func_array() (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 786)
Drupal\Core\Render\Renderer->doCallback() (Line: 377)
Drupal\Core\Render\Renderer->doRender() (Line: 201)
Drupal\Core\Render\Renderer->render() (Line: 157)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 578)
Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 158)
Drupal\Core\Render\Renderer->renderPlain() (Line: 419)
Drupal\views\Plugin\views\PluginBase->viewsTokenReplace() (Line: 1356)
Drupal\views\Plugin\views\field\FieldPluginBase->renderAltered() (Line: 1249)
Drupal\views\Plugin\views\field\FieldPluginBase->renderText() (Line: 1177)
Drupal\views\Plugin\views\field\FieldPluginBase->advancedRender() (Line: 238)
template_preprocess_views_view_field() (Line: 287)
Drupal\Core\Theme\ThemeManager->render() (Line: 436)
Drupal\Core\Render\Renderer->doRender() (Line: 201)
Drupal\Core\Render\Renderer->render() (Line: 1745)
Drupal\views\Plugin\views\field\FieldPluginBase->theme() (Line: 778)
Drupal\views\Plugin\views\style\StylePluginBase->elementPreRenderRow()
call_user_func_array() (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 786)
Drupal\Core\Render\Renderer->doCallback() (Line: 377)
Drupal\Core\Render\Renderer->doRender() (Line: 201)
Drupal\Core\Render\Renderer->render() (Line: 717)
Drupal\views\Plugin\views\style\StylePluginBase->renderFields() (Line: 584)
Drupal\views\Plugin\views\style\StylePluginBase->renderGrouping() (Line: 475)
Drupal\views\Plugin\views\style\StylePluginBase->render() (Line: 2170)
Drupal\views\Plugin\views\display\DisplayPluginBase->render() (Line: 1533)
Drupal\views\ViewExecutable->render() (Line: 183)
Drupal\views\Plugin\views\display\Page->execute() (Line: 1630)
Drupal\views\ViewExecutable->executeDisplay() (Line: 81)
Drupal\views\Element\View::preRenderViewElement()
call_user_func_array() (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 786)
Drupal\Core\Render\Renderer->doCallback() (Line: 377)
Drupal\Core\Render\Renderer->doRender() (Line: 201)
Drupal\Core\Render\Renderer->render() (Line: 241)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 578)
Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare() (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse() (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray()
call_user_func() (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch() (Line: 163)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 57)
Drupal\Core\StackMiddleware\Session->handle() (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch() (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup() (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 23)
Stack\StackedHttpKernel->handle() (Line: 717)
Drupal\Core\DrupalKernel->handle() (Line: 19)

```

I found out that the error might be theme related (I am on Bootstrap). And on some pages I could narrow it down to the system block 'site\_branding': Disabling this block makes the error disappear on some pages, but not on all.

My first guess was, that this might be an twig compatibility issue (may be in my bootstrap sub-theme), but it occurs also when I use other themes. So I am completely lost here.

How could I debug this error? Does the error message show, which component could be the cause of the error? Can anybody point out, which change between Drupal 8 and 9 could be responsible of the error?

# Answer
> 4 votes
This is the last line in the stack trace before the render pipeline is throwing the error:

```
Drupal\views\Plugin\views\PluginBase->viewsTokenReplace() (Line: 1356)

```

This might be caused by a `|replace` filter rewriting a Views field in the View you are trying to display as main content of the page.

See the deprecation warning in Drupal 8.9 (Twig 1.x):

```
function twig_replace_filter($str, $from, $to = null) {
  if (\is_string($from) && \is_string($to)) {
    @trigger_error('Using "replace" with character by character replacement is deprecated since version 1.22 and will be removed in Twig 2.0', E_USER_DEPRECATED);

```

https://api.drupal.org/api/drupal/vendor%21twig%21twig%21src%21Extension%21CoreExtension.php/function/twig\_replace\_filter/8.9.x

Drupal 9 has upgraded to Twig 2.x

https://api.drupal.org/api/drupal/vendor%21twig%21twig%21src%21Extension%21CoreExtension.php/function/twig\_replace\_filter/9.2.x

---
Tags: migrations, 9, debugging
---


title: Adding a 'OR' condition to query

text:
# Question
Title: Adding a 'OR' condition to query
I need to add a OR condition to my query so that I can get all nodes related to a particular term. Here is what I have done :

```
$query = \Drupal::database()->select('taxonomy_index', 'ti');
$query->fields('ti', ['nid']);

// OR CONDITION
$or_group = $query->orConditionGroup()->condition('ti.tid', $params[1], 'IN');

$query->condition('ti.tid', $params[0], 'IN');
$query->condition('ti.status', 1);

// Added OR CONDITION TO QUERY.
$query->condition($or_group);

$query->execute()->fetchAllAssoc('nid');

```

This is the how the query get build :

> ## QUERY
>
> SELECT ti.nid AS nid
>
> FROM {taxonomy\_index} ti
>
> WHERE (ti.tid IN (:db\_condition\_placeholder\_0))
>
> AND (ti.status = :db\_condition\_placeholder\_1)
>
> AND (ti.tid IN (:db\_condition\_placeholder\_2));
>
> ## PARAMS
>
> Array (
>
> \[:db\_condition\_placeholder\_0\] =\> 170
>
> \[:db\_condition\_placeholder\_1\] =\> 1
>
> \[:db\_condition\_placeholder\_2\] =\> 227
>
> );

As you can see the last "AND" condition should be "OR".

Thanks.

# Answer
If you really want to use an or then it should be

```
$query = \Drupal::database()->select('taxonomy_index', 'ti');
$query->fields('ti', ['nid']);

// OR CONDITION
$or_group = $query->orConditionGroup()
  ->condition('ti.tid', $params[1], 'IN')
  ->condition('ti.tid', $params[0], 'IN');

$query->condition('ti.status', 1);

// Added OR CONDITION TO QUERY.
$query->condition($or_group);

$query->execute()->fetchAllAssoc('nid');

```
> 1 votes

# Answer
The solution seemed to be putting the explicit "IN" in the query, making the simplified version:

```
$entity_ids = $query
    ->condition('attributes.color', array('red', 'green'), 'IN')
    ->condition('attributes.building_type', 'bikeshed')
    ->execute();

```
> 0 votes

---
Tags: 8, database
---