title: Custom webform Element not rendered

text:
# Question
Title: Custom webform Element not rendered
It looks like this is a frequent question, but I still can not figure out, why my custom webform element is not showing up. (I read already this post and also the example module)

`web/modules/custom/site_registration/src/Plugin/WebformElement/PersonCountElement.php`:

```
<?php

namespace Drupal\site_registration\Plugin\WebformElement;

use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Annotation\WebformElement;
use Drupal\webform\Plugin\WebformElement\Hidden;
use Drupal\webform\WebformSubmissionInterface;

/**
 * Provides a 'site_person_count' element.
 *
 * @WebformElement(
 *   id = "site_person_count",
 *   label = @Translation("Person Count"),
 *   description = @Translation("Provides a fancy person counter."),
 *   category = @Translation("Custom"),
 * )
 *
 * @see \Drupal\webform_example_element\Element\WebformExampleElement
 * @see \Drupal\webform\Plugin\WebformElementBase
 * @see \Drupal\webform\Plugin\WebformElementInterface
 * @see WebformElement
 */
class PersonCountElement extends Hidden {

  /**
   * {@inheritdoc}
   */
  public function prepare(array &$element, WebformSubmissionInterface $webform_submission = NULL) {
    parent::prepare($element, $webform_submission);

    // Here you can customize the webform element's properties.
    // You can also customize the form/render element's properties via the
    // FormElement.
    //
    // @see \Drupal\webform_example_element\Element\WebformExampleElement::processWebformElementExample
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form = parent::form($form, $form_state);
    // Here you can define and alter a webform element's properties UI.
    // Form element property visibility and default values are defined via
    // ::defaultProperties.
    //
    // @see \Drupal\webform\Plugin\WebformElementBase::form
    // @see \Drupal\webform\Plugin\WebformElement\TextBase::form
    return $form;
  }

}

```

`web/modules/custom/site_registration/src/Element /PersonCountElement.php`:

```
<?php

namespace Drupal\site_registration\Element;

use Drupal\Core\Render\Element\FormElement;
use Drupal\Core\Render\Element\Hidden;

/**
 * Provides a 'site_person_count'.
 *
 * Webform elements are just wrappers around form elements, therefore every
 * webform element must have correspond FormElement.
 *
 * Below is the definition for a custom 'site_person_count' which just
 * renders a simple text field.
 *
 * @FormElement("site_person_count")
 *
 * @see FormElement
 * @see https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21FormElement.php/class/FormElement
 * @see \Drupal\Core\Render\Element\RenderElement
 * @see https://api.drupal.org/api/drupal/namespace/Drupal%21Core%21Render%21Element
 * @see \Drupal\webform_example_element\Element\WebformExampleElement
 */
class PersonCountElement extends Hidden {

  public function getInfo() {
    $properties = parent::getInfo();

    // $properties['#theme'] = 'input__site_person_count';
    return $properties;
  }

}

```

Is there anything more to it?

# Answer
> 0 votes
Ok, this was a really stupid mistake! my `src/Element` folder had actually a space in the name.

correct: `src/Element/PersonCountElement.php`
wrong: `src/Element /PersonCountElement.php`

With the correct folder name, it works like a charm.

---
Tags: webforms, 10
---


# Question
Title: Webform get email addresses from entity select unlimited
I have an Entity select element that references a role. The element is unlimited so multiple users can be selected at one time. I need to get each selected user's email address.

Using a computed twig element, I can get the email address of the first selected user with `webform_token()`:

```
{% set reviewer_email_address = webform_token('[webform_submission:values:reviewer:entity:mail]', webform_submission, [], options) %}
{{ reviewer_email_address }}

```

Something simple like:

```
{{ data.reviewer.0 }}
{{ data.reviewer.1 }}

```

prints the user id of the users. So the user entities are present.

How do I get the email address from `{{ data.reviewer.0 }}`?

# Answer
This is a non DRY solution:

```
{% set reviewer_0 = webform_token('[webform_submission:values:reviewer:0:entity:mail:clear]', webform_submission, [], options) %}
{% set reviewer_1 = webform_token('[webform_submission:values:reviewer:1:entity:mail:clear]', webform_submission, [], options) %}
{% set reviewer_2 = webform_token('[webform_submission:values:reviewer:2:entity:mail:clear]', webform_submission, [], options) %}
{% set reviewer_3 = webform_token('[webform_submission:values:reviewer:3:entity:mail:clear]', webform_submission, [], options) %}
{% set reviewer_4 = webform_token('[webform_submission:values:reviewer:4:entity:mail:clear]', webform_submission, [], options) %}
{% set reviewer_5 = webform_token('[webform_submission:values:reviewer:5:entity:mail:clear]', webform_submission, [], options) %}
{% if reviewer_0|length %}{{ reviewer_0 }}{% else %}{% endif %}
{% if reviewer_1|length %},{{ reviewer_1 }}{% else %}{% endif %}
{% if reviewer_2|length %},{{ reviewer_2 }}{% else %}{% endif %}
{% if reviewer_3|length %},{{ reviewer_3 }}{% else %}{% endif %}
{% if reviewer_4|length %},{{ reviewer_4 }}{% else %}{% endif %}
{% if reviewer_5|length %},{{ reviewer_5 }}{% else %}{% endif %}

```

with "Remove whitespace around the"
computed value and between HTML tags

and "Automatically update the computed value using Ajax".
Checked

in the computed twig element.

The twig needs to be improved in case there are more than 6 reviewers and for DRY principle.
> 0 votes

---
Tags: webforms, 9
---


# Question
Title: file_exists(): Unable to find the wrapper "private" - did you forget to enable it when you configured PHP?
I just installed a bare boned Drupal 10 locally. and Windows 10 with PHP 8.1.14

I set the private file path as follows:

```
$settings['file_private_path'] = $app_root . '/../private';

```

Its path shows correct "**/admin/config/media/file-system**". Now when I went to Drupal status page, it shows

`Warning: file_exists(): Unable to find the wrapper "private" - did you forget to enable it when you configured PHP? in Drupal\Component\FileSecurity\FileSecurity::writeFile() (line 152 of core\lib\Drupal\Component\FileSecurity\FileSecurity.php).`

I applied the security code for the .htaccess file, but still showing this

Then I added a code snippet in the theme preprocess function like this:

```
if(file_exists('private://.htaccess')) {
    print 'I found it<br>';
}
else {
    print 'It does not exists<br>';
}

```

It always shows file does not exists. But of course file is there.

I did not face this issue in previous Drupal versions. Btw, in my php.ini allow\_url\_fopen is On and opessl is enabled.

Anyone there to help me to fix this issue?

# Answer
I could not say what happened. But reinstalling the Drupal dump fixed the problem.
> 0 votes

---
Tags: files, stream-wrappers
---


# Question
Title: How to Save Configuration Data for Custom Block
I'm have a custom module that creates a custom block plugin, but am having trouble figuring out how to add some custom configuration settings to the block.

Just for understanding how to do this, I've got a `checkboxes` form element that I've added to my block creation code in my `bootstrap_theme_toggler/src/Plugins/Block/themeToggler.php` file as such:

```
<?php

namespace Drupal\bootstrap_theme_toggler\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a 'Theme Toggler' Block.
 *
 * @Block(
 *   id = "theme_toggler",
 *   admin_label = @Translation("Theme Toggler"),
 *   category = @Translation("Theme Toggler Block"),
 * )
 */
class themeToggler extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    return [
      '#theme' => 'block__toggler',
      '#attached' => [
        'library' => ['bootstrap_theme_toggler/theme-toggler'],
      ],
      // 'label_display' => FALSE
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state) {

    // for checkbox, the values used are the option array keys, and the array values are the lables.
    $form['toggler_block_themes']['colors'] = array(
      '#type' => 'checkboxes',
      '#title' => $this->t('Color Theme Modes'),
      '#options' => array('blue' => $this->t('Blue'), 'red' => $this->t('Red')),
      '#description' => $this->t('Select the color theme modes to use on this toggler.'),
    );
    // kint($form['favorites']['colors']['#options']);

    // $form['toggler_block_themes']['colors']-> processCheckboxes;
    // kint($form_state);
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    $values = $form_state->getValues();
    $this->configuration['toggler_block_themes'] = $values['toggler_block_themes'];
  }

}

```

This works fine to create the checkboxes form element on the block configuration page, however, it's not saving the boxes that are checked when I save the configuration. Do I need a `bootstrap_theme_toggler.settings.yml` and/or `bootstrap_theme_toggler.schema.yml` file in my modules config folder, and if so how do I structure those to support a checkboxes form element. If not what should I change for the checked boxes to save when saving the config. Perhaps it is saving and I'm not loading them correctly when I go back to the config form after saving, I can't tell.

# Answer
It appears that it was saving the configuration data, but I was not recalling it properly when re-entering the configuration form. To correct this, I needed to get the checkboxes configuration values, or if they don't exist create default values, and set them as the `#default_value` for the form element as updated below:

```
<?php

namespace Drupal\bootstrap_theme_toggler\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a 'Theme Toggler' Block.
 *
 * @Block(
 *   id = "theme_toggler",
 *   admin_label = @Translation("Theme Toggler"),
 *   category = @Translation("Theme Toggler Block"),
 * )
 */
class themeToggler extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    return [
      '#theme' => 'block__toggler',
      '#attached' => [
        'library' => ['bootstrap_theme_toggler/theme-toggler'],
      ],
      // 'label_display' => FALSE
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state) {

    $config = $this->configuration['toggler_block_themes']['colors'] ?? array('blue','red');
    // for checkbox, the values used are the option array keys, and the array values are the lables.
    $form['toggler_block_themes']['colors'] = array(
      '#type' => 'checkboxes',
      '#title' => $this->t('Color Theme Modes'),
      '#options' => array('blue' => $this->t('Blue'), 'red' => $this->t('Red')),
      '#description' => $this->t('Select the color theme modes to use on this toggler.'),
      '#default_value' => $config,
    );
    // kint($form['favorites']['colors']['#options']);

    // $form['toggler_block_themes']['colors']-> processCheckboxes;
    // kint($form_state);
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    $values = $form_state->getValues();
    $this->configuration['toggler_block_themes'] = $values['toggler_block_themes'];
  }

}

```
> 0 votes

---
Tags: blocks, configuration
---


# Question
Title: menu.tree_storage service is missing from my site
I have upgraded my Drupal 9 site to Drupal 10.1. One of my custom module uses `\Drupal::service('menu.tree_storage')->loadByProperties();` which works fine in drupal 9.5.9, but I get the following error message in Drupal 10.1.

> You have requested a non-existent service "menu.tree\_storage"

When I used `drush dcs | grep "tree"`, the menu.tree\_storage is missing from my Drupal 10 site. Yet it is listed as an argument in the core.services.yml file.

Is there a way to fix this?

# Answer
In case this helps someone else: Since we only use the load method of the MenuTreeStorage class, we were able to replace it with the MenuLinkManager.

```
-    $container->get('menu.tree_storage'),
+    $container->get('plugin.manager.menu.link'),
-    $menu_link = $this->menuTreeStorage->load($id);
+    $menu_link = $this->menuLinkManager->getDefinition($id, FALSE);

```

See https://www.drupal.org/project/drupal/issues/3385730 for possible further follow up of core maintainers.
> 0 votes

# Answer
Menus are config entities and can be loaded using the entity type manager instead of using menu tree storage service.

https://www.drupal.org/node/3027453
> -1 votes

---
Tags: navigation, 10, symfony-services
---


# Question
Title: Why isn't an image from the local domain shown with the explanation that, for security reasons, only images from the local domain are allowed?
I'm running Drupal Core 9.3.7, with basically the default set up. The Basic HTML editor is CKEditor. If I include an image in a page, that image is not shown when I view the page; on inspection, it is actually there, but with the `height="16" width="16"` attributes, and a title that says:

> This image has been removed. For security reasons, only images from the local domain are allowed

The image **is** in the local domain (the relative path is */files/inline-images/Picture%201.png*); it was literally uploaded in the content editor. If I put in the URL of the image into the browser, it works. It doesn't seem an upload or a permission issue.

If I go to *Configuration » Text formats and editors » Basic HTML » Configure* and deselect *Restrict images to this site*, the images appear.

Any help would be much appreciated. I'm a complete Drupal newbie.

# Answer
> 1 votes
I solved this by re-ordering the filters, so tracking is done before the Restriction check.

* Track images uploaded via a Text Editor
* Restrict images to this site\*
* Image Resize Filter: Resize images based on their given height and width attributes

---
Tags: nodes, media, 9
---


# Question
Title: Fetch the total number of rows in Rules View to use that number in Rules
I have a View that lists entity IDs of some sort and I have created a Rules View for this. In Rules, I have created a component where I want to fetch the total number of rows from that Rules View and do something with that number which should be an integer, I believe. I don't want to do something with each row. I just need to collect the total. I'm using the "Collect view result rows" action to try to collect the total number of rows as a number. How do I make this number available in my Rules component without looping over the entire list?

# Answer
Here's a working recipe. (since no one is replying, I asked ChatGPT but it couldn't help me either)

Requirements: Drupal 7, Views 3, Views Rules

Step 1: Create a View and add the following fields:

1. Global: View Results Counter (reverse the order and set the label to #)
2. List the entity IDs
3. Add filters as you see fit.
4. Set the pager setting to: display all items.

Step 2: Create a Rules View In the Rules Settings choose: edit field info Here configure the Rules: row variables

1. "#" set it to "enabled", check the box "Use rendered result", choose "integer" as the Data type and leave the label and Name as it is. The name should now be "counter"
2. ID set it to "enabled", choose "Course" as the Data type (that is my ECK entity name) and I set the label to "Id" and the name to "id"

Hit apply.

Step 3: Create a Rules component (as component plugin I chose: "Rule")

1. Add the action: "Collect view result rows", leave everything as it is and hit "save"
2. Add a variable: Set the Type as "integer" and the optional initial value: choose "Data selector" and drill down to "counter:0" This will take the first counter value from the first row. Since we have set it to reverse, we now have the total number of items in the view which is what we want. I left the name of the Variable label and the Variable name as it gave me so that was "Added variable" and "variable\_added"
3. Hit save
4. Show a message and enter: \[variable-added:value\]
5. Go to the Components overview page and click on the "execute" button next to the name of your rule ... et voila!

```
 { "rules_show_me_the_total_number_of_active_courses" : {
 "LABEL" : "Show me the total number of Active Courses",
 "PLUGIN" : "rule",
 "OWNER" : "rules",
 "TAGS" : [ "component", "courses", "rule", "test", "vbo" ],
 "REQUIRES" : [ "views_rules", "rules" ],
 "DO" : [
   { "views_rules_collect_rows" : {
       "USING" : { "views_rules_display" : "course_collection_for_cron:views_rules_1" },
       "PROVIDE" : {
         "counter" : { "counter" : "List of #" },
         "id" : { "id" : "List of Id" }
       }
     }
   },
   { "variable_add" : {
       "USING" : { "type" : "integer", "value" : [ "counter:0" ] },
       "PROVIDE" : { "variable_added" : { "variable_added" : "Added variable" } }
     }
   },
   { "drupal_message" : { "message" : "The Added Variable value counter: [variable-added:value]" } }
 ]

```

} }
> 0 votes

---
Tags: 7, views, rules
---


title: Multilanguage View path translation

text:
# Question
Title: Multilanguage View path translation
I'm building a multilanguage site and I have a View of taxonomy terms with the following configuration

when I hover the menu Wines I can see the /en/products link, that's perfect when I switch to my second language if I hover the menu it shows /it/products

I managed to translate the menu entry "Wines" so now it shows the Italian word "Vini" while browsing the /it/ site, but not the Path, I'd like it to be /it/prodotti

Using URL Aliases doesn't work, I can add the alias but if I type /it/prodotti it gives page not found.

I don't have this problem with Pages, only with Views, is there a solution? The rest of the website works perfectly with the 2 enabled languages: language switch, translations, menus, etc.

Thanks

# Answer
Translated views will need language-specific path aliases.

You'll add a path alias as normal at `/admin/config/search/path/add`

But make sure to set the path as the desired language with the language dropdown select. Do not add the language prefix, Drupal will handle that based on the language selection from the dropdown.

Example image:
> 0 votes

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


# Question
Title: The title of a particular node became part of the breadcrumbs of administration pages
In the Claro theme, I have the *System breadcrumb* block in the *Breadcrumb* region. The breadcrumb shows *Homepage \> \[Title for node 444\] \> Structure \> \[Administration page title\]* instead of *Homepage \> Structure \> \[Administration page title\]*, where *\[Title for node 444\]* is the title for the node whose ID is 444, and *\[Administration page title\]* is the title for the shown administrative page.

Upgrading to Drupal 10.1.2 didn't solve the issue.

How can I remove the node title, which should not be there since the shown page is an administrative page not related to nodes nor to that node in particular?

# Answer
I can reproduce this problem by assigning an admin alias

```
/admin/structure

```

to a node. Then the title of the node is displayed in the breadcrumbs.

To solve this problem search for the alias in the alias table:

```
/admin/config/search/path?search=admin

```

Delete the alias and clear the cache.

You might also want to check the admin menu for an entry pointing at the node.
> 2 votes

---
Tags: 9, breadcrumbs
---


# Question
Title: How do I access $this in a dataProvider method?
Is it possible to access `$this` in a PHPUnit `BrowserTestBase` data provider method to get access to properties defined in the testBase class? It seems that the sequence of processing during startup of the tests means that the properties in my test base class are not available at the dataProvider stage, they are only available after the test function has actually started, and received its first test data parameters. But by this time it is too late and NULL has already been passed as the value.

Example, my TestBase class has

```
  /**
   * @var string
   */
  protected $valueAsConstant = 'some predefined value';

  /**
   * @var string
   */
  protected $valueInSetup;

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

    $this->valueInSetup = 'value given in setUp method';

  }

```

The actual test is

```
  /**
   * @dataProvider dataQuestion()
   */
  public function testQuestion($value) {
  }

  public function dataQuestion() {
    $data = [
      [$this->valueAsConstant],
      [$this->valueInSetup],
    ];
    return $data;
  }

```

This produces the following (url shortened for ease of reading)

```
Testing modules/d8testing
Test 'D8testingTest::testQuestion with data set #0 ('some predefined value')' started
Test 'D8testingTest::testQuestion with data set #0 ('some predefined value')' ended
Test 'D8testingTest::testQuestion with data set #1 (null)' started
Test 'D8testingTest::testQuestion with data set #1 (null)' ended

```

# Answer
It seems not possible to use fields inside a dataprovider. A (temporary) workaround I used is to put an array in between:

```
public function setUp() {
  $this->fields = [
    'value_1' => $this->valueInSetup1,
    'value_2' => $this->valueInSetup2,
  ];
}

```

```
  /**
   * @dataProvider dataQuestion()
   */
  public function testQuestion($key) {
    $value = $this->fields[$key]
  }

  public function dataQuestion() {
    return [
      ['value_1'],
      ['value_2'],
    ];
  }

```

Which is not really a clean/readable approach though... So I will refactor this code later on so that accessing fields is not needed anymore inside the `dataProvider`, which is probably the best advice here.
> 0 votes

# Answer
I hit this problem today as well, and it seems you are correct in your assumption from the comments that properties initialized within `setUp()` are not available in the data provider. According to the documentation, the data provider is run before `setUp()`, which means that any properties that are initialized within `setUp()` won't be initialized in time to be used inside the data provider.

Lucky for me, I was only initializing two different instances of the same class inside my `setUp()`, and needed to use one or the other inside my different test cases. I therefore solved it in my case by creating two constants at the top of the test class, one for each object instance from `setUp()`. Then I put the corresponding constant inside the different test cases of the data provider, and used that data inside the test method to decide which of the class properties I needed for any given test case. Not elegant and scalable, but very straightforward and simple. YMMV.
> 0 votes

---
Tags: 8, testing
---


# Question
Title: Opening a nested paragraph in a modal window
I have a paragraph (image with some fields) inside a parent paragraph.

Inside the template of the parent paragraph I'd like to open the nested paragraph via link () in a modal window.

How can I access the nested paragraph in the template of the parent paragraph as a link?

# Answer
The most generic solution would be a layout paragraph type designed to display a hidden modal window. A layout paragraph type usually contains only one field, a paragraph reference field to add more nested paragraphs. There is no need to reference nested or parent paragraphs, paragraphs render recursively.

You can also make a modal version of the image paragraph type which puts `{{ content }}`, containing the image field and other fields, in a modal window body. See for example Ajaxly login/signup in bootstrap modal
> 0 votes

---
Tags: paragraphs
---


# Question
Title: Permission denied error using Wkhtmltopdf on drupal 9 entityprint
I downloaded the Wkhtmltopdf library using Homebrew and configured it on drupal 9 on the entityprint module on /admin/config/content/entityprint. It is in the /usr/local/bin directory, but when I try to print a PDF via drupal I get this error.

> Error generating document: Failed to generate PDF: sh: 1: /usr/local/bin/: Permission denied

I have given 777 permissions to that directory recursively.

# Answer
i had configured it wrong, i had put only the directory for the binary location, the correct configuration is attached in an image . thank you
> 1 votes

---
Tags: 9
---


# Question
Title: How can I fix the "The specified database connection is not defined: default" error?
I installed PHP 7.4.21, then Drupal 9.2.1, and Drush 10.5.0 with Composer as well.

Running Drush without arguments, I get the list of all the available commands.
Running `drush cr` gives me the following error.

> The specified database connection is not defined: default

`drush cr --root=/home/ip/d916/web` gives the same error.

The output of `drush cr -vvv` is the following.

> ### Exception trace
>
> at /home/ip/d916/web/core/lib/Drupal/Core/Database/Database.php:371
> Drupal\Core\Database\Database::openConnection() at /home/ip/d916/web/core/lib/Drupal/Core/Database/Database.php:169
> Drupal\Core\Database\Database::getConnection() at n/a:n/a
> call\_user\_func\_array() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:258
> Drupal\Component\DependencyInjection\Container-\>createService() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:176
> Drupal\Component\DependencyInjection\Container-\>get() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:437
> Drupal\Component\DependencyInjection\Container-\>resolveServicesAndParameters() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:240
> Drupal\Component\DependencyInjection\Container-\>createService() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:176
> Drupal\Component\DependencyInjection\Container-\>get() at /home/ip/d916/web/core/lib/Drupal/Core/Cache/ChainedFastBackendFactory.php:89
> Drupal\Core\Cache\ChainedFastBackendFactory-\>get() at /home/ip/d916/web/core/lib/Drupal/Core/Cache/CacheFactory.php:83
> Drupal\Core\Cache\CacheFactory-\>get() at n/a:n/a
> call\_user\_func\_array() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:258
> Drupal\Component\DependencyInjection\Container-\>createService() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:176
> Drupal\Component\DependencyInjection\Container-\>get() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:437 Drupal\Component\DependencyInjection\Container-\>resolveServicesAndParameters() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:240
> Drupal\Component\DependencyInjection\Container-\>createService() at /home/ip/d916/web/core/lib/Drupal/Component/DependencyInjection/Container.php:176
> Drupal\Component\DependencyInjection\Container-\>get() at /home/ip/d916/web/core/lib/Drupal/Core/DrupalKernel.php:586
> Drupal\Core\DrupalKernel-\>preHandle() at /home/ip/d916/web/core/includes/utility.inc:35
> drupal\_rebuild() at /home/ip/d916/vendor/drush/drush/src/Commands/core/CacheCommands.php:234
> Drush\Commands\core\CacheCommands-\>rebuild() at n/a:n/a
> call\_user\_func\_array() at /home/ip/d916/vendor/consolidation/annotated-command/src/CommandProcessor.php:257
> Consolidation\AnnotatedCommand\CommandProcessor-\>runCommandCallback() at /home/ip/d916/vendor/consolidation/annotated-command/src/CommandProcessor.php:212
> Consolidation\AnnotatedCommand\CommandProcessor-\>validateRunAndAlter() at /home/ip/d916/vendor/consolidation/annotated-command/src/CommandProcessor.php:176
> Consolidation\AnnotatedCommand\CommandProcessor-\>process() at /home/ip/d916/vendor/consolidation/annotated-command/src/AnnotatedCommand.php:311
> Consolidation\AnnotatedCommand\AnnotatedCommand-\>execute() at /home/ip/d916/vendor/symfony/console/Command/Command.php:255
> Symfony\Component\Console\Command\Command-\>run() at /home/ip/d916/vendor/symfony/console/Application.php:1027
> Symfony\Component\Console\Application-\>doRunCommand() at /home/ip/d916/vendor/symfony/console/Application.php:273
> Symfony\Component\Console\Application-\>doRun() at /home/ip/d916/vendor/symfony/console/Application.php:149
> Symfony\Component\Console\Application-\>run() at /home/ip/d916/vendor/drush/drush/src/Runtime/Runtime.php:118
> Drush\Runtime\Runtime-\>doRun() at /home/ip/d916/vendor/drush/drush/src/Runtime/Runtime.php:48
> Drush\Runtime\Runtime-\>run() at /home/ip/d916/vendor/drush/drush/drush.php:72
> require() at /home/ip/d916/vendor/drush/drush/drush:4

Composer works without any mistake. Drupal work fine too. Unfortunately I can't work without Drush 10.

How can I fix the *The specified database connection is not defined: default* error?

# Answer
You say that Drupal works fine. Do you really mean that your Drupal 9.2.1 website is fully functional without a database connection? That is surprising!

You can start by connecting to this environment via `ssh` and testing a connection to the database using the command-line `mysql` utility and the database authentication credentials stored in your `settings.php` file.

If you get a successful connection, run some diagnostic commands like `USE `drupal`;` (replacing `drupal` with the DB name specified in your settings) and `SHOW TABLES;` and `SELECT COUNT(*) FROM `node`;` (just be very careful not to issue any commands that insert, update, or delete any data!)

If Drupal really can connect to the database, and you can connect in this way from the command line, then you will have narrowed the problem down to Drush.

You can make sure that you are really running the correct project-local version of Drush 10 that you installed with Composer by executing `which drush` at the command prompt to see if you are instead using a gloabally installed Drush, perhaps even a different version.

If that is the case, please specify the full path to your local Drush to be sure you are executing the correct Drush PHAR:

```
$ cd /home/ip/d916/
$ ./vendor/bin/drush status
$ ./vendor/bin/drush cr

```

If these commands work for you, then you have different options depending on your hosting. The Drush docs are excellent, and will help you to decide the correct path forward.
> 2 votes

# Answer
If you have an extra file with your local settings, like for example `settings.local.php`, check if it is placed in the correct directory.

In this case it must be in the `sites/default/` directory, not in the `sites/` root folder. Most likely the error is caused by a misplaced configuration file.

If that's not the case, or you have only one `settings.php`, check if you have a valid configuration for your database in the `$databases[][]` array in it, for the "default" site it must be named "`$databases['default']['default']`" and must contain all your database information.

Example:

```
## database settings
$databases['default']['default'] = [
  'database' => 'drupal9',
  'username' => 'drupal9',
  'password' => 'drupal9',
  'prefix' => '',
  'host' => 'database',
  'port' => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
];

```
> 1 votes

# Answer
I ran into this recently. If this is a shared host, or a multisite setup, you will need to include the `--uri=https://[example-domain.com]` parameter with your drush command. That's how it is going to find your particular site's db connection info.
> 0 votes

# Answer
If you're using local development, such as with Vagrant, Lando, or DDEV, be sure you've established a shell connection to your environment using a command such as `vagrant ssh`, `lando ssh`, or `ddev ssh`, then run your commands from within your SSH session. Otherwise, the Drupal Console command can't connect to the database.

This is true for any other commands like `drush` that require database access, although many local development environments have shortcuts like `ddev drush` that handle that connection for you. Drupal console does not have such a shortcut, so an SSH connection to your local environment is essential.
> 0 votes

# Answer
I had a same issue while executing a drush command. The reason behind my error was a missing directory alias in sites.php file. For ex: I had a site with "example.local.com" and I had created a site folder with the name "example". I had to add a directory alias in sites.php file to fix the issue.

```
$sites['example.local.com'] = 'example';

```

Hope this helps someone!!

Refer: https://www.techpond.in/drush-specified-database-connection-not-defined-default
> 0 votes

---
Tags: drush
---


# Question
Title: Exposed date filter that uses "Is between" doesn't include end date
SITUATION:

* Create a view of transactions (a custom entity in my case, but I don't think this is relevant)
* Filter against `Authored on` (which includes both the date and time of creation)
* Expose the filter
* Choose **Operator: Is between**
* Display the view with 10/01/2020 and 10/31/2020 as start and end dates for October
* Note: I'm using the Date Popup module for date entry, which accepts mm/dd/yyyy

Transactions on 10/31/2020 are omitted. How can I include end-date transactions, short of telling users to put 11/01/2020 instead of 10/31/2020 (which is what seems natural to them)?

# Answer
> 3 votes
It's a core bug, as @prkos mentioned, end time is assumed 00:00:00 when it needs to be 23:59:59

```
/**
 * Implements hook_form_FORM_ID_alter().
 */
function mymodule_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if (!empty($form['created']['max'])) {
    // use array_unshift() so custom submit runs before the default submit.
    array_unshift($form['#submit'], '_fix_max_date_submit_function');
  }
}

function _fix_max_date_submit_function($form, FormStateInterface $form_state) {
  $date_filter = $form_state->getValue('created');
  if ($date_filter['max']) {
    $date_filter['max'] = $date_filter['max'] . ' 23:59:59';
    $form_state->setValue('created', $date_filter);
  }
}

```

---

### Alternative solution

You might have to use this solution if you don't like the default `Y-m-d` formatting and rather have a `m/d/Y` input for example. Below I use `Y-m-d`, but you can always change it.

It's a core bug, as @prkos mentioned, end time is assumed 12:00:00 AM when it needs to be 11:59:59 PM

If you enable Views sql query at `/admin/structure/views/settings` you'll see the query is like:

So all you have to do is swap the last timestamp with the corrected timestamp that takes 11:59:59 PM into account.

You can do that with hook\_views\_query\_alter, but hold your horses, this hook can only run inside of **mymodule.views\_execution.inc** file, so create that file and then you can do

```
<?php

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\views\ViewExecutable;

/**
 * Implements hook_views_query_alter()
 */
function mymodule_views_query_alter($view, $query) {
  if (!empty($query->where[1]['conditions'])) {
    foreach ($query->where[1]['conditions'] as $con_key => $con_val) {
      $has_created_date_condition = strpos($con_val['field'], 'node_field_data.created') !== FALSE;
      if (($has_created_date_condition)) {
        // timezone set in /admin/config/regional/settings, will get "Users may set their own time zone" if checked.
        $timezone = date_default_timezone_get();

        $min_date = $view->exposed_data['created']['min'];
        $min_date_obj = DrupalDateTime::createFromFormat('Y-m-d', $min_date, $timezone);
        $min_date_timestamp = $min_date_obj->getTimestamp();

        $max_date = $view->exposed_data['created']['max'];
        $fixed_max_date_obj = DrupalDateTime::createFromFormat('Y-m-d h:i:s A', $max_date . ' 11:59:59 PM', $timezone);
        $fixed_max_date_timestamp = $fixed_max_date_obj->getTimestamp();

        $query->where[1]['conditions'][$con_key]['field'] = 'node_field_data.created';
        $query->where[1]['conditions'][$con_key]['value'][0] = $min_date_timestamp;
        $query->where[1]['conditions'][$con_key]['value'][1] = $fixed_max_date_timestamp;
        $query->where[1]['conditions'][$con_key]['operator'] = 'BETWEEN';
      }
    }
  }
}

```

# Answer
> 1 votes
I agree this implementation lacks some UX polishing.

The reason why that day is omitted in your case is because you're not including the time, so **a time of 00:00:00 is assumed**, which is the beginning of the day and most of that day's time will be excluded. The first day also assumes it, but because it's the beginning of the range it includes the whole day.

The solution is to **use the time along with the date**, and give clues to users to orientate them with using Placeholder example values and the Filter field Description:

Empty form:

After filling in:

You can come up with better UX Label and Description, I'm just demonstrating a good starting point.

# Answer
> 1 votes
This issue is also solved by the patch provided in https://www.drupal.org/node/2982968

---
Tags: 8, views
---


# Question
Title: phpwkhtmltopdf engine pdf printing configuration issues
The screenshot below shows my Entity Print configurations for created styled PDFs from node content.

As shown in the screenshot I am using the phpwkhtmltopdf engine and the mikehaertl/phpwkhtmltopdf package is installed via composer.

However, when I try generating the target PDF, the following errors results:

> Error generating document: Failed to generate PDF: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: 1: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: cannot open ?php: No such file /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: 2: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: namespace: not found /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: 4: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: use: not found /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: 6: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: /bin: Permission denied /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: 7: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: INSTALL.txt: not found /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: 8: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: INSTALL.txt: not found /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: 9: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: INSTALL.txt: not found /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: 10: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: INSTALL.txt: not found /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: 12: /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: Syntax error: newline unexpected

I gave Pdf.php 777 permissions too.

Can anyone help, please?

# Answer
> /opt/drupal/vendor/mikehaertl/phpwkhtmltopdf/src/Pdf.php: cannot open ?php: No such file

You need to install the missing library using composer

```
composer require mikehaertl/phpwkhtmltopdf

```

In addition, you might also need `h4cc/wkhtmltopdf`, see Entity Print documentation
> 0 votes

# Answer
The location has to be configured as per this picture
> 0 votes

---
Tags: theming, 9
---


# Question
Title: How to update payment status inside an order?
I am trying to update order status and payment status depending upon the value we get in a variable called $payment\_status. I am able to update order status but I am unable to update payment status inside that order. I am getting an error "The website encountered an unexpected error. Please try again later. Error: Class 'Drupal\commerce\_order\Payment\Payment' not found" The code I used is as follows:-

```
//update order status based on payment status
  $order = \Drupal\commerce_order\Entity\Order::load($order_id);
  // dpm($order);
  if($payment_status === 'payment.captured' ){
    $order->set('state', 'completed' );
    $order->save();
    $payments = \Drupal\commerce_order\Payment\Payment::loadByProperties(['order_id' => $order_id]);
      foreach ($payments as $payment)
      {
        $payment->setState('completed')->save();
      }
  }
  else{
    $order->set('state', 'pending' );
    $order->save();
  }

```

How to solve this?

# Answer
Please change the code from

```
 \Drupal\commerce_order\Payment\Payment::loadByProperties(['order_id' => $order_id]);
        TO
 \Drupal::entityTypeManager() ->getStorage('commerce_payment') ->loadByProperties([ 'order_id' => [$orderid], ]);

```
> 2 votes

# Answer
It should be like below:

```
$payments = \Drupal::entityTypeManager()->getStorage('commerce_payment')->loadByProperties(['order_id' => $order_idS]);

```
> 0 votes

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


# Question
Title: How to create reusable custom block templates or duplicate existing blocks?
Drupal noob here.

Problem: Unable to reuse blocks created using Bootstrap Layouts module; being forced to manually re-enter data in order to duplicate a block in a new locaion.

Details and any research: Custom blocks seem to be made for reusability, but I'm struggling to find and insert any of the previously created blocks into new pages using the layout builder

Tried: searched Stack, Drupal forums and Google for "unable to reuse drupal custom blocks" and similar queries; read through what I understand of the Drupal and Bootstrap Layouts documentation.

Attached image shows an example of a custom grid block ("What We Do") which I'd like to be able to insert on a different page; unable to find it in any kind of list/library when in the target page layout builder. Forced to recreate it from scratch. Surely there's a way!

# Answer
> 0 votes
Inline custom content blocks created on-the-fly inside a node's layout builder are intentionally not reuseable.

To create reuseable custom content blocks, go to to the custom block library `/admin/content/block` (if Drupal v10) or `/admin/structure/block/block-content` (if Drupal v9) and create the block there. The blocks created here are the reuseable ones.

---
Tags: blocks
---


title: Override output of taxonomy name field

text:
# Question
Title: Override output of taxonomy name field
In drupal 9, the default output for a taxonomy term name field related to a specific piece of content is:

```
<element>"Item1, Item2, Item3"</element>

```

I want:

```
<element>Item1</element><element>Item2</element><element>Item3</element>

```

I there a way to do this? I can't see to target this in a theme suggestion for related taxonomy term name fields.

I only want to change the output for a specific view and display.

# Answer
> 1 votes
Do you mean you don't see the suggestions in Twig Debug? They are still there, see Override field twig template in views.

You don't need to override a template, however. Views has a built-in Twig template engine. In the field settings open *Rewrite Results* and add your HTML element:

```
<i>{{ field_foo }}</i>

```

If you want to remove the comma separator look in *Multiple Field Settings*.

---
Tags: views, 9
---


# Question
Title: How can I get the untranslated field value from a translated paragraph?
Normally you can't have different paragraph items per language so I simply want to hide selected paragraphs depending on a field value in the paragraph. I added an untranslatable list field listing all active languages and editors can select one or multiple languages for which the paragraph should be rendered. On other languages it should be hidden.

So I implemented `hook_ENTITY_TYPE_access()`, got that field value, calculated an `$allowed` value and returned an `AccessResult::forbiddenIf($allowed === FALSE)`.

This works fine for the default language, BUT it doesn't work when viewing the translated node. **On translations the field always comes out empty**. Even if I get the `getUntranslated()` paragraph.

How can I make my logic work for the translations as well? Why does the visibility field always come out empty on translations? How can I get the selected values?

```
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\paragraphs\ParagraphInterface;

/**
 * Implements hook_ENTITY_TYPE_access().
 */
function MYMODULE_paragraph_access(ParagraphInterface $paragraph, $operation, AccountInterface $account) {

  if ($operation === 'view' && $paragraph->hasField('field_visibility') && !$paragraph->get('field_visibility')->isEmpty()) {

    $current_language_id = \Drupal::languageManager()->getCurrentLanguage()->getId();

    $visibility = $paragraph->get('field_visibility')->getValue();

    $allowed =  array_search($current_language_id, array_column($visibility, 'value'));

    return AccessResult::forbiddenIf($allowed === FALSE);
  }

  // No opinion.
  return AccessResult::neutral();
}

```

# Answer
> 1 votes
Okay, so the code in the question should have just worked. But it didn't because the paragraph translatability was misconfigured. The actual issue was this: #2864682: Sub-paragraph fields cannot be translated.

As soon as I correctly configured the "workaround" from the issue, the code from the question fired just fine.

---
Tags: entities, i18n-l10n, paragraphs
---


# Question
Title: How to programatically load the blocks that are shown on a specific page?
I need to programmatically update the paths for blocks that are displayed on a specific page, I can load all blocks using:

```
$nodeStorage = \Drupal::entityTypeManager()->getStorage('block');
$ids = $nodeStorage->getQuery()
                ->execute();
$items = $nodeStorage->loadMultiple($ids);

```

but I only want to load the blocks that are displayed on a certain page, but 'pages' doesn't work:

```
->condition('pages', '/mycat/pagename')

```

what should I use?

# Answer
Apparently this is not possible because the visibility of blocks is not part of their storage info, it's part of the config.

So the best you can do is filter by theme

```
$nodeStorage = \Drupal::entityTypeManager()->getStorage('block');
$blocks = $nodeStorage->loadByProperties(['theme' => 'theme_name']);

```

and loop through the returned data to check their path info:

```
foreach ($blocks as $block) {
  $visibility = $block->getVisibility();
  if (!isset($visibility['request_path']['pages'])) {
    continue;
  }

  $existing_pages_string = $visibility['request_path']['pages'];
  $existing_pages_array = array_map('trim', explode("\n", $existing_pages_string));

  if (in_array($old_path, $existing_pages_array)) {
    $new_pages = str_replace($old_path, $new_path, $existing_pages_string);
    $visibility['request_path']['pages'] = $new_pages;
    $block->setVisibilityConfig('request_path', $visibility['request_path']);
    $block->save();
  }
}

```
> 1 votes

---
Tags: blocks
---


# Question
Title: Webform: Remove automatically generated empty composite item in results edit
When I enable, submit, and edit results in the webform example composite module, an extra item is automatically generated.

I'd like to keep "Add 1 more items", but remove the automatically generated "empty" composite item. I've done this with fields with this code:

```
/**
 * Implements hook_form_alter().
 */
function my_module_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // Hide Last Item in tag widget.
  $field_names = [
    'field_tags',
    'field_tags_two',
  ];
  foreach ($field_names as $field_name) {
    if (isset($form[$field_name])) {
      $max_delta = $form[$field_name]['widget']['#max_delta'];
      if (!$form_state->getBuildInfo()['callback_object']->getEntity()
          ->isNew() && isset($form[$field_name]['widget'][1])) {
        unset($form[$field_name]['widget'][$max_delta]);
        $form[$field_name]['widget']['#max_delta'] = $max_delta - 1;
      }
    }
    // Unset the Add another item button.
    unset($form[$field_name]['widget']['add_more']);
  }
}

```

How do I do this with webform composite elements?

# Answer
> 0 votes
The empty\_items property needs to be set to 0. There may be a configuration for this, but I couldn't find it. Here's the code:

```
/**
 * Implements hook_webform_submission_form_alter().
 */
function my_module_webform_submission_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  /** @var \Drupal\webform\WebformSubmissionForm $form_object */
  $form_object = $form_state->getFormObject();

  /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
  $webform_submission = $form_object->getEntity();

  $webform = $webform_submission->getWebform();
  $data = $webform_submission->getData();
  foreach ($data as $element_key => $element_value) {
    $element = $webform->getElement($element_key);
    if (!empty($element['#webform_key'])) {
      if ($element['#webform_key'] == 'my_composite') {
        $form['elements']['container']['my_composite']['#empty_items'] = 0;
      }
    }
  }
}

```

---
Tags: webforms, 9
---


title: I can't access the login page

text:
# Question
Title: I can't access the login page
I have a backup of a site built with Drupal 7.60. I was able to complete the installation on my local machine, but I could not access http://localhost/showbizz-plaza/?q=user nor http://localhost/showbizz-plaza/user/login, although Drupal is installed.

>

>

The following is the content of the .htaccess file.

```
#
# Apache/PHP/Drupal settings:
#

# Protect files and directories from prying eyes.
<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\.(?!well-known).*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock))$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig\.save)$">
  <IfModule mod_authz_core.c>
    Require all denied
  </IfModule>
  <IfModule !mod_authz_core.c>
    Order allow,deny
  </IfModule>
</FilesMatch>

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

# Follow symbolic links in this directory.
Options +FollowSymLinks

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

# Set the default handler.
DirectoryIndex index.php index.html index.htm

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

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

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

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

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

# Various rewrite rules.
<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteRule ^login https://showbizzplaza.be/user/login [R=301,L]
  # Set "protossl" to "s" if we were accessed via https://.  This is used later
  # if you enable "www." stripping or enforcement, in order to ensure that
  # you don't bounce between http and https.
  RewriteRule ^ - [E=protossl]
  RewriteCond %{HTTPS} on
  RewriteRule ^ - [E=protossl:s]

  # Make sure Authorization HTTP header is available to PHP
  # even when running as CGI or FastCGI.
  RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

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

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

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

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

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

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

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

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

# Add headers to all responses.
<IfModule mod_headers.c>
  # Disable content sniffing, since it's an attack vector.
  Header always set X-Content-Type-Options nosniff
</IfModule>

```

I'm using PHP 7.2, Apache 2.4.52, MariaDB 10.6.12. Creating a new Drupal 7.60 project works perfectly fine, but I have something to work on this existing site.

# Answer
> 0 votes
I finally fixed this, seems like my Apache virtual host was not properly configured.

In `/etc/apache2/sites-available`. Create `showbizz-plaza.conf`:

```
<VirtualHost *:80>
ServerName showbizz-plaza.local
DocumentRoot /var/www/showbizz-plaza

<Directory /var/www/showbizz-plaza/>
AllowOverride All
</Directory>

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

```

In `/etc/hosts` add:

```
127.0.0.1 showbizz-plaza.local

Then in project root directory, rename or remove index.html since apache by default first renders html file before php file.

```

Lastly enable config:

```
sudo a2ensite showbizz-plaza.conf
sudo a2enmod rewrite
sudo systemctl reload apache2

```

---
Tags: .htaccess
---


# Question
Title: Display paragraph field value in field.html.twig - Paragraphs module
I need to display a field value available to `paragraph.html.twig` in `field.html.twig`. I have a paragraph type called `buttoncontainer` with a field name called `field_background_color`. I have a paragraph type called `button` nested within that as per the attached screenshot. I need to make the `field_background_color` value available to `field.html.twig`.

Let's say `field_background_color` equates to `#333333`

In `field.html.twig` I want to do something like:

```
<div style="background: {{ color }};">
    {% for item in items %}
        {{ item.content }}
    {% endfor %}
</div>

```

Is this something that can be done with a preprocess function?

I tried

```
function mysubtheme_preprocess_paragraph(&$variables) {

  $paragraph = $variables['paragraph'];

  if ($paragraph->getType() === 'sidebar_button_repeater') {
    if (!$paragraph->field_background_color->isEmpty()) {
      $variables['color'] = $paragraph->get('field_background_color')->first()->getValue();
    }
  }
}

```

...but it won't output the value in `field.html.twig`. The goal is simply to allow the user to determine the div background color behind the buttons they create.

Update: I also added:

```
 {% set paragraph_parent = paragraph.getParentEntity() %}
{% set color = paragraph_parent.field_background_color.0.value %}
Color  is {{ color }}.

```

...but that doesn't work in `field.html.twig` either. It does however work in `paragraph.html.twig` templates.

I found a very useful link at Access A Referenced Node's Fields - Field Level Templating that may inform a change to the code. Maybe syntax using `item`? I can return the NESTED paragraph field values using `{{ item.content['#node'].field_background_color.value }}` but I can't return the PARENT paragraph field value.

My specific version of `field.html.twig` file is `field--paragraph--sidebar-button-repeater.html.twig` and `{{ item.content }}` does natively output the parent field `field_background_color` value (see img). The problem is how to capture that specific value so I can use it in a situation like: `<div style="background: [output from field_background_color ];">` in `field--paragraph--sidebar-button-repeater.html.twig`. I was hoping some iteration of `{{ item.content['#node'].field_background_color.value }}` would achieve it. Can some parent parameter be added to capture the field value?

Here's my `field--paragraph--sidebar-button-repeater.html.twig` code. With the preprocessor function above in mind am I missing anything in `set` to output `{{ color }}`

```
Color is {{ color }}

    {% for item in items %}
        {{ item.content }}
    {% endfor %}

```

This works for me but may not be the cleanest way:

```
{% set bgcolor = "" %}
{% for item in element['#items'] %}
    {% set bgcolor = item.entity.field_background_color.value %}
{% endfor %}

{% if bgcolor == "#d25d12" %}
<div style="background:#d25d12;">
{% for item in items %}
       {{ item.content }}
    {% endfor %}
<div>
{% endif %}

```

# Answer
> 1 votes
To have a variable in a field template you need a field preprocess hook:

```
use Drupal\paragraphs\ParagraphInterface;

function mysubtheme_preprocess_field(&$variables) {

  $paragraph = $variables['element']['#object'];
  if ($paragraph instanceof ParagraphInterface) {
    if ($paragraph->getType() === 'sidebar_button_repeater') {
      if (!$paragraph->field_background_color->isEmpty()) {
        $variables['color'] = $paragraph->get('field_background_color')->value;
      }
    }
  }

}

```

# Nested Paragraphs

If the field is in the parent paragraph of a nested paragraph:

```
$parent = $paragraph->getParentEntity();

```

And get the field value from $parent:

```
function mysubtheme_preprocess_field(&$variables) {

  $paragraph = $variables['element']['#object'];
  if ($paragraph instanceof ParagraphInterface) {
    if ($paragraph->getType() === 'child_type') {
      $parent = $paragraph->getParentEntity();
      if ($parent instanceof ParagraphInterface) {
        if ($parent->getType() === 'parent_type') {
          if (!$parent->field_background_color->isEmpty()) {
            $variables['color'] = $parent->get('field_background_color')->value;
          }
        }
      }
    }
  }

}

```

# Why instanceof?

In the comments it was asked why to use `instanceof`?

In older Drupal versions you would use:

```
$entity_type = $variables['element']['#entity_type'];
$bundle = $variables['element']['#bundle'];
if ($entity_type === 'paragraph' && $bundle === 'my_bundle') {
  // This works but your IDE doesn't understand it:
  $parent = $paragraph->getParentEntity();
  ...
}

```

In OOP code:

```
if ($paragraph instanceof ParagraphInterface) {
  if ($paragraph->getType() === 'my_bundle') {
    $parent = $paragraph->getParentEntity();
    ...
  }
}

```

Now it's safe to use methods defined in ParagraphInterface. The IDE will help you with autocomplete and by marking unknown methods causing run-time errors.

---
Tags: paragraphs
---


# Question
Title: Why do routes created in a React router that do not exist in Drupal give a 404 when I reload the browser?
I have a `Drupal 10` site with one page at the following URL: `localhost:9090/my-page`. On that page, I have a `Drupal block` that includes a `React app` with its own `Browser Router`.

React **BrowserRouter** configuration:

```
<BrowserRouter basename="/my-page">
  <App />
</BrowserRouter>

```

React **Routes**:

```
<Routes>
  <Route index path="/demo-1" element={<DemoOne />} />
  <Route path="/demo-2" element={<DemoTwo />} />
</Routes>

```

When I access the `My Page`, the `React App` shows up, and I can use `React Router` normally, and the **URL changes**. The problem occurs when I **reload the page**; Drupal gives me a **404 error**.

Example: **localhost:9090/my-page/demo-1**

I'm using `Nginx`, and perhaps I need some extra configuration for this scenario.

**Final Note:**

React APP is embed directly inside Drupal page with **Drupal Block Plugin**. So there is no **index.html**.

This is an example what I exactly need:

https://iap.unido.org/data/sdg-9-industry?p=LBY

Base is `/data` and `/data/sdg-9-industry` is some page inside `React`.

# Answer
There is a 404 because JavaScript routers can create paths in the browser which do not actually exist on the backend web application, and the router pushes those paths onto the browser history. For this to not be a 404 when reloading the browser, create the path on the Drupal site also.

This is nothing to do with Drupal specifically.
> 1 votes

---
Tags: blocks, uri, 10
---


# Question
Title: How to pass block instance configuration settings to TWIG template?
I've got a custom block plugin which has some configuration settings that can set from the block configuration form. How can I then access that configuration info later when the block is being rendered? I know that if I know the block's instance id, I can get the configuration data using:

`\Drupal::config('blockID'])->getRawData()`

However, I'm having trouble finding a hook that can determine the block instance id at the same level as the template so that it can pass that data as a TWIG variable.

I can find the block id inside of `HOOK_preprocess_block(&$variables)`, but then I don't know how to pass anything from this hook to the theme template.

Vice versa, if i use `HOOK_preprocess_TEMPLATE(&$variables)`, I cannot figure out how to get the block instance id in order to pull the configuration values.

I know what the default block id is and can hard code that into the theme template hook, however, this breaks down if more than one instance of the block is placed into the site. What is the right approach to retrieving block instance configuration settings for use in the theme TWIG template?

# Answer
> 0 votes
Thanks to Jaypan over at the Drupal forums who provided the answer to this issue, in a post regarding a different config form question. The proper way to pass config data to the theme template is to define variables in the template registration, in the theme's hook function. Then in the block plugin class definition's `build()` function we can populate those variables with values from the configuration.

In theme's `hook_theme()` function, register the template with variables to be passed to the template.

```
/**
 * Implements hook_theme().
 */
function hook_theme() {
  return [
    // The theme key.
    'bubblepop' => [
      // The variables used in the render array.
      'vars' => [
        'color' => NULL,
        'text' => NULL,
      ],
      // I believe this must be the same as the theme key, with any
      // underscores turned into hyphens.
      'template' => 'bubblepop',
    ],
  ];
}

```

In the block's build function we can then populate them with config values:

```
public function build() {
  $config = $this->getConfiguration();
  return [
    // An arbitrary theme, defined in hook_theme().
    '#theme' => 'bubblepop',
    // Attributes are defined in hook_theme().
    '#color' => $config['color'],
    '#text' => $config['text'],
  ];
}

```

---
Tags: blocks, configuration
---


# Question
Title: Assign new role to user after puchasing a product
I installed and configure Drupal commerce successfully in Drupal 8 and now I want to change the role of a user when he/her purchase a product. E.g I have a product type ***test*** and user role ***paid*** now when the ***test*** user purchase a product I want to assign the ***paid*** role to this user after successful purchase.

I did this in Drupal 7 via rules module but how in Drupal 8.

# Answer
> 4 votes
For Drupal Commerce on Drupal 8, Rules is not complete or integrated. This leaves many such tasks like this for custom development. Fortunately, it's also easier to alter individual parts of the Commerce system thanks to Drupal 8's object oriented architecture. In this case, you'd write a new class called an event subscriber to assign that user role on the "placed" transition - the point at time an order completes checkout or is placed by an administrator. It should then handle assigning the user role to the order owner.

There may be contributed modules available for Rules integration to support individual tasks like this, but it hasn't been a core priority as of yet while we focus on other major feature groups (e.g. shipping, addressbook, recurring billing, etc.).

# Answer
> 1 votes
Commerce license provides this feature out of the box. From readme.txt :

> The Commerce License allows the creation of products that sell access to some aspect of the site. This could be a role, publication of a node, and so on.
>
> This access is controlled by a License entity, which is created for the user when the product is purchased.
>
> The nature of what a License entity grants is handled by License type plugins.

The modules ships with a Role plugin.

---

## Configuration

To create products that **grant a role when purchased** :

1. Configure a checkout flow which **does not allow anonymous checkout**.
2. Configure an Order Type to use this checkout flow.
3. Configure an Order Item Type to use this Order Type, and work with Licenses.
4. Configure a Product Variation Type to use this Order Item Type, and provide Licenses.
5. Configure a Product Type that uses this Product Variation Type.
6. Create one or more products that provide licenses. In the product variation, **configure the license type to use the Role license** type provided by the plugin

And that's it ! Additionally this *almost* smoothly integrates with recurring subscriptions.

# Answer
> 0 votes
Ryan Szrama has a good answer. This may require a custom module to get it to do what you want since Rules is no longer a part of Drupal 8, 9 or 10. There are no modules that do this either.

Commerce License does not work here since that is more for subscription variation types that will require expiration/renewal.

If your store sells digital files for example, that is also managed by commerce license and does not allow both a role license and a file license on the same product variation and will not manage both.

Therefore the best solution is a simple custom module that on commerce order being marked completed to a registered user, assign user role X to buyer. If guest checkout (anonymous user) ignore.

---
Tags: commerce
---


# Question
Title: How to enable WebP upload to a custom form's managed_file input
This question is not about image styles, which are all already configured to accept WebP. Our theme uses a custom form with elements like

```
$form['cta1']['fp_cta1_background'] = [
    '#type'              => 'managed_file',
    '#upload_validators' => array( 'file_validate_is_image' => array() ),
    '#upload_location'   => 'public://images/',
    '#title'             => t( 'Ozadje' ),
    '#default_value'     => theme_get_setting( 'fp_cta1_background' ),
];

```

Now, the server has GD installed and it's what Drupal (9.5) is using. And when I checked what `file_validate_is_image` resolves to for GD, it's as expected in local code as well — it explicitly supports WebP.

Yet when trying to upload to this form, I nonetheless get the error:

```
The specified file blabla.webp could not be uploaded.

Only files with the following extensions are allowed:
   jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp.

```

**Any ideas what's going on?**

PS: I know I could override or even skip that validator with things like this, but it would be repetitive and I'd rather get to the bottom of the original problem if possible:

```
'#upload_validators' => array(
    'file_validate_extensions' => array('png gif jpg jpeg webp'),
    'file_validate_size' => array(300000),
    'file_validate_image_resolution' => array('800x600', '400x300'),
  ),

```

# Answer
In Drupal 9.5 this list of allowed extensions comes from https://github.com/drupal/drupal/blob/9.5.10/core/modules/file/src/Upload/FileUploadHandler.php#L35

```
/**
 * The default extensions if none are provided.
 */
const DEFAULT_EXTENSIONS = 'jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp';

```

This is used in https://github.com/drupal/drupal/blob/0918c86fce10885c7b657a9aa2116b16981d3f8b/core/modules/file/src/Upload/FileUploadHandler.php#L323 if no extension validator is set, so it looks like you need to specify it each time indeed.

**Update**: Core issue: Allow user-uploaded WebP images everywhere in Drupal by default: image fields, media library, text editors
> 2 votes

---
Tags: forms
---


# Question
Title: Import content in nodes with media:image fields using Migrate from csv source
I try to import content from a `.csv` file into *article* nodes of a fresh D9 install using `Migrate`, `Migrate Plus`, `Migrate Tools`, `Migrate csv source` and `Migrate File (extended)`

My *article* content type has a `field_article_media_image` expecting a media image item.

When I run the migration, the *articles* are created correctly BUT the `field_article_media_image` is still empty. I see the image has been imported in the filesystem, but created as a file, not as a media item (not present in the media tab) and it is not linked to the article.

```
//import-articles.yml

id: import_articles
label: Import articles
migration_group: import_articles_group

destination:
  plugin: entity:node

source:
  constants:
    DESTINATION_PATH: 'public://migrations/articles/images/'
  plugin: 'csv'
  path: 'migrations/articles/articles.csv'
  delimiter: ';'
  enclosure: '"'
  header_offset: 0
  ids:
    - id
  fields:
    0:
      name: id
      label: 'Id'
    1:
      name: title
      label: 'Title'
    2:
      name: body
      label: 'Body'
    3:
      name: field_article_media_image
      label: 'Image'
process:
  title: title
  body/value: body
  body/format:
    plugin: default_value
    default_value: 'basic_html'
  field_article_media_image:
    - plugin: image_import
      source: field_article_media_image
      destination: constants/DESTINATION_PATH
      title: title
      skip_on_error: true
    - plugin: log
  type:
    plugin: default_value
    default_value: article

```

The log gives no error. Am I missing something or am I doing something wrong?

**EDIT**

After what @Joseph commented, I tried this code:

```
...
    field_article_media_image:
        source: field_article_media_image
        plugin: entity_lookup
        entity_type: media
        bundle: image
        bundle_key: bundle
        value_key: 'name'
        access_check: 0
...

```

Everything is working now, I think `value_key` needed quotes, and *maybe* `access_check` had to be set to false.

# Answer
> 0 votes
How your article is related to the image is actually like this:

```
Article (node) -> Image (media) -> File (file)

```

So there are actually *three* migrations you have to do, assuming you're not doing anything special and just doing vanilla migrations.

* The first migration will be to a `File` entity. The destination of this migration is `entity:file` which will migrate the information to the `file_managed` table. This is what migrates file metadata, like where it is in the file system, when it was changed, when it was modified, etc.
* The second migration will be to a `Media` entity. The destination of this migration is `entity:media` with bundle `image`, which will create a media entity of the file. This migration is usually 1:1 with the file it's representing. This is the entity that should be related to by other entities in the system. You do a `migrate_lookup` on the `File` migration using that file's ID.

+ *I believe this is the migration you're missing.*
* The last migration will be your `Article` migration, which is your article data from your CSV (the migration you wrote). You'll need to do a `migrate_lookup` on the media migration using the file's ID for `field_article_media_image`.

# Answer
> 0 votes
What I did that work:

```
  field_hero_image/target_id:
-
  plugin: migration_lookup
  migration: previous_migrate_media_image
  source: node_uid
-
  plugin: skip_on_empty
  method: row
  message: 'nid is missing'

migration_dependencies:
  required:
    - previous_migrate_user
    - previous_migrate_media_image
  optional: { }

```

---
Tags: migrations
---


# Question
Title: How can I reference previously imported media entities?
I have been trying to attach media entities to node entities in Drupal 8 with a custom migration but despite numerous attempts and countless hours reviewing forums i'm stumped - I'm desperately hoping someone can help explain where I might be going wrong.

Steps I have taken:

1. Created a custom migration to import files (Using Migrate Plus & Migrate Source CSV) - successful
2. Custom migration to import files into Drupal media entities (image bundle) - successful

Now that I have the media imported, I am trying to reference it so I can look to ditch the normal default field\_image.

**CSV format:**

```
fid, uid, filename, filepath, uri, filemime, filesize, status, timestamp, uuid, alt

```

As the files are now media elements I know I can't reference them by file ID (FID), presumably it would be the media ID (MID) but I have no idea how to get this.

I tried to use the migrate\_lookup to reference the existing migrations but during import i'm not getting any error messages which makes it hard to tell whether i'm targeting the right thing or not.

I have also tried to add a default value to test a single value but this also didn't work.

```
id: news_nodes
label: News Articles
migration_group: custom

dependencies:
  enforced:
    module:
      - migrate_custom

source:
  plugin: news_nodes
  node_type: article
  target: db_migration

destination:
  plugin: entity:node
  default_bundle: article

process:
  nid: nid
  vid: vid
  uid:
    plugin: default_value
    default_value: 1
  langcode:
    plugin: default_value
    source: language
    default_value: en
  title: title
  uid: node_uid
  status: status
  created: created
  changed: changed
  promote: promote
  sticky: sticky
  revision_uid: revision_uid
  revision_log: log
  revision_timestamp: timestamp
  body/format:
    plugin: static_map
    bypass: true
    source: body_format
    map:
      1: plain_text
      2: restricted_html
      3: full_html
      4: full_html
  body/value: body_value
  body/summary: body_summary
  field_tags: tags

  field_image: image
  field_image:
    -
      plugin: migration_lookup
      migration: import_files
      source: filename
    -
      plugin: skip_on_empty
      method: process

  field_media_image:
      plugin: sub_process
      source: field_media_image
      process:
        target_id:
          -
            plugin: migration_lookup
            migration: import_media_files
            source: fid
            no_stub: true
          -
            plugin: skip_on_empty
            method: process

  # field_media_image/target_id:
  #   -
  #     plugin: migration_lookup
  #     migration: import_files
  #     source: image_fid
  #   -
  #     plugin: media_generate
  #     destinationField: field_media_image
  #     imageAltSource:
  #       plugin: default_value
  #       default_value: 'Featured image'
  #     imageTitleSource:
  #       plugin: default_value
  #       default_value: 'Featured image'
  #   -
  #     plugin: skip_on_empty
  #     method: process

  field_news_companies: company_tags
  field_news_companies:
    plugin: sub_process
    source: field_company_companies
    process:
      target_id: tid
migration_dependencies:
  required:
    - custom_user
    - import_files
    - import_media_files
    - upgrade_d7_taxonomy_term_company_companies
    - upgrade_d7_taxonomy_term_tags

```

The commented out section was trying this: https://drupal.stackexchange.com/a/249401/94547 however I get 'Cannot load a NULL ID. in assert()' error.

The node entity i'm trying to import to is the default article content type.

* Default image field - field\_image
* Name of media field - field\_media\_image

I really would like to understand what i'm missing. I'm new to migrations so any advice on how to help would be appreciated!

# EDIT

Having looked at a number of replies, I think we have narrowed down the issue to my source plugin `plugin: news_nodes`. which I am listing below.

The files/media have been imported using the CSV source but the nodes use custom PHP to query other custom fields which are required (taxonomy).

If I use the same source and plugin details as `field_image` in my `field_media_image` a media entity is referenced but not one that matches the file used in `field_image`. I'm guessing it's passing the file id and the media entity is handing back a media item with the same numeric id.

Below is the custom plugin. For all I know the way I have set this up entirely wrong and needs to be re-made - any advice would be great.

**Full code available on Github:** https://github.com/lmonk72/migrate\_custom

```
<?php

namespace Drupal\migrate_custom\Plugin\migrate\source;

use Drupal\migrate\Row;
use Drupal\migrate\Plugin\migrate\source\SqlBase;

/**
 * @file
 * Contains \Drupal\migrate_custom\Plugin\migrate\source\Node.
 */

/**
 * Extract nodes from Drupal 7 database.
 *
 * @MigrateSource(
 *   id = "news_nodes"
 * )
 */
class NewsNodes extends SqlBase {

  /**
   * {@inheritdoc}
   */
  public function query() {
    // this queries the built-in metadata, but not the body, tags, or images.
    $query = $this->select('node', 'n')
      ->condition('n.type', 'article')
      ->fields('n', array(
        'nid',
        'vid',
        'type',
        'language',
        'title',
        'uid',
        'status',
        'created',
        'changed',
        'promote',
        'sticky',
      ));
    $query->orderBy('nid');
    return $query;
  }

  /**
   * {@inheritdoc}
   */
  public function fields() {
    $fields = $this->baseFields();
    $fields['body/format'] = $this->t('Format of body');
    $fields['body/value'] = $this->t('Full text of body');
    $fields['body/summary'] = $this->t('Summary of body');
    $fields['field_image/target_id'] = $this->t('Image');
    return $fields;
  }

  // /**
  //  * {@inheritdoc}
  //  */
  public function prepareRow(Row $row) {
    $nid = $row->getSourceProperty('nid');

    // body (compound field with value, summary, and format)
    $result = $this->getDatabase()->query('
      SELECT
        fld.body_value,
        fld.body_summary,
        fld.body_format
      FROM
        {field_data_body} fld
      WHERE
        fld.entity_id = :nid
    ', array(':nid' => $nid));
    foreach ($result as $record) {
      $row->setSourceProperty('body_value', $record->body_value );
      $row->setSourceProperty('body_summary', $record->body_summary );
      $row->setSourceProperty('body_format', $record->body_format );
    }

    // taxonomy term IDs
    // (here we use MySQL's GROUP_CONCAT() function to merge all values into one row.)
    $result = $this->getDatabase()->query('
      SELECT
        GROUP_CONCAT(fld.field_tags_tid) as tids
      FROM
        {field_data_field_tags} fld
      WHERE
        fld.entity_id = :nid
    ', array(':nid' => $nid));
    foreach ($result as $record) {
      if (!is_null($record->tids)) {
        $row->setSourceProperty('tags', explode(',', $record->tids) );
      }
    }

    // Company taxonomy term IDs
    // (here we use MySQL's GROUP_CONCAT() function to merge all values into one row.)
    $result = $this->getDatabase()->query('
      SELECT
        GROUP_CONCAT(fld.field_company_companies_tid) as tids
      FROM
        {field_data_field_company_companies} fld
      WHERE
        fld.entity_id = :nid
    ', array(':nid' => $nid));
    foreach ($result as $record) {
      if (!is_null($record->tids)) {
        $row->setSourceProperty('company_tags', explode(',', $record->tids) );
      }
    }

    $result = $this->getDatabase()->query('
      SELECT
        fld.field_image_fid,
        fld.field_image_alt,
        fld.field_image_title,
        fld.field_image_width,
        fld.field_image_height
      FROM
        {field_data_field_image} fld
      WHERE
        fld.entity_id = :nid
    ', array(':nid' => $nid));
    // Create an associative array for each row in the result. The keys
    // here match the last part of the column name in the field table.
     $image = [];

    foreach ($result as $record) {
      $image[] = [
        'target_id' => $record->field_image_fid,
        'alt' => $record->field_image_alt,
        'title' => $record->field_image_title,
        'width' => $record->field_image_width,
        'height' => $record->field_image_height,
      ];
    }
    $row->setSourceProperty('image', $image);

    return parent::prepareRow($row);
  }

  /**
   * {@inheritdoc}
   */
  public function getIds() {
    $ids['nid']['type'] = 'integer';
    $ids['nid']['alias'] = 'n';
    return $ids;
  }

  /**
   * {@inheritdoc}
   */
  public function bundleMigrationRequired() {
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function entityTypeId() {
    return 'node';
  }

  /**
   * Returns the user base fields to be migrated.
   *
   * @return array
   *   Associative array having field name as key and description as value.
   */
  protected function baseFields() {
    $fields = array(
      'nid' => $this->t('Node ID'),
      'vid' => $this->t('Version ID'),
      'type' => $this->t('Type'),
      'title' => $this->t('Title'),
      'format' => $this->t('Format'),
      'teaser' => $this->t('Teaser'),
      'uid' => $this->t('Authored by (uid)'),
      'created' => $this->t('Created timestamp'),
      'changed' => $this->t('Modified timestamp'),
      'status' => $this->t('Published'),
      'promote' => $this->t('Promoted to front page'),
      'sticky' => $this->t('Sticky at top of lists'),
      'language' => $this->t('Language (fr, en, ...)'),
    );
    return $fields;
  }
}
?>

```

# Answer
> 0 votes
I have migrated images a few times, at first I used the same approach as you:

1. Create an image migration.
2. Use migration\_lookup on the node migration.

This works fine, my best guess is your node migration fails to identify the image id because it references the file id. Taking a look at your `migrate_map_import_media_files` table should help you clarify things a bit.

That said, if you just need to get the job done, I would suggest you give migrate\_file a try.

You can use it to migrate everything at once, so you wouldn't need the extra migrations.

Example usage:

```
source:
  constants:
    images_destination: 'public://images/'
  ...

process:
  field_media_image:
    -
      plugin: explode
      delimiter: ,
      source: images
    -
      plugin: image_import
      destination: 'constants/images_destination'
      title: !file
      alt: title
      skip_on_error: true

```

You only need the explode if you have a coma separated list of image paths, like I did. If you have only one file you can remove it.

# Answer
> 0 votes
What I did that work:

```
  field_hero_image/target_id:
-
  plugin: migration_lookup
  migration: previous_migrate_media_image
  source: node_uid
-
  plugin: skip_on_empty
  method: row
  message: 'nid is missing'

migration_dependencies:
  required:
    - previous_migrate_user
    - previous_migrate_media_image
  optional: { }

```

---
Tags: 8, media, migrations
---


title: Query webform submissions

text:
# Question
Title: Query webform submissions
I'm attempting to perform a query on webform submissions so I can display all submissions submitted by a specific user. However I'm not sure how to make this query. I made a guess that webform submissions were nodes themselves and performed a query like this

```
    $query = \Drupal::entityQuery('node')
        ->condition('type', 'webform');
    $nids = $query->execute();
    die(print_r($nids));

```

But it produced no results. Is there a way I can perform a query on webform submissions so that I can select all submissions authored by a specific user?

UPDATE: Looking through the webform module, I did see some code querying submissions.

```
$query = $this->getQuery();
$query->condition('webform_id', $webform->id());
$query->condition('in_draft', FALSE);
$query->range(0, 1);

```

This is exactly the kind of query I want to perform but when I try to use getQuery() I get

> Call to undefined function Drupal\my\_module\my\_helper\_class\getQuery()

I understand how to start entity queries for nodes like this

```
 \Drupal::entityQuery('node')

```

But is there a way to start an entity query without specifying the entity type? Or is there a way to find out what kind of entity type webform queries are?

# Answer
Webform submissions are content entities, so something like this should work:

```
$query = \Drupal::entityQuery('webform_submission')
    ->condition('uid', $uid)
    ->accessCheck(FALSE);
$result = $query->execute();

```
> 11 votes

# Answer
Remember to include accessCheck(FALSE) or you won't get any result.

```
$query = \Drupal::entityQuery('webform_submission')
    ->condition('uid', $uid)
    ->accessCheck(FALSE);
$result = $query->execute();

```
> 2 votes

---
Tags: 8, webforms
---


# Question
Title: Remove an item from list of taxonomy terms based on the value of a Boolean field
I have set up terms for a taxonomy vocabulary ("User Group"). Each taxonomy term has a field "Hide from selection", which defaults to `False`.

When rendering the widget (as a dropdown list in a form), I would like to hide the groups whose "Hide from selection" field is set to `True`. This field allows multiple input, as a user may belong to multiple groups.

How should I implement it using hooks? Thank you. I am new to Drupal.

# Answer
If your widget is a selectbox, you could use a custom EntityReferenceSelection described here or use the Hook *hook\_query\_TAG\_alter* (*your\_module\_query\_entity\_reference\_alter*) described here.

The module "Client-side Hierarchical Select" does currently not provide a Hook to alter the options. Only the status field is considered.
One way to accomplish your goal would be to create your own FieldWidget based on the Cshs widget or alter the options with a Hook like *hook\_field\_widget\_complete\_WIDGET\_TYPE\_form\_alter* (*your\_module\_field\_widget\_complete\_cshs\_form\_alter*).
> 0 votes

# Answer
I found a way to do this using Drupal hook. It works with any widget type and also works with dynamically adding new widgets through Ajax.

```
use Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_form_alter().
 *
 * For my_form_id, hide user_group term from available options
 * based on the value of a field of the term, "field_should_hide"
 */
function my_module_form_alter(array &$form, FormStateInterface $form_state, string $form_id) {

  if($form_id === "my_form_id") {

    $term_ids_to_hide = [];

    // Get all the IDs of user group terms
    $term_ids = Drupal::entityQuery('taxonomy_term')->condition('vid', 'user_group')->execute();

    if (!empty($term_ids)) {
      // Load the terms, including their fields
      $terms = Term::loadMultiple($term_ids);

      foreach ($terms as $term) {
        // Store the Term IDs we want to hide
        $term_id = $term->id();
        $shouldHide = $term->get('field_should_hide')->value;

        if ($shouldHide == 1) {
          $term_ids_to_hide[] = $term_id;
        }
      }

      foreach ($form["field_user_group"]["widget"] as $w_key => $widget) {
        if (isset($widget["target_id"])) {
          $options = $widget["target_id"]["#options"];

          foreach ($options as $o_key => $value) {
            if (in_array($o_key, $term_ids_to_hide)) {
              // Hide the terms from widget option
              unset($form["field_user_group"]["widget"][$w_key]["target_id"]["#options"][$o_key]);
            }
          }
        }
      }
    }
  }
}

```
> 0 votes

---
Tags: taxonomy-terms
---


# Question
Title: How to show menu tab only for certain node type?
I have the following,

In the `routing.yml`

```
mymodule.cache_clear:
  path: '/node/{node}/cache'
  defaults:
    _form:  '\Drupal\mymodule\Form\APICacheClearForm'
    _title: 'Cache Clear'
  requirements:
    _permission: 'access content'
    entity: \d+
  options:
    _admin_route: TRUE
    parameters:
      node_type:
        type: entity:node
        bundle:
          - blog

```

In the `links.task.yml`

```
mymodule.cache_clear:
  title: 'Cache Clear'
  route_name: topgun_api.cache_clear
  route_parameters: { node_type: blog }
  base_route: entity.node.canonical

```

I don't see the tab being shown only on blog content type.

Is it not possible to accomplish this without using `_custom_access`?

# Answer
The code below work for me.

in the `routing.yml`

```
mymodule.cache_clear:
  path: '/node/{node}/cache'
  defaults:
    _form:  '\Drupal\mymodule\Form\APICacheClearForm'
    _title: 'Cache Clear'
  requirements:
    _permission: 'access content'
    node: \d+
  options:
    _admin_route: TRUE
    parameters:
      node:
        type: entity:node
        bundle:
          - blog

```

In the links.task.yml

```
mymodule.cache_clear:
  title: 'Cache Clear'
  route_name: mymodule.cache_clear
  route_parameters: { node_type: blog }
  base_route: entity.node.canonical

```
> 1 votes

# Answer
> Is it not possible to accomplish this without using `_custom_access`?

The other alternative is:

**mymodule.links.task.yml**

```
mymodule.cache_clear:
  title: 'Cache Clear'
  route_name: mymodule.cache_clear
  base_route: entity.node.canonical

```

**mymodule.module**

```
/**
* Implements hook_menu_local_actions_alter().
*/
function mymodule_menu_local_tasks_alter(&$data, $route_name) {
  // Load the node entity based on the current route parameters.
  $route_match = \Drupal::routeMatch();
  $node = $route_match->getParameter('node');

  // Remove if it's not a blog type.
  if ($node instanceof \Drupal\node\NodeInterface
    && $node->getType() != 'blog') {
     unset($data['tabs'][0]['mymodule.cache_clear']);
  }
}

```
> 0 votes

---
Tags: 9, navigation
---


# Question
Title: Is there a trick to hide the time portion of a date-time field in a form?
I have some fields that are "Date and time". I want to ignore the time portion and only solicit date portion from the user. However, since there is already have data in these fields, Drupal does not allow me to easily change the field to "Date". I feel like there must be a simple trick to hide the time portion from the form, but I can't figure out how to do this (without going the install script route of changing a data type). Any ideas? Maybe something in a form\_alter? Drupal 9. Thank you

Adding: I am trying to use the hook element\_info\_alter to hide the time portion, which works well. However, I run into the problem where upon submit, it fails the verification for datetime, so I am trying to duplicate the datetime verification routine, except it will ignores the time portion. BUt I haven't got that working. There must be a Is there a simpler way to do this, or no?

```
function modulename_element_info_alter(array &$types) {

  $types['datetime']['#process'][] = 'our_datetime_set_format';
}

function our_datetime_set_format($element) {

  $fname = $element['#parents'][0]; //field name
  if (want_dateonly($fname)) {
    $element['time']['#access'] = FALSE;  //hides the time portion
    $element['#date_time_format'] = '';
    $element['#date_time_element'] = 'none';
    $element['#element_validate'][0] = 'validateDateSkipTime';
  }
  return $element;
}

```

# Answer
The following seems to work to hide the time portion of a datetime field on a form. The code also prevents the verification from failing when the user submits.

in your modname\_form\_alter hook function:

```
    $form['field_date1']['widget'][0]['value']['#date_time_element'] = 'none';
    $form['field_date1']['widget'][0]['value']['#date_time_format'] = '';

```
> 0 votes

---
Tags: forms
---


# Question
Title: How to send variables to a custom theme from a custom module
I'm trying to pass a variable from a custom module to a custom theme. I have a Controller class in a custom module

```
<?php

namespace Drupal\course_catalog\Controller;

use Drupal\Core\Controller\ControllerBase;

Class CourseCatalog extends ControllerBase {
  public function build() {

    $item = 'Test content';

    return [
      '#theme' => 'region__content',
      '#item' => $item,
    ];
  }
}

```

And this `hook_theme()` in the `.module`

```
<?php

/**
 * Implements hook_theme().
 */
function course_catalog_theme() {
  return [
    'region__content' => [
      'variables' => ['item' => NULL]
    ]
  ];
}

```

Lastly I have my custom theme I have `region--content.html.twig`

```
<h2>Content: {{ item }}</h2>

```

This `item` value never render on the page. Have I missed something here ?

# Answer
> 0 votes
Below Should work. In your hook\_theme inside .module, set the variable you want as array or value in the variables.

```
$item = 'Test content';
'variables' => [
      'content' => 'content value from .module hook_theme ',
      'item' => $item,

    ],

```

Check the spelling of template file inside .module file or controller and that it actually exists in /templates.

---
Tags: theming, hooks
---


# Question
Title: Multiple primary key defined When importing DB to Dev
I'm trying to update my D9 dev site database using my production database, but it keeps erroring out when it reaches to ALTER table section in the database.

This is the ERROR 1068 (42000) at line 37370: Multiple primary key defined.

Error right when it reaches:

ALTER TABLE `ban_ip` ADD PRIMARY KEY (`iid`), ADD KEY `ip` (`ip`)

I'm using:

* PHP8.1.23
* MYSQL 8.0.32
* Drupal 9

Never had this issue until last week. Does anyone have any thoughts on this?

# Answer
Azure MySQL Flex updated to MySQL8.0.30+ and had sql\_generate\_invisible\_primpary\_key turned to "ON" when the default should be "OFF". So essentially it's generating invisible primary keys causing the error `Multiple Primary Key defined`.

To fix it here are the steps:

1. Login to azure
2. Go to your MySQL Flex server
3. Search for "Server Parameters" on the left sidebar
4. Click "ALL" tab in the middle of the page
5. Search for "sql\_generate\_invisible\_primary\_key"
6. Turn it "OFF"
7. Save and done!

Hope this helps anyone who has this issue. Good luck!
> 1 votes

---
Tags: database, 9, importing-exporting
---


# Question
Title: How I can use Drush for portal deployment and redeployment?
I have downloaded Composer on a Windows 11 computer. I have installed Drush with `composer require drush/drush`, or maybe `composer global require drush/drush`.

As I haven't mentioned any specific version, the 12.x release got installed in my system.

Somehow there were some installation issue over my office Internet network when I'd installed Drush. I think not every module been pulled, because of that whenever I ran Drush I had this error.

> \[preflight\] Package "drupal/core" is not installed

So I ran once `composer global require drupal/core`.

I had certain issues while installing Drush. I had followed https://stackoverflow.com/questions/76587828/install-of-laravel-laravel-failed. Also I have uncommented `;extension=gd` in the php.ini file.

After all the steps I tried, I am able to run Drush command from the command prompt.

I am using `XAMPP`. I don't know how I can utilize `drush` for the portal deployment / re-deployment.

# Answer
> 0 votes
Drush changed the install method somewhen after Drush 9: https://www.drush.org/12.x/install/ \- it will no longer accept a global drush, but you need to add `./vendor/bin` to your path:

> 2. Execution. Change your working directory to your project root, and call Drush via `vendor/bin/drush`. To make this easier, append `./vendor/bin` to the end of your `$PATH`; this allows you to call Drush via drush once your working directory is set. If you only have only one Drupal codebase on your system, you may put `/path/to/vendor/bin/drush` in your `$PATH`; if you do this, then it is not necessary to set your working directory before calling Drush.

---
Tags: drush, composer
---