# Question
Title: Unable to send e-mail. Contact the site administrator if the problem persists
When my web form is filled and submitted, I get redirected to a page that says:

> Thank you for submitting.

but theres a red warning box there that says:

> Unable to send e-mail. Contact the site administrator if the problem persists.

I think its the SMTP server, but I don't know how to fix that.

# Answer
> 13 votes
Try using:

SMTP Authentication Support

with PHPMailer

If You use Gmail to set up STMP follow this steps:

1. SMTP server: smtp.gmail.com
2. SMTP port: 465
3. Use encrypted protocol:Use SSL
4. SMTP Authentication -- Your User Name and password
5. Leave the other options by Default

# Answer
> 2 votes
The error:

> Unable to send e-mail.

is coming from drupal\_mail() and it's considered to be very general and it may relate to many different things such as misconfiguration of your Drupal site, PHP configuration or SMTP service of your operating system.

The first thing to do, is to check mail system or Apache logs (e.g. `/var/log/apache2/error.log`) for more details about the error, as you could simply be missing `sendmail` it-self (unless you'd like to use any external SMTP service).

If your Drupal is hosted on your dedicated server and it's a brand new configuration, most likely you're missing SMTP server (since it's pointing to `localhost` by default), unless you're planning to use the external one.

If it's your local development machine, either ignore the error (since it should work fine on the dedicated server), try installing MailCatcher, or you'll have to install SMTP server as stated above.

Here are few other suggestions:

* if using SMTP module, check if you've configured (see README file) it correctly, including the right server settings,
* check value of `mail_system` variable, if it's overridden - reset it into default value (`drush vdel mail_system`),
* check your PHP mail configuration (`php -i | grep -ie mail -e smtp`) and confirm that `sendmail_path`, `SMTP` host and `smtp_port` are correct,
* check connectivity to your SMTP server by using `telnet`, e.g.

```
telnet $(php -r 'echo ini_get("SMTP") . " " . ini_get("smtp_port");')

```

to double check whether host is not down, resolved by the DNS, or not blocked by the firewall,
* if using `postfix`, check if `httpd_can_sendmail` is set to `1` (`setsebool httpd_can_sendmail 1`).

Finally test your e-mail by the following PHP command:

```
php -r 'mail("drupal@mailinator.com", "Mail test", "It works!");'

```

and check this page if the e-mail has been received.

# Answer
> 1 votes
Check your Drupal watchdog and PHP error logs. They could be logging errors that will help you figure out what is the problem. Also, check with your system administrator to see if the SMTP server credentials that you are using are valid (i.e., address, port, encryption, password, etc.).

# Answer
> 1 votes
If just seeing what would be sent is enough, the maillog module is very handy.

# Answer
> 1 votes
I was caught in this problem due to Amazon SES sandbox issue. Amazon SES does not allow you to send email to non verified domains in sandbox mode. You would have to request for production access and the problem will be solved.

# Answer
> 1 votes
Following settings worked for me on windows.

If You use Gmail to set up STMP follow this steps:

SMTP server: smtp.gmail.com

SMTP port: 465

Use encrypted protocol:Use SSL

SMTP Authentication -- Your gmail User Name and password

Leave the other options by Default

# Answer
> 0 votes
The accepted answer has solved this problem, but note that at the time of this post, Gmail blocks all *Less secure application* because your drupal site is not running with HTTPS.

1. Then you must **Allow less secure applications** in your Gmail's My Account by

* My account \> Connection and Security \> Allow less secure applications
    * Or follow the link in the warning email received from Gmail at the moment you tried to connect with the smtp module
2. Or get a **SSL certificate** for your drupal site.

# Answer
> 0 votes
On same shared hostings You can't send e-mail without creating email for webmaster. For ex. if you have domain test.com, You have to create email webmaster@test.com or admin@test.com in your Cpanel and set this email as primary email of website. This e-mail will be in "From" field in your mail. Or create own mail for domain and set this mail as primary for site. It depends for security settings on shared hosting.

# Answer
> 0 votes
Step 1: you can settings SMTP Step 2: comand line open port 465 "-A INPUT -p tcp --dport 465 -j ACCEPT"

# Answer
> 0 votes
In case it helps anyone else out:

I have been receiving this error and discovered it was because I had both the Cc and Bcc set to the same email address in my drupal\_mail headers. (this was because I was testing)

---
Tags: 7, webforms, emails
---


title: Solr Search Custom search form template

text:
# Question
Title: Solr Search Custom search form template
I have solr search setup on my drupal8 website. I have a view setup that has two pages in it. I have the search box via an exposed form placed as a block in my header region.

What I want to do is to create a new search form that has different text in the submit button and submits the form to a different page than the search form in the header.

Is there a way through the view or display modes to expose a new template so that I can customize the button and action on the form?

# More Details

I was able to create a new solr search form by duplicated the "page" in the solr search view. I modified the name and machine name and modified the input-submit.html.twig template to remove the ID from the submit button. I did that because I have a search form in the header region of my website and then adding another form to the page in a Layout Builder with the same id was causing a conflict and chrome was yelling about it. ID's have to be unique after all.

Layout Builder won't let me save the layout though. I had to revert back to the default and then rebuild my page layout in layout builder. I have to add all of the blocks and then I get to save the layout once. I can the form into the page now, but I won't be able to make any changes to the page in the future.

Well, I suppose i can remove the search form, save the layout, go back in and make my changes and then add the search form back to the layout builder. That is not ideal.

Any trick to fix that issue?

# Possible Solution, but not ideal

I added the view page block into the Block Layout and restricted to only the page I needed it on. That should work for now, but I would prefer to be able to see all of the content blocks in the Layout Builder.

# Answer
You can use view mode of all content types where you want to show in searching. Best things are

* Create views modes for all content type
* assign or enable view mode for that content type
* create views and use render as the entity with that view mode.
* Theme based on need or UI/UX
* Custom form or create a template for search form so you can change the submit template with different UI.
> 0 votes

---
Tags: 8, search, layout-builder
---


# Question
Title: Unable to store value of an property or entity key in ConfigEntityType form
I have a propay\_account\_number in config entity type which I am unable to save using the below code. What is incorrect and how can I fix it to make it work ?

src\Entity\PropayAccount.php

```
namespace Drupal\propay_api\Entity;

use Drupal\Core\Config\Entity\ConfigEntityBase;

/**
 * Defines the Propay Account entity.
 *
 * @ConfigEntityType(
 *   id = "propay_api_account_number",
 *   label = @Translation("Propay"),
 *   handlers = {
 *     "list_builder" = "Drupal\propay_api\PropayAccountListBuilder",
 *     "form" = {
 *       "add" = "Drupal\propay_api\Form\PropayAccountCreateForm",
 *       "edit" = "Drupal\propay_api\Form\PropayAccountRenewForm",
 *       "delete" = "Drupal\propay_api\Form\PropayAccountDeleteForm",
 *     }
 *   },
 *   config_prefix = "account_number",
 *   admin_permission = "administer site configuration",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label",
 *     "propay_account_number" = "propay_account_number"
 *   },
 *   config_export = {
 *     "id",
 *     "label"
 *   },
 *   links = {
 *     "edit-form" = "/admin/config/development/propay-api/account-number/{propay_api_account_number}",
 *     "delete-form" = "/admin/config/development/propay-api/account-number/{propay_api_account_number}/delete",
 *     "enable" = "/admin/config/development/propay-api/account-number/{propay_api_account_number}/enable",
 *     "disable" = "/admin/config/development/propay-api/account-number/{propay_api_account_number}/disable",
 *   }

 * )
 */

class PropayAccount extends ConfigEntityBase {

    /**
     * The Propay ID.
     *
     * @var string
     */
    protected $id;

    /**
     * The Propay Label.
     *
     * @var string
     */
    protected $label;

    /**
     * The Propay Account Number.
     *
     * @var string
     */
    protected $propay_account_number;

    public function id() {
        return $this->id;
    }

    public function label(){
        return $this->label;
    }

    public function getAccountNumber() {
      return $this->propay_account_number;
    }

}

```

config\schema\propay\_api.schema.yml

```
propay_api.account_number.*:
  type: config_entity
  label: 'Propay Account Number'
  mapping:
    id:
      type: string
      label: 'ID'
    label:
      type: label
      label: 'Label'
    propay_account_number:
      type: string
      label: 'Propay Account Number'

```

src\Form\PropayAccountCreateForm.php

```
    <?php

    /**
     * @file
     * Contains \Drupal\propay_api\Form\PropayAccountCreateForm.
     */

    namespace Drupal\propay_api\Form;

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

class PropayAccountCreateForm extends EntityForm
{

    public function form(array $form, FormStateInterface $form_state)
    {
        $form = parent::form($form, $form_state);

        $entity = $this->entity;
        $form['id'] = [
            '#type' => 'textfield',
            '#title' => $this->t('ID'),
            '#required' => TRUE,
            '#default_value' => ($entity->id()) ?? '',
        ];

        $form['label'] = [
            '#type' => 'textfield',
            '#title' => $this->t('LABEL'),
            '#required' => TRUE,
            '#default_value' => ($entity->label()) ?? '',
        ];

        $form['propay_account_number'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Propay Account Number'),
            '#required' => TRUE,
            '#default_value' => ($entity->getAccountNumber()) ?? '',
        ];

        return $form;
    }

    public function save($form, FormStateInterface $form_state)
    {
        $entity = $this->entity;
        $entity->set('propay_account_number', $form_state->getValue('propay_account_number'));
        $entity->save();
    }
//event tried formSubmit() but it did not help save the values in propay_account_number

}

```

# Answer
> 0 votes
Try this one for saving config.

> ```
> $config = Drupal::service('config.factory')->getEditable('my_module.settings');
> $config->set('my_module.dsu_single_indexing_server',json_encode(array_unique($values)))->save();
>
> ```

---
Tags: 8
---


# Question
Title: How can I serve individual static text files with the same name from the webroot for each multisite instance?
I use Drupal 8 and I want serve statics files in each multiple sites with Nginx.

I've a site at `web/sites/site_1/` and a site at `web/sites/site_2/`.

I want serve *ads.txt* or *robots.txt* for each sites with different content.

I can add directory in `site_1/statics/` with files and serve this files at root with Nginx but I don't know how I can to do this.

Is it possible to do this with Nginx? Or is there some other way?

# Answer
It maybe is possible with Nginx but Nginx config is off-topic. Please have a look at the RobotsTxt module instead. The RobotsTxt module simply provides you a /robots.txt route that behaves just like a normal robots.txt file with the difference that you can configure the content of it from the back-end **per site**. You only need to pay attention that you deleted the physical robots.txt file to let the RobotsTxt module do its work.

> Use this module when you are running multiple Drupal sites from a single code base (multisite) and you need a different robots.txt file for each one. This module generates the robots.txt file dynamically and gives you the chance to edit it, on a per-site basis, from the web UI.
>
> **Note:** You must delete or rename the robots.txt file in the root of your Drupal installation for this module to display its own robots.txt file(s).

This solves your robots.txt problem. The ads.txt needs to be solved the same way. You need to create a custom module that does just the same as the RobotsTxt module for the /ads.txt route. With an admin settings form to store its content.
> 0 votes

---
Tags: 8, multi-sites
---


# Question
Title: How to migrate multilingual image alt fields from CSV?
I'm migrating multilingual content to Drupal 8 from a group of CSV files, and I'm about 95% of the way there. I have an image field attached to an article content type that shares the image among all translations, but the alt attribute is translatable. The remaining 5% problem is in configuring the migration to use a single common image file `fid` for all languages but a different `alt` text for other languages.

**articles.csv**

```
id,title_en,title_fr,body_en,body_fr,image,alt_en,alt_fr
1,Title 1,Titre 1,<p>English Body paragraph text 1</p>,<p>French Body paragraph text 1</p>,image1.jpg,Alt text English 1,Alt text French 1
2,Title 2,Titre 2,<p>English Body paragraph text 2</p>,<p>French Body paragraph text 1</p>,image2.jpg,Alt text English 2,Alt text French 2
3,Title 3,Titre 3,<p>English Body paragraph text 3</p>,<p>French Body paragraph text 1</p>,image3.jpg,Alt text English 3,Alt text French 3

```

**images.csv**

```
image
image1.jpg
image2.jpg
image3.jpg

```

## English Content Migration w/ Image & Alt text

My default English content migration works great with images being imported and attached to nodes.

**migrate\_plus.migration.articles\_images.yml**

```
id: articles_images
status: true
dependencies:
  module:
    - file
migration_tags:
  - CSV
migration_group: default
label: Article Images
source:
  constants:
    source_base_path: ../import/images
    uri_file: 'public://images/imported'
  plugin: csv
  track_changes: true
  path: ../import/images.csv
  header_row_count: 1
  keys:
    - image
  column_names:
    -
      image: Image
process:
  source_full_path:
    -
      plugin: concat
      delimiter: /
      source:
        - constants/source_base_path
        - image
    -
      plugin: urlencode
  uri_file:
    -
      plugin: concat
      delimiter: /
      source:
        - constants/uri_file
        - image
    -
      plugin: urlencode
  filename:
    -
      plugin: skip_on_empty
      method: row
      source: image
    -
      plugin: get
      source: image
  uri:
    plugin: file_copy
    source:
      - '@source_full_path'
      - '@uri_file'
destination:
  plugin: 'entity:file'
migration_dependencies:
  required: {  }
  optional: {  }

```

**migrate\_plus.migration.articles\_en.yml**

```
id: articles_en
status: true
migration_tags:
  - CSV
migration_group: default
label: Articles
source:
  plugin: csv
  path: ../import/articles.csv
  header_row_count: 1
  keys:
    - id
  column_names:
    -
      id: Id
    -
      title_en: 'Title EN'
    -
      title_fr: 'Titre FR'
    -
      body_en: 'Text EN'
    -
      body_fr: 'Texte FR'
    -
      image: Image
    -
      alt_en: 'Alt Text EN'
    -
      alt_fr: 'Alt Text FR'
process:
  type:
    plugin: default_value
    default_value: article
  title: title_en
  body/value: body_en
  body/format:
    plugin: default_value
    default_value: basic_html
  field_image/target_id:
    -
      plugin: skip_on_empty
      method: process
      source: image
    -
      plugin: migration
      migration: articles_images
      source: image
      no_stub: true
  field_image/alt:
    -
      plugin: skip_on_empty
      method: process
      source: image
    -
      plugin: skip_on_empty
      method: process
      source: alt_en
    -
      plugin: get
      source: alt_en
destination:
  plugin: 'entity:node'
migration_dependencies:
  optional:
    - articles_images

```

## French Content Translation w/ different alt text

However, every configuration I try to make the foreign language translations use the same FID but a *different* alt text fails.

**migrate\_plus.migration.articles\_fr.yml**

```
id: articles_fr
status: true
migration_tags:
  - CSV
migration_group: default
label: Articles French
source:
  plugin: csv
  path: ../import/articles.csv
  header_row_count: 1
  keys:
    - id
  column_names:
    -
      id: Id
    -
      title_en: 'Title EN'
    -
      title_fr: 'Titre FR'
    -
      body_en: 'Text EN'
    -
      body_fr: 'Texte FR'
    -
      image: Image
    -
      alt_en: 'Alt Text EN'
    -
      alt_fr: 'Alt Text FR'
process:
  type:
    plugin: default_value
    default_value: article
  nid:
    plugin: migration
    source: id
    migration: articles_en
  langcode:
    plugin: default_value
    default_value: fr
  title:
    -
      plugin: skip_on_empty
      method: row
      source: title_fr
    -
      plugin: get
      source: title_fr
      language: fr
  body/value:
    -
      plugin: skip_on_empty
      method: row
      source: body_fr
    -
      plugin: get
      source: body_fr
      language: fr
  body/format:
    plugin: default_value
    default_value: basic_html
  field_image/target_id:
    plugin: migration
    migration: articles_images
    source: image
    language: fr
  field_image/alt:
    -
      plugin: skip_on_empty
      method: process
      source: image
    -
      plugin: skip_on_empty
      method: process
      source: alt_fr
    -
      plugin: get
      source: alt_fr
      language: fr
destination:
  plugin: 'entity:node'
  translations: true
migration_dependencies:
  required:
    - articles_en
  optional: {  }

```

Running the French data migration, I get an error message.

```
InvalidArgumentException: Invalid translation language (und) specified.
in Drupal\Core\Entity\ContentEntityBase->getTranslation() (line 745 of
web/core/lib/Drupal/Core/Entity/ContentEntityBase.php).
Invalid translation language (und) specified.
(web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php:770)

```

**French Content Translation w/ basic image sharing**

I've also tried processing just the field\_image to copy over to the the foreign translations, but it gives the same error:

```
field_image:
  plugin: migration
  migration: articles_images
  source: image
  no_stub: true

```

Adding or leaving off the `language: fr` parameter from any of the field processors seems to make no difference -- the error is the same either way.

## The intended resulting data structure

Inspecting a `field_image` attached to a node that was created and translated manually through Drupal UI at `node/X/devel` shows the following structure:

```
[field_image] => array(
  [x-default] => array(
    [0] => array(
      [target_id] => 123
      [alt] => English Alt text
      [title] =>
      [width] => 480
      [height] => 360
    )
  )
  [fr] => array(
    [0] => array(
      [target_id] => 123
      [alt] => French alt text.
      [title] =>
      [width] => 480
      [height] => 360
    )
  )
)

```

## Additional Resources

These blog posts and example repositories have been helpful in the lead up to where I'm currently stuck:

# Answer
> 8 votes
I think I've figured this out. You need to define the 'content\_translation\_source' property on the translated node, so that Drupal knows what language it's coming from.

Eg:

**migrate\_plus.migration.articles\_fr.yml**

```
process:
  #...
  content_translation_source:
    plugin: default_value
    default_value: en
  #...

```

(Be sure to substitute the value `en` for whatever language you've first imported content -- the example in the OP uses English, but this might be anything).

---

I was asked how I figured this out:

I'm the guy who got multilingual migrations into D8 core, so I do know a bit about the matter :)

In this case, I used xdebug and put a breakpoint where the exception was thrown (ContentEntityBase.php line 745). It looked weird that it was using 'und' as the langcode, rather than 'en'—so I looked up the call stack to see where that was coming from. It turns out to be from content\_translation\_entity\_presave(), which runs:

$source\_langcode = !$entity-\>original-\>hasTranslation($langcode) ? $manager-\>getTranslationMetadata($entity)-\>getSource() : NULL;

In this case `$manager->getTranslationMetadata($entity)->getSource()` is basically equivalent to `$entity->content_translation_source->value`.

I wondered, why would that yield 'und'? I checked what happens when I translate an entity in the browser, and in that case it gives me 'en'. Something must be setting the source language! Indeed, ContentTranslationHandler::entityFormEntityBuild() calls setSource() when we're translating in-browser.

So, I figured I would just replicate that behaviour in the migration, by setting content\_translation\_source in the process. This also explains why D6 -\> D8 migration of translations work, since d6\_node\_translation.yml has content\_translation\_source in the process.

# Answer
> 0 votes
Thanks @vasi, Those who are still facing the issue can update the translation script like:

```
process:
  content_translation_source: source_langcode

```

where source\_code is the default nodes language\_code

---
Tags: 8, migrations, importing-exporting
---


# Question
Title: How to configure CkEditor's styles dropdown?
I have made changes to the configuration of CKEditor for the basic\_html rule set as follows:

When I then try to use the editor, however, I get the following:

I have tried clearing the cache multiple times. I have tried rebuilding the cache with drush cache-rebuild.

Is there something else you are suppose to do to be able to configure CKEditor in Drupal 8?

# Answer
> 9 votes
**1. Your Custom style should be present in your CSS file. 2. Your FILTER SETTING should be proper.** To check, same way as yours, I just enabled style and and put `h1.heading-a|Title`(which I took from css/base/elements.css for example purpose) in style dropdown and and it did show up as shown in the second image.

>

Second Image

>

**Hence, the issue is, to properly put the `Class|Key` in the `Styles dropdown` section and make sure that it is available in `CSS`.**

Later to check the custom one, I did put `h2.myclass {color: red}` in `elements.css` and saved and cleared cache. And as you can see it showed up in following image

**UPDATE-1: FILTER SETTING**

Now the reason why, horizontal line and underline icon are not visible as you have stated in your comment. For that you need to check the FILTER SETTINGS. Have you played with `Limit allow HTML tags and correct faulty HTML` list which you can see at the bottom of the basic HTML setting page as shown in following image. If you delete `<hr>` from the list the icon will not shown up. Just I checked, if I remove `<hr>` form list the icon also gets disappeared.

>

**And your Enable filter setting should be as shown in following image.**

# Answer
> 2 votes
For people on drupal 8.4: there is a bug in CKEditor itself on this manner. See https://www.drupal.org/project/drupal/issues/2911749 for more information and patches.

> One possible workaround is to replace the ckeditor.js with that one from \> Drupal 8.3.7 (should be version 4.6.2), then everything should work well \> again.

In composer.json, add this to your "extra" section. See comment #33 in the link (credit to @ayalon on drupal.org):

```
"patches": {
  "drupal/core": {
    "Downgrade CkEditor until https://www.drupal.org/node/2911749 is fixed": "https://www.drupal.org/files/issues/fix_ckeditor_styles_dropdown-2911749-17.patch"
  }
}

```

# Answer
> 1 votes
I had a similar problem when using the Basic HTML text format and wanted to add a style like `p.class|Title`. The difference was that I even couldn't open the style list, because the style button was disabled.

To fix this I edited the text format and added `<p class="">` to the "Limit allowed HTML tags" field.

# Answer
> 1 votes
Check if you missed to **class** attribute for allowed HTML tags. Change

```
<a href hreflang> <em>

```

to

```
<a class href hreflang> <em>

```

# Answer
> 0 votes
In my case it did not work, because the line with a specific CSS class under "Styles dropdown" was too long.

This works:

```
code.c-bolt-code-snippet__code.c-bolt-code-snippet__code--block|Codeblock

```

but this does not work:

```
code.c-bolt-code-snippet__code.c-bolt-code-snippet__code--block.c-bolt-code-snippet-syntax--light|Codeblock

```

---
Tags: 8, wysiwyg
---


# Question
Title: Change language name based on the domain i'm on
I'm looking for a solution which can alter/change a language name based on the domain I'm on.

Here I can configure one name, which is used everywhere, but can't be configured for each domain: /admin/config/regional/language

I got a site with multiple domains. Every domain has a set of languages: en, nl and fr etc.

Each domain has different labels for those languages. For example: domain 1: en: English domain 2: en: International

Any suggestions?

Altering every form, every view output, just feels wrong.

# Answer
You are looking for url/domain language negociation + url/path language negociation, right ? You need both of domain+path in */admin/config/regional/language/detection/url* to determine wich language to display.

I think you have to implement a new LanguageNegociation plugin in a module which do this. Have a look at :

**core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUrl.php**

You should be able to get your own detector (quiet looking like LanguageNegotiationUrl with both domain+path) by extending LanguageNegotiationMethodBase.
> 2 votes

# Answer
Read the Enable language negotiation page in the Multilingual guide. It's explained in there.

> Generally, the URL method will be enabled and will be the first on the list, meaning that if the language is specified in the URL of the page, the page will be displayed in that language. The URL method can be configured to use either the domain or language path prefix of the page. If the language is not specified in the URL, the next method on the list will be used.
> 0 votes

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


# Question
Title: How do I use an entity reference field as a sidebar navigation on a view?
I have 2 content types: *category* and *project*. On *project*, I have a reference field to *category*.

I would like to list all my nodes from *project* in a view and then use all the *category* nodes as links for filtering this list.

I know it is possible with a taxonomy term, but I'm trying to achieve it with a reference field. Is it possible with the view UI?

I'm using Drupal 8.8.2.

# Answer
Yes. Doing this with content types is really no different than with taxonomies. You can leverage the reference value with a Views relationship. You description sounds like it would use two Views, one for the block of navigational links in the sidebar, and the other for the lists of projects.

For the first you just want a view of the categories. I'd use fields and rewrite the output to link to each category title to a url like `/projects/{{category_title}}`. "Rewrite output" is an option available in the modal for the field. Alternatively, and perhaps more straightforward is to use the option to "output as a link."

The second page display View is based on the project type, and has a relationship to the category. Create a contextual filter to pull the category title from the URL, matching whatever you set up in the block.
> 0 votes

---
Tags: views, nodes
---


# Question
Title: Exclude node from search API results based on values in existing fields
My `content` node includes a `verified` checkbox that's marked by a human reviewer who then also enters a date. The node is verified only when the box is checked and the date is entered. A `content` node may be published before it is verified.

How can I keep an unverified content node from appearing in search API results?

One solution is to add a `search API exclude entity` field to the `content` node and to set the value of the exclude field in a presave hook based on the `verified` checkbox and date. This isn't difficult, but it seems there should be a more straightforward way of accomplishing what's needed.

I've looked at modules, but those I've seen don't seem to fit the need. I imagine I'm just missing something obvious, but what is it?

I don't think it's relevant, but I'll mention that I'm using Solr search.

# Answer
Given no alternative answers, I solved this problem by

* installing the `Search API Exclude Entity` module
* adding a field of type `Search API Exclude Entity` named `search_exclude` to the `content` node
* adding the following to my custom `rsc` module

```
function rsc_node_presave(EntityInterface $node) {
  switch ($node->getType()) {
    case 'content':
      $node->field_search_exclude->value = <conditions to exclude node>;
      break;
  }
}

```
* going to `/admin/config/search/search-api/index/default_solr_index/processors`
* checking the `Search API Exclude Entity` box
* selecting the `Search API Exclude Entity` tab at the bottom of the page
* checking the `field_search_exclude (content)` box
* reindexing the content

Seems to be working well. When unverified nodes are saved, the search\_exclude field is set and that keeps the nodes out of the search results.
> 1 votes

---
Tags: 8, search
---


# Question
Title: How to get node title using this query on template?
Im building a custom filter in Drupal 8 based on some queries.

I got this already, here im filtering by values on body:

```
$query = db_select('node__body', 'n')
                            ->fields('n')
                            ->condition('n.body_value', "%" . $searchWord . "%", 'LIKE')
                            ->condition('n.bundle', 'mycontenttype');
     $getList = $query->execute()->fetchAll();

```

Then i pass the variable to the Twig:

```
return [
            '#filters' => $getList,

```

In the twig im doing:

```
{% for oneItem in filters %}

```

But im unable to get the title of the node here, what im missing?

# Answer
> 2 votes
1. You shouldn't do queries like like that. You should use `EntityQuery`. See https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21Query%21QueryInterface.php/function/QueryInterface%3A%3Acondition/8.8.x and EntityFieldQuery to search Content Type for text and select matching Nodes `EntityQuery` will return the nids. Then use the node storage's `loadMultiple` to get the node themselves. Typically something like `Drupal::entityTypeManager()->getStorage('node')->loadMultiple($nids)`
2. I would expect the Node title would be gotten in your loop with `{{ oneItem.title }}`. If that's not working I suggest installing and enabling the devel module, and sticking `{{ dump(filters) }}` in your custom template to investigate the structure you're getting

---
Tags: theming, modal-dialogs
---


title: How do I empty the cart?

text:
# Question
Title: How do I empty the cart?
I want to programmatically empty the cart after these events.

1. Add to cart
2. Update quantity (in cart page)

In fact users must have only one product in their cart.

# Answer
I've done some research and came up with this ...

```
$view = \Drupal\views\Views::getView('retrieve_orders');
$view->setDisplay('get_order_id_from_current_user');
$view->execute();
$result = $view->result;
foreach ($view->result as $row) {
    $order_id = $row->order_id;
}
$order = \Drupal::entityTypeManager()->getStorage('commerce_order')->load($order_id);
$cart_manager = \Drupal::service('commerce_cart.cart_manager');
$cart_manager->emptyCart($order);

```

All you have to do is put that in a form validate custom handler. (I used views to retrieve current order id of current user )
> 0 votes

# Answer
Are you sure you want to empty the cart? Or do you just want to limit the quantity of any product to one?

I recently had a similar situation. I added a `hook_form_alter` to hide the quantity so it can't be readily changed. There's not a specific FORM\_ID you can use for an add to cart form because they get a hash added to them, so it looks like this:

```
function my_module_form_alter(array &$form, FormStateInterface $form_state, string $form_id){
  if (strpos($form_id, 'commerce_order_item_add_to_cart_form_') === 0) {
    ... plus any other logic specific to your use case

    _my_module_specific_add_to_cart_form_alter($form, $form_state, $form_id);
  }
}

function _my_module_specific_add_to_cart_form_alter(array &$form, FormStateInterface $form_state, string $form_id){
  // Doesn't make sense to buy more than one, so hide it.
  $form['quantity']['#type'] = 'hidden';

  ... plus any additional changes, e.g., I have this:
  // There's only one variation, so hide it. (
  $form['purchased_entity']['#type'] = 'hidden';
}

```
> 0 votes

---
Tags: 8, commerce
---


# Question
Title: Can I turn a regular content type into a Commerce product display?
I have an existing working site with lots of content. I've come to the realisation that I could actually sell this content. So is there a way to turn my existing content type into a product display for Drupal 7 Commerce or would you recommend to export all these nodes and create a new product display type and add them back in?

# Answer
> 1 votes
All you need is a product reference on a node for that node to be a "Display Node." A simple solution would be to just add that and any other fields you think necessary to the "selling" part of the node's function. You might need an alternative View Mode for the content type if there are items you need displayed or not dependent on circumstances.

---
Tags: 7, commerce
---


# Question
Title: How can I prevent memory size exhaustion when dumping variables in Twig?
hello everyone i have a problem with kint , in my twig page i want to listing all variables contains int 'content' variable to make some logic on it , but the page can't loaded because the big pip memory , can any one tell me how to solve this problem to dump the 'content' variable?

> this is the msg

```
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 29994336 bytes) in /var/www/html/core/modules/big_pipe/src/Render/BigPipe.php on line 336

```

# Answer
There are several options to prevent this:

1. The most obvious one, increase memory
2. Create a new node or entity or whatever with only a single field you want to output in kint(), so the server doesn't have to run it for multiple fields
3. Make your kint() more specific, don't do kint(content) but kint(content\['field\_name'\]) for example

If none of these work, figure out how to set up xdebug, which is probably a much cleaner way of debugging.
> 1 votes

# Answer
Variable content is pretty large to print, but you can try to lower your printing depth in `modules/contrib/devel/kint/kint/config.default.php`

by setting `$_kintSettings['maxLevels']` to lower number than 7.
> 0 votes

---
Tags: 8, theming, debugging
---


# Question
Title: Create custom form button that does not submit webform
I have webform created via Webform UI, and it's multi-step webform.

In second step *('personal information')* I add custom button using `HOOK_form_alter` with following code

```
'generate_pdf' => [
    '#type' => 'submit',
    '#value' => t('Generate PDF'),
    '#limit_validation_errors' => [],
    '#submit' => ['generate_pdf_template'],
]

```

function **generate\_pdf\_template** takes values from **$form**, **$form\_state** inserts them into twig templat, creates PDF and automatically downloads it.

My issue is, that this **generate\_pdf** button submits the form and user is not able to send form via original submit button. Can I somehow prevent submission when `generate_pdf` is clicked so user can download PDF and still be able to send webform with original button and webform's handlers.

# Answer
Something like this may work.

`#name` and `#submit` are required.

The name makes sure the button does not get confused with other submit buttons.

The `#submit` value calls a custom function you have to create.

`#limit_validation_errors` prevents form validation, which may or may not be useful.

```
  $form['generate_pdf'] = [
    '#type' => 'submit',
    '#value' => $this->t('Generate PDF'),
    '#name' => 'generatepdf',
    '#submit' => ['::generatepdf'],
    '#limit_validation_errors' => array(),
  ];

```
> 1 votes

---
Tags: 8, webforms
---


title: Unable to auto-create node from webform

text:
# Question
Title: Unable to auto-create node from webform
I attempted to create a custom module that automatically creates a node upon submission. I used the second response in this post: How to create a node out of a webform submission?

Per the instructions, I added a php file to a new custom module created through Drupal console. It has an info.yml and .module files.

I took the code from the second comment and altered to suit my module, and add dependencies. (For some reason, the dependencies were incorrect.)

My PtcWebformHandler.php file contents:

```
<?php

namespace Drupal\ptc_node_from_form\Plugin\WebformHandler;

use Drupal\Core\Annotation\Translation;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;
use Drupal\webform\Annotation\WebformHandler;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\WebformSubmissionInterface;
use Drupal\webform\Plugin\WebformHandler\EmailWebformHandler;

/**
 * Create a new Article node from a webform submission.
 *
 * @WebformHandler(
 *   id = "add_new_company",
 *   label = @Translation("Create a node on submit"),
 *   category = @Translation("Content"),
 *   description = @Translation("Creates a new Article node from Webform Submissions."),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_UNLIMITED,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 *   submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_REQUIRED,
 * )
 */

class PtcWebformHandler extends WebformHandlerBase {

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission)
  {
    // Get an array of form field values.
    $submission_array = $webform_submission->getData();

    // Prepare variables for use in the node.
    $title = $submission_array['subject'];

    // Create the node.
    $node = Node::create([
      'type' => 'company',
      'status' => FALSE,
      'title' => $title
    ]);

    $node->save();
  }
}

```

Before enabling the module, I added the email handler (the other post doesn't specifically say to, but it says a handler is required. And the code references an email array.)

After enabling the module, I submited a form, and checked for the node. And... no node.

I'm still getting used to Drupal 8 module development. I tried my hand at creating a service. But I doubt it is necessary (if I understand services). In any regard, it still doesn't create a new node upon form. submission.

I tried to use xdebug to see what the data was being passed to the method inside the PtcWebformHandler class. It didn't hit anything.

What am I missing.

(It worked when I added the router from the first comment in the aforementioned post.)

Source: https://www.drupal.org/project/reroute\_email

# Answer
Do you have a node type "company" that exists?
Is the machine name correct?
Does your $title have a correct value?

You might just be missing `->enforceIsNew()` but I'm not sure if that is required.

Try the below code and build further from there. (Edit the required values!!)

```
$newNode = Node::create([
  'type' => 'your_node_type_machine_name',
  'title' => 'the title of the new node',
]);

$newNode->enforceIsNew();
$newNode->save();

```

Also make sure you include

```
use Drupal\node\Entity\Node;

```

But looks like you already have that.
> 0 votes

---
Tags: 8, nodes, forms
---


title: Get the public path directory

text:
# Question
Title: Get the public path directory
I want to save file programmatically in public path, and I want to know how can I get `Public Directory path` in Drupal 8. In Drupal 7, I would use the following code.

```
drupal_realpath(file_default_scheme() . '://')

```

What is the equivalent in Drupal 8?

# Answer
According to the realpath API, you can get it with:

```
\Drupal::service('file_system')->realpath(file_default_scheme() . '://');

```
> 24 votes

# Answer
In case you want to get just "sites/default/files" or "sites/your-multisite/files" Then you should use

```
// Add to the top of the file.
use Drupal\Core\StreamWrapper\PublicStream;

// In your method.
print PublicStream::basePath();

```
> 6 votes

---
Tags: 8, files
---


# Question
Title: How can I exclude configuration from import/export?
I thought this was a simple use case of the new Configuration management system, but I haven't had any luck finding out how to solve this:

## Problem

I want to store configuration in git and use drush to export configuration during development and then on deployment import the configuration. Pretty similar to doing a features revert in Drupal 7. My problem is that I don't want to store access codes in git for various integrations. This results in these configurations being deleted on
`$ drush cim -y`

## Where I looked

I was hoping there would be a simple list/configuration for configs that should be excluded on import/export. It seems there was at some point but it must have been removed again, since it's available at present Drupal 8 release.

I looked into how config changes are being made comparing the active and sync storange to see if there as a place where I could remove changes, this didn't seem to be the case. I looked at how drush does the configuration import as it has some configuration excludes of it's own, but it didn't look like this was extensible. I looked at `ConfigEvents`, but these all seem to happen after an import, so doesn't look like this can be used.

Am I missing something, or is it not possible to simply exclude configs from import/export?

# Answer
It's not possible to have *excludes* specifically, but there is something.

Just like $conf in Drupal 7, there's $config in settings.php that you can use to override anything in configuration locally. The format is `$config['name.of.config']['nested']['key']`.

Note that whatever is stored in configuration is still in git, so you either need to keep none or your testing access codes in git. Also, the UI will show what's actually stored in config and will currently not provide any indication that it is overridden. There are pending issues to improve that.

I understand that this has limitations but right now, it's not possible to keep something out of the exported configuration. As far as I know.
> 9 votes

# Answer
You can use the "Config Ignore" module: https://www.drupal.org/project/config\_ignore

> Ever experienced that your site's configuration was overridden by the configuration on the filesystem, when doing a drush cim?
>
> Not anymore!
>
> This module is a tool to let you keep the configuration you want, in place.
> 15 votes

# Answer
You can use a combination of config\_ignore and config\_split for this.

Config ignore allows you to ignore a subset of configuration entities during import (also prevents deletes since the 2.x release). Unfortunately it doesn't prevent excluding config during export.

To exclude configuration entities during export, you can use config\_split, create a new config\_split entity, and leave the folder empty. This prevents the configuration from being exported to the file system; instead, it exports it in the database.

I wrote Exclude config from configuration management in Drupal 8 about this topic.
> 10 votes

# Answer
Since Drupal 8.8 modules can now be excluded from configuration synchronization by adding `$settings['config_exclude_modules']`to your settings.php file.

> ```
> $settings['config_exclude_modules'] = ['devel', 'stage_file_proxy'];
>
> ```

See the change record Modules can be excluded from the configuration synchronization.
> 7 votes

# Answer
In order to split configurations you can use https://www.drupal.org/project/config\_split.

> Enter config\_split that provides a Drupal console command for importing and exporting filtered configuration. Drush integration is likely to follow soon (after all the filter is inspired by the --skip-modules filter of drush).

You can split exports into different dirs which you can then git ignore.

There was a very nice presentation in drupal con dublin 2016 by the people in charge of the CMI initiative which I urge you to check out no matter what.
> 6 votes

# Answer
## Drupal 8

Please note that this module **is deprecated** and will not receive a Drupal 9 release.

---

You can use Drush CMI tools. Then you have a `drush cexy` command and a `config-ignore.yml` to provide a list you can adjust. We needed it once to have block instances excluded while at the same time the block bases needed to get processed.

> **We want to export all configuration, but we want to exclude certain patterns.**
>
> This is where the `--ignore-list` option of `drush cexy` comes in.
>
> In our project we have a ./drush folder, so we stick a file in their called **config-ignore.yml** with contents as follows.
>
> ```
> ignore:
>   - field.field.contact_message.*
>   - field.storage.contact_message.*
>   - contact.form.*
>   - core.entity_form_display.contact_message*
>   - core.entity_form_display.contact_form*
>   - core.entity_view_display.contact_message*
>   - core.entity_view_display.contact_form*
>   - system.site
>   - workbench_email.workbench_email_template.*
>
> ```
>
> So now we run `drush cexy` like so
>
> ```
> drush cexy --destination=/path/to/config-export --ignore-list=/path/to/drush/config-ignore.yml
>
> ```
>
> So what this does is export the active configuration, and then apply the ignore list to remove unwanted configuration.
>
> So now when you run `git status` you should only see changes you want to commit.

Source: https://www.previousnext.com.au/blog/introducing-drush-cmi-tools

> **Installation**
>
> ```
> cd ~/.drush
> wget https://raw.githubusercontent.com/previousnext/drush_cmi_tools/8.x-1.x/drush_cmi_tools.drush.inc
> drush cc drush
>
> ```

Source: https://github.com/previousnext/drush\_cmi\_tools
> 3 votes

# Answer
I just tested @berdir in #1 answer and it run perfectly. Only I add a little note: you have to put whole config in this var, complete. Wihtout it, $config var not run correctly.

Something like this:

```
 $config['language.negotiation'] = array(
  'session' => array(
    'parameter' => 'language',
  ),
  'url' => array(
    'source' => 'domain',
    'prefixes' => array(
      'es' => '',
      'pt-br' => '',
    ),
    'domains' => array(
      'es' => 'YourLocalDomain',
      'pt-br' => 'Anotherlocaldomain',
    ),
  ),
  'selected_langcode' => 'site_default',
  'langcode' => 'es',
);

```

Documentation: https://www.drupal.org/node/1928898

Note from above documentation: "Note that values overrided via $config within settings.php will not be viewable from the Drupal administration interface."
> 2 votes

# Answer
**Using config split (recommanded)**

The config split module was made specifically for this need.

Config split is integrated with drush.

**Using Drush only**

Drush it's also supposed to be able to do that by using the `--skip-modules` flag.

You can add the following lines in a drupal/drushrc.php in the webroot of your project to do it automatically.

```
$command_specific['config-export']['skip-modules'] = array('devel');
$command_specific['config-import']['skip-modules'] = array('devel');

```

See http://www.drush.org/en/master/config-exporting/#ignoring-development-modules

Sadly **there is a bug** with this functionality: https://github.com/drush-ops/drush/issues/1820. So for the moment you also need to add those config files in your .gitignore so exported config files don't get committed. Their is an ongoing to perhaps abandon this (buggy) functionality from drush in favor of config split.
> 2 votes

---
Tags: configuration
---


# Question
Title: Are there any quality of life add ons for Content Admin page? Easier sorting, searching, etc
I think the words make it vague for a google search since I'm not really finding anything. Looking for enhancements to the Content screen in Admin (that lists all of your content items). You can search for things and sort by a few select fields but looking to expand this and make it more specific to our content types. Thanks!

# Answer
> 1 votes
The content page is actual just a view. You can just edit it to make it do what you want to. This is set up via the initial site creation so you will not loose your changes when core is updated.

---
Tags: views
---


# Question
Title: Can we pass argument to a form from a Twig template
I have a form that accepts a custom argument **sourceid**

```
 public function buildForm(array $form, FormStateInterface $form_state, $sourceid = NULL)

```

Now, this form is displayed in a twig template multiple times using a for loop. For each instance of this form the **sourceid** is different in the twig template. The value of the sourceid is present in the twig template. Can I pass it to the form from the twig template itself? Or should I modify my controller and render the form in the template along with the id?

Code in the twig template displaying the form is as follows:

```
{% for item in field %}
    {% if item.content %}
      <p> {{ item.content|raw }} </p>
      <p> {{ item.sourceid|raw }} </p>
      <div>{{ metadata_form }}</div>
    {% endif %}
(% endfor %}

```

The variable `metadata_form` has the form element in it.

# Answer
I think the most elegant way is to modify your controller so all the logic happens in the controller and only the markup in twig. If you have that option that's the way to go.

That being said, there are ways to get what you want. The most convenient way I know is the twig\_tweak module and use the function

```
{{ drupal_form('yourmodule\\namespace\\Form\\yourForm', sourceid) }}

```

I have not tested it myself but it should work.
> 1 votes

---
Tags: 8, theming, forms
---


# Question
Title: Search API + Apache SOLR - No highlighted excerpts returned for stemmed terms
I have a **Drupal 7** site using the **Search API** and **Search API Apache SOLR** modules to provide search functionality to site visitors.

I'm running Apache SOLR 4.10.2 within my development Vagrant VM environment, and search results are returned for both stemmed and unstemmed terms which is great:

---

Example search term: **"car"**

Apache SOLR returns nodes with fields containing the text **"car"** and **"cars"**

---

The problem is, when Apache Solr returns nodes containing the stemmed term **"cars"**, no highlighted excerpts are returned. However results containing the exact term **"car"** are returned with a hightlighted excerpt as expected.

After extensive searching I found this blog post which contains instructions on how to enable stemming for highlighted excerpts, but no luck.

Here is the excerpt of my **schema.xml** config file as per the instructions in the blog post:

```
<!--  Setup simple analysis for spell checking -->

 <fieldType name="textSpell" class="solr.TextField" positionIncrementGap="100">
   <analyzer>
     <tokenizer class="solr.StandardTokenizerFactory" />
     <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/>
     <filter class="solr.LengthFilterFactory" min="4" max="20" />
     <filter class="solr.LowerCaseFilterFactory" />
     <filter class="solr.RemoveDuplicatesTokenFilterFactory" />
     <filter class="solr.PorterStemFilterFactory"/>
   </analyzer>
 </fieldType>

```

I have **restarted my VM** and **cleared and reindexed** all the nodes, but still no dice.

Has anyone else had this issue before?

Thanks in advance!

# Answer
> 2 votes
I'm guessing that you, like me, had the "Highlight" filter enabled, which you shouldn't actually do for Solr. I found this nugget of info here:

https://www.drupal.org/node/2358065#comment-9319765

Though Solr returns the excerpt, that processor removes it if there's not an exact match.

# Answer
> 0 votes
In case someone using Drupal 8 sees this question (as I did), the advice to turn off the **Highlight** filter, which was correct for Drupal 7, is not the solution for Drupal 8. Instead:

* Edit your index at `admin/config/search/search-api`
* At the **Processors** tab, select the **Highlight** checkbox
* In the **Highlight** tab at the bottom of the page under **Processor settings**, select **Create excerpt**
* Save
* Edit your Solr Server at `admin/config/search/search-api`
* Open the **ADVANCED** section near the bottom of the page
* Select **Retrieve result data from Solr** and **Retrieve highlighted snippets**
* Save

Now you'll get highlighted snippets for stemmed words. No need to reindex.

---
Tags: search
---


# Question
Title: Create Multiple Line Items with Add to Cart Form
I am selling "TablesFor8" at an event, and would like to make it possible for the individual purchasing a "TableFor8" to specify names and food choices of the 8 individuals who will sit at that table. Is there a way to do this?

# Answer
First, to answer your question, I am running Commerce on Drupal 7. Then, thanks for this, but I figured it out. What I ended up doing was creating a custom line-item type for "Tables for 8" and including a multi-value field \[Name, Meal Choice\] on that line item type. That, coupled with a little CSS allowed me to create a form \[I actually used Views-Accordion to make that form appear as a dropdown\] that allowed Tables for 8 purchasers to enter the names and meal choices of their guests.

Easy peasy, once you know how to do it!
> 0 votes

---
Tags: commerce
---


# Question
Title: "Button with id|name|label|value "Log in" not found"
Trying to run some functional JS tests, Anyone know what is up here?

```
Runtime:       PHP 7.1.33
Configuration: /app/phpunit.xml

Testing Drupal\Tests\commerce_product\FunctionalJavascript\ProductAttributeJavascriptTest
Test 'Drupal\Tests\commerce_product\FunctionalJavascript\ProductAttributeJavascriptTest::testProductAttributeValues' started
Test 'Drupal\Tests\commerce_product\FunctionalJavascript\ProductAttributeJavascriptTest::testProductAttributeValues' ended

//

1) Drupal\Tests\commerce_product\FunctionalJavascript\ProductAttributeJavascriptTest::testProductAttributeValues
Behat\Mink\Exception\ElementNotFoundException: Button with id|name|label|value "Log in" not found.

/app/web/core/tests/Drupal/Tests/WebAssert.php:77
/app/web/core/tests/Drupal/Tests/UiHelperTrait.php:77
/app/web/core/tests/Drupal/Tests/UiHelperTrait.php:250
/app/web/modules/contrib/commerce/tests/src/FunctionalJavascript/CommerceWebDriverTestBase.php:87
/app/web/modules/contrib/commerce/modules/product/tests/src/FunctionalJavascript/ProductWebDriverTestBase.php:60

```

There is an HTML output that works and has a log in button with value = "Log in" I can supply the .lando || phpunit.xml if that helps.

Output page :

```
<hr />ID #9 (<a href="Drupal_Tests_commerce_product_FunctionalJavascript_ProductAttributeJavascriptTest-8-36295254.html">Previous</a> | <a href="Drupal_Tests_commerce_product_FunctionalJavascript_ProductAttributeJavascriptTest-10-36295254.html">Next</a>)<hr />GET request to: http://drupal-orange-project.lndo.site/user/login<hr />Ending URL: http://drupal-orange-project.lndo.site/user/login<hr /><html lang="en" dir="ltr" class=" js"><head>
    <meta charset="utf-8">
<meta name="Generator" content="Drupal 8 (https://www.drupal.org)">
<meta name="MobileOptimized" content="width">
<meta name="HandheldFriendly" content="true">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/core/misc/favicon.ico" type="image/vnd.microsoft.icon">

    <title>Log in | Drupal</title>
    <link rel="stylesheet" media="all" href="/core/modules/system/css/components/ajax-progress.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/align.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/autocomplete-loading.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/fieldgroup.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/container-inline.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/clearfix.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/details.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/hidden.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/item-list.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/js.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/nowrap.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/position-container.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/progress.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/reset-appearance.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/resize.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/sticky-header.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/system-status-counter.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/system-status-report-counters.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/system-status-report-general-info.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/tabledrag.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/tablesort.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/css/components/tree-child.module.css?q4jmda">
<link rel="stylesheet" media="all" href="/core/modules/system/tests/modules/css_disable_transitions_test/css/disable_transitions.theme.css?q4jmda">

<!--[if lte IE 8]>
<script src="/core/assets/vendor/html5shiv/html5shiv.min.js?v=3.7.3"></script>
<![endif]-->

  </head>
  <body>
        <a href="#main-content" class="visually-hidden focusable">
      Skip to main content
    </a>

      <div class="dialog-off-canvas-main-canvas" data-off-canvas-main-canvas="">
    <div class="layout-container">

  <header role="banner">

  </header>

  <main role="main">
    <a id="main-content" tabindex="-1"></a>
    <div class="layout-content">
        <div>
    <div data-drupal-messages-fallback="" class="hidden"></div><form class="user-login-form" data-drupal-selector="user-login-form" action="/user/login" method="post" id="user-login-form" accept-charset="UTF-8">
  <div class="js-form-item form-item js-form-type-textfield form-item-name js-form-item-name">
      <label for="edit-name" class="js-form-required form-required">Username</label>
        <input autocorrect="none" autocapitalize="none" spellcheck="false" autofocus="autofocus" data-drupal-selector="edit-name" aria-describedby="edit-name--description" type="text" id="edit-name" name="name" value="" size="60" maxlength="60" class="form-text required" required="required" aria-required="true">

            <div id="edit-name--description" class="description">
      Enter your Drupal username.
    </div>
  </div>
<div class="js-form-item form-item js-form-type-password form-item-pass js-form-item-pass">
      <label for="edit-pass" class="js-form-required form-required">Password</label>
        <input data-drupal-selector="edit-pass" aria-describedby="edit-pass--description" type="password" id="edit-pass" name="pass" size="60" maxlength="128" class="form-text required" required="required" aria-required="true">

            <div id="edit-pass--description" class="description">
      Enter the password that accompanies your username.
    </div>
  </div>
<input autocomplete="off" data-drupal-selector="form-myrmxvb4c2hhvtvec5t9ozbmf4d7sx7xyzocl7jjk88" type="hidden" name="form_build_id" value="form-MyRMXVb4C2hhvtVec5T9oZbmf4D7SX7XYzoCL7JJK88">
<input data-drupal-selector="edit-user-login-form" type="hidden" name="form_id" value="user_login_form">
<div data-drupal-selector="edit-actions" class="form-actions js-form-wrapper form-wrapper" id="edit-actions"><input data-drupal-selector="edit-submit" type="submit" id="edit-submit" name="op" value="Log in" class="button js-form-submit form-submit">
</div>

</form>

  </div>

    </div>
          <aside class="layout-sidebar-first" role="complementary">
          <div>
    <div id="block-fbgd5hmx">

  <h1>Log in</h1>

  </div>
<div id="block-zncqsq6z">

        <h2 class="visually-hidden">Primary tabs</h2>
  <ul><li><a href="/user/login" data-drupal-link-system-path="user/login" class="is-active">Log in<span class="visually-hidden">(active tab)</span></a></li>
<li><a href="/user/register" data-drupal-link-system-path="user/register">Create new account</a></li>
<li><a href="/user/password" data-drupal-link-system-path="user/password">Reset your password</a></li>
</ul>

  </div>

  </div>

      </aside>

  </main>

</div>
  </div>

    <script type="application/json" data-drupal-selector="drupal-settings-json">{"path":{"baseUrl":"\/","scriptPath":null,"pathPrefix":"","currentPath":"user\/login","currentPathIsAdmin":false,"isFront":true,"currentLanguage":"en"},"pluralDelimiter":"\u0003","suppressDeprecationErrors":false,"ajaxTrustedUrl":{"form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM":true},"user":{"uid":0,"permissionsHash":"59b0d4b8256570a057e21f4ac353f2481743b37a6aca5e0126c010e2958d98f3"}}</script>
<script src="/core/modules/system/tests/modules/js_deprecation_log_test/js/js_deprecation_log.js?v=8.8.1"></script>
<script src="/core/misc/drupalSettingsLoader.js?v=8.8.1"></script>
<script src="/core/misc/drupal.js?v=8.8.1"></script>
<script src="/core/misc/drupal.init.js?v=8.8.1"></script>
<script src="/core/modules/system/tests/modules/css_disable_transitions_test/js/disable_transitions.theme.js?v=8.8.1"></script>

</body></html>

```

.lando.yml

```
name: drupal-orange-project
recipe: drupal8
config:

  # php - Optional - Default is latest php supported by Drupal 8.
  # See: https://www.drupal.org/docs/8/system-requirements/php-requirements
  php: '7.2'

  # nginx - Optional - Default Apache
  # See: https://www.drupal.org/docs/7/system-requirements/web-server
  via: nginx

  # DataBase - Optional - Default latest mysql.
  # database: mysql
  #   type: 8

  # webroot - Optional - Location of webroot relative to your approot.
  # If ommitted this will be your approot itself.
  webroot: web

  # xdebug - Optional
  # If you are having trouble getting xdebug to work please see:
  # https://docs.devwithlando.io/services/php.html#using-xdebug
  xdebug: true

services:

  # Solr default version 7.1
  # Supported Versions: https://docs.devwithlando.io/services/solr.html
  index:
    type: solr

    # Optionally declare the name of the solr core.
    core: orange_solr

    # Dynamically assign a port each time you start your app
    portforward: true

    # Optionally use custom solr config files eg (schema.xml and solrconfig.xml)
    # This is helpful if frameworks require custom config eg Drupal.
    # This is relative to the app root (may be different from your webroot).
    config:
      conf: web/modules/contrib/search_api_solr/solr-conf/7.x

  # node default version 8.9
  # https://docs.devwithlando.io/services/node.html
  node:
    type: node
    run:
      # Installs all requirements for orange_framework/gulpfile.js
      # This should probably be done in a package.json and package.lock in the orange_framework
      - cd $LANDO_MOUNT
      - npm install gulp gulp-sass gulp-sourcemaps gulp-rename
      - npm install gulp-postcss postcss-easysprites autoprefixer gulp-cli

  mailhog:
    type: mailhog
    hogfrom:
      - appserver
    portforward: true

  webdriver:
    type: compose
    services:
      image: selenium/standalone-chrome
      user: root
      ports:
        - "4444:4444"
      volumes:
        - /dev/shm:/dev/shm
      command: /opt/bin/entry_point.sh

proxy:
  index:
    - solr.drupal-orange-project.lndo.site:8983

  mailhog:
    - mail.drupal-orange-project.lndo.site

tooling:
  node:
   service: node
  npm:
    service: node
  gulp:
    service: node

```

# Answer
> 1 votes
Here's what I've found after being annoyed about this over and over again.

1. `SIMPLETEST_BASE_URL` should be set to a URL that is resolvable from where phpunit is run.

* Inside a container, the hostname should match the name of the container where nginx or apache is running e.g. `http://apache` or `http://nginx` or whatever lando uses (look up the name using `docker ps` and isolate the service name from docker-compose).
    * Outside a container, the hostname should match the resolvable URL e.g. `http://web.internal`.
2. I additionally had issues on my own docker-compose setup running traefik with a http to https redirect using self-signed certificates. But even though I disabled these, used a http address, hacked the /etc/hosts files in all the containers, I was not able to work around the issue.

My work around currently is to run tests inside the container using phpunit. This is far from ideal as I cannot run from my IDE, but at least it's working for me.

---
Tags: 8, testing
---


# Question
Title: How do I add a script just above the closing body tag?
## How do I add a script on Drupal 8 site/app just above closing body tag?

Vendor provided some JS in the following form:

```
<script>
    ... code
</script>

```

Asked me to place immediately above `</body>`.

**The script was only to run for Anonymous traffic.**

Here's how I did it:

THEME = name of your theme

1. Removed `<script>` and `</script>` from code
2. Minified using https://javascript-minifier.com/
3. Created file name-of-my-script.min.js
4. Uploaded to THEME/js/custom/name-of-my-script.min.js
5. Added library to bottom of THEME.libraries.yml

```
name-of-my-library:
  version: 1.0
  js:
    js/custom/name-of-my-script.min.js: {preprocess: false} // {preprocess: false} is responsible for code showing up above </body>

```
6. Added the following code to THEME.theme to an already existing function: `function THEME_preprocess_page(&$variables) {}`

```
$logged_in = $variables['logged_in'];
    if (!$logged_in) {
    $variables['#attached']['library'][] = 'THEME/name-of-my-library';
}

```
7. Cleared cache.

## Resourses that helped:

# Answer
You can achieve this simply by using jquery. If you want to access it from all theme pages you need to add the below line in your global common js file which has access to all the theme pages in the app.

```
$('body').append('<script src="/name-of-your-library"></script>');

```
> 0 votes

---
Tags: 8, theming, javascript
---


title: Creating ajax modal from event

text:
# Question
Title: Creating ajax modal from event
Here's the deal. I want to create a modal popup when an add to cart event is triggered.

I've got the event working just fine but can't seem to get the ajax to work properly. What I'm working off of was using the magnific popup library and was creating the popup using `\Drupal::messenger()->addMessage($content, NULL);` where content was a render array and the theme has

```
{{ attach_library('commerce_add_to_cart_confirmation/confirmation_overlay_css') }}
{{ attach_library('commerce_add_to_cart_confirmation/magnific_modal') }}

```

right at the top.

I thought this was very weird and funky. After some searching I found that you could create an ajax response like :

```
  $content = "Something to show in the modal";
  $title = "Hi, I'm a Modal";
  $response = new AjaxResponse();
  $response->addCommand(new OpenModalDialogCommand($title, $content, ['width' => '700']));
  return $response;

```

So I started doing this instead but it wouldn't work. I was told that nothing was handling that return since this function was just called because of an event. That made sense.

I then found this which seemed to be doing nearly the same as me.
I modified my code to use the same method.
No dialog box. :( I used xdebug and saw that there was no ajax response coming from the kernel::response and thus my function kept returning no response.

I then thought that it could be that ajax isn't loaded. I used the chrome network dev tool and found no ajax.dialog there. I tried adding this to my .module file :

```
function commerce_add_to_cart_confirmation_page_attachments(array &$attachments) {
  $attachments['#attached']['library'][] = 'core/drupal.dialog.ajax';
}

```

Then I saw ajax.dialog in the network but still no popup on my site.
The module linked above uses a hook to some commerce form (I can't tell which because the name is so cluttered) and wonder if that makes a difference.

How can I create a modal popup from a `CartEvents::CART_ENTITY_ADD` event subscriber? Am I missing something to do with the libraries or something wrong with my php?

# Answer
> 1 votes
> How can I create a modal popup from a CartEvents::CART\_ENTITY\_ADD event subscriber? Am I missing something to do with the libraries or something wrong with my php?

You can't return a response from any event, this is only possible from specific kernel events by setting the response in the event. But the example you have linked should work in your case. It splits the task into two event subscribers:

```
  public static function getSubscribedEvents() {
    return [
      CartEvents::CART_ENTITY_ADD => 'onAddToCart',
      KernelEvents::RESPONSE => 'onResponse',
    ];
  }

```

which are in the same service class, so the second event can use the variable the first one has set:

```
  public function onAddToCart(CartEntityAddEvent $event) {
    $this->purchasedEntity = $event->getEntity();
  }

  public function onResponse(FilterResponseEvent $event) {
    $response = $event->getResponse();

    // We only care if this happened after an entity was added to the cart.
    if (!$this->purchasedEntity) {
      return;

    ...

    $event->setResponse($response);
  }

```

---
Tags: 8, commerce, ajax, modal-dialogs
---


# Question
Title: How to add class attributes to radio options in Drupal 8 Webform YAML Editor
What I'd like to be able to do is provide some extra detail to the HTML markup that the Webform module provides in Drupal 8, specifically being able to classify individual radio button options.

**What I Have:**

```
gift_selection:
  '#type': radios
  '#required': true
  '#title': 'Gift Selection'
  '#description': 'Choose from the following free gifts!'
  '#description_display': before
  '#attributes':
    class:
      - promo-gift
  '#options':
    GIFT-BAG: 'Canvas Tote Bag'
    GIFT-KEY: 'Logo Keychain'
    GIFT-BADGE: 'License Plate Badge'
    GIFT-DECAL: 'Reusable Decals'

```

Results in...

```
<fieldset class="promo-gift fieldgroup form-composite required form-group" data-drupal-selector="edit-gift-selection" id="edit-gift-selection--wrapper" required="required" aria-required="true">
  <label class="control-label js-form-required form-required">
    <span>Gift Selection</span>
  </label>
  <div class="fieldset-wrapper">
    <span class="field-prefix">
      <div class="description">Choose from the following free gifts!</div>
    </span>
    <div class="brand-border-radius radio">
      <input class="promo-gift form-radio form-control" data-drupal-selector="edit-gift-selection-gift-bag" type="radio" id="edit-gift-selection-gift-bag" name="gift_selection" value="GIFT-BAG">
      <label for="edit-gift-selection-gift-bag" class="control-label option">Canvas Tote Bag</label>
    </div>
    <div class="brand-border-radius radio">
      <input class="promo-gift form-radio form-control" data-drupal-selector="edit-gift-selection-gift-key" type="radio" id="edit-gift-selection-gift-key" name="gift_selection" value="GIFT-KEY">
      <label for="edit-gift-selection-gift-key" class="control-label option">Logo Keychain</label>
    </div>
    <div class="brand-border-radius radio">
      <input class="promo-gift form-radio form-control" data-drupal-selector="edit-gift-selection-gift-badge" type="radio" id="edit-gift-selection-gift-badge" name="gift_selection" value="GIFT-BADGE">
      <label for="edit-gift-selection-gift-badge" class="control-label option">License Plate Badge</label>
    </div>
    <div class="brand-border-radius radio">
      <input class="promo-gift form-radio form-control" data-drupal-selector="edit-gift-selection-gift-decal" type="radio" id="edit-gift-selection-gift-decal" name="gift_selection" value="GIFT-DECAL">
      <label for="edit-gift-selection-gift-decal" class="control-label option">Reusable Decals</label>
    </div>
  </div>
</fieldset>

```

The code above runs as you might expect, but there's no contextual separation between the div wrappers for the rendered options. I've not been able to find any documentation that suggests that this is even possible, however, I've tried to do the following, and I think it might be able to see what I'm doing, but the renderer of the form doesn't know how to handle the extra info.

**What I'd Like To Have:**

```
gift_selection:
  '#type': radios
  '#required': true
  '#title': 'Gift Selection'
  '#description': 'Choose from the following free gifts!'
  '#description_display': before
  '#attributes':
    class:
      - promo-gift
  '#options':
    GIFT-BAG:
      '#label': 'Canvas Tote Bag'
      '#attributes':
        class:
          - gift-bag
    GIFT-KEY:
      '#label': 'Logo Keychain'
      '#attributes':
        class:
          - gift-key
    GIFT-BADGE:
      '#label': 'License Plate Badge'
      '#attributes':
        class:
          - gift-badge
    GIFT-DECAL:
      '#label': 'Reusable Decals'
      '#attributes':
        class:
          - gift-decal

```

Resulting in...

```
<fieldset class="promo-gift fieldgroup form-composite required form-group" data-drupal-selector="edit-gift-selection" id="edit-gift-selection--wrapper" required="required" aria-required="true">
  <label class="control-label js-form-required form-required">
    <span>Gift Selection</span>
  </label>
  <div class="fieldset-wrapper">
    <span class="field-prefix">
      <div class="description">Choose from the following free gifts!</div>
    </span>
    <div class="brand-border-radius radio gift-bag">
      <input class="promo-gift form-radio form-control" data-drupal-selector="edit-gift-selection-gift-bag" type="radio" id="edit-gift-selection-gift-bag" name="gift_selection" value="GIFT-BAG">
      <label for="edit-gift-selection-gift-bag" class="control-label option">Canvas Tote Bag</label>
    </div>
    <div class="brand-border-radius radio gift-key">
      <input class="promo-gift form-radio form-control" data-drupal-selector="edit-gift-selection-gift-key" type="radio" id="edit-gift-selection-gift-key" name="gift_selection" value="GIFT-KEY">
      <label for="edit-gift-selection-gift-key" class="control-label option">Logo Keychain</label>
    </div>
    <div class="brand-border-radius radio gift-badge">
      <input class="promo-gift form-radio form-control" data-drupal-selector="edit-gift-selection-gift-badge" type="radio" id="edit-gift-selection-gift-badge" name="gift_selection" value="GIFT-BADGE">
      <label for="edit-gift-selection-gift-badge" class="control-label option">License Plate Badge</label>
    </div>
    <div class="brand-border-radius radio gift-decal">
      <input class="promo-gift form-radio form-control" data-drupal-selector="edit-gift-selection-gift-decal" type="radio" id="edit-gift-selection-gift-decal" name="gift_selection" value="GIFT-DECAL">
      <label for="edit-gift-selection-gift-decal" class="control-label option">Reusable Decals</label>
    </div>
  </div>
</fieldset>

```

For example, notice the difference in the wrapper div class attribute values:

`brand-border-radius radio` vs. `brand-border-radius radio gift-bag`

What actually ends up happening with this approach is that the values supplied for the options are displayed as `Array`, which leads me to believe there is a display file that I need to extend to look for these additional attributes. Not sure where to go for this or what the best practice here would be if I need to modify a specific component dealing with Webforms so it doesn't break with a future update.

# Answer
```
$form['radio'] = [
  '#type' => 'radios',
  '#title' => 'Choose an answer option',
  '#options' => [
    0 => 'yes',
    1 => 'no',
  ],
  0 => [
    '#description' => 'description for yes',
  ],
  1 => [
    '#description' => 'description for no',
  ]
];

```
> -2 votes

---
Tags: theming, webforms, 8
---


title: Get a field instance's settings

text:
# Question
Title: Get a field instance's settings
What's the equivalent of `field_info_instance()` for Drupal 8?

The default field settings are stored as configuration in a file like field.field.ENTITYTYPE.BUNDLE.FIELDNAME.yml, but how do I get their current value?

# Answer
Using the *entity\_field.manager* service, you are able to get an array of BaseFieldDefinition classes. This service is injectable as well, but for copy-paste working code, you can do the following:

```
$bundle_fields = \Drupal::getContainer()->get('entity_field.manager')->getFieldDefinitions($entity_type, $bundle);
$field_definition = $bundle_fields[$field_name];
$catalog_id = $field_definition->getSetting($setting_name);

```
> 15 votes

# Answer
Using a field instance:

```
$settings = $field->getFieldDefinition()->getSettings();

```

For example, in a field widget:

```
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
  $element = [];

  // Get the settings.
  $settings = $items[$delta]->getFieldDefinition()->getSettings();

  // ... build render array

  return $element;
}

```
> 5 votes

# Answer
The most simple way to get field config is to use EntityTypeManager.

```
$entity_type = 'node';// node, taxonomy_term, taxonomy_vocabulary, ...
$bundle = 'article';// the content type machine name
$field = 'field_article_tags';// the field machine name

$fieldConfig =  \Drupal::entityTypeManager()
  ->getStorage('field_config')
  ->load($entity_type . '.' . $bundle . '.' . $field);

```
> 5 votes

# Answer
I wanted to get the Type and Label from the field definition. This did not work:

```
$setting_name = 'label';
$label = $field_definition->getSetting($setting_name);

```

This worked:

```
$label = $field_definition->getLabel();
$type = $field_definition->getType();

```
> 1 votes

---
Tags: entities, 8
---


title: structure_sync not working

text:
# Question
Title: structure_sync not working
I am trying to use structure\_sync within my Drupal 8.4.4 project to export the block content of custom blocks as a configuration (see also the discussion "Custom blocks cannot be properly exported and imported").

Installation via composer went fine and the module also reports everything goes fine when trying the `export-blocks` function for example:

```
$ drush export-blocks
Exporting blocks...
Exported "Copyright"                                          [ok]
Exported "Social Links"                                       [ok]
Exported "Flyout"                                             [ok]
Successfully exported blocks                                  [ok]
The custom blocks have been successfully exported.            [status]

```

However, no configuration files were actually created in the `sync_dir` (or elsewhere).

Is there some other undocumented pre-requisite?

# Answer
> 0 votes
The custom block content needs to be edited and saved again - otherwise `structure_sync` will not be able to recognize, that something has changed and thus it does not want to export the block content.

# Answer
> 2 votes
It is not well explained in the documentation, but `structure_sync` works by generating a new configuration item with all the exported content. It does not generate new files by itself.

Later, when you export the configuration, the new config item appears.

---
Tags: 8, configuration
---


title: How do I export/import views?

text:
# Question
Title: How do I export/import views?
I know how to do it in Drupal 6/7, but I cannot find where to export/import views in Drupal 8. From which admin page is possible to do it, in Drupal 8?

# Answer
Views are configuration entities in Drupal 8, and can be exported via the Configuration Management module.
> 23 votes

# Answer
Views are available through configuration in Drupal 8, and can be exported via the Configuration Management interface.

In the admin menu select "Configuration" in the DEVELOPMENT section, select "Configuration synchronization":

In that menu area, the Export tab leads to the path: http://sitename/admin/config/development/configuration/single/export

In that area, a single view can be exported or imported, and the steps are about the same so I'll include Export here to help explain.

1. Select 'Export' menu tab.
2. Select 'Single item' sub menu tab.
3. From the first item drop down 'Configuration type' select 'View'.
4. From the second item drop down 'Configuration name' select the name of your view.

The result is a views.view.view\_machine\_name.yml "YAML" file that can be copy pasted into the 'Import' area.
> 41 votes

# Answer
If you'd like to export a view for use in the default configuration of a custom module, you can run a Drupal Console command:

```
drupal config:export:view

```

See: `config:export:view` docs page.
> 2 votes

# Answer
Once a single view exported using the configuration management module, the view can be imported on a site of interested by creating a simple custom module and placing the yml file corresponding to the view in /config/install folder (remove the first line containing the uuid ) The view will be imported when activating the module
> 0 votes

---
Tags: views, 8
---


# Question
Title: Allow guests to subscribe to specific taxonomy terms and send them weekly updates/notifications
I would like to display a block to my visitors, where they can enter their email, name and a list of topics (taxonomy terms) they are interested in (e.g. "technology", "health", "science").

When subscribed, they should regularly receive updates/summaries via email, with new content in these topics.

I don't want users to necessarily sign up first, but also allow guests to subscribe to topics.

Is this possible with Drupal 8 natively or via plugin? Or do I need to write my own plugin?

# Answer
Try to use https://www.drupal.org/project/simplenews. This can be integrated with Views and Rules.
> 2 votes

---
Tags: emails, notifications
---


# Question
Title: How can I delete vocabulary terms at a certain level?
I know there are several threads here about deleting terms with various techniques; I'm going to experiment deleting terms with drush at a certain level, say level three terms and below in the hierarchy. I was just curious if anyone here has any good ideas for this to inspire my work!

---

I'm pretty sure that can be done with the TermStorage class method loadAllParents, then determining which terms will be removed based on that count. I had forgotten about that method, loadParents would be much harder to use in this case, because we want to move all the way up the hierarchy.

# Answer
> 0 votes
Since my answer is being criticized for not being an answer (use loadAllParents and then perform the delete logic), I'll post some code, I guess that's what users want. This is untested and probably needs some more work, but this is basically what I meant

```
<?php

$manager = \Drupal::entityTypeManager()->getStorage('taxonomy_term');

$vid = 'some_vocabulary_id';

$tree = $manager->loadTree($vid, $parent = 0, $max_depth = NULL, $load_entities = TRUE);

$result = [];

foreach ($tree as $term) {
  $parents = $manager->loadAllParents($term->id());
  if (count($parents) > 3) {
    $result[] = $term;
  }
}

foreach ($result as $item) {
  $manager->delete($item);
}

```

---
Tags: 8, taxonomy-terms, drush
---


# Question
Title: What's the proper way to refer to all the code in `core/lib/Drupal`, or the code in `core/lib/Drupal/Core' or `core/lib/Drupal/Core/Foo`?
When we say 'core' we mean the whole of Drupal core that you get from the Drupal project page.

On D7, core code that wasn't in modules tended to be called 'the includes' IIRC.

But on D8 they're not include files any more. They in `core/lib/Drupal` and we have:

* `core/lib/Drupal`
* `core/lib/Drupal/Core`
* `core/lib/Drupal/Components`
* `core/lib/Drupal/Core/Foo`
* `core/lib/Drupal/Components/Foo`

What's the correct way to refer to these?

# Answer
> 4 votes
What you describe is correct, when you install Drupal, everything in the 'core' directory is considered the core set of Drupal files, or the bare minimum installation package.

The files in 'core/lib' is essentially all of the source code for the running system. Personally, this is what "core" means to me. The files (for the most part1) outside of that are the scaffold (or support files).

The files in 'core/lib/Drupal/Core' are called "Core", pronounced with a big C. The files in 'core/lib/Drupal/Component' are called "Component", pronounced with a big C. Confusing, yes?

"Component" are the set of files that Drupal uses, but don't actually rely on anything else in "Core". For example, `DateTimePlus` and `Time` are two Components, that don't need anything in 'core/lib/Drupal/Core'.

"Core" are the set of files that Drupal uses, but are interdependent on each other, and also require "Component". For example, `DrupalDateTime` relies on `DateTimePlus` (in Component) and the Language subsystem (in Core).

1Ignoring tests for this discussion.

---
Tags: 8
---


# Question
Title: Error "The module ldap does not exist" after composerizing project
I've inherited a tarball-based Drupal 8.7.8 project.

I'm moving it to new hosting, and assuming responsibility for updates and maintenance.

After updating core to 8.8.2, and updating all contrib themes and modules to their latest versions, I used the amazing new core-based tool to convert the tarball to a Composer-based project.

This worked well, with one exception: Composer refuses to install the latest `8.x-3.0-beta7` of the LDAP module, and insists on installing `8.x-3.0-beta3`. But now Drush is showing messages like:

```
$ lando drush en new_custom_module

In ExtensionList.php line 522:

  The module ldap does not exist.

```

And if I try to enable it, I get this:

```
$ lando drush en ldap

In PmCommands.php line 247:

  Unable to install modules ldap due to missing modules ldap.

```

I have rebuilt caches about a million times. (It used to be that you needed to do a registry rebuild if you did funny business like move an installed module to a different path in the filesystem. But now that is just part of the `drush cr` process.)

LDAP is not actually a module *per se*, it's a project that contains all of its "submodules."

It's very odd that the maintainer added an `ldap.info.yml` file but there is no `ldap.module` file.

I wish I could just uninstall it, but LDAP auth is a client requirement. They are locking down the site logins unless users are in their Active Directory Domain.

The weird thing is ... it *might* still work, since all the submodules are installed. (Can't test in my local; deploy environment not set up yet.)

Comparing my new dev branch with the production site (before composerization and the downgrade from beta7 to beta3) I have verified that all the same LDAP submodules are installed:

```
$ lando drush pml |grep ldap
  Lightweight Directory Access Protocol   LDAP Authentication (ldap_authentication)                                            Enabled    8.x-3.0-beta3
  Lightweight Directory Access Protocol   LDAP Authorization Provider (ldap_authorization)                                     Enabled    8.x-3.0-beta3
  Lightweight Directory Access Protocol   LDAP Help (ldap_help)                                                                Enabled    8.x-3.0-beta3
  Lightweight Directory Access Protocol   LDAP Query (ldap_query)                                                              Enabled    8.x-3.0-beta3
  Lightweight Directory Access Protocol   LDAP Servers (ldap_servers)                                                          Enabled    8.x-3.0-beta3
  Lightweight Directory Access Protocol   LDAP Users (ldap_user)                                                               Enabled    8.x-3.0-beta3

```

How do I proceed to troubleshoot this situation?

Is it safe to manually remove all traces of the LDAP module in the database, since all the submodules seem to be installed and enabled?

I've written about this in the LDAP project's issue queue, but I have no responses after a week so I brought it here.

I'm grateful in advance for any guidance.

**UPDATE** (2020-03-01):

The package maintainer has responded to the Drupal.org thread, suggesting that I should run the following command:

```
composer update drupal/ldap drupal/ldap_authentication drupal/ldap_authorization drupal/ldap_servers drupal/ldap_query drupal/ldap_user --with-dependencies

```

This command executes without error, but claims there is "nothing to install or update":

```
    Finished: success: 12, skipped: 0, failure: 0, total: 12
Package "drupal/ldap_authentication" listed for update is not installed. Ignoring.
Package "drupal/ldap_authorization" listed for update is not installed. Ignoring.
Package "drupal/ldap_servers" listed for update is not installed. Ignoring.
Package "drupal/ldap_query" listed for update is not installed. Ignoring.
Package "drupal/ldap_user" listed for update is not installed. Ignoring.
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update

```

After running this command, `drush pml` shows that I still have `beta3` installed, so this remains unresolved.

# Answer
The reason is that 8.x-3.0-beta3 doesn't define a separate ldap module. You need version 8.x-3.0-beta7 which defines ldap as a "meta" module.

`composer why-not drupal/ldap 8.x-3.0-beta7` will probably tell you that you need the dev version of drupal/authorization.

**Added:**

I'm unable to explain why, but `composer why-not` (or `composer prohibits` if you prefer) doesn't actually report that you need the dev version of drupal/authorization.

Anyway, just install the dev version and everything works:

```
composer require drupal/authorization:1.x-dev
composer update drupal/ldap drupal/ldap_servers [...]  --with-dependencies

```

PS! Someone installing the ldap module directly, not converting from a tar ball, will not get this issue.
> 3 votes

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


# Question
Title: D8 doesn't create .htaccess for private file system path
Following this guide: https://www.drupal.org/documentation/modules/file it says

> "When you specify the private directory in admin/config/media/file-system it will automatically create the sub-directory & create a simple .htaccess file with Deny from all."

When you edit your `settings.php` and add the `$settings['file_private_path'] = 'sites/default/files/private'` after `drush rc` it doesn't create the `.htaccess` file in my `sites/default/files/private` and I do not know how the correct `.htaccess` should look so I could add it manually?

,

# Answer
Try

```
Deny from all
# Turn off all options we don't need.
Options None
Options +FollowSymLinks

```
> 1 votes

# Answer
This is a better `.htaccess` to use:

```
# Turn off all options we don't need.
Options -Indexes -ExecCGI -Includes -MultiViews

# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
  # Override the handler again if we're run later in the evaluation list.
  SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>

# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
  php_flag engine off
</IfModule>
<IfModule mod_php7.c>
  php_flag engine off
</IfModule>

```

This `.htaccess` is the one that should have been placed in your private files directory by Drupal 8 (or 9) core. (Perhaps permissions on the private directory prevented Drupal from creating the file.)

The accepted answer above is adequate to quiet the warning from Drupal status report, but does not actually prevent the remote script execution exploit addressed in the original core security advisory from 2013.

**EDIT (2021-10-14):**

I stand corrected. In the case of the private files directory, there's actually a bit more to it.

The `.htaccess` I posted above (last April) contains "Apache htaccess directives to prevent execution of files in a location."

This `.htaccess` is added to *public* file directories like `./sites/default/files/` to *prevent remote execution of uploaded PHP scripts* -- a vector for some very nasty exploits that can compromise not only your Drupal site, but in some cases your entire server.

But the very next method in `Drupal\Component\FileSecurity` contains "Apache htaccess directives to block access to a location."

That section looks like this:

```
# Deny all requests from Apache 2.4+.
<IfModule mod_authz_core.c>
  Require all denied
</IfModule>

# Deny all requests from Apache 2.0-2.2.
<IfModule !mod_authz_core.c>
  Deny from all
</IfModule>

```

The second `.htaccess` is the one which is necessary to *prevent all remote access to a directory*. In the case of the directories used for Drupal's `private://` and `temporary://` stream wrapper file paths, it would seem prudent to add both of these.

Also, if you installed Drupal a long time ago and have been upgrading incrementally, it might be good to check the `.htaccess` files in your public, private, temporary and config directories to make certain they are up to date. Sometimes when an older version is present, it prevents Drupal security hardening from adding the latest version.
> 6 votes

---
Tags: 8, .htaccess, files
---


# Question
Title: How can you filter an integer column by "Starts with"?
I have a view, and I want the users to be able to filter on an Integer field. String fields allow for filtering by 'Starts with'. I would like to do the same but with an integer.

If the user enters "10" it would match 100, 1010, etc, but not 210.

# Answer
> 2 votes
You can do this with a combine fields filter.

You first need to include the field you want to filter on. Once the field is in you add the filter combine fields filter and set it to exposed. Change the operator to "begins with" and select the integer field.

Save the changes and you should have the filtering option with the begins with option on an iteger field.

# Answer
> 2 votes
I was hoping for a way to do this without a custom filter, but after some research it clear why this is not available out of the box. 'Starts with' is implemented as `field LIKE $value . '%'` which contains both an implicit cast and a LIKE. There may be issues on databases other than MySQL due to the implicit casting.

**src/Plugin/views/filter/StartsWithFilter.php**

```
<?php

namespace Drupal\startswith\Plugin\views\filter;

use Drupal\views\Plugin\views\filter\NumericFilter;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\display\DisplayPluginBase;

/**
 * My custom numeric filter.
 *
 * @ingroup views_filter_handlers
 *
 * @ViewsFilter("starts_with_filter")
 */
class StartsWithFilter extends NumericFilter {
  /**
   * {@inheritdoc}
   */
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    parent::init($view, $display, $options);
  }

  public function operators() {
    $operators = parent::operators();
    $operators += [
      'starts' => [
        'title' => $this
          ->t('Starts with'),
        'short' => $this
          ->t('begins'),
        'method' => 'opStartsWith',
        'values' => 1,
      ]
    ];

    return $operators;
  }

  protected function opStartsWith($field) {
    $group = $this->options['group'];

    $this->query->where[$group]['conditions'][] = array(
      'field' => $field ,
      'value' => db_like($this->value['value']) . '%',
      'operator' => 'LIKE',
    );

  }
}

```

Replaces the standard NumericFilter with our custom Filter.

**startswith.module**

```

function startswith_views_data_alter(&$data) {

  foreach($data as $k1 => $v1) {
    foreach($v1 as $k2 => $v2) {
      $has_filter = isset($v2['filter']) && isset($v2['filter']['id']);

      if ($has_filter) {
        $numeric_filter = $v2['filter']['id'] == 'numeric';

        if ($numeric_filter) {
          $data[$k1][$k2]['filter']['id'] = 'starts_with_filter';
        }

      }
    }
  }

}

```

---
Tags: views, 8
---


# Question
Title: Is there a way to create a Webform automatically via script using Drush or another method?
I'm automating a base Drupal 8 install using a bash script with Composer and Drush commands that installs Drupal and uses Drush and other methods to set my basic site configurations.

I'd like to also create some other basic settings like creating a standard Webform contact form, including its URL, etc.

Is this possible to do somehow via a script? Perhaps have a Webform config export stored somewhere and import it via the script? Note, this would be a new site so its UUID would differ each time.

# Answer
> 2 votes
You can create a new site from an existing configuration using `drush site:install --existing-config`. Create the config through exporting from an existing site and copy it over to the new project.

See https://www.drupal.org/node/2897299 and https://www.drupal.org/project/drupal/issues/2980670

The docs are a bit outdated though, you now need to use `$settings['config_sync_directory']` instead of `$config_directories['sync']`, see https://www.drupal.org/node/3018145

# Answer
> 1 votes
You can exactly do what you touched on with config: put a placeholder into the yaml for the URL and remove the uuid completely. As you import into a new site, that will generate a new one for you.

---
Tags: drush
---