# Question
Title: What is the right way to force a session start?
I'm currently porting SimpleFBConnect module to Drupal 8. This module uses Facebook PHP SDK which expects that we have established a session before the user is redirected to Facebook for authentication.

By reading SessionManager API, I assumed that SessionManager::start would start the session. However, this does not seem to be the case. The same thing applies to SessionManager::save (description says that this function will "Force the session to be saved and closed.").

The only way how I was able to force a session start was to call `SessionManager::regenerate`.

Is this the correct way to force session start in Drupal 8?

Debug code, which will show that SessionManager::start will not start the session.

```
class TestController extends ControllerBase {
  public function test() {
    $session_manager = Drupal::service('session_manager');
    $session_manager->start();

    if ($session_manager->isStarted()) {
      $msg = 'Sesssion started';
    }
    else {
      $msg = 'Sesssion not started';
    }

    return array(
      '#markup' => $msg
    );
  }
}

```

# Answer
> 2 votes
Drupal only starts a session if at the end of the request the `$_SESSION` super global contains any data. Empty sessions are actively destroyed. This is in order to maximize cache-hit ratios when operating a site behind a reverse proxy server (e.g. Varnish).

Like pointed out by @Berdir already, the proper way to trigger a session start in Drupal is to store something in it. However, the Facebook SDK tries to protect its users against data-loss due to improper session management. According to the source code, this feature can be disabled via the method FacebookRedirectLoginHelper::disableSessionStatusCheck(). Please use that instead of trying to enforce a session start.

# Answer
> 7 votes
Okay, found the answer from this change record: https://www.drupal.org/node/2228871

The session can be force-started like this:

```
// Force session start if we don't already have a session.
$session = \Drupal::service('session');
if (!$session->isStarted()) {
  $session->migrate();
}

```

# Answer
> 1 votes
I think the only way to force a session is to store something in it.

There's no point in manually starting it, since Drupal won't save a session that has no session data, AFAIK.

So try to just put a dummy key in $\_SESSION.

# Answer
> 0 votes
I know this is an old question but this showed up high in the search results when I was trying to figure out why even when I stored something in a user's session, it wasn't always actually creating a session when dealing with anonymous users. If you run into this same issue, it's very likely due to the Internal Page Cache core module caching things at such a low level that sessions don't get started if the page is already cached. To quote the documentation:

> Websites that serve personalized content to anonymous users (dynamic, per-session, e.g. a shopping cart) will want to disable the Internal Page Cache module. This module assumes pages are identical for all anonymous users. Those websites can still take advantage of the Dynamic Page Cache module\[.\]

The solution is to either disable the module (while using other forms of caching), or keep it enabled and possibly decorate the service to allow the request through to Drupal if no session is detected, allowing the session to be initialized (and thus a cookie sent), and then have subsequent requests served from the page cache. This assumes that your anonymous content is all identical and you only need sessions for back-end stuff that doesn't change the content itself. An example of this is if you're trying to keep track of which recent pages a user has just visited to avoid showing those when a user asks for a random page, which is something we have on Omnipedia.

---
Tags: 8, sessions
---


# Question
Title: Is the config object adapted to store datas from many users ( for the purpose of a subscription custom module )?
I have created a custom module that allows to subscribe to some news.

Each user ( and there will be thousands of them ) can register to some news category using that form

On form submit, the couple \[loti, emails\] is stored in a config object, as such:

```
 public function addSubscriberFromLot($lot, $userEmail) {
    $config = \Drupal::configFactory()
      ->getEditable('my_module_news_subscription.settings');
    $subscribersforLot = $config->get($lot);
    if ($subscribersforLot === null) {
      $config->set($lot, [$userEmail])->save();
    }
    elseif ($subscribersforLot !== null && !(in_array($userEmail, $subscribersforLot))) {
      array_push($subscribersforLot, $userEmail);
      $config->set($lot, $subscribersforLot)->save();
    }
  }

```

the config schema being

```
my_module_news_subscription.settings:
  type: mapping
  mapping:
    lot1:
      type: sequence
      label: ‘lot 1’
      sequence:
        type: string
        label: 'Email of subscribers'
    lot2:
      type: sequence
      label: ‘lot 2’
      sequence:
        type: string
        label: 'Email of subscribers'
    lot3:
      type: sequence
      label: ‘lot 3’
      sequence:
        type: string
        label: 'Email of subscribers'
    lot4:
      type: sequence
      label: ‘lot 4’
      sequence:
        type: string
        label: 'Email of subscribers'
    lot5:
      type: sequence
      label: ‘lot 5’
      sequence:
        type: string
        label: 'Email of subscribers'

```

Is there anything wrong with using that config object for that purpose ?

Can this withstand thousands of entries ?

Is there a more adapted way of store that datas ?

# Answer
Configuration defines your site. Users are not configuration, so neither would per-user settings be configuration.

If you need to save data per user, you can use the user.data service.
> 1 votes

---
Tags: configuration
---


title: How to add a class to the image tag

text:
# Question
Title: How to add a class to the image tag
The input in file field.html.twig is normally like this:

```
{% for item in items %}
<div{{ attributes }}>{{ item.content }}</div>
{% endfor %}

```

And you get the output in HTML like this:

```
<div><img src="path/to/image/image.png" alt="my wonderful image"></div>

```

But I want to add a class to img-tag. How do I receive the following output:

```
<div><img class="img-fluid" src="path/to/image/image.png" alt="my wonderful image"></div>

```

I am looking for a solution like this (solution in another post), but it is not working. Can anybody help?

# Answer
I'd prefer to avoid editing templates for such simple things as adding just classes. I'd recommend to edit templates only if you really need to make changes to the markup.

For adding a simple class to your image all you need is the following snippet placed in your custom (sub-)theme's `*.theme` file. (Replace `MYTHEME` with the actual machine name of your theme). This one identifies the image by its image style (so ensure to have an unique image style applied to your image):

```
/**
 * Implements template_preprocess_image().
 */
function MYTHEME_preprocess_image(&$variables) {

  // Check the image style.
  if ($variables['style_name'] == 'img_fluid') {

    // Set class.
    $variables['attributes']['class'][] = 'img-fluid';
  }
}

```

If you are fine with adding the class not to the `img` tag directly, but to its **wrapping container** you could also use the following snippet. You can broaden the if-request as you like to only fire on certain content types (as you maybe use the same field in other content types as well), p.e. check for `$variables['element']['#object']->bundle()`. Replace `field_MYIMAGE` with your actual field name.

```
/**
 * Implements template_preprocess_field().
 */
function MYTHEME_preprocess_field(&$variables) {

  // Check for your image field.
  if ($variables['element']['#field_name'] == 'field_MYIMAGE') {

    // Set class.
    $variables['attributes']['class'][] = 'img-fluid';
  }
}

```
> 7 votes

# Answer
You can first add theme suggestions for image elements based on the image style. Add this in your mytheme.theme file:

```
/**
 * Implements hook_theme_suggestions_HOOK_alter().
 *
 * Add theme suggestions for img elements.
 */
function mytheme_suggestions_image_alter(array &$suggestions, array $variables) {
  if (isset($variables['style_name']) && !is_null($variables['style_name'])) {
    $suggestion = 'image__' . $variables['style_name'];
    $suggestion = str_replace('-', '_', $suggestion);
    $suggestions[] = $suggestion;
  }
}

```

Then if you inspect your image you will see a theme suggestion based on the image style of that image. For example if you have an image style 'blog\_item\_teaser':

```
<!-- FILE NAME SUGGESTIONS:
   * image--blog-item-teaser.html.twig
   x image.html.twig
-->

```

so now you can copy image.html.twig into your own theme and rename it to image--blog-item-teaser.html.twig and you can add your class there:

```
<img{{ attributes.addClass('card-img-top') }} />

```

Of course, this will be applied to all images that use that image style.
> 3 votes

# Answer
You can first add attributes to your item and then add a class to it. Like this:

`{{ item.content, item.attributes.addClass('img-fluid') }}`
> 0 votes

# Answer
2 is correct. However; it comes with drawbacks. Namely, there is nothing in the array passed via $variables to differentiate one img field from another. In my case, I wanted to add classes to support Bootstrap functionality. BUT; I only want to do that in certain cases.

One line of jQuery did does the trick.

```
  $(".people-photo > img").addClass("card-img-top").removeAttr("width height");

```

And bonus: same line allowed me to easily get rid of height/width attributes that overrides Bootstrap.
> 0 votes

# Answer
In the view you created, select *URL to image* from *Formatter*.

>

Then, in the view template file, you can get the image URL using code similar to the following one.

```
<img class="img-fluid" src="{{ fields.field_cover_photo.content }}" alt="test">

```

*field\_cover\_photo* is the field machine name, in my case.
> 0 votes

---
Tags: 8, theming
---


title: How to exclude contents from migration

text:
# Question
Title: How to exclude contents from migration
I'm using Migrate to import entities.

I want to exclude rows based on a custom plugin (my source has a "url" field and I've to check if this url contains a "www.mysite.com" string: if not, the rows must be ignored).

How can I do this?

# Answer
> 5 votes
This hook might be the solution it excludes different contents from migrating:

```
use Drupal\migrate\Row;
use Drupal\migrate\Plugin\MigrateSourceInterface;
use Drupal\migrate\Plugin\MigrationInterface;

function hook_migrate_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration) {
  // Ignore content types from being migrated.
  if ($migration->id() == 'd6_node_type') {
    $ignore_content_types = array('content_type1', 'content_type2');
    if (in_array($row->getSource()['type'], $ignore_content_types)) {
      return FALSE;
    }
  }

  // Ignoring content of 4 content types.
  $ignore_content_types_content = array('d6_node__content_type1', 'd6_node__content_type2');
  if (in_array($migration->id(), $ignore_content_types_content)) {
    return FALSE;
  }
}

```

# Answer
> 0 votes
Via yml approach you would do as following:

```
process:
  name:
    -
      plugin: skip_on_empty
      method: row
      source: name
    -
      plugin: get
      source: name

```

---
Tags: 8, migrations
---


title: Attempt to get Image URL in D8 Twig

text:
# Question
Title: Attempt to get Image URL in D8 Twig
**Background:**
***Created a custom views bloc*k** to use unformatted view showing fields set under 'Format'.
Also, ***created an override template*** as *views-view-fields--bookstheme--block.html.twig* and then created the HTML structure within this custom template and then I am simply printing the field like for example Eg:- **`{{ fields.booktitle.content}}`**

Below is attempt within to get the image field URL.

**Observation:**
*Solution Attempt #1 worked for me and Solution Attempt #2 didnt. Request help on what I missed out.*

**Solution Attempt #1: \[ Works \]**

```
{# Below image field from view o/p #}
{{ fields.field_books_theme_pic.content }}
{# Creating a Field URI post setting up relationship to image field fields.uri.content gives uri format eg:- public://image.jpg #}
{{ fields.uri.content|striptags|trim }}
{# and this gives the image uri for src ref #}
{{ file_url(fields.uri.content|striptags|trim) }}

```

**Solution Attempt #2 \[ Something missing, no output \]**

```
{% set url = fields.field_books_theme_pic.content|render|striptags %}
{{ url }}

```

# Answer
> 2 votes
```
{% set url = file_url(content.field_books_theme_pic['#items'].entity.uri.value) %}

```

"file\_url" needs a URI to convert.

Another options is to go to that fields display settings and change the display option from image to "URL to image". Then you can just render the field value:

```
{{ content.field_books_theme_pic }}

```

If you are working in twig template files, the only thing that changes is context. content.something, fields.something, paragraph.something...

If this is a field of type image, what you are looking for is the array key "URI".

I always use {{ dump(whatever | keys) }}. For your case try pasting this into your twig file:

```
{{ dump(fields.field_books_theme_pic | keys) }}

```

and see if you can trace down to the uri key (you must have devel enabled and the usual config in local files). If you cant find the uri key in your current setup via the twig template file, then you know you probably need to do some preprocessing to make it available to your template.

Personally, if I feel I need granular markup I would go after the field template itself: "field--field-name.html.twig" for example, and control my markup there. That way, whether I use that field in a view, or a content type, or anywhere, it will always render the same. Plus all I have to do then is print that field in other template files to get the same results.

# Answer
> 0 votes
In the view you created, select *URL to image* as image formatter.

>

Then, in the view template file, you will be able to access the image URL with code similar to the following one.

```
<img class="img-fluid" src="{{ fields.field_cover_photo.content }}" alt="test">

```

*field\_cover\_photo* is the field machine name, in my case.

---
Tags: views, 8, theming
---


# Question
Title: How to stop PHP errors (notices, warnings, deprecation, etc) from showing on front end?
PHP erros (they are all actually deprecation warnings) are appearing on many pages of the site, and I've done all the recommended things to turn them off:

* display\_errors is "Off" (checked with phpinfo())
* `drush site:mode` is set to `prod`
* On the "Logging and Errors" page, "None" is ticked.

What else is there to do?

The errors/warnings - with full stack trace - appear even for anonymous users. I don't want them to appear for anyone, and I would have expected the settings detailed above to achieve this.

# Answer
If

* On the "Logging and Errors" page, "None" is ticked.

doesn't help, look for this line

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

```

This is discussed since 2015 whether you should be able to see in UI that your choice is overridden. See https://www.drupal.org/project/drupal/issues/2621920.
> 2 votes

---
Tags: 9
---


# Question
Title: Menu item still visible even though alterRoutes denies access to it
I have the following RouteSubscriber in a custom module:

```
namespace Drupal\frilaering_access\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

class RouteSubscriber extends RouteSubscriberBase {

  protected function alterRoutes(RouteCollection $collection) {

    if ($route = $collection->get('user.logout')) {
      $route->setRequirement('_access', 'FALSE');
    }

    //THIS ONE STILL APPEARS IN THE MENU FOR SOME REASON
    if ($route = $collection->get('entity.user.edit_form')) {
      $route->setRequirement('_access', 'FALSE');
    }

    if ($route = $collection->get('entity.user.canonical')) {
      $route->setRequirement('_access', 'FALSE');
    }
  }
}

```

And although access is denied the link to the user edit page is still visible in the menu. The other 2 menu items are hidden as they should be.

Any idea why this is not working for the user.edit\_form?

EDIT - here is my subscriber:

```
services:
  frilaering_access.route_subscriber:
    class: Drupal\frilaering_access\Routing\RouteSubscriber
    tags:
      - { name: event_subscriber }

```

# Answer
Sorry, I just discovered that the "Edit user" link is provided by the module "User current paths", so the solution was to use the route "user\_current\_paths.edit\_redirect".
> 0 votes

---
Tags: routes, 9
---


# Question
Title: How do I interpret unmet dependencies error messages?
We recently discovered that our clients are running into issues when installing Drupal using our custom default profile. I managed to fix some initial errors like missing libraries, but this other problem stumped me.

> Drupal\Core\Config\UnmetDependenciesException: Configuration objects provided by custom\_profile have unmet dependencies: core.entity\_form\_display.media.document.default (field.field.media.document.field\_document, field.field.media.document.field\_media\_in\_library, media.type.document), core.entity\_view\_display.node.page.default (field.field.node.page.field\_content\_keywords, field.field.node.page.field\_header\_image, field.field.node.page.field\_header\_video\_url, field.field.node.page.field\_hide\_overlay\_title, field.field.node.page.field\_meta\_tags, field.field.node.page.field\_secondary\_title, field.field.node.page.field\_social\_media\_image, field.field.node.page.field\_title\_link, field.field.node.page.field\_title\_placement, field.field.node.page.layout\_builder\__layout, metatag), filter.format.rich\_text\_editor\_limited (entity\_embed), pathauto.pattern.default\_media\_pattern (pathauto) in Drupal\Core\Config\UnmetDependenciesException::create() (line 100 of core/lib/Drupal/Core/Config/UnmetDependenciesException.php).
> Drupal\Core\Config\UnmetDependenciesException::create('custom\_profile', Array) (Line: 522)
> Drupal\Core\Config\ConfigInstaller-\>checkConfigurationToInstall('module', 'custom\_profile') (Line: 132)
> Drupal\Core\ProxyClass\Config\ConfigInstaller-\>checkConfigurationToInstall('module', 'custom\_profile') (Line: 177)
> Drupal\Core\Extension\ModuleInstaller-\>install(Array,) (Line: 83)
> Drupal\Core\ProxyClass\Extension\ModuleInstaller-\>install(Array,) (Line: 1660)
> install\_install\_profile(Array) (Line: 700)
> install\_run\_task(Array, Array) (Line: 571)
> install\_run\_tasks(Array, NULL) (Line: 118)
> install\_drupal(Object) (Line: 48)

I searched our code base for the files listed above. The core.entity\_\* files are located in the /profiles/custom/custom\_profile/config/install directory, but the field.field.node.page.\* files are all in the /modules/custom/custom\_core/config/install directory.

Which of those files does Drupal think are missing, the core.entity.\* files or the fields in the parenthesis?

# Answer
The dependencies in parentheses are the ones the exception is reporting as missing.
> 1 votes

---
Tags: installation-profiles
---


# Question
Title: How to add menu item active class while using url aliases?
My active class name is not working for menu items that redirect to a node using URL aliases

For example, if I have a node `node/10` and its alias URL is `movie/avengers`, I'm not able to see the active class for the menu item if the link is provided as an alias URL (`movie/avengers`)

The active class is available and it toggles between the links on clicks if I'm providing the link as `node/[id]` instead of URL aliases for the menu item.

So please advise how can I use the active classes for menu items even if I'm providing URL aliases instead `node/[id]`

# Answer
The menu system is based on system paths like node/10. They are transformed to path aliases automatically when menu links are rendered. If you use the menu link option on the node edit page the menu link is created correctly. If you add a menu link by hand and use the path alias instead of the system path you break the relationship between node and menu link. This is not a good idea for maintaining node menu links and it doesn't work for multilingual sites.

The active class could then be an additional minor issue explained already because of the broken relationship. Although in a simple test with a menu link stored as `link_uri = internal:/path/alias` I couldn't reproduce the issue. Drupal was still able to connect the correct system path for the active link, visible on the web page by toggling the highlighted link and also in the HTML source by the `data-drupal-link-system-path` link attribute pointing at `node/[id]`.
> 0 votes

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


# Question
Title: How do I access paragraphs with the JSON API?
With the JSON API module, I am trying to access paragraphs. In the JSON object it does not allow me to access the nested paragraphs.

How would I go about accessing the paragraphs with the JSON API?

\*****Update with Solution\*****

1. In the api call you need to have the correct URL format: `/jsonapi/{entity_type_id}/{bundle_id}[/{entity_id}]?_format=api_json`. The key here is to add this at the end of your the URL for the api call: `?include={name of paragraph}`. For example: `/jsonapi/node/page?_format=api_json&include=field_testing_json_api`
2. Once you have the correct API call, you need to go to the Drupal admin dashboard and go to `people/permissions` and under the `Paragraphs Type Permissions` section you need to grant access to `view content` to the specific paragraph you want the user to access.

# Answer
2 steps required :)

1. create the paragraph(s) by doing a POST request, and receiving the revision ID of the created paragraph,
2. update the parent entity by assigning the paragraphs' revision ids to the paragraph field (entity revision reference field).

---

**Step 1.**

```
jsonbody = {
    'data': {
        'type': 'paragraph--study_history',
        'attributes': {
            'parent_id': localStorage.getItem('uid'),
            'parent_type': 'user',
            'parent_field_name': 'field_study_history'
        },
        'relationships': {
            'field_school_ref': {
                'data': {
                    'type': 'node--school',
                    'id': this.reg_selectedUni['id']
                }
            }
        }
    }
};

return this.api.apiPost('/jsonapi/paragraph/study_history', {}, jsonbody)

```

We are using our custom service `api` (ApiService.ts) which has the `apiPost` function that does exactly what you'd imagine :) So the logic above should be easy to adapt to your own code.

Note that if you want to add more fields (text fields for example, you add them to the attributes section).

---

**Step 2.** Here’s how we update the user, PATCH it to have the created “study history” paragraphs.

```
const jsonbody = {
    'data': {
        'type': 'user--user',
        'id': uuid,
        'relationships': {
            'field_study_history': {
                'data': [
                    {
                        'type': 'paragraph--study_history',
                        'id': schoolhist_info['data']['id'],
                        'meta': {
                            'target_revision_id': schoolhist_info['data']['attributes']['revision_id'],
                        }
                    },
                    {
                        'type': 'paragraph--study_history',
                        'id': unihist_info['data']['id'],
                        'meta': {
                            'target_revision_id': unihist_info['data']['attributes']['revision_id'],
                        }
                    }
                ]
            }
        }
    }
};
return this.api.apiPatch(this.endpoint.getUsers + '/' + uuid, {}, jsonbody);

```

Where `this.endpoint.getUsers` is `/jsonapi/user/user`. This should be enough to get it to work, else comment and I can update.
> 5 votes

# Answer
Try using http://yourhost.local/jsonapi/paragraph/myparagraph

It is navigable through your browser http://yourhost.local/jsonapi
> 0 votes

# Answer
## Situation

Assuming you have published content that uses Paragraphs, and you want to retrieve the Nodes AND the Paragraphs:

1. Ensure you have permissions set to allow anonymous users to view your specific Paragraph types
2. Try the query pattern in your browser:
`/jsonapi/node/<entity_type>?filter[status]=1&include=<field_name>,<field2_name>`

To break it down:

`/jsonapi/node/<entity_type>` \- the JSON API endpoint for a type of node

`?filter[status]=1` \- only return published nodes

`&include=<field_name>,<field2_name>` \- additionally include these fields

Note that you must explicitly request your paragraph fields by name.

If the fields are restricted to authenticated users only, you'll nee to include an API key via either the request header or in the URL as a query parameter:

`?api-key=<KEY>`

## Common issues

Depending on permissions, some data may appear in the JSON API response, but restricted fields may not. If a Paragraph field is restricted, you'll see this in the response:

```
"item--<hash>": {
   "href": "https://www.mysite.com/jsonapi/paragraph/<paragraph_type>/<hash>"
   "meta": {
      "rel": "item",
      "detail": "The current user is not allowed to GET the selected resource."
   }
}

```

If this happens, you may need your Drupal user's API key (see the Key\_auth module)
> 0 votes

---
Tags: 8, paragraphs
---


# Question
Title: ajax form, send data from js modal to form
I have the following form:

When I click the "Add Filter" button, I need to open a modal with a select input element. Then I need to send the user's choice back to the Drupal Form instance and extend the original form, based on the user's input.

I'm not sure of the best way to do this. 2 options I've thought of are:

1. Is it possible to have the "Add Filter" ajax callback send an "OpenModalDialogCommand" with a new form, then have the new form "submitForm" method send the data to the original form?
2. Another possibility would be to collect the data clientside and send it to the original form.

However I'm not sure how to get the user data into the original form in either of the options above.

# Answer
> 0 votes
I have worked on a similar case in D7. Take a look at these tutorials. https://www.deeson.co.uk/labs/insert-form-pop-modal-ctools-and-drupal-7 http://internetdevels.com/blog/big-manual-for-creating-ctools-popups-in-drupal-7

# Answer
> 0 votes
Steps:

1. Add button with 'OpenModalDialogCommand' (Form 1).
2. Use ajax submission in modal form (Form 2) remember:

```
$form['actions']['submit'] = [
...
 '#ajax' => [
   'callback' => [$this, 'submitAjax'], // The callback for step 3
   'event' => 'click', // what ever event you want to trigger.
   'url' => Url::fromRoute('Form 2 route here'), // Required
   'options' => ['query' => ['ajax_form' => 1]], // Required
 ],

```

\],
3. In the callback of step 2, add AppendCommand, InvokeCommand ... to set the value or replace HTML to form 1's wrapper.
4. Do not forget to add command CloseModalDialogCommand in step 2 callback

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


# Question
Title: Not receiving dropdown of custom autocomplete textfield
I am currently trying to create a postcode lookup which returns a street name in an autocomplete dropdown.

To do this I have created a new module containing the following files:

* src/Controller/AutocompleteTestController.php
* src/Form/AutocompleteTestForm.php
* js/autocomplete.js
* my\_module.info.yml
* my\_module.routing.yml
* my\_module.libraries.yml

*AutocompleteTestController:*

```
<?php

namespace Drupal\autocomplete_test_v1\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Component\Utility\Xss;

/**
 * Defines a route controller for watches autocomplete form elements.
 */
class AutocompleteTestController extends ControllerBase {

  /**
   * Handler for autocomplete request.
   */
  public function get(Request $request) {
    $results = [];
    $input = $request->query->get('q');

    // Get the typed string from the URL, if it exists.
    if (!$input) {
      return new JsonResponse($results);
    }

    $input = Xss::filter($input);

    $input = $this->getLatLong($input);

    $results[] = [$input];

    return new JsonResponse($results);
  }

  public function getLatLong($postcode){
    $gmapsAPI = 'hidden';
    $query = "https://maps.google.co.uk/maps/api/geocode/json?components=postal_code:" . urlencode($postcode) . "&output=json&key=".$gmapsAPI;
    $data = file_get_contents($query);

    if($data){
        $data = json_decode($data);
        $street = $data->results[0]->formatted_address;
        return array('Street' => $street);
    }else{
        return false;
    }
  }
}

```

*AutocompleteTestForm:*

```
<?php

namespace Drupal\autocomplete_test_v1\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\Textfield;

/**
 * Form to handle article autocomplete.
 */
class AutocompleteTestForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId()
  {
    return 'autocomplete_test_v1_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['address'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Autocomplete address'),
      '#autocomplete_route_name' => 'autocomplete_test_v1.addresses',
      '#autocomplete_route_parameters' => [],
      '#process' => [
        [Textfield::class, 'processAutocomplete'],
      ],
      '#attributes' => [
        'autocomplete' => 'off',
      ],
      '#attached' => [
        'library'  => [
            'autocomplete_test_v1/autocomplete'
        ],
      ],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Extracts the entity ID from the autocompletion result.
    $address_v1 = $form_state->getValue('address');
  }
}

```

*my\_module.routing.yml:*

```
autocomplete_test_v1.addresses:
  path: '/autocomplete_test_v1/autocomplete'
  defaults:
    _controller: '\Drupal\autocomplete_test_v1\Controller\AutocompleteTestController::get'
    _format: json
  requirements:
    _permission: 'access content'

autocomplete_test_v1.autocomplete_test_v1_form:
  path: '/admin/autocomplete_test_v1/autocomplete/form'
  defaults:
    _form: 'Drupal\autocomplete_test_v1\Form\AutocompleteTestForm'
    _title: 'Automcomplete Test'
  requirements:
    _permission: 'access content'

```

*Autocomplete.js:*

```
(function ($) {
    Drupal.behaviors.autocomplete.attach = function attach(context) {
      var $autocomplete = $(context).find('input.form-autocomplete,textfield.form-autocomplete').once('autocomplete');
      if ($autocomplete.length) {
        var blacklist = $autocomplete.attr('data-autocomplete-first-character-blacklist');
        $.extend(Drupal.autocomplete.options, {
          firstCharacterBlacklist: blacklist || ''
        });

        $autocomplete.autocomplete(Drupal.autocomplete.options).each(function () {
          $(this).data('ui-autocomplete')._renderItem = Drupal.autocomplete.options.renderItem;
        });

        $autocomplete.on('compositionstart.autocomplete', function () {
          Drupal.autocomplete.options.isComposing = true;
        });
        $autocomplete.on('compositionend.autocomplete', function () {
          Drupal.autocomplete.options.isComposing = false;
        });
      }
    };
  })(jQuery);

```

**Problem** My main problem is that the dropdown does not appear properly (A thin empty bar). A response is generated however.

Any tips or help would be greatly appreciated :)

# Answer
**Solution**
For anyone who comes across a similar error; the problem lay within the controller.
So the results I was generating as `$input` was an array in which I was embedding into another array of `$results[]`.

**Code Changes**
Change this:

```
$input = $this->getLatLong($input);

$results[] = [$input];

```

To this:

```
$results[] = $this->getLatLong($input);

```

Make sure that your key values are either defined in #autocomplete\_route\_parameters as well.
> 0 votes

---
Tags: forms, javascript, routes, 9
---


# Question
Title: Accessing /admin/content returns "Page not found"
The stock Content view in a Drupal 9 install is returning a 404 when accessing /admin/content.

We added two contextual filters to this View that are ignored if you are an Admin (passes "all" value).

If you navigate to /admin/content/node, you get the View. But admin/content is a 404, and other sites we have work fine (no filters on the View). I see someone changed the path in the View, but changing it back causes it to ping pong between 404 and the View. Is there something else that could cause this?

# Answer
> 1 votes
Figured it out - I needed to set 'skip default argument when constructing View URL' on both filters. Now it works.

---
Tags: views, 9
---


title: Does Drupal have its own CLI?

text:
# Question
Title: Does Drupal have its own CLI?
It is unclear to me from the this document if Drupal has its own CLI, different from *Drush* and *Drupal Console* and including some very basic commands such as cache flush and installing a module.

Does Drupal have its own CLI?

* Is it a local or global CLI?
* Is it usable in XAMPP?

# Answer
Drupal does not currently have its own CLI that is bundled with a standard Drupal installation.

The issue that you linked to is a feature request/proposal that has not been implemented yet. It may be implemented at some point, but reading through the issue, it is still a plan at this stage.

Drush is effectively the Drupal CLI; it has been around since at least the days of Drupal 5, and it supports most core features and also is supported by many contrib modules.

My guess is that the core feature request that you linked to hasn't moved forward because Drush already exists and does what people need.

Drush can be used with XAMPP; it can basically be used anywhere that you have either local or SSH access (which means some very cheap shared hosting providers will not allow you to use it, but it will basically work everywhere else).
> 4 votes

# Answer
As the issue, which is not documentation but rather an idea issue, reads, there are a tiny few commands in Drupal Core, which would not be useful in most cases at this time. It is a “local” CLI if I understand you correctly and should be executable in any context.

You have not found an undocumented way to avoid Drush. I advise not to try it. Use Drush.
> 2 votes

# Answer
> from the this document

Please take a closer look, it's not a documentation, it's "Drupal core ideas".

> Does Drupal have its own CLI?

Yes.

> Is it a local or global CLI?

Local.

> Is it usable in XAMPP?

Usable is a matter of opinion but I'd argue the answer is "no".

The available commands are:

* generate-theme Generates a new theme based on latest default markup.
* help Display help for a command
* install Installs a Drupal demo site. This is not meant for production and might be too simple for custom development. It is a quick and easy way to get Drupal running.
* list List commands
* quick-start Installs a Drupal site and runs a web server. This is not meant for production and might be too simple for custom development. It is a quick and easy way to get Drupal running.
* server Starts up a webserver for a site.

Since XAMPP is already a webserver and it's unlikely you are developing a custom theme at this point, I would argue this is not at all useful to you. Indeed use drush.
> 0 votes

---
Tags: installation
---


title: Migrate core Date field with two values

text:
# Question
Title: Migrate core Date field with two values
I have a content type on a D7 site that has a Date field with two values, "from" and "to". I have the same content type on a D9 (9.4.1) site. It also has a Date field with two values. When I try to migrate content from the D7 to the D9 site, the "from" value comes over, but the "to" value does not.

I have tried every solution I can find on this forum and others, but with no success.

Devel shows that the "from" value on the source site is field\_date\[und\]\[0\]\[value\] and the "to" value is field\_date\[und\]\[0\]\[value2\].

The two corresponding indices on the destination site are field\_date\[0\]\[value\]\[date\] and field\_date\[1\]\[value\]\[date\].

It should be a simple matter of migrating field\_date\[und\]\[0\]\[value\] to field\_date\[0\]\[value\]\[date\] and field\_date\[und\]\[0\]\[value2\] to field\_date\[1\]\[value\]\[date\].

The following will migrate the "from" date, but not the "to" date.

```
field_date:
    -
      plugin: sub_process
      source: field_date
      process:
        value:
          plugin: format_date
          source: value
          from_format: 'Y-m-d H:i:s'
          to_format: 'Y-m-d\TH:i:s'

```

But how do I get the second date (whose source is "value2") to be included in the migration? Is there some way to specify that "value" is field\_date/0/value/date and then modify that to field\_date/1/value/date for the second one?

# Answer
> 0 votes
Maybe you are wrong properties of date range field. Try with config

```
field_date:
-
  plugin: sub_process
  source: field_date
  process:
    value:
      plugin: format_date
      source: value
      from_format: 'Y-m-d H:i:s'
      to_format: 'Y-m-d\TH:i:s'
    end_value:
      plugin: format_date
      source: value2
      from_format: 'Y-m-d H:i:s'
      to_format: 'Y-m-d\TH:i:s'

```

# Answer
> 0 votes
Taking a hint from MrD's answer above, I solved the problem by replacing the Date field on my destination site with a Date Range field. The final block on the migration configuration for this field is:

```
field_conference_dates:
-
  plugin: sub_process
  source: field_date
  process:
    value:
      plugin: format_date
      from_format: 'Y-m-d H:i:s'
      to_format: Y-m-d
      source: value
    end_value:
      plugin: format_date
      from_format: 'Y-m-d H:i:s'
      to_format: Y-m-d
      source: value2

```

That worked. I suppose that I could have eventually made the Date field work, but this was a lot less effort.

---
Tags: migrations, 9
---


# Question
Title: Disabling Browse to Library in Media Upload Field
I'm on Drupal 7.2 with the included Media Module. I'm also using WYSIWYG if that matters at all.

I'm seeing that when a user clicks the image upload field, they have a choice of either 'web' or 'library'. The Library option shows all files that other users have uploaded to be included in other nodes. How do I disable that so that they don't see all the other files?

I don't use galleries- just upload/attach images to nodes that the users themselves create. Guests and Registered Users BOTH can see the nodes and image files- but I don't want them to have access to all the images that have been uploaded previously.

I think this has something to do with Private/Public, but I can't figure it out. Any input?

# Answer
On Drupal 8+ go to: `/admin/config/media/browser`

Set the "Enabled browser plugins" to only "upload" and save the page.

Now when people click on the button in the WYSIWYG to add something, they should only get the upload option and not see the library.
> 1 votes

# Answer
This can be accomplished with a module, and this hook:

```
/**
 * Implements hook_media_browser_plugins_alter().
 */
function my_module_media_browser_plugins_alter(&$plugins) {
  // Hide the "Library" tab on the WYSIWYG media upload widget.
  unset($plugins['library']);
}

```
> 0 votes

---
Tags: 7, media
---


# Question
Title: Which PHP parameter do I need to tweak in order to fix the PHP APCU CACHING site status warning?
I get a memory warning in my Drupal site, but I still have sufficient free memory on the server.

Which parameter do I need to tweak in order to fix this warning?

>

# Answer
> 4 votes
It is the `apc.shm_size` PHP configuration. Set it to `64M` or higher and see how that looks.

---
Tags: caching
---


# Question
Title: What is the relationship between internal page cache and dynamic page cache?
I faced a problem in my browser. Firstly, I removed an internal cached page that could be accessed by anonymous authenticated users. The page was still cached from the dynamic page cache.

I accessed the page by reloading the web browser that cached the page; the browser displayed the cached page, and the page was cached from the internal page cache.
Then, I cleaned the internal page cache and the dynamic page cache.

I accessed the page by reloading it from the web browser that cached the page; the browser displayed the not-cached page, and the page wasn't cached from the internal page cache.

What is the relationship between internal page cache and dynamic page cache?

# Answer
As I understand it, the internal page cache runs strictly for anonymous users and doesn't vary the content. So, for example, if the "About" page was cached, there would only be one copy of it, and all anonymous users would get that.

Dynamic page cache runs for all users (authenticated and anonymous) and also has the ability to vary the content in either case. So you would want to use this if you wanted to serve up personalized content (like based on session or IP address or whatever) for anonymous users. And you would probably want to disable the Internal page cache so it doesn't get in the way. Otherwise, should be fine to keep them both enabled.
> 0 votes

---
Tags: caching, 9
---


# Question
Title: "Uncaught Error: Class 'Consolidation\Log\LogLevel' not found in /app/vendor/consolidation/log/src/ConsoleLogLevel.php:21"
I am using lando for the first time and having difficulties. I cloned a git repo and ran the "lando start" and "lando composer install"commands. After that, when I am trying to run the "lando drush cim" command it provides the following error:

> Fatal error: Uncaught Error: Class 'Consolidation\Log\LogLevel' not found in /app/vendor/consolidation/log/src/ConsoleLogLevel.php:21

# Answer
Until there is a better way, you need to create manually the class *ConsoleLogLevel*

Inside your app root directory, create a file *vendor/consolidation/log/src/ConsoleLogLevel.php* with the following content :

```
<?php
namespace Consolidation\Log;
class ConsoleLogLevel extends \Psr\Log\LogLevel
{
    const SUCCESS = 'notice';
}

```

Drush commands should now work as expected (tested for a *Drupal* 10.x alpha installation with *Drush* 11.x and *consolidation/log* version 3.x)
> 0 votes

---
Tags: drush, 9
---


# Question
Title: How can I log a stack trace when I throw an exception? Is the logger PSR-3 compatible?
I'm trying to log a stacktrace when I throw an exception as suggested here.

I tried this:

```
  catch (\Exception $e) {
    \Drupal::logger('mymodule')->error($e->getMessage(), [ 'exception' => $e]);
  }

```

However, the stacktrace doesn't get logged; I only see the error message. How can I log the stacktrace as well?

# Answer
> 1 votes
This is not possible in Drupal 9 because the Drupal 9 logger is not PSR-3 compatible.

However, Drupal 10 alpha already supports PSR-3 logging, so this feature will be available shortly.

# Answer
> 1 votes
This works fine for Drupal 8 and 9:

```
catch (\Exception $e) {
  \Drupal::logger('mymodule')->error("<pre>$e</pre>");
}

```

This works because `Exception::__toString` includes the stack trace. `<pre>` ensures that line breaks are shown properly in your browser when looking at the error logs.

---
Tags: debugging, 10
---


# Question
Title: Authentication from a dynamically generated form
I have implemented a feature for PDF conversion using an external java program based on iText (performance is not an issue, the system is for internal usage only, users are less than a hundred, concurrent connections less than ten and daily PDF conversions just a handfull or two). I get the HTML from an element on my page, I append all CSS rules and send the standalone HTML so obtained to the server using a dynamically generated form:

```
$('#convert-to-pdf-link').click(function() {
    let inner = '<html><head><title>' + document.title  + '</title>' ;

    let rules_text = '' ;
    [...document.styleSheets].forEach(function(sheet) {
        let rules = [ ... (sheet.cssRules || sheet.rules) ] ;
        rules.forEach(function(rule) {
            rules_text += rule.cssText + "\n" ;
        }) ;
    }) ;

    inner += `<style>${rules_text}</style>` ;

    inner += '</head><body >' ;
    let contents = $('.node--type-mytype').html() ;
    inner += contents ;
    inner += '</body></html>' ;

    let form = document.querySelector('form[action="/ls/topdf"]') ;
    if (form === null) {
        form = document.createElement('form') ;
        form.setAttribute('action', '/ls/topdf') ;
        form.setAttribute('method', 'post') ;
        document.body.append(form) ;
    }
    let input_el = form.querySelector('input[name="input_file"]') ;
    if (input_el === null) {
        input_el = document.createElement('input') ;
        input_el.setAttribute('type', 'text') ;
        input_el.setAttribute('name', 'input_file') ;
        input_el.classList.add('hidden') ;
        form.append(input_el) ;
    }
    input_el.value = inner ;
    form.submit() ;

    return false ;
}) ;

```

The controller gets the html from the form, saves it to file, runs the conversion program, and returns the resulting PDF in a `BinaryFileResponse`:

```
class UtilitiesController extends ControllerBase {
 [...]
    public function convertToPdf(Request $request) {
        $scheme = \Drupal::config('system.file')->get('default_scheme') ;
        $dirname = "$scheme://appoggio" ;
        $filesystem = \Drupal::service('file_system') ;
        $filesystem->prepareDirectory($dirname,
            FileSystemInterface::CREATE_DIRECTORY|FileSystemInterface::CREATE_DIRECTORY) ;
        $basename = time() ;
        $input_uri = "$dirname/$basename.html" ;
        $body = $request->request->get('input_file') ;
        $infile = file_save_data($body, $input_uri, $replace=FileSystemInterface::EXISTS_REPLACE) ;
        $inpath = $filesystem->realpath($input_uri) ;
        $pdf_uri =  "$dirname/$basename.pdf" ;
        $pdfpath = $filesystem->realpath($pdf_uri) ;
        $command = "java -jar /opt/TestConvHtml2Pdf_jar/TestConvHtml2Pdf.jar '$inpath' '$pdfpath'" ;
        exec($command, $output, $retval) ;
        if ($retval === 0) {
            $response = new BinaryFileResponse($pdf_uri, 200, ['Content-Type' => 'application/pdf']) ;
            $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, "$basename.pdf") ;
            return $response ;
        }
        else {
            $this->log->error("odg_to_pdf() failed with error code $retval. Details:<br>" .
                implode('<br>', $output)) ;
            foreach ($output as $line)
                $rows[] = [ $line ] ;
            return [
                '#theme' => 'table',
                '#header' => [ "Errore nella conversione in PDF: $retval" ],
                '#rows' => $rows,
            ] ;
        }
    }
}

```

Everything works nicely, but only if I keep the route to the controller open, i.e., in `mymodule.routing.yml`,

```
mymodule.to_pdf:
  path: '/ls/topdf'
  defaults:
      _controller: '\Drupal\mymodule\Controller\UtilitiesController::convertToPdf'
  methods: [POST]
  options:
    no_cache: 'TRUE'
  requirements:
    _access: 'TRUE'

```

If I replace `_access: 'TRUE'` with `_role: 'authenticated'`, I get a 403, in spite of the fact that the session cookie *is* present in the request. I tried to spot other differences in the headers of the request for conversion and of other requests, but I couldn't find any.

What am I missing?

# Answer
> 2 votes
Roles are config, whereas routes are code. As such, it's generally better to set a route to a permission, which is code based, rather than a role, so that both the route and permission are controlled in code. As such, try changing `_role` to a `_permission`, and set that permission to the given role.

# Answer
> 1 votes
Try adding \_csrf\_token: "TRUE" in the routing requirements, like so,

```
requirements:
_csrf_token: 'TRUE'

```

You will also be required to auto generate the token from Drupal and use it in the request uri like so `/ls/topdf?token=some auto generated token`

Here is an example of how to auto generate a token from Drupal (I'm not sure if your Javascript runs on Java or on The Drupal app, but assuming it's from the Drupal app, you can pass the token from Drupal to your js);

```
$url = \Drupal\Core\Url::fromRoute('mymodule.to_pdf');
$token_service = Drupal::service('csrf_token')
$the_token = $token_service->get($url->getInternalPath());

```

Thus:

```
form.setAttribute('action', `/ls/topdf?token=${the_token from drupalSettings}`) ;

```

**Another** solution might be using an absolute path in the form action, using your current setup without changing anything about it.

**And another** would be to include an options key in your route definitions with parameters of an entity type user.

```
options:
  parameters:
    user:
      type: entity:user

`// update your controller method`
public function convertToPdf(AccountInterface $user, Request $request) {

```

and using that user entity to check for, is authenticated, has permissions and all, as your application requires.

---
Tags: routes, authentication-authorization
---


title: Mails aren't sent

text:
# Question
Title: Mails aren't sent
I'm simply trying to send a mail with the following code.

```
function contact_form_mail($key, &$message, $params){
    switch ($key) {
        case 'contact':
            // Set headers etc
            // $message['headers']['Reply-To'] = $params['to'];
            $message['headers']['Content-Type'] = 'text/html';
            $message['headers']['From'] = $params['from'];
            $message['to'] = $params['to'];
            $message['subject'] = $params['subject'];
            $message['body'] = $params['body'];
        break;
    }
}

public function sendForm(){
        $user = $this->getCurrentUser();
        $recipent = $this->findEmailForLocation($this->getLocation());
        if(empty($recipent)){ return; }
        $request = \Drupal::request();
        $subject = $request->get('subject');
        $body = $request->get('body');
        if(empty($subject) || empty($body)){
            return $this->redirect('contact_form.contact', ['error' => 'Fill in all fields.']);
        }
        $mailManager = \Drupal::service('plugin.manager.mail');
        $mailManager->mail(
            'contact_form',
            'contact',
            ['test@test.com'],
            $user->getPreferredLangcode(),
            ['to' => [$recipent], 'from' => $user->getEmail(), 'subject' => $subject, 'body' => $body],
            $user->getEmail(),
            TRUE
        );
        return $this->redirect('contact_form.contact', ['success' => 'Data sent']);
    }

```

I'm getting this error.

> Warning: Invalid argument supplied for foreach() in Drupal\Core\Mail\MailManager-\>doMail() (line 286 of core/lib/Drupal/Core/Mail/MailManager.php).

I have no clue which value is wrong and/or what kind of datatype it should be.

# Answer
After looking for answers for a while I figured out that `body` needs to be an array instead of a string. Not sure why. But I changed it, and it directly started working.
> 0 votes

---
Tags: emails, 9
---


# Question
Title: After installing webform, unable to use composer
The crux of this matter is that composer is now not working. I get the following when I try to run almost any composer command. (This Drupal 9 site is a composer installed site, and I would like to keep it that way, if possible.) Your requirements could not be resolved to an installable set of packages.

> Problem 1
>
> * Root composer.json requires ckeditor/autogrow, it could not be found in any version, there may be a typo in the package name. Problem 2
> * Root composer.json requires ckeditor/codemirror, it could not be found in any version, there may be a typo in the package name. Problem 3
> * Root composer.json requires ckeditor/fakeobjects, it could not be found in any version, there may be a typo in the package name. Problem 4
> * Root composer.json requires ckeditor/image, it could not be found in any version, there may be a typo in the package name. Problem 5
> * Root composer.json requires ckeditor/link, it could not be found in any version, there may be a typo in the package name. Problem 6
> * Root composer.json requires codemirror/codemirror, it could not be found in any version, there may be a typo in the package name. Problem 7
> * Root composer.json requires jquery/hotkeys, it could not be found in any version, there may be a typo in the package name. Problem 8
> * Root composer.json requires jquery/image-picker, it could not be found in any version, there may be a typo in the package name. Problem 9
> * Root composer.json requires jquery/inputmask, it could not be found in any version, there may be a typo in the package name. Problem 10
> * Root composer.json requires jquery/intl-tel-input, it could not be found in any version, there may be a typo in the package name. Problem 11
> * Root composer.json requires jquery/rateit, it could not be found in any version, there may be a typo in the package name. Problem 12
> * Root composer.json requires jquery/select2, it could not be found in any version, there may be a typo in the package name. Problem 13
> * Root composer.json requires jquery/textcounter, it could not be found in any version, there may be a typo in the package name. Problem 14
> * Root composer.json requires jquery/timepicker, it could not be found in any version, there may be a typo in the package name. Problem 15
> * Root composer.json requires progress-tracker/progress-tracker, it could not be found in any version, there may be a typo in the package name. Problem 16
> * Root composer.json requires signature\_pad/signature\_pad, it could not be found in any version, there may be a typo in the package name. Problem 17
> * Root composer.json requires svg-pan-zoom/svg-pan-zoom, it could not be found in any version, there may be a typo in the package name. Problem 18
> * Root composer.json requires tabby/tabby, it could not be found in any version, there may be a typo in the package name. Problem 19
> * Root composer.json requires tippyjs/6.x, it could not be found in any version, there may be a typo in the package name.
>
> Potential causes:
>
> * A typo in the package name
> * The package is not available in a stable-enough version according to your minimum-stability setting see for more details.
> * It's a private package and you forgot to add a custom repository to find it
>
> Read for further common problems.

I have now:

* Uninstalled webform (TG, I have not started using it!)
* uninstalled and re-installed ckeditor
* Checked composer.library.json and all the required libraries are there
* Modified my website composer.json to reflect the changes needed as this instruction, but I cannot run `composer update` nor `composer require wikimedia/composer-merge-plugin`
* Re-installed the Webform module, not all its sub-modules, like I did before (The Devel module has also been added as part of the original Webform install, but I have not touched it, and it is still there.)

Everything else on my Drupal 9, Ubuntu 20.04 is normal, but I do need to run a security update (from 9.4.2 to 9.4.3) which I also cannot do.

I have also tried to install the patch manually with `curl https://www.drupal.org/files/issues/2021-09-15/3233119-8.x-5.x-2.patch | patch -p1` from the *modules/contrib/webform* directory, but this error is shown.

> patching file composer.libraries.json Reversed (or previously applied)
> patch detected! Assume -R? \[n\] y Hunk #1 succeeded at 73 (offset 7 lines). Hunk #2 succeeded at 91 (offset 7 lines).
> Hunk #3 succeeded at 109 with fuzz 2 (offset 7 lines).
> Hunk #4 succeeded at 127 (offset 7 lines).
> Hunk #5 succeeded at 145 with fuzz 2 (offset 7 lines).
> Hunk #6 succeeded at 163 with fuzz 2 (offset 7 lines).
> Hunk #7 succeeded at 181 with fuzz 2 (offset 7 lines).
> Hunk #8 succeeded at 199 (offset 7 lines).
> Hunk #9 succeeded at 217 (offset 7 lines).
> Hunk #10 succeeded at 235 (offset 7 lines).
> Hunk #11 succeeded at 253 (offset 7 lines).
> Hunk #12 succeeded at 271 with fuzz 2 (offset 7 lines).
> Hunk #13 succeeded at 289 (offset 7 lines).
> Hunk #14 succeeded at 307 (offset 7 lines).
> Hunk #15 succeeded at 325 (offset 7 lines).
> Hunk #16 succeeded at 343 (offset 7 lines).
> Hunk #17 succeeded at 361 (offset 7 lines).
> Hunk #18 succeeded at 379 (offset 7 lines).
> Hunk #19 succeeded at 397 (offset 7 lines).
> Hunk #20 succeeded at 415 (offset 7 lines).
> Hunk #21 succeeded at 433 with fuzz 2 (offset 7 lines).
> Hunk #22 succeeded at 451 (offset 7 lines).
> Hunk #23 succeeded at 469 with fuzz 1 (offset 7 lines). can't find file to patch at input line 239 Perhaps you used the wrong -p or --strip option? The text leading up to this was: -------------------------- |diff --git a/src/Commands/WebformCliService.php b/src/Commands/WebformCliService.php |index 3ce05014a..87eb562a6 100644 |--- a/src/Commands/WebformCliService.php |+++ b/src/Commands/WebformCliService.php -------------------------- File to patch: composer.libraries.json patching file composer.libraries.json Hunk #1 FAILED at 1204. 1 out of 1 hunk FAILED -- saving rejects to file composer.libraries.json.rej

I know just so much about programming / script writing that I am actually dangerous.

I looked at the patch file and at the end the is a statement that starts with a opening curly bracket, but then there is no ending curly bracket but just some closing square brackets. Is this correct?

I really would appreciate some help with this. My Drupal site building has now scratched to a halt when otherwise I was managing quite nicely.

As an addendum I also ran composer diagnose, and this is the output.

> Checking composer.json: WARNING
> require.ckeditor/autogrow : unbound version constraints (*) should be avoided
require.ckeditor/codemirror : unbound version constraints (*) should be avoided
> require.ckeditor/fakeobjects : unbound version constraints (*) should be avoided
require.ckeditor/image : unbound version constraints (*) should be avoided
> require.ckeditor/link : unbound version constraints (*) should be avoided
require.codemirror/codemirror : unbound version constraints (*) should be avoided
> require.jquery/hotkeys : unbound version constraints (*) should be avoided
require.jquery/image-picker : unbound version constraints (*) should be avoided
> require.jquery/inputmask : unbound version constraints (*) should be avoided
require.jquery/intl-tel-input : unbound version constraints (*) should be avoided
> require.jquery/rateit : unbound version constraints (*) should be avoided
require.jquery/select2 : unbound version constraints (*) should be avoided
> require.jquery/textcounter : unbound version constraints (*) should be avoided
require.jquery/timepicker : unbound version constraints (*) should be avoided
> require.progress-tracker/progress-tracker : unbound version constraints (*) should be avoided
require.signature\_pad/signature\_pad : unbound version constraints (*) should be avoided
> require.svg-pan-zoom/svg-pan-zoom : unbound version constraints (*) should be avoided
require.tabby/tabby : unbound version constraints (*) should be avoided
> require.tippyjs/6.x : unbound version constraints (\*) should be avoided
> Checking platform settings: OK
> Checking git settings: OK
> Checking http connectivity to packagist: OK
> Checking https connectivity to packagist: OK
> Checking github.com rate limit: OK
> Checking disk free space: OK
> Checking pubkeys:
> Tags Public Key Fingerprint: 5781 ........
> Dev Public Key Fingerprint: 4AC4...........
> Checking composer version: You are not running the latest stable version, run `composer self-update` to update (2.3.7 =\> 2.3.10)
> Composer version: 2.3.7
> PHP version: 7.4.3
> PHP binary path: /usr/bin/php7.4
> OpenSSL version: OpenSSL 1.1.1f 31 Mar 2020
> cURL version: 7.68.0 libz 1.2.11 ssl OpenSSL/1.1.1f
> zip: extension present, unzip present, 7-Zip not available

# Answer
When you install the Webform module with composer, there are two parts:

1. Webform module and its submodules
2. Various libraries for additional features (these are installed by merge)

It seems like somehow the library merge is now causing an error.

## If you are using version control

Just roll back composer.json and composer.lock and you should be able to update.

This is why using a version control system like git is great.

## If you are not using version control

You'll have to fix the composer.json manually.

Normally, if the webform libraries are correctly installed, you should have a section like this:

```
"merge-plugin": {
    "include": [
        "web/modules/contrib/webform/composer.libraries.json"
    ]
},

```

After backing up my files, I would try deleting this section, deleting composer.lock, and then trying the composer update command again.
> 1 votes

---
Tags: webforms, configuration, composer
---


title: Webform custom input mask

text:
# Question
Title: Webform custom input mask
I'm trying to apply a custom input mask on a webform textfield
What I want is pretty similar to the built-in "Currency (+)" input mask, except I don't want the currency symbol.
However I can't figure out how to simply copy the currency input mask rule in order to modify it.
From the webform source code it seems that the regex used for this input mask is `^\$ [0-9]{1,3}(,[0-9]{3})*.\d\d$` but if I enter this value in the custom input mask field it simply doesn't work
I've also tried inputing `'regex': '[0-9]*'` in the custom input mask field and it works for simple regex like this one, but if I copy the currency one as `'regex': '^\$ [0-9]{1,3}(,[0-9]{3})*.\d\d$'` it doesn't (as if there wasn't any input mask entered).

I'm surprised the built-in input mask is hardcoded to use the $ sign and nobody seems to want to remove or use another symbol !

Could someone help me please ?
Thank you very much !

# Answer
> 1 votes
When I select "currency" under Input Mask and then view the webform source, I see:

```
'#input_mask': '''alias'': ''currency'''

```

Currency is an alias provided by webform, which extends the 'numeric' alias provided by InputMask; see /js/webform.element.inputmask.js. If you want the Currency mask, but without the prefix $, then you can use this in the source:

```
currency:
  '#type': textfield
  '#title': 'Currency'
  '#input_mask': '''alias'': ''currency'', ''prefix'': '''''
  '#required': true

```

Or, from the UI, select Custom under Input masks and add:

```
'alias': 'currency', 'prefix': ''

```

The key here is leveraging the alias "currency," but setting the prefix to empty. If you take a look at the webform javascript, you'll see other keys that can be overridden in the same way, for example, "placeholder" and "digits."

```
window.Inputmask.extendAliases({
  currency: {
    prefix: '$ ',
    groupSeparator: ',',
    alias: 'numeric',
    placeholder: '0',
    autoGroup: true,
    digits: 2,
    digitsOptional: false,
    clearMaskOnLostFocus: false
  },

```

You can learn more about extending InputMask aliases in the InputMask documentation.

Webform also provides some great examples in /modules/webform\_examples/config/install/webform.webform.example\_input\_masks.yml.

---
Tags: webforms
---


title: How to get file uri from entity video

text:
# Question
Title: How to get file uri from entity video
I have some code to get video using view builder.

```
$view_builder = \Drupal::entityTypeManager()->getViewBuilder('media');
$storage = \Drupal::entityTypeManager()->getStorage('media');
$entity_id = $storage->load($course_video_source[0]['target_id']);
$build_video_course = $view_builder->view($entity_id, 'default');
$video_html = render($build_video_course);

```

The `$video_html` is returned html string as an object. How do I get the source file only without the `<video>` tag?

```
object(Drupal\Core\Render\Markup)#21215 (1) {
  ["string":protected]=>
  string(426) "<div><div><div class="visually-hidden">Video file</div><div><div class="video--wrapper"><video-js class="video-js video-container" playsinline="true" crossorigin="anonymous"><source  src="/milo/docroot/sites/default/files/2021-05/1.%20LARI%20-%20SEJARAH%20%28UPDATE%20TERBARU%2016%20Mei%29%20-%203.mp4" type="video/mp4" /></video-js></div></div></div></div>"
}

```

# Answer
Starting with a Media entity:

```
$media_type = \Drupal::entityTypeManager()->getStorage('media_type')->load($media->bundle());

$file_field_name = $media_type->getSource()->getSourceFieldDefinition($media_type)->getName();

$file_uri = $media->get($file_field_name)->entity->getFileUri();

```
> 2 votes

---
Tags: media, 9
---


title: CSS in custom module not loading

text:
# Question
Title: CSS in custom module not loading
I'm trying to load a css file in a custom module, to style a template file I'm rendering. I followed the basic steps:

```
global-styling:
  version: 1.0
  css:
    layout:
      css/rr_users.css: {}
  dependencies:
    - rr_users/global-styling

```

and

```
name: RR users module
description: Generates editing pages for users
package: Custom
type: module
core_version_requirement: ^9
libraries:
  - rr_users/global-styling

```

I can't find out why this isn't working. It looks to me that I did it correctly. Also I already tried to look up a solution, but none of the found ones worked out for me.

I already tried to empty the cache etc.

# Answer
> 0 votes
`libraries` is not a valid key for a module .info.yml file; that key is for theme info files only. The full list of valid properties is available here.

There are a few different ways to attach libraries to a page from a module, depending on the requirement and available context. Those different methods are discussed, with examples, under Attaching a library to page(s) in the official docs.

Given the tags on the question, Attaching a library to a view might be of most interest to you:

```
/**
* Implements hook_views_pre_render().
*/
function yourmodule_views_pre_render(ViewExecutable $view) {
  if (isset($view) && ($view->storage->id() == 'super_awesome_view')) {
    $view->element['#attached']['library'][] = 'custom/custom_view';
  }
}

```

# Answer
> 0 votes
Adding assets (CSS, JS) to a Drupal module via \*.libraries.yml / Attaching a library to all (or a subset of) pages shows that a module should implement `hook_page_attachments()` to attach its libraries to all the pages or more pages. It could also use a preprocess function, which is useful in the case the pages to which you want to attach the library use the same theme hook.

The method you are using is listed in Adding assets (CSS, JS) to a Drupal theme via \*.libraries.yml / Attaching a library to all pages, which also says:

> If you prefer attaching a library from within your module you can use `hook_preprocess_HOOK()` or `hook_page_attachments()`.

---
Tags: views, 9
---


# Question
Title: Is "event_subscriber" a reserved naming convention for services? Are there guidelines to follow?
So I was working on a project today, and an event subscriber we had written the better part of a year ago was determined to no longer be firing. Here is the definition:

```
services:
  my_module.event_subscriber:
    class: Drupal\my_module\EventSubscriber\XYZFeeds
    tags:
      - { name: event_subscriber }

```

I went through the normal debugging, and found that the event was not being added to the registry. Further debugging uncovered that having the name contain `event_subscriber` was causing it to not get picked up. If I changed that to anything else it would work, for example:

```
services:
  my_module.my_module_xyz_subscriber:
    class: Drupal\my_module\EventSubscriber\XYZFeeds
    tags:
      - { name: event_subscriber }

```

I cannot find any documentation that explicitly states that you cannot use that phrase in a service name.The only convention I am aware of is to always prefix the service name with the module it comes from.

Did something change from D8 to D9, or does this come from the Symfony Framework components that are part of Drupal?

# Answer
It doesn't appear to be reserved/disallowed by Drupal or Symfony - this works fine for me in 9.3.13 after adding the code and rebuilding cache (no extra steps):

*custom\_module.services.yml*

```
services:
  custom_module.event_subscriber:
    class: Drupal\custom_module\EventSubscriber\XYZFeeds
    tags:
      - { name: event_subscriber }

```

*src/EventSubscriber/XYZFeeds.php*

```
<?php

namespace Drupal\custom_module\EventSubscriber;

use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class XYZFeeds implements EventSubscriberInterface {

  public static function getSubscribedEvents() {
    return [
      ConfigEvents::SAVE => 'configSave',
      ConfigEvents::DELETE => 'configDelete',
    ];
  }

  public function configSave(ConfigCrudEvent $event) {
    $config = $event->getConfig();
    \Drupal::messenger()->addStatus('Saved config: ' . $config->getName());
  }

  public function configDelete(ConfigCrudEvent $event) {
    $config = $event->getConfig();
    \Drupal::messenger()->addStatus('Deleted config: ' . $config->getName());
  }

}

```

This produces the expected messages on config save/delete, so it seems likely your problem is something more localised.

One idea for further debugging that springs to mind is to check that you have no custom (or even contrib) code which is altering the service, perhaps even removing it. This can be done using a service provider, so grep-ing the relevant folders for `ServiceProvider` might be a first step.

It would also be worth a test to change the first part of the ID rather than the second, to see if is indeed `event_subscriber` that's causing the problem, or the string as a whole:

```
services:
  my_module_test.event_subscriber:
    class: Drupal\my_module\EventSubscriber\XYZFeeds
    tags:
      - { name: event_subscriber }

```

If the altered version works with `.event_subscriber`, at least you've ruled that out as the problem.
> 2 votes

# Answer
The service name can contain a tag name. Drupal core itself has services like *form\_test.event\_subscriber*, *migrate.plugin\_event\_subscriber*, or *module\_install\_class\_loader\_test1.event\_subscriber*.

The fact their names end in *event\_subscriber* makes more evident those services are event subscribers. That's not a requirement for the service to be recognized as event subscriber, though, as Drupal see those as even subscribers because those services use *event\_subscriber* as one of their tags.

To answer to the questions in the question title, *event\_subscriber* isn't a reserved naming convention for services, and there are any guidelines to follow in choosing an event subscriber name, except that two event subscribers cannot have the same name.
To answer the questions in the question body, nothing changed in Drupal 9, in its code or in the code used by Symfony that could cause the issue described in the question. The services I linked before are implemented in Drupal 9, which means that even in Drupal 9 a service with a name that ends in *event\_subscriber* isn't an issue.
> 1 votes

---
Tags: event-subscribers
---


title: Reusable documents with media

text:
# Question
Title: Reusable documents with media
With the *Media* module in the core of Drupal 9 in the *Media* type document there is the field `field_media_document` with the option "display".

When I use a *Media* field in a content type how do I decide if a media should be displayed in one node and not displayed in another node?

It seems that this case cannot be handled.

In Drupal 7 with *Media* module contrib the display option was in the content type field.

# Answer
Thanks to this module: drupal.org/project/media\_library\_media\_modify it is possible to use multimedia items several times, but with different attributes per node, for example the property 'display' and 'description'.
> 1 votes

---
Tags: media, 9
---


# Question
Title: How can I retrieve the current currency symbol?
I know there must be an API that returns the current currency symbol, but when I searched for it, I didn't find anything.

How can I retrieve the current currency symbol?

# Answer
> 3 votes
With Drupal 7, if you want to get the default (current) currency you can use the following code.

```
$cur = commerce_currency_load();
$sym = $cur['symbol'];

```

# Answer
> 3 votes
With the Commerce Multicurrency module and Drupal 7, you can use the following code.

```
$enabled_curr = commerce_currencies(TRUE);
$current_curr = $enabled_curr[commerce_multicurrency_get_user_currency_code()];
$curr_symbol = $current_curr['symbol'];

```

# Answer
> 3 votes
From Drupal 8, you can use the following code.

```
// Add the following line on the top of the file using the rest of the code.
use Drupal\commerce_price\Entity\Currency;

// Get the currency code from the active store.
$currency_code = $store->get('default_currency')->getValue()[0]['target_id'];
$currency = Currency::load($currency_code);
$symbol = $currency->get('symbol');

```

# Answer
> 2 votes
With Drupal 8/9, if you are using the commerce\_currency\_resolver module (which is pretty cool):

```
$currency_code = \Drupal::service('commerce_currency_resolver.current_currency')
                 ->getCurrency();

```

---
Tags: commerce
---


# Question
Title: How do I programmatically add images to a node?
I have a content type to which I added an image field. The database has a custom table with different columns, including the image ID.

Previously, I created a batch that writes data from this table to entity fields. It creates many nodes from the records in the table with filled fields. I need to do the same but for images. Part of the code from the batch is the following one.

```
if (empty($entity_id)) {
  $info = [
    'type' => 'product',
    'title' => $productTitle,
    'field_name' => (string) $product->name,
    'field_product_cid' => (string) $product->cid,
    'field_custom_url' => $product->url,
    'uid' => 1,
    // here I need to add an image to the field_image field from the table
  ];
  $node = $this->entityTypeManager->getStorage('node')->create($info);
  $node->save();
}
else {
  $storage = $this->entityTypeManager->getStorage('node');
  $node = $storage->load($entity_id);

  // Change fields of node.
  $node->set('title', $productTitle);
  $node->set('field_name', (string) $product->name);
  $node->set('field_custom_url', $product->url);
  // and here change field_image if the node already exists
  $node->save();
}

```

# Answer
Someting like this:

```
$node = $storage->load($entity_id);
$image_source_path = '/some/path'
$image_target_path = 'public://some/path';
$image_data = file_get_contents ($image_source_path);
$image_alt = 'some alt text';
// Drupal 9 >= 9.3.0 or Drupal 10
$image_object = \Drupal::service('file.repository')
                    ->writeData($image_data, $image_target_path);
// Drupal 8
//$image_object = file_save_data ($image_data, $image_target);
$node->set('field_image', [
    'target_id' => $image_object->id(),
    'alt' => $image_alt,
]);
$node->save();

```
> 2 votes

---
Tags: nodes, 9, batch-operations
---


# Question
Title: Getting the "processed" value of a formatted text field
I have a formatted text field on a content type that I'm using as the body of an email. If I load the node and print out the field I get:

```
>>> $n->field_thankyou_email_body->getValue()
=> [
     [
       "value" => "<b>Thanks!!</b>",
       "format" => "subscriber_text_lb",
     ],
   ]

```

The array is missing the "processed" value, how do I get that? Or alternatively how do I manually run the value through the text format?

# Answer
A field property is accessed like an object property:

```
$node->field_formatted_text->processed

```

As a side note, use this only for cases like this which are outside of the page render context. The preferable way is to render the text field in a render array to preserve attached metadata. See How to safely render node body on a custom variable?
> 2 votes

---
Tags: 9, input-formats
---


title: Custom Controller: How to return a 404

text:
# Question
Title: Custom Controller: How to return a 404
I have a custom controller with a parametric route:

```
site_checkout.greeting.show:
  path: '/path/{a_id}/{b_id}/greeting'
  defaults:
    _controller: '\Drupal\my_module\Controller\GreetingController::greetingShow'

```

How can I display the normal 404 page, if a\_id or b\_id are not found in the database?

```
class GreetingController extends ControllerBase {

  public function greetingShow($a_id, $b_id) {

    $a = AUtils::getAById($a_id);

    if(!$a || $b_id !== $a->get('uid')->getString() || $a->get('x')->getString() !== '1') {
      // just show the standard 404, but how?
    }

    return [];
  }
}

```

# Answer
You just throw an exception anywhere in your controller and this is caught by Drupal to build a themed error page:

```
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

...

  if (!$a || $b_id !== $a->get('uid')->getString() || $a->get('x')->getString() !== '1') {
    throw new NotFoundHttpException();
  }

```
> 5 votes

---
Tags: 9
---


# Question
Title: where are menu item configurations stored?
In drupal 8, which file holds the information of the menu items? I do a config-export and do not see which file is changed when I change the menu items.

# Answer
Menu is a Entity, like a Node (sure, with some differences). There is a config and content, config you can export and import through UI, but not with content, this you will find only in DB.

Maybe you can find some modules to import/export content, but its not available at default install of Drupal 8.
> 2 votes

# Answer
While parent menus are considered config, the items inside each menu are considered content. https://www.drupal.org/project/content\_sync allows you to export/import content as .yml files in a way similar to how configuration is synced.
> 0 votes

---
Tags: 8, configuration
---


# Question
Title: How to enable a module on a ResourceTest?
I'm running a functional test that extends the ResourceTestBase however it is throwing the following error:

`ServiceNotFoundException: The service "cache_tags.invalidator.checksum" has a dependency on a non-existent service "redis.factory".`

the module i'm testing has a dependency on redis and i have included the line:

`protected static $modules = ['user', 'rest', 'redis'];`

In my class but I still get this error.

my test class:

```
<?php

namespace Drupal\Tests\my_module\Functional\Rest;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Url;
use Drupal\Tests\rest\Functional\ResourceTestBase;
use GuzzleHttp\RequestOptions;
use Psr\Http\Message\ResponseInterface;

/**
 * Tests creation of a user using REST.
 *
 * @group my_module
 */
class myUserCreateTest extends ResourceTestBase {

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected static $auth = 'basic_auth';

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['user', 'rest', 'redis'];

  /**
   * {@inheritdoc}
   */
  public function setUp(): void {
    parent::setUp();

    $auth = isset(static::$auth) ? [static::$auth] : [];
    $this->provisionResource([static::$format], $auth);

    $this->setUpAuthorization('POST');
  }

  /**
   * Tests user creation
   */
  public function testCreateUser() {
    $create_user_url = Url::fromUserInput('/my-api/my_module/create')
      ->setRouteParameter('_format', static::$format);
    $request_body = [
      "mail" => "mail@mail.com",
      "custom_id" => "12345",
    ];

    $request_options = $this->getAuthenticationRequestOptions('POST');
    $request_options[RequestOptions::BODY] = $this->serialize->encode($request_body, static::$format);
    $request_options[RequestOptions::HEADERS]['Content-Type'] = static::$mimeType;

    $response = $this->request('POST', $create_user_url, $request_options);
    print_r($response);
    $this->assertResourceResponse(200, FALSE, $response);
  }

  /**
   * {@inheritdoc}
   */
  protected function setUpAuthorization($method) {
    switch ($method) {
      case 'POST':
        $this->grantPermissionsToAuthenticatedRole(['restful post create']);
        break;

      default:
        throw new \UnexpectedValueException();
    }
  }

  /**
   * {@inheritdoc}
   */
  protected function getExpectedUnauthorizedAccessCacheability() {
    return new CacheableMetadata();
  }

  /**
   * {@inheritdoc}
   */
  protected function assertAuthenticationEdgeCases($method, Url $url, array $request_options) {

  }

  /**
   * {@inheritdoc}
   */
  protected function assertNormalizationEdgeCases($method, Url $url, array $request_options) {

  }

  /**
   * {@inheritdoc}
   */
  protected function assertResponseWhenMissingAuthentication($method, ResponseInterface $response) {

  }

}

```

# Answer
It turns out I had to comment out the redis configuration settings in settings.php.
> 2 votes

---
Tags: 9, testing
---


# Question
Title: Display only the value of a field in a content-type template
I'm attempting to display a plain text field so that I can use it to embed youtube videos

In my template I have

```
<iframe width="420" height="315" src="https://www.youtube.com/embed/{{ content.field_video }}" frameborder="0" allowfullscreen></iframe>

```

However when it renders it produces a mess

```
<iframe width="420" height="315" src="https://www.youtube.com/embed/

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'field' -->
<!-- FILE NAME SUGGESTIONS:
   * field--node--field-video--beer.html.twig
   * field--node--field-video.html.twig
   * field--node--beer.html.twig
   * field--field-video.html.twig
   * field--string.html.twig
   x field.html.twig
-->
<!-- BEGIN OUTPUT from 'core/themes/stable/templates/field/field.html.twig' -->

            <div data-quickedit-field-id=" node="" 15="" field_video="" en="" full"="">C0DPdy98e4c</div>

<!-- END OUTPUT from 'core/themes/stable/templates/field/field.html.twig' -->

" frameborder="0" allowfullscreen></iframe>

```

I understand that part of it is because I'm in debug mode, but it's also wrapping it in a quick edit field div. And even if it didn't I'd rather not exit debug mode just to work on this. Is there a way to output just the value and nothing more? Like something similar to {{ content.field\_video.value }}?

If I can't disable quick edit field by field, is there a way to print a field while keeping the HTML intact? When I put the entire iframe into field it turns the html tags into text.

I tried

```
{{ content.field_video|raw }}

```

but the output still showed the html tags as text. I tried

```
{{ content.field_video.value|raw }}

```

But that did not show anything.

# Answer
I was able to print the value by using

```
{{ content.field_video[0] }}

```
> 1 votes

# Answer
I ended up needing to use

```
fields.field_name.content|striptags|trim

```

but this was inside a `views-view-field--view-name.html.twig` template... so it might be a different use case. Drupal 9. Media oembed video content type.
> 0 votes

---
Tags: theming, 8
---


title: jQuery update - access denied

text:
# Question
Title: jQuery update - access denied
Trying to setup the latest jquery update dev version, needed for the installation of the amazing social\_count mobile-friendly count widget, I can't configure the module. When logging as user #1 and going to http://www.example.com/admin/config/development/jquery\_update, all I get is access denied. I tried 'drush cc all' to clear the cache but in vain. Any ideas?

# Answer
> 0 votes
Jquery Update doesn't implement hook\_menu but instead uses form\_alter with jquery\_update\_form\_system\_performance\_settings\_alter

You can find the configuration options at `admin/config/development/performance`.

# Answer
> 0 votes
I encountered this error today after upgrading jquery\_update to version 7.x-4.0-alpha1.

I gained access by navigating to `/admin/people/permissions` and granting "Administer jQuery Update" permission to Administrators.

I realise that the question is nine years old, but for anyone encountering the issue today, the lack of this permission may be the cause.

---
Tags: 7, installation
---


# Question
Title: Setup migration of a Drupal 8 node(s) to Drupal 9
Are there plugins that exist that can read a Drupal 8 source by node type and help get set up for a scripted migration? The content type name is different between the source and the target. I found ContentEntity, but I am not sure if this can facilitate the need. I have a Drupal 8 database next to a Drupal 9 database. Otherwise, I assume I will have to build out an entire SQL source plugin.

# Answer
> 0 votes
It is possible by using Migrate Drupal D8 module.

If you don't like the above module approach another way to achieve it is to expose content as json in old site using JSON API and use Migrate API to import data in the new site. It gives you the flexibility to define bundles and fields in new site.

Here is another guide on how to achieve it

---
Tags: migrations, 9
---


# Question
Title: Joomla user password to Drupal migration
I have a Joomla 3.10 and a Drupal 9 site.

I want to migrate user passwords from Joomla to Drupal. I have seen that Joomla uses bcrypt and Drupal uses sha512 as the password encryption.

Is it possible to migrate user passwords from Joomla to Drupal? If yes, how can I do this?

# Answer
> 1 votes
If the other site uses Phpass (Portable PHP password) password hashes, which are used from Drupal and from Joomla (starting with versions 2.5.18 and 3.2.1), then it's possible to migrate passwords. Drupal is able to handle Phpass password hashes that start with *$P$*, which are MD5 hashes normally used by phpBB3, that start with *$H$*, still MD5 hashes, that start with *U$*, which are Drupal 6 password hashes updated by `user_update_7000()`, and that start with *$S$*, the usual SHA512 password hashes Drupal 7 uses.

For other password hashes, a module should create a service that implements `PasswordInterface` and that verifies the password entered from the user matches the password hash stored in the database in `PasswordInterface::check()`.
As reference, the default code used by Drupal core is in the `PhpassHashedPassword` class.

# Answer
> 2 votes
No. If the password hash algorithms are different you cannot migrate the hash with Drupal Core alone without installing a module that changes the algorithm, if such module exists.

# Answer
> 0 votes
The answer depends on a lot of different factors.

Drupal uses not only sha512, but also a certain salt strategy, certain loop strategy, and data storage strategy in the password field in the database. Drupal core has a concept of supporting a few different password strategies and contributed modules can support others.

I did find this Password Bcrypt module for Drupal 7 which could be helpful to you.

---
Tags: users, migrations
---


# Question
Title: How to keep 403 pages from being cached in Dynamic Page Cache
I am creating a custom module. In the routing.yml of the custom module, I have the following \_permission and no\_cache settings.

```
mymodule.test:
  path: '/mymodule/test'
  defaults:
    _controller: '\Drupal\mymodule\Controller\MyModuleController::build'
    _title: 'Page Title'
  requirements:
    _permission: 'xxx authentication'
  options:
    no_cache: 'TRUE'

```

When anonymous users access this route, they will see the 403 page (Currently setting node content) configured in system.site.yml. This is a natural process.

However, the 403 page displayed is cached by Dynamic Page Cache. (Caching by Internal Page Cache is not confirmed at this time.)

The masked key is shown below(There is also a key when "session.exists" is 0).

```
response:[cookies:big_pipe_nojs]=:[languages:language_interface]=ja:[request_format]=html:[route]=entity.node.canonical<hash>:[session.exists]=1:[theme]=mytheme:[timezone]=Asia/Tokyo:[url.path]=/mymodule/test:[url.query_args:_wrapper_format]=:[url.site]=<site info>:[user.permissions]=<hash>:[user.roles]=anonymous

```

Is there any way to prevent Dynamic Page Cache from caching the 403 page?

# Answer
> 1 votes
You won't find a cache entry for a route with a no\_cache option. The cache key is from a different route, probably the subrequest building the error page:

* main request: \[route\]=mymodule.test
* subrequest: \[route\]=entity.node.canonical

This should be no problem to cache the error page. This is like an error message "Access denied", only that is an entire HTML page, normally not containing dynamic content.

This is the answer so far, with the details the question provides. You can't reach the subrequest by adding the no\_cache option to the main request route. You could add the same option to the node route as well, but this is certainly overkill. In most cases you don't even need the no\_cache on routes at all, instead you add the necessary cache metadata inside of the request. The standard access denied exception is not cacheable by default, for advance use cases even http exceptions are now available as cacheable version and can transport cache metadata to the response. To be clear, this is all happening in the main request.

Since you are mentioning also the Internal Page Cache, this module is not suitable for dynamically created content, only for static database content. So uninstall this module in such use cases.

---

*I just don't want to have 404 or 403 pages cached by Dynamic Page Cache. How can I configure it not to cache "only 403, 404 pages or 403, 404 node content", but not the entire node module?*

Check in the subrequest whether the main request has set an exception attribute and then disable caching of the node:

```
function mymodule_preprocess_node(&$variables) {
  if (\Drupal::request()->attributes->has('exception')) {
    $variables['#cache']['max-age'] = 0;
    \Drupal::service('page_cache_kill_switch')->trigger();
  }
}

```

See HttpExceptionSubscriberBase::onException().

---
Tags: 9
---


title: Language-dependent logo

text:
# Question
Title: Language-dependent logo
How can I use a custom logo image in Drupal 8 that is language dependent? There does not seem to be an appropriate setting in the *Content and Language Translation* configuration page.

# Answer
Langauge is a visibility condition for blocks, so you could use multiple branding blocks and hard code the paths.

Setting it automatically is a little harder, language is not available in $variables in preprocess so you'd need to add it - you could add these to all preprocess functions and templates:

```
/**
 * Preprocess variables for all templates.
 * @param $variables
 */
function HOOK_preprocess(&$variables) {
  // Inject the current language into every template to ease theme development.
  $variables['current_language'] = \Drupal::languageManager()->getCurrentLanguage();

  // Inject a usable directory path.
  $variables['theme_path'] = base_path() . $variables['directory'];
}

```

You can use these in the branding block or page template to set a path to a language specific logo, e.g.:

```
<img src="{{ theme_path ~ '/logo-' ~ current_language.getID() ~ '.svg' }}" alt="{{ 'Home'|t }}" />

```

So you'd have logo-en.svg for english, logo-sv.svg for Swedish etc in your theme root, `getID()` just returns the two character language code.

You could go further and just build the whole thing in preprocess, just for the template you are using (either page or the branding block).
> 6 votes

# Answer
```
function MYTHEME_preprocess_block(&$variables) {
  $language = \Drupal::languageManager()->getCurrentLanguage()->getId();
  $variables['language'] = $language;
  switch ($variables['base_plugin_id']) {

  case 'system_branding_block':
    if ($variables['content']['site_logo']['#access'] && $variables['content']['site_logo']['#uri'] && $variables['language']=='fr') {
      $variables['site_logo'] = str_replace('.svg', '-fr.svg', $variables['content']['site_logo']['#uri']);
    }
    break;
  }
}

```
> 4 votes

# Answer
I like Jeff Burnz idea. If you want to have a more "robust" solution, you could make your own custom block type (hardcode) and put the logic there, so it could have also a fallback, if a new language logo is not available for some reason.

My second reason is: I don't like to put ANY kind of logic into presentation layer.
> 1 votes

# Answer
A better answer for the above would be to actually use the language code already provided ( Drupal \> 8.2 ) in Twig:

Drupal 8.2-8.7.5:

```
<img src="{{ base_path ~ directory }}/logos/logo-{{ language.getId() }}.png" alt={{ 'Home'|t }}" />

```

Drupal \>8.7.5:

```
<img src="{{ base_path ~ directory }}/logos/logo-{{ language }}.png" alt={{ 'Home'|t }}" />

```

Some info on the above:

* `base_path` is the subdirectory Drupal is installed under (if your home page is at `/` you can omit that )
* `~` is the Twig concatenate operator
* `directory` is the path to your current theme

As an example, if we assume that:

* Drupal is accessible from `example.com` (not `example.com/my-drupal` or other directory )
* Current theme is located in `/themes/custom/mytheme`
* Current language code is `en`

The above example will resolve to `/themes/custom/mytheme/logos/logo-en.png`
> 1 votes

# Answer
The following solution works well for me :

```
function MYTHEME_preprocess_block__system_branding_block(&$variables) {
  /**
   * this will return "en", "fr" ...
  */
  $variables['language'] = \Drupal::languageManager()->getCurrentLanguage()->getId();
  // Inject a usable directory path.
  $variables['theme_path'] = base_path() . $variables['directory'];
}

```

In templates/block--system-branding-block.html.twig :

```
{% if site_logo or site_name %}
  <a href="{{ path('<front>') }}" title="{{ 'Home'|t }}" rel="home" class="navbar-brand">
    {% if site_logo %}
      <img src="{{ theme_path }}/logo-{{ language }}.svg" alt={{ 'Home'|t }}" class="img-fluid d-inline-block align-top" />
    {% endif %}
    <span class="ml-2 d-none d-md-inline">{{ site_name }}</span>
  </a>
{% endif %}

```
> 1 votes

# Answer
Found an easier hack for the lazier of us that doesn't involve any programming at all - just add the following to your `block--system-branding-block.html.twig`:

```
<img src= "{{ path('<front>') ~ 'logo.png' }}" alt="{{ 'Home'|t }}" />

```

This would look for logo.png for your site default language (usually English), rulogo.png for Russian etc.
> 0 votes

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


# Question
Title: How to set date display format for jQuery datepicker?
I am using the standard jQuery datepicker in Drupal 7 and I would like to change how it saves and displays dates. Instead of displaying 10/11/2013, I would like it to display as November 10, 2013 for clarity. Is it possible to accomplish this?

# Answer
To change how the datepicker displays in your content entry form, go to Structure \> Content types \> *YourType* \> Manage fields \> *YourField*. Expand the section labeled, "MORE SETTINGS AND VALUES", then select the desired date format from the "Date entry options" select list.
> 2 votes

# Answer
Check out this

```
 $(function(){
        $("#to").datepicker({ dateFormat: 'yy-mm-dd' });
        $("#from").datepicker({ dateFormat: 'yy-mm-dd' }).bind("change",function(){
            var minValue = $(this).val();
            minValue = $.datepicker.parseDate("yy-mm-dd", minValue);
            minValue.setDate(minValue.getDate()+1);
            $("#to").datepicker( "option", "minDate", minValue );
        })
    });

```
> 1 votes

# Answer
For Drupal 9 you can create the new custom library and attach it to some elements. Example of library code :

```
(function ($, Drupal, drupalSettings) {
  Drupal.behaviors.FAJqueryUiDatepickerLocale = {
    attach: function attach(context, settings) {
      // console.log(drupalSettings);
      $.datepicker.regional['drupal-locale'] = $.extend({
        dateFormat: Drupal.t('dd/mm/yy'),
      }, drupalSettings.jquery.ui.datepicker);
      $.datepicker.setDefaults($.datepicker.regional['drupal-locale']);
    }
  };
})(jQuery, Drupal, drupalSettings);

```

Works fine for me.
> 0 votes

---
Tags: 7, javascript, datetime
---