# Question
Title: update drupal core from a version to a new version with composer
i want to update the core from 8.7.6 to 8.9.2 and when I try this command "**composer require drupal/core:^8.9.2 --update-with-dependencies**" i have got an error like below , can anyone help me please to solve this and get the migration work

the error :

```
 Problem 1
    - webflo/drupal-core-require-dev 8.7.6 requires drupal/core 8.7.6 -> satisfiable by drupal/core[8.7.6] but these conflict with your requirements or minimum-stability.
    - webflo/drupal-core-require-dev 8.7.6 requires drupal/core 8.7.6 -> satisfiable by drupal/core[8.7.6] but these conflict with your requirements or minimum-stability.
    - webflo/drupal-core-require-dev 8.7.6 requires drupal/core 8.7.6 -> satisfiable by drupal/core[8.7.6] but these conflict with your requirements or minimum-stability.
    - Installation request for webflo/drupal-core-require-dev (locked at 8.7.6, required as ^8.7.0) -> satisfiable by webflo/drupal-core-require-dev[8.7.6].

```

my composer.json

```
{
    "name": "drupal-composer/drupal-project",
    "description": "Project template for Drupal 8 projects with composer",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "authors": [
        {
            "name": "",
            "role": ""
        }
    ],
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        {
            "type": "package",
            "package": {
                "name": "harvesthq/chosen",
                "version": "1.8.7",
                "type": "drupal-library",
                "dist": {
                    "url": "https://github.com/harvesthq/chosen/releases/download/v1.8.7/chosen_v1.8.7.zip",
                    "type": "zip"
                },
                "require": {
                    "composer/installers": "^1.2.0"
                }
            }
        }
    ],
    "require": {
        "php": ">=5.6",
        "composer/installers": "^1.2",
        "cweagans/composer-patches": "^1.6.5",
        "drupal-composer/drupal-scaffold": "^2.5",
        "drupal/admin_toolbar": "^1.27",
        "drupal/bootstrap_barrio": "^4.22",
        "drupal/bootstrap_layouts": "^5.1",
        "drupal/bootstrap_sass": "^1.9",
        "drupal/chosen": "^2.8",
        "drupal/config_ignore": "^2.1",
        "drupal/config_split": "^1.4",
        "drupal/console": "^1.0.2",
        "drupal/core": "8.7.6",
        "drupal/devel": "^2.1",
        "drupal/ds": "^3.4",
        "drupal/eu_cookie_compliance": "^1.8",
        "drupal/google_analytics": "^3.0",
        "drupal/google_tag": "^1.2",
        "drupal/honeypot": "^1.29",
        "drupal/memcache": "^2.0",
        "drupal/menu_admin_per_menu": "^1.0",
        "drupal/menu_link_attributes": "^1.0",
        "drupal/module_filter": "^3.1",
        "drupal/pathauto": "^1.4",
        "drupal/redirect": "^1.4",
        "drupal/robotstxt": "^1.2",
        "drupal/simple_sitemap": "^3.3",
        "drupal/sitemap": "^1.5",
        "drupal/smtp": "^1.0@beta",
        "drupal/views_bootstrap": "^4.1",
        "drupal/yaml_editor": "^1.0",
        "drush/drush": "^9.0.0",
        "harvesthq/chosen": "^1.8",
        "vlucas/phpdotenv": "^2.4",
        "webflo/drupal-finder": "^1.0.0",
        "webmozart/path-util": "^2.3",
        "zaporylie/composer-drupal-optimizations": "^1.0"
    },
    "require-dev": {
        "webflo/drupal-core-require-dev": "^8.7.0"
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "sort-packages": true
    },
    "autoload": {
        "classmap": [
            "scripts/composer/ScriptHandler.php"
        ],
        "files": ["load.environment.php"]
    },
    "scripts": {
        "pre-install-cmd": [
            "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
        ],
        "pre-update-cmd": [
            "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
        ],
        "post-install-cmd": [
            "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
        ],
        "post-update-cmd": [
            "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
        ]
    },
    "extra": {
        "composer-exit-on-patch-failure": true,
        "patchLevel": {
            "drupal/core": "-p2"
        },
        "installer-paths": {
            "web/core": ["type:drupal-core"],
            "web/libraries/{$name}": ["type:drupal-library"],
            "web/modules/contrib/{$name}": ["type:drupal-module"],
            "web/modules/custom/{$name}": ["type:drupal-custom-module"],
            "web/profiles/contrib/{$name}": ["type:drupal-profile"],
            "web/profiles/custom/{$name}": ["type:drupal-custom-profile"],
            "web/themes/contrib/{$name}": ["type:drupal-theme"],
            "web/themes/custom/{$name}": ["type:drupal-custom-theme"],
            "drush/Commands/{$name}": ["type:drupal-drush"]
        },
        "drupal-scaffold": {
            "initial": {
                ".editorconfig": "../.editorconfig",
                ".gitattributes": "../.gitattributes"
            }
        }
    }
}

```

# Answer
A few things I would try:

**composer require webflo/drupal-core-require-dev 8.9.2**

If that fails try deleting the composer.lock file and then running **composer update drupal/core --with-dependencies**

If your composer.json requirement for drupal/core isn't allowing the jump to 8.9.2, then update that and run the second command again.
> 0 votes

# Answer
I have often read this is not the recommended way, but in my Drupal installations I get fewest problems with a simple

```
composer update

```

command. This updates all, and solves such dependencies reliable.

Another solution is to combine core and webflo/drupal-core-require-dev in the same composer command:

```
composer update drupal/core:^8.9.2 webflo/drupal-core-require-dev:^8.9.2 --with-dependencies

```

Always backup your database and codebase before, so you can switch back if something went terribly wrong.

It could be helpful to read the release notes of the core and module version steps between your upgrade. Sometimes there are important hints.
> 0 votes

---
Tags: updating, composer
---


# Question
Title: What is the recommended way for using PHPUnit?
Installing Drupal 9 with the *drupal/recommended-project* Composer package ships without PHPUnit. Why? (In Drupal 8 it is included. The documentation only tells about Drupal 8.)

Which version of PHPUnit should I use? In this post kiamlaluno answered that Drupal 9 supports PHPUnit 8 at the moment; therefore, I think that version 8.5 is OK, isn't it?

I installed PHPUnit 8.5.8 with composer, but when I try to use it, I get this error.

> Class "Symfony\Bridge\PhpUnit\SymfonyTestsListener" does not exist.

This post suggest installing symfony/phpunit-bridge, Composer choose version 5.1, but it didn't work, and I got the same error message. Is this a wrong version for Drupal 9 and PHPUnit 8.5.8? It solved the issue commenting out the listener class in phpunit.xml. But I'm not shure if this is the right way.

4. Is there anywhere a documentation/tutorial for the actual official release of drupal to get PHPUnit running the recommended way?

# Answer
> 3 votes
*drupal/recommended-project* doesn't install PHPUnit, which is instead installed with the drupal/core-dev meta-package. For example, if I wanted to install Drupal 9.0.3, including PHPUnit, I would use the following commands.

```
composer create-project drupal/recommended-project:^9.0 my-project
cd my-project
composer require 'drupal/core-dev:^9.0'

```

As said in Starting a Site Using Drupal Composer Project Templates / Adding drupal/core-dev, *drupal/core-dev* still doesn't depend on *drupal/core*. Specifying a version of *drupal/core-dev* is necessary to get a version that matches the Drupal core version you are using. Also, if you want to install Drush, you need to first install *drupal/core-dev* and then *drush/drush*.

As for the PHPUnit version, *drupal/core-dev* 9.0.3 requires the following packages.

* phpspec/prophecy: ^1.7
* phpunit/phpunit: ^8.4.1
* symfony/phpunit-bridge: ^4.4

Using more recent version for *phpunit/phpunit* and *symfony/phpunit-bridge* hasn't been tested, yet.

For Drupal 8.8.0, *drupal/core-dev* 8.8.0 requires a version of *phpunit/phpunit* that matches *^6.5 || ^7*, a version of *phpspec/prophecy* that matches *^1.7*, and a version of *symfony/phpunit-bridge* that matches *^3.4.3*. Even with Drupal 8.8.0, installing PHPUnit after installing Drupal core with *drupal/recommended-project* requires the same steps I described for Drupal 9.

---
Tags: testing, 9
---


title: Using container element in form widget

text:
# Question
Title: Using container element in form widget
I want to build a widget for a own field type. In the function formElement() of my widget I want the elements wrapped in a div. For this purpose exists the container element. So I build my form:

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

    $element['myitem'] = [
      '#type' => 'container',
      '#attributes' => [
          'class' => ['my-item'],
      ],
      '#attached' => [
        'library' => [
          'mymodule/mylibrary',
        ],
      ],
    ];
   $element['myitem']['label'] = [
    '#type' => 'select',
    '#title' => t('Label'),
    '#default_value' => isset($items[$delta]->label) ? $items[$delta]->label : NULL,
    '#options' => $options_for_label,
  ];
  //… more elements

  return $element;
}

```

The rendering of the form looks like I wanted. But the form entries will not be saved. There are no errors and none of the elements were attached to the entity and persisted in the database.

If I don't use the container element and place my elements direct in $element like this:

```
 $element['label'] = [
  '#type' => 'select',
  '#title' => t('Label'),
  '#default_value' => isset($items[$delta]->label) ? $items[$delta]->label : NULL,
  '#options' => $options_for_label,
];
//… more elements

```

then all will be saved.

How can I get my widget-form elements be wrapped within a div for styling?

(A similar question using container element within form widget, here with focus at form state was asked 3 years ago, but without answer :-( )

# Answer
> 3 votes
From WidgetBase::form:

```
// Most widgets need their internal structure preserved in submitted values.
$elements += ['#tree' => TRUE];

```

When customizing the structure you also need to make sure the values get submitted correctly. For example by adding WidgetInterface::massageFormValues to your widget.

A much easier way though is to keep the standard structure, which is using property names as form keys, and add the container by #prefix/#suffix:

```
$element['label'] = [
  '#type' => 'select',
  '#title' => t('Label'),
  '#default_value' => isset($items[$delta]->label) ? $items[$delta]->label : NULL,
  '#options' => $options_for_label,
  '#prefix' => '<div class="my-item">',
  '#suffix' => '</div>',
];

```

---
Tags: 8, entities, forms
---


# Question
Title: How can I use Migrate API to migrate taxonomy with an unknown level of parent child relationships in tact?
I have a JSON file with an entry that looks like this:

`"taxonomy": "abc/historical_controls/abc2000_2013"`

In my YML file I have it mapped like this:

```
  field_abc_asset_taxonomy_auto:
    -
      plugin: skip_on_empty
      method: process
      source: taxonomy
    -
      plugin: explode
      delimiter: /
    -
      plugin: callback
      callable: ltrim
    -
      plugin: callback
      callable: rtrim
    -
      plugin: entity_generate
      value_key: name
      entity_type: taxonomy_term
      bundle_key: vid
      bundle: abc_asset_taxonomy_auto

```

This works in that it brings over the terms correctly, but in a flat file. I need them to come over so that each term is a child of the term before it so:

`abc
 historical_controls
 abc2000_2013`

The problem is there is an unknown number of items. It could be 2, it could be 10.

Is there a way to migrate hierarchical taxonomy with an unknown number of parent child relationships?

Note, I've seen several examples that use a determinant number of sources but this wouldn't work here. The "Migrate Hierarchical Taxonomy" module uses a determinant number as well. How can I achieve this with the Migrate API preferably without writing a custom plugin?

# Answer
Maybe too late but for the sake of being complete: I think you'll find the answer here Using Drupal 8's Migrate API, how can I map a nested (hierarchical) taxonomy term to the imported entity? First migrate the terms without parents. After that update the parent-field.
> 0 votes

---
Tags: 8, taxonomy-terms, migrations
---


# Question
Title: Check if the user has flagged content with any flag
It is possible with the following code to check if a content has been flagged by the current user with a certain flag:

```
$flag = flag_get_flag('flag_name');
if ($flag && $flag->is_flagged($node->nid, $GLOBALS['user']->uid)) {
  print "This node is flagged";
}

```

But, how to check if the user has flagged content with any flag ?

# Answer
> 0 votes
The flag module has a utility function `flag_get_flags()` that retrieves multiple flags, with an option to filter on the entity type of the flag:

```
// Same logic, looped over multiple node flags:
$flags = flag_get_flags('node')
foreach ($flags as $flag_name => $flag) {
  if ($flag && $flag->is_flagged($node->nid, $GLOBALS['user']->uid)) {
    print "This node is flagged";
  }
}

```

---
Tags: 7, theming
---


# Question
Title: Upload multiple Standolane Media Entities (Images) without Reference Field
I'd like to Upload Images as Media Entities without referencing them in another Entity. In `media/add/image` I can upload a single Image. That's fine. What I'd like to achieve is a Multiple Upload Widget where I can Upload multiple Images and provide default values for all Images (Taxonomy Reference). After creation these Media Entities can be edited further or assigned to other content Entities or just be viewed in Galleries according to their Taxonomy Term.

# Answer
> 1 votes
The Media Bulk Upload module will allow you to upload many images at once.

> This is the Drupal 8 module to bulk upload files and create the media entities automatically for them. It uses DropzoneJS to quickly upload multiple files.

The bulk uploader will allow you to edit fields on the media item before saving. You'll want to set alt text for each image, and your Taxonomy Term reference.

---
Tags: media
---


# Question
Title: Load nodes by property, including empty ones
I want to render a node with certain properties set. For example, I want to load every node which ONLY has field\_a and the other fields are empty.

If I use

```
$this->nodeStorage->loadByProperties(['type' => 'node_type', 'field_a' => $value]);

```

-\> this will load every node which has field\_a, but the other fields are not necessarily empty. I tried setting all the other fields to null, but it throws an InvalidQueryException. How can I change that query to IS NULL or which function can I use?

# Answer
`loadByProperties()` executes an entity query with `->condition()` for each property. You can't use this for empty fields, you need

```
$query->notExists('field_example');

```

according to How get empty record on date field with entityQuery?
> 4 votes

---
Tags: 8, entities
---


# Question
Title: how to print a form in twig where a variable number of form elements have been printed already?
I am using a Twig template to render a form that has a variable number of elements.

Each element's key in the form is sequential integer.

So in my template, I can do this:

```
{% for item in form|children %}
  {{ item }}
{% endfor %}

```

However, then I have a broken form, because there's no `<FORM>` HTML element, or the form ID for submission.

I've looked at twig templates for forms in core, but they all work with fixed elements, so they're able to do something like this, seen in `modules/content_moderation/templates/entity-moderation-form.html.twig`:

```
{{ form|without('current', 'new_state', 'revision_log', 'submit') }}

```

# Answer
> 0 votes
If you look at *form.html.twig* in the Drupal Core's system module, you'll see:

```
{#
/**
 * @file
 * Default theme implementation for a 'form' element.
 *
 * Available variables
 * - attributes: A list of HTML attributes for the wrapper element.
 * - children: The child elements of the form.
 *
 * @see template_preprocess_form()
 *
 * @ingroup themeable
 */
#}
<form{{ attributes }}>
  {{ children }}
</form>

```

Using this as a guide, you should be able to do:

```
<form{{ attributes }}>
  {% for item in form|children %}
    {{ item }}
  {% endfor %}
</form>

```

*children* is already a variable in the template so you can just use it like:

```
<form{{ attributes }}>
  {% for item in children %}
    {{ item }}
  {% endfor %}
</form>

```

But if you're not wrapping the individual children, why even use a custom template? Why not just use the default *form.html.twig*.

---
Tags: forms
---


# Question
Title: How to get the entity ID in a twig template
I have a custom entity, with the template `my-custom-entity--my-entity.html.twig`.

How do I access the ID in the template? ***I can do this by implementing `hook_preprocess_entity`, but am wondering if the ID is already available in the template.***

# Answer
> 0 votes
You can just add the full object to a twig variable, so

```
$vars['myentity'] = $my_entity;

```

and then access with

```
{{ myentity.id }}

```

A bit more elegant is to implement hook\_theme:

```
/**
 * Implements hook_theme().
 */
function MODULENAME_theme() {
  return [
    'customentity' => [
      'render element' => 'elements',
    ],
  ];
}

```

and a preprocess function to expose it to twigs customentity and maybe content variables:

```
function template_preprocess_customentity(&$variables) {
  $variables['customentity'] = $variables['elements']['#node'];

  // Helpful $content variable for templates.
  $variables += ['content' => []];
  foreach (Element::children($variables['elements']) as $key) {
    $variables['content'][$key] = $variables['elements'][$key];
  }
}

```

---
Tags: 8, theming, entities
---


title: redirect whole site to HTTPS

text:
# Question
Title: redirect whole site to HTTPS
When I include the snippet found in answer to this question How to simply make the whole site HTTPS? to redirect to https in my htaccess.php file, all urls resove to /index instead of going to the page originally requested (Ex: user tries to access example.com/about, and is redirected to https://example.com).

Here is the snippet I used:

```
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

```

I have also tried the slight variation found at https://www.drupal.org/https-information, which has the same unsatisfactory result:

```
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www.domainname\.com*
RewriteRule ^(.*)$ https://domainname.com/$1 [L,R=301]

```

**How can I make the site all https without breaking the ability to navigate to a specific page?**

Edited to add: I've got the Secure Pages module, but haven't managed to get it to work. If you have advice on that point instead I'd happily take it.

# Answer
> 3 votes
You might be interested in the htaccess module:

> Htaccess is a module which autogenerates a Drupal root htaccess file based on your settings.
>
> Drupal tries to provide a one size fits all htaccess for Apache webservers, but this goal is increasingly difficult. This module allows the webmaster to set specific options.
>
> Also, this module is dedicated to webmasters who don't want to manually modify htaccess every time during a version upgrade to use Drupal.

It offers enabling HTTPS and then generates the .htaccess file for you.

# Answer
> 11 votes
```
RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS

RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.

```

# Answer
> 0 votes
The example from @rjkunde didn't work on my local Lando based drupal development environment, the browser gave me the error message: "The page isn’t redirecting properly". The drupal documentation on Enabling HTTP Secure (HTTPS) helped me to solve the problem by adding a second rewrite condition `RewriteCond %{HTTP:X-Forwarded-Proto} !https`:

```
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

```

---
Tags: redirection, .htaccess, ssl
---


# Question
Title: Is it possible to update/remove/install 1 package with composer without updating everything?
I have seen a few posts answering this and saying that "composer require package" or "composer update package" will do this; but absolutely everything i do with composer attempts to update everything listed in require section of composer.json.

I thought perhaps just removing the require lines in composer.json would avoid this mess; but composer then removes these modules from my docroot.

I simply want to remove my broken (not sure why) version of drush on the server and replace it with a new one without updating core or any contrib modules.

composer remove drush/drush - but it fails the removal and then tries to update everything

> xxx:~/www/d8$ composer remove drush/drush drush/drush is not required in your composer.json and has not been removed
>
> > DrupalProject\composer\ScriptHandler::checkComposerVersion Package "drush/drush" listed for update is not installed. Ignoring. Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages.

any composer command i try (rmeove, update, require) seems to want to update everything.. and then fails because of dependencies conflicts (which is good; since I don't want anything being updated anyway).

# composer.json

```
{
    "name": "drupal-composer/drupal-project",
    "description": "Project template for Drupal 8 projects with composer",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "authors": [
        {
            "name": "",
            "role": ""
        }
    ],
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    ],
    "require": {
        "php": ">=7.0.8",
        "composer/installers": "^1.2",
        "cweagans/composer-patches": "^1.6.5",
        "drupal-composer/drupal-scaffold": "^2.5",
        "drupal/address": "^1.7",
        "drupal/admin_toolbar": "^1.27",
        "drupal/auto_entitylabel": "^3.0@beta",
        "drupal/backup_migrate": "^4.0",
        "drupal/block_class": "^1.0",
        "drupal/clientside_validation": "^1.2",
        "drupal/coffee": "^1.0@beta",
        "drupal/commerce": "2.17",
        "drupal/conditional_fields": "^1.0@alpha",
        "drupal/console": "^1.0.2",
        "drupal/content_access": "^1.0@alpha",
        "drupal/core": "^8.7.0",
        "drupal/csv_serialization": "^1.4",
        "drupal/ctools": "^3.2",
        "drupal/date_popup": "^1.0",
        "drupal/date_popup_timepicker": "^1.0@alpha",
        "drupal/entity_reference_revisions": "^1.7",
        "drupal/external_links_new_tab": "^1.2",
        "drupal/extlink": "^1.1",
        "drupal/field_group": "^1.0",
        "drupal/field_permissions": "^1.0@RC",
        "drupal/filefield_paths": "^1.0@beta",
        "drupal/fillpdf": "4.x-dev",
        "drupal/viewsreference": "^1.4",
        "drush/drush": "^10.2",
        "vlucas/phpdotenv": "^2.4",
        "webflo/drupal-finder": "^1.0.0",
        "webmozart/path-util": "^2.3",
        "zaporylie/composer-drupal-optimizations": "^1.0"
    },
    "require-dev": {
        "webflo/drupal-core-require-dev": "^8.7.0"
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "sort-packages": true
    },
    "autoload": {
        "classmap": [
            "scripts/composer/ScriptHandler.php"
        ],
        "files": ["load.environment.php"]
    },
    "scripts": {
        "pre-install-cmd": [
            "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
        ],
        "pre-update-cmd": [
            "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
        ],
        "post-install-cmd": [
            "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
        ],
        "post-update-cmd": [
            "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
        ]
    },
    "extra": {
        "composer-exit-on-patch-failure": true,
        "patchLevel": {
            "drupal/core": "-p2"
        },
        "installer-paths": {
            "web/core": ["type:drupal-core"],
            "web/libraries/{$name}": ["type:drupal-library"],
            "web/modules/contrib/{$name}": ["type:drupal-module"],
            "web/profiles/contrib/{$name}": ["type:drupal-profile"],
            "web/themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/Commands/contrib/{$name}": ["type:drupal-drush"]
        },
        "patches": {
            "drupal/core": {
                "Drag-drop fix for field group config": "https://www.drupal.org/files/issues/2019-12-09/drupal-tabledrag_testing-2769825-48.patch",
                "part of above": "https://www.drupal.org/files/issues/2019-11-21/3062742_4.patch",
                "multiple terms in views issues": "https://www.drupal.org/files/issues/2019-11-14/drupal-empty_value_fix-2882076-14.patch",
                "more drag-drop fixes": "https://www.drupal.org/files/issues/2019-12-14/3089151-17-D8.patch"
            },
            "drupal/conditional_fields": {
                "Date field value is always empty": "https://www.drupal.org/files/issues/2020-01-19/conditional_fields-date_fields_empty-2956612-8.patch"
            },
            "drupal/fillpdf": {
                "Add token support for before/after text": "https://www.drupal.org/files/issues/2020-02-18/3109697-6.patch"
            },
            "drupal/field_group": {
                "Conditional field support": "https://www.drupal.org/files/issues/2019-12-10/field_group-support_conditional_fields-3099051-6.patch",
                "HTML5 validation broken in tabs": "https://www.drupal.org/files/issues/2019-10-04/field_group-HTML5_validation_prevents_submission_in_tabs-2969051-9.patch"
            },
            "drupal/serial": {
                "Feeds support": "https://www.drupal.org/files/issues/2020-02-28/serial-feeds-support-3035978-6.patch"
            }
        },
        "drupal-scaffold": {
            "initial": {
                ".editorconfig": "../.editorconfig",
                ".gitattributes": "../.gitattributes"
            }
        }
    }
}

```

# Answer
> 1 votes
The proper way is `composer require package/name`, `composer remove package/name`, or `composer update package/name`. Version number is optional. You are doing it correctly.

The line about "Updating dependencies" is expected. It is not updating the versions of your packages (unless required by the require/remove statement), it's updating dependency information based on your require/remove/update.

---
Tags: drush, composer
---


# Question
Title: Attaching Theme Library to Custom Module
I have a subtheme called `bootstrap_subtheme`. It has a library called `global-styling`. I created a custom module called `telephone_alter`. In `telephone_alter.module`, I have the following:

```
function telephone_alter_form_user_form_alter(&$form){
  $form['#attached']['library'][] = 'bootstrap_subtheme/global_styling';
}

```

it does not load the `bootstrap_subtheme` library stylesheet. I do `dump($form)` and get the following:

```
  "#attached" => array:1 [▼
    "placeholders" => array:1 [▼
      "form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM" => array:1 [▼
        "#lazy_builder" => array:2 [▶]
      ]
    ]
  ]

```

seems like the attachment isn't even grabbing it. Yes I am using the right form alter according to the api: hook\_form\_FORM\_ID\_alter() and my ID is `user_form` . It does fire off, if I attach css from within my module's folder, but not my subtheme. Any help would be great! Thank you.

One more note:

my `root` dir is as follows:

```
modules
   -telephone_alter
theme:
   contrib:
      -bootstrap
   custom:
      -bootstrap_subtheme

```

Here is bootstrap\_subtheme.libraries.yml:

```
global-styling:
  js:
    js/popper.min.js: {}
    js/bootstrap.min.js: {}
    js/global.js: {}
  css:
    component:
      css/style.css: {}
  dependencies:
    - core/jquery
    - core/drupal

```

# Answer
> 1 votes
Based on that structure, you're referencing the library incorrectly. It should be `$form['#attached']['library'][] = 'bootstrap_subtheme/bootstrap_subtheme.global-styling';`

As noted in a comment below, the duplicate use of the theme name may not be necessary, and `$form['#attached']['library'][] = 'bootstrap_subtheme/global-styling';` should work according to the docs. (Note the use of a dash, matching the library name versus an underscore in your code.)

---
Tags: theming, javascript
---


title: Debug PHP code with XDebug and VS Code

text:
# Question
Title: Debug PHP code with XDebug and VS Code
For development I use a local Drupal 7 installation on Xampp under Windows 10. I use Visual Studio Code as IDE and want to debug my PHP code with it. I tried to set that up but can not quite get it working. This is my configuration:

* Xampp installation path: c:\xampp
* PHP: c:\xampp\php (version PHP 7.3.17 64bit)
* Drupal files: c:\xampp\htdocs

php.ini additions:

```
[XDebug]
zend_extension = "c:\xampp\php\ext\php_xdebug-2.9.6-7.3-vc15-x86_64.dll"
xdebug.remote_autostart = 1
xdebug.profiler_append = 0
xdebug.profiler_enable = 0
xdebug.profiler_enable_trigger = 1
xdebug.profiler_output_dir = "c:\xampp\tmp"
xdebug.remote_enable = 1
xdebug.remote_handler = "dbgp"
xdebug.remote_host = "127.0.0.1"
xdebug.remote_log = "c:\xampp\tmp\xdebug.txt"
xdebug.remote_port = 9000
xdebug.trace_output_dir = "c:\xampp\tmp"
xdebug.remote_cookie_expire_time = 36000

```

VS Code launch config:

```
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "runtimeExecutable": "c:\\xampp\\php\\php.exe",
            "pathMappings": {
              "c:\\xampp\\htdocs": "${workspaceFolder}"
            },
            "xdebugSettings": {
              "show_hidden": 1
            }
          }
    ]
}

```
* I downloaded the correct xdebug DLL and put it in:
c:\xampp\php\ext\php\_xdebug-2.9.6-7.3-vc15-x86\_64.dll
* In my Chrome browser I installed the "XDebug Helper" extension.
* In VS Code I installed the XDebug extension and set a few breakpoints in my code.

Then I open my Drupal site in Chrome and hit debug in the XDebug Browser extension.
The breakouts don't get deactivated as "unbound" but the debugger does not stop at any of them either.

What am I missing?

# Answer
> 1 votes
In my VS Code launch config I had to change the `pathMappings` from this:

```
"c:\\xampp\\htdocs": "${workspaceFolder}"

```

into that:

```
"c:\\xampp\\htdocs\\sites\\all": "${workspaceFolder}"

```

---
Tags: debugging
---


# Question
Title: Access denied when trying to import single configuration item
I am using Drupal 8.9.2 and trying to import a view using the Configuration Management UI in the admin. I did this with no issue importing the view from my local dev environment to our dev server, but when I try to do the same thing on our test server, I get "Access Denied".

The way I did this was by going to my local environment and going to Configuration \> Development \> Configuration synchronization \> Export. Then choosing "Single Item". Under "Configuration Type", I chose "View" and then selected my view. I then copied this code and went to my dev server and went to Configuration \> Development \> Configuration Synchronization \> Import and chose "Single Item" and chose "View" for "Configuration type". I pasted my code in and clicked submit and my View was successfully imported and all was well. Now when I do this exact same process on my test server, when I get to the part where I submit my pasted code and click submit, I get:

Is there a specific directory that I must not have access to on the server? Or Drupal doesn't have access to on the server? I'm not sure what happens behind the scenes during this type of import process. In my settings.php I have this for the config sync stuff:

```
$config_directories['sync'] = '../config/sync';

```

And I checked that directory and it does have read/write permissions. Is that even the directory I need to check as far as permissions go for a single item config import?

# Answer
OK, so this one was determined to be an Akamai issue for sure. There were some measures that it takes if it thinks it is a denial of service attack and for some reason that was what was happening. Our admin adjusted some settings and the error went away.

THANKS
> 0 votes

---
Tags: 8, configuration, importing-exporting
---


# Question
Title: Get a list of all users and into an array
I was wondering what how to get all the user and put all their UIDs into an array? I have seen similar questions but none really answer my question.

# Answer
In Drupal 7 you can fetch all the users using entity\_load like following,

```
$users = entity_load('user');

```

and array\_keys($users) will gives you the array of uid's
> 23 votes

# Answer
You can achieve the outcome in Drupal 8 by:

```
$query = \Drupal::entityQuery('user');

$uids = $query->execute();

```
> 11 votes

# Answer
Another Drupal 8 solution using `\Drupal::entityTypeManager()`.

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

$query = $userStorage->getQuery();
$uids = $query
  ->condition('status', '1')
  ->condition('roles', 'moderator')
  ->execute();

$users = $userStorage->loadMultiple($uids);

```
> 5 votes

# Answer
Just sharing a snippet I created recently to get HTML and EMAIL of all existing users in the database.

Works well up to 2000+ users. After that I suggest implementing batching or an alternative direct database query.

This relies on Drupal loading each user.

```
$query = new EntityFieldQuery();

$query->entityCondition('entity_type', 'user');
$html = '<table>';
$result = $query->execute();

$uids = array_keys($result['user']);

// THIS IS YOUR ARRAY OF UIDS.
$users = user_load_multiple($uids);

// EXTRA CODE.
foreach($users as $user){
  $mail = $user->mail;
  $name = $user->name;
  $html .= '<tr><td>'.$mail.'</td>'.'<td>'.$name.'</td></tr>';
}
$html .= '</table'>;

```

Will return a simple html table which you can copy into excels easily etc.

To get them in an array simply use the variable stated in the code for UIDS.
> 3 votes

# Answer
To answer some of the comments: If you are working with a big number of users you won't be able to load all users in an array without timeout so you'll probably need to batch process them...

Here is how (yes it is:

```
 function _set_batch_revench_agains_users(){
  $batch = [
    'operations' => [
      ['_revench_against_users_batch_process']
    ],
    'finished' => '_revench_against_users_batch_finished',
    'title' => t('Punishing users for ungratefulness and general insolence.'),
    'init_message' => t('Batch is starting, he he he...'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('Batch has encountered an error, nooooo!'),
    'file' => drupal_get_path('module', 'revench_agains_users') . '/user_agains_users.module'
  ];
  batch_set($batch);
  batch_process('admin');
}

/**
 * Batch 'Processing' callback
 */

function _revench_against_users_batch_process(&$context){
 //all this $context stuff is mandatory, it is a bit heavy, but the batchAPI need it to keep track of progresses
  if (!isset($context['sandbox']['current'])) {
    $context['sandbox']['count'] = 0;
    $context['sandbox']['current'] = 0;
  }

  //don't use entity field query for such simple use cases as gettings all ids (much better performances, less code to write...)
  $query =  db_select('users', 'u');
  $query->addField('u', 'uid');
  $query->condition('u.uid', $context['sandbox']['current'], '>');
  $query->orderBy('u.uid');
  // Get the total amount of items to process.
  if (!isset($context['sandbox']['total'])) {
    $context['sandbox']['total'] = $query->countQuery()->execute()->fetchField();

    // If there are no users to "update", stop immediately.
    if (!$context['sandbox']['total']) {
      $context['finished'] = 1;
      return;
    }
  }

  $query->range(0, 25);
  $uids = $query->execute()->fetchCol();
  //finaly ! here is your user array, limited to a manageable chunk of 25 users
  $users_array = user_load_multiple($uids);
  //send it to some function to "process"...
  _burn_users_burnburnburn($users_array); // I won't reveal the content of this function for legal reasons
  //more mandatory context stuff
  $context['sandbox']['count'] += count($uids);
  $context['sandbox']['current'] = max($uids);
  $context['message'] = t('burned @uid ... feels better ...', array('@uid' => end($uids)));

  if ($context['sandbox']['count'] != $context['sandbox']['total']) {
    $context['finished'] = $context['sandbox']['count'] / $context['sandbox']['total'];
  }

}

/**
 * Batch 'finished' callback
 */
function _revench_against_users_batch_finished($success, $results, $operations) {
  if ($success) {
    // Here we do something meaningful with the results.
    $message = t('@count users successfully burned:', array('@count' => count($results)));

    drupal_set_message($message);
  }
  else {
    // An error occurred.
    // $operations contains the operations that remained unprocessed.
    $error_operation = reset($operations);
    $message = t('An error occurred while processing %error_operation with arguments: @arguments some users might have escaped !', array('%error_operation' => $error_operation[0], '@arguments' => print_r($error_operation[1], TRUE)));
    drupal_set_message($message, 'error');
  }
}

```
> 0 votes

---
Tags: users
---


# Question
Title: How to programmatically create an image style?
I need to create image style programmatically in Drupal 7. I found this issue: https://www.drupal.org/project/drupal/issues/2735969 and much more other issues, but all are for Drupal 8. I can't find anything to Drupal 7. Is that impossible in Drupal 7?

# Answer
> 1 votes
You're looking for the `image_style_save` and `image_effect_save` functions.

An example from the comments on the `image_style_save` docs page:

```
$style = image_style_save(array('name' => 'avatar'));
$effect = array(
  'name' => 'image_scale',
  'data' => array(
    'width' => 64,
    'height' => 64,
    'upscale' => TRUE,
  ),
  'isid' => $style['isid'],
);
image_effect_save($effect);

```

---
Tags: 7, media
---


# Question
Title: Should I use Drush or Drupal Console with a new site?
Between Drush and Drupal Console, which seems to have similar functionalities, which one should I install?

# Answer
You should use Drush.

Drush is about to be added to the `drupal/recommended-project`, see #3159647, while Drupal Console seems to be abandoned and currently is incompatible with Drupal 9 due to mismatched dependencies, see #4251.

Maybe Drupal Console finally accomplished its mission by triggering the modernisation of Drush. And there's no need for two CLIs. Now forces can be joined again.
> 10 votes

---
Tags: 9
---


# Question
Title: Custom PHP Unit test trait for a custom module cannot be found
I have created a new Trait for testing my custom module and placed it in `my_module/tests/src/Traits` with the namespace `Drupal\Test\my_module\Traits`, the same as core modules do.

When I try to use this in my PHP Unit kernel test I just get the following error:

```
Fatal error: Trait 'Drupal\Test\my_module\Traits\CustomTrait' not found

```

Is there something special that needs to be included to allow custom traits in testing?

# Answer
> 2 votes
The namespace should Drupal\Test**s**\my\_module\Traits - notice this is Tests with an s at the end, not Test

---
Tags: 8, testing
---


# Question
Title: How can I make kint() load faster when debugging twig templates?
I've seen quite a bit of discussion about how kint() from the Devel module is difficult to work with because it maxes out PHP memory limits and makes the browser drag. I've heard some thoughts on improving its speed by limiting the number of levels. For example, in settings.php, you can do the following:

```
require_once DRUPAL_ROOT . '/modules/contrib/devel/kint/kint/Kint.class.php';
Kint::$maxLevels = 3;

```

Any other ways to improve the speed of kint()?

# Answer
> 23 votes
There are two other ways other users have mentioned for setting the max output levels in addition to the settings.php method mentioned in the question, plus a couple other ideas below:

1. Create a `/modules/contrib/devel/kint/kint/config.php` file and add / modify the line `$_kintSettings['maxLevels'] = 3;` (by @mdrummond on Slack)
2. In a preprocess function, add the following: (by @thpoul on Slack)

```
kint_require();
Kint::$maxLevels = 3;

```
3. Be sure to never click the `+` sign, that shows the entire tree. Click the block instead. You can click the right arrow to open the output in a new window for easier viewing (like when the output is in a block). (by @cwightrun on Slack)
4. Instead of using kint(), create a preprocess function and use a debugger to explore the variables. (by @danny\_englander on Slack)
5. Pass kint() a specific variable instead of making it roll through the whole tree (by @No Sssweat below).
6. If you just need to know what variables exist, you can just view the keys by doing a `{% for key, value in _context %}` loop (by @mortendk below)

# Answer
> 8 votes
Kint is not the only library that you can use for debbuging variables and twig templates.

I suggest to use Symfony var-dumper that IMHO is one of the most powerful lib for debuging variables. Symfony var-dumper is integrated with latest version of devel module (see this issue in the devel issue queue Add a basic symfony var-dumper integration)

For use var-dumper with devel

* download and install devel module
* install var-dumper via composer (`composer require symfony/var-dumper`)
* go to devel settings page and set var-dumper as the default dumper
* use `{{ devel_dump() }}` or `{{ kpr() }}` or `{{ dpm() }}` instead of {{ kint() }} for debug variables in twig templates

# Answer
> 7 votes
FYI, as of Devel v3, you'll need to make two updates if you use the top method suggested by @chrisshattuck

1. Go to `admin/config/development/devel?q=/admin/config/development/devel`
2. Make sure "Kint" is selected.
3. To override the max depth, go to `settings.local.php` and update the max\_depth variable.

```
  include_once(DRUPAL_ROOT . './../vendor/kint-php/kint/src/Kint.php');
  if (class_exists('Kint')) {
    Kint::$max_depth = 4;
   }

```

# Answer
> 2 votes
Here is another tip:

Instead of using `{{ kint() }}` which will return everything, you can be more specific by passing the variable that you need; thus, it will load faster.

For example: In **node--\[type\].html.twig** you can pass the content variable to kint:

`{{ kint(content) }}`

If you know the name of the field, you can be even more specific:

```
{{ kint(content.field_name['#items'].getValue()) }}

```

This will only return the value(s) of field name.

# Answer
> 2 votes
instead of using kint you can do this little trick instead just to get an idea of whats in there

node.html.twig

```
<ol>
{% for key, value in _context  %}
<li>{{ key }} </li>
 {% if loop.index == 2 %}}
    <pre>{{ dump( value ) }}</pre>
{% endif %}
{% endfor %}
</ol>

```

yes it dont gives all the love that kint wants to show you, but at least you get the names etc out

# Answer
> 0 votes
When it is impossible to get the HTML view or it is too slow to load the **kint** output.

I will serialize the variable and save it with

`\Drupal::logger('custom debug')->notice($string);`

Then I will copy it to unserialize.com and choose **Krumo** display....

# Answer
> 0 votes
To limit the number of levels from Kint, you go to your local.settings.php or settings.php and use

```
$_kintSettings['maxLevels'] = 3;

```

# Answer
> -2 votes
Adding `$GLOBALS['_kint_settings']['maxLevels'] = 4;` in your settings.local.php should do the trick. Feel free to change the number of levels here.

---
Tags: theming, 8, performance
---


# Question
Title: How to create an add content link with views
I have a view of the Project node type (created by the pm module) that works well. For authorized users I would like to create a link button that will allow them to create a new project. I've spent the last several hours surfing the web trying to find out how to do this. I am new to Drupal so a solution that avoids using CSS & php would be most welcome.

# Answer
> 2 votes
You needn't use the PHP module, using PHP in the backend UI is usually a bad idea anyway.

First of all, the node creation link is simply a system link like `/node/add/project` which works only for users with the correct permissions.

There are ways to correctly route links through Drupal in Views (custom text—output as link), but as this is just for administrative reasons, you can probably simplay paste HTML like `<a href="/node/add/project">add Project</a>` in a custom text field / View header / View footer.
This displays the link for everyone with access to the View though.

If you want to display the link to specific users only, the easiest way is to simply create a block with the aforementioned link, display it on the same page as the View and show it only on specific user roles.

You could also set up a different view with different access privileges and attach it via an additional module, but I would deem this overkill.

# Answer
> 1 votes
Add this in Global header as custom unfiltered text.

```
<a href="/node/add/project" class="button button-action button--primary button--small"/>Add Project
</a>

```

---
Tags: views
---


# Question
Title: Aegir Installation - how to get the sender email correct to allow install to pass
During the Aegir installation procedure, the

```
sudo apt-get install -y aegir3 aegir-archive-keyring

```

step runs through a series of installation commands that eventually try to send an email from the aegir user to the aegir user.

Depending on my build environment this may work or not depending on whether the the aegir user is set up as a valid email sender. I already have the sending email squared away with MSMTP and can send email from my command line but the installer seems to always be assuming the sending is aegir@hostname.

It would be very nice if I could figure out how to 1) override the sender in the installation script or 2) set the email address of the aegir user manually via CLI.

You'd think that 2 would be very easy to find on the internet but, believe it has been anything but easy. Does anyone know how to alter the apt-get install of Aegir to pick up the sender email address from some environment variable?

Thanks

# Answer
> 2 votes
Found the answer in section 7.1 at https://docs.aegirproject.org/install/#7-install-aegir

```
sudo apt install debconf-utils
mkdir -p ~/projects/aegir/core
git clone https://git.drupal.org/project/provision.git ~/projects/aegir/core/provision
echo "aegir3-hostmaster aegir/email string valid@email.com" | sudo debconf-set-selections
sudo apt install aegir3

```

---
Tags: aegir
---


# Question
Title: hook_node_access() doesn't work for anonymous users
I am still unable to understand what `hook_node_access()` does.
I am trying to give view access to the *Basic* content type nodes to anonymous users, but the code I wrote doesn't work, as anonymous users still get an access denied error.

```
function modules_session_node_access($node,$op,$account) {
  $type = is_string($node) ? $node : $node->type;
  $is_anonymous = !user_is_logged_in();
  if ($op == 'view' && $is_anonymous && $type='basic') {
    return NODE_ACCESS_ALLOW;
  }
  return NODE_ACCESS_IGNORE;
}

```

Why doesn't that code allow anonymous users to view the *Basic* nodes?

# Answer
There is a typo in the code. The code would grant the access to anonymous users when the operation is *view*, but for any content type.

```
  if ($op == 'view' && $is_anonymous && $type='basic') {
    return NODE_ACCESS_ALLOW;
  }

```

The last part of the `if()` statement (`&& $type='basic'`) always evaluate to `TRUE` because it's assigning `'basic'` to `$type` and that value is then "converted" into a Boolean value. (A string that isn't empty, nor `'0'`, is equivalent to `TRUE`).

The correct code would be the following one, assuming that *modules\_session* is the machine name for the module implementing that hook.ì and *basic* is the content type machine name.

```
function modules_session_node_access($node,$op,$account) {
  $type = is_string($node) ? $node : $node->type;
  if ($op == 'view' && !user_is_logged_in() && $type == 'basic') {
    return NODE_ACCESS_ALLOW;
  }
  return NODE_ACCESS_IGNORE;
}

```

That apart, `hook_node_access()` implementations aren't invoked for pages showing more than a node and when:

* The user accessing the node has the *bypass node access* permission
* The user accessing the node doesn't have the *access content* permission

In the first case, the user has the permission to access the node even if one of the `hook_node_access()` implementations wouldn't give the user the permission to access it. In the latter case, the user doesn't have the permission to access the node even if all the `hook_node_access()` implementations would give the user the permission to access it.

Even if the anonymous users would have the *access content* permission, a single `hook_node_access()` implementation giving them the permission to see a node isn't sufficient for anonymous users to see it. It's enough another `hook_node_access()` implementation returns `NODE_ACCESS_DENY` for anonymous users, and the anonymous users won't access the node.

The function invoking `hook_node_access()` is `node_access()`, which contains the following code. (Comments are mine.)

```
// Users with the "bypass node access" permission always have access to the node.
if (user_access('bypass node access', $account)) {
  $rights[$account->uid][$cid][$op] = TRUE;
  return TRUE;
}

// Users without the "access content" permission will never have access to the node.
if (!user_access('access content', $account)) {
  $rights[$account->uid][$cid][$op] = FALSE;
  return FALSE;
}

```

a comment after the invocation of `hook_node_access()` make clear in which case the access is granted.

> We grant access to the node if both of the following conditions are met:
>
> * No modules say to deny access.
> * At least one module says to grant access.

Then, if a node is unpublished, anonymous users cannot access it. Only the user who created it can view it, if the user has the *view own unpublished content* permission, which isn't checked when the author is the anonymous user.

```
// Check if authors can view their own unpublished nodes.
if ($op == 'view' && !$node->status && user_access('view own unpublished content', $account) && $account->uid == $node->uid && $account->uid != 0) {
  $rights[$account->uid][$cid][$op] = TRUE;
  return TRUE;
}

```
> 0 votes

---
Tags: 7, nodes, hooks
---


# Question
Title: Get an entity reference's field values in its field template
I have an entity reference field and the template `field--my-custom-entity--field-my-entity-reference.html.twig`

In the template I print the content.

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

```

**How do I print fields created on this entity reference field?**

Despite wishful thinking, this does not work: `{{ item.content.field_my_field }}`, nor does any of the 100 other possibilities I tried. Twig `dump()` was not helpful.

# Answer
> 4 votes
To get the entity reference's field values:

1. Change the display of your field to **Rendered Entity** like the following
2. Now you have access to your entity values in your twig inside `item.content` for example if your entity reference on content you will find `#node` key inside `item.content` array for example you can render `field_my_field` like the following.

```

     {% for item in items %}
      {{ item.content['#node'].field_my_field.value }}
    {% endfor %}

```

**Update:**
In case of custom entity change ***#node*** by ***#my\_entity\_type***

---
Tags: entities
---


title: Get Url Alias in Algolia

text:
# Question
Title: Get Url Alias in Algolia
I have implemented an Algolia search in my drupal instance and would like to use the node url alias (/some-example-path) rather than node id (/node/{nodeId}). Is there a quick and easy way to do this using the Search API?

# Answer
For D7: Under the **Configuration -\> Search and Metadata -\> Search\_API** and then go to the **Algolia Index** and **Filters tab** (path will be like: `/admin/config/search/search_api/index/algoliaindex/workflow`, where `algoliaindex` is the machine name of your Algolia index), then under **Data Alterations-\>Enabled data alterations** check the **URL field** box. This will add a field to your Algolia index called `search_api_url`.

TIP: If you want to be able to search for text anywhere in the node (not just in indexed fields, you can also check the **Complete entity view** option. Under **Processors** for **Complete entity view** use the **HTML filter**. Under **Processor settings** at the bottom of the page, for **HTML filter-\>Fields to run on** check **Entity HTML output** and delete all contents from the **Tag boosts** field (otherwise it will index the boosts as well and you'll have to change your displayed search index values on the front-end). This will then add a plain-text version of the node as a field in your index called `search_api_viewed` that you can display in your search results.
> 1 votes

# Answer
Using Search API in Drupal 8, you could write a custom processor to create dynamic custom fields which will then be indexed by Algolia, Solr or whatever Search API supports.

Documentation: https://www.drupal.org/docs/8/modules/search-api/developer-documentation/create-custom-fields-using-a-custom-processor
> 0 votes

# Answer
Use PathAuto module

> The Pathauto module automatically generates URL/path aliases for various kinds of content (nodes, taxonomy terms, users) without requiring the user to manually specify the path alias. This allows you to have URL aliases like /category/my-node-title instead of /node/123. The aliases are based upon a "pattern" system that uses tokens which the administrator can change.

For learn how work with it read How to Use Pathauto in Drupal 8
> -1 votes

# Answer
I wrote an interceptor for the indexing service. I iterate through the associated nodes and pull the title from the node, clean the title text of any entities/special characters and append it to a "url string".
> -1 votes

---
Tags: path-aliases
---


# Question
Title: How to create content / entity via ajax on a view?
I have a view listing some content and I want to have an "Add new" button, which should load the node form via ajax (either modal or into a div). After I save the form, it should still stay on the page. Updating the view would also be nice, but for the first thing I'm trying to load the node form via ajax. How can I do that?

# Answer
The most basic version would be to add 'use-ajax' to the "Add new" button link pointing at a controller which returns an ajax command replacing the div. See https://www.drupal.org/docs/drupal-apis/ajax-api/basic-concepts#s-trigger-ajax-request-with-a-link.

Modals use also the 'use-ajax' class but need additional 'data-dialog-\*' attributes. Then you can load normal HTML content in a dialog box, you don't need an Ajax controller in this case. See https://www.drupal.org/docs/drupal-apis/ajax-api/ajax-dialog-boxes

In a submit handler of the form you have to make a redirect to a URL you have setup to display the updated view together with the form.
> 0 votes

---
Tags: 8, ajax
---


title: Add relationship to node view

text:
# Question
Title: Add relationship to node view
I recently installed the "simplenews" and "simplenews\_scheduler" modules. The first module generates a view where you can see the newsletters.

My idea was to create a relationship in that view to gather the data from the "simplenews\_scheduler" table to know if a newsletter has an active schedule.

I tried the "views\_data" and "views\_data\_alter" hooks but I can't add the "activated" field of the "simplenews\_scheduler" table. **The base table of the view is "node\_field\_data"**

Is it possible to do what I'm trying to do? And if so, can someone tell me what I should do? Thank you very much.

# Answer
> 1 votes
To create a view from a database table instead of using ***hook\_views\_data*** you can use `Views Custom Table` module:

> View custom table module provide you functionality to integrate your custom table data to views, and access all it's column in views. This module use hook\_view\_data to add custom tables in views.

it's easy just follow the 7 steps in **How to use** section in module page.

---
Tags: 8, views
---


# Question
Title: How to change the default selection in views filter?
Content type has two fields: Property type and bedroom.

I created a view where above fields were exposed to visitors.

When I visit my site, I see -Any - is the default value for the both fields. First field is the property type and the second field is the bedroom field.

**Property type field :**

**Bedroom field:**

How can I replace the default value *-Any -* by the corresponding field label? For example, for *property type* field, I like to see *Property Type* as the default value and for the *bedroom* field, I like to see *bedroom* as the default value in the drop down list.

# Answer
You can change it with custom code in a module or overriding your theme.

You can also use the Better Exposed Filters module. Change the `Exposed form options` in your Views to use that module option. Then in the further settings you'll be able to override what the options are called for each filter separately.

Drupal 7 also had Views Advanced Labels.

> Use this field to rewrite the filter options displayed. Use the format of current\_text|replacement\_text, one replacement per line. For example:
>
> ```
>  Current|Replacement
>  On|Yes
>  Off|No
>
> ```
>
> Leave the replacement text blank to remove an option altogether.
> 2 votes

# Answer
As stated by prkos in his comment (sorry, I don't have enough reputation to reply to his comment), you could benefit of Better Exposed Filters. What you would need to do is:

1. Enable Better Exposed Filters and clear the cache
2. In your view, open the Advanced section \> Exposed Form \> select 'Better Exposed Filters'
3. On the settings Exposed Form \> Exposed form Style \> Settings, go down and find your exposed filter
4. Expand your filter and rewrite the '- Any -' as this: - Any -|Bedrooms
5. That will change the LABEL of the select option, but the value will always be 'All' unless you change it via code. If code is what you need, please say so and I will try to provide a useful snippet.
> 0 votes

---
Tags: views
---


# Question
Title: How to make node edit form meta panel accordions default to closed?
When editing a node the meta panel fieldset accordions default to being open if they contain data.

I understand why this has been done, but I think it makes for a very noisy and potentially confusing UI for my editors.

How could I go about making these closed by default?

# Answer
There are different approaches to change this behaviour. For instance, you could choose between these two at least:

* CSS + JS: using a selector like .layout-region-node-secondary (depending on Theme), you could loop using a jQuery $.each() over the different 'details' and, if you find the 'open' property, remove it.
* PHP: Using Hook Event Dispatcher, you could attach to the node alter event and upon firing, you could just alter the form accessing the $form / $form\_state variables and removing the CSS from the items you'd like to.
> 2 votes

---
Tags: theming, 9
---


# Question
Title: Paragraph's fields value loaded in a custom controller are in the default language instead of the current language
I made a custom controller that load a paragraph field from a node and then render some part in a template. The paragraph field field\_title and field\_description are translatable.

The translation works fine on the admin side. I followed https://www.drupal.org/docs/8/modules/paragraphs/multilingual-paragraphs-configuration and I can see the content is translated from the admin. But my controller only loads the default language value instead of the current language.

```
<?php

/**
 * @file
 * Contains \Drupal\MyModule\Controller\MyModuleController.
 */

namespace Drupal\MyModule\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

class MyModuleController extends ControllerBase {

    /**
     * Controller load the game
     *
     * @return \Drupal\MyModule\Controller\RedirectResponse
     */
    public function gameView() {

        $nid = 1;

        // Load the game
        $game = \Drupal::entityTypeManager()->getStorage('node')->load($nid);

        $stages = [];

        // Get all the stages of the game
        $paragraph_field_items = $game->get('field_stages')->getValue();
        if (!$paragraph_field_items) {
            throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException('This game has no level');
        }

        // Get storage for paragraph
        $paragraph_storage = \Drupal::entityTypeManager()->getStorage('paragraph');
        // Collect paragraph field's ids.
        $ids = array_column($paragraph_field_items, 'target_id');
        // Load all paragraph objects.
        $paragraphs_objects = $paragraph_storage->loadMultiple($ids);

        /** @var \Drupal\paragraphs\Entity\Paragraph $paragraph */
        foreach ($paragraphs_objects as $paragraph) {
          // Get field from the paragraph.

          $description = [
              '#type' => 'processed_text',
              '#text' => $paragraph->get('field_description')->value,
              '#format' => 'basic_html',
          ];

          $stages [] = [
              'title' => $paragraph->get('field_title')->value,
              'image' => $paragraph->get('field_image'),
              'description' => $description,
              'east_lv95' => $paragraph->get('field_east_lv95')->value,
              'north_lv95' => $paragraph->get('field_north_lv95')->value,
          ];
        }

        return [
            '#theme' => 'game_map',
            '#party' => $party,
            '#stages' => $stages,
            '#game' => $game,
        ];
    }

```

# Answer
Based on the comments I changed `$game->get('field_stages')->getValue();` for `$game->get('field_stages')->referencedEntities();`. This allow me to greatly simply a part of the code.

To load the correct language I added `$paragraph = \Drupal::service('entity.repository')->getTranslationFromContext($paragraph);` inside the loop. Using getTranslationFromContext on the $game didn't works for the paragraph.

I'm not 100% satisfied as I feel translation should be loaded directly when all the fields are loaded with referencedEntities(). But it works and perhaps caching do some magic behind the scene.

This answer helped a lot https://drupal.stackexchange.com/a/269493/1761

```
// Load the game
$game = \Drupal::entityTypeManager()->getStorage('node')->load($gameID);

$stages = [];

// Get all the stage of the game
$paragraph_field_items = $game->get('field_stages')->referencedEntities();

if (!$paragraph_field_items) {
    throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException('This game has no level');
}

/** @var \Drupal\paragraphs\Entity\Paragraph $paragraph */
foreach ($paragraph_field_items as $paragraph) {

  // Get the translation
  $paragraph = \Drupal::service('entity.repository')->getTranslationFromContext($paragraph);

  $description = [
      '#type' => 'processed_text',
      '#text' => $paragraph->get('field_description')->value,
      '#format' => 'basic_html',
  ];

  $stages [] = [
      'title' => $paragraph->get('field_title')->value,
      'image' => $paragraph->get('field_image'),
      'description' => $description,
      'east_lv95' => $paragraph->get('field_east_lv95')->value,
      'north_lv95' => $paragraph->get('field_north_lv95')->value,
  ];
}

```
> 1 votes

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


title: Avoid combining products in cart

text:
# Question
Title: Avoid combining products in cart
With Drupal 8 / Drupal Commerce 2, I can't find a way to disable product combining in cart (same products in cart appears on the same line with quantity \> 1). In my use case I never want this to happen.

I found that in

```
/modules/contrib/commerce/modules/cart/src/Form/AddToCartForm.php

```

...we have a submitForm method which calls

```
$this->cartManager->addOrderItem($cart, $order_item, $form_state->get(['settings', 'combine']);

```

So it seems like my form needs to have a combine variable set to FALSE.

How could I set this variable or override

```
public function addOrderItem(OrderInterface $cart, OrderItemInterface $order_item, $combine = TRUE, $save_cart = TRUE);

```

...in

```
/modules/contrib/commerce/modules/cart/src/CartManagerInterface.php

```

...to define the default value of $combine to FALSE ?

Thanks

# Answer
I could achieve this by implementing hook\_form\_alter on add to cart form (in a custom module) and setting combine like this :

```
$form_state->set(['settings', 'combine'], FALSE);

```
> 1 votes

# Answer
Edge-case, but if you're adding items to the cart programmatically from a custom form, here's what I found to have worked.

```
$cart_manager = \Drupal::service('commerce_cart.cart_manager');

$line_item = $cart_manager->addEntity($cart, $variationobj, $quantity, FALSE, TRUE);

```

This will call `addEntity()` and set Combined to `FALSE`.
> 1 votes

---
Tags: 8, commerce
---


title: Edit search form with a module

text:
# Question
Title: Edit search form with a module
I have made and installed a new module, called searchIcon. The problem is I want to edit the default value "Search" next to the search form. I tried the code below, but it does not seem to work.

```
<?php

/*
 * Implementation of hook_form_alter()
 */

function searchIcon_form_alter(&$form, &$form_state, $form_id) {
    if ($form_id == 'search_block_form') {
        $form['actions']['submit']['#value']= 'TESTSEARCH';
    }
}

?>

```

How could I change the text "search" to e.g. "TESTSEARCH"?

# Answer
> 0 votes
Okay, I think there must have been a typo somewhere or something, but anyway, this setup works:

info yaml:

```
name: Search Icon
description: This module replaces search value by an icon.

type: module
core: 8.x
core_version_requirement: ^8 || ^9

```

module:

```
<?php

/*
 * Implementation of hook_form_alter()
 */

function searchIcon_form_alter(&$form, &$form_state, $form_id) {
    if ($form_id == 'search_block_form') {
        $form['actions']['submit']['#value']= 'TESTSEARCH';
    }
}

```

Please note that the module does not work as intended yet, the value should be replaced by an html decimal code for the desired icon.

---
Tags: forms
---


# Question
Title: How can I disable the cache for a specific page or have the cache ignore query params?
I need to disable the cache for a specific page, or get the cache to ignore query params. I have tried this, but it does not disable the cache for me https://www.drupal.org/project/page\_cache\_query\_ignore

After trying multiple ways to disable the cache for a specific page or even the whole site I have nothing that works.

I have tried all of these in `settings.php`

```
$settings['cache']['default'] = 'cache.backend.null';
$settings['cache']['bins']['render'] = 'cache.backend.null';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';
$settings['cache']['bins']['page'] = 'cache.backend.null';
$settings['cache']['bins']['entity'] = 'cache.backend.null';

```

There is also talk of using `\Drupal::service('page_cache_kill_switch')->trigger();` but I am unsure where to place this to disable the cache for a regular page.

This is for the search page, that uses query params for the search query. Drupal 8 is caching the page so each visit to the search after the first search always shows the results for the first search.

The header for Drupal dynamic cache is always a HIT

`X-Drupal-Dynamic-Cache: HIT`

# Answer
> 2 votes
After a lot of trying and retrying I settled on the following solution

```
function mythemename_preprocess_page(&$variables)
{
  if(isset($_SERVER['QUERY_STRING'])) {
    $params = \GuzzleHttp\Psr7\parse_query($_SERVER['QUERY_STRING']);
    if(isset($params['keys']) && strlen($params['keys']) > 0 && preg_match('#^/search#', $_SERVER['REQUEST_URI'])) {
      \Drupal::service('page_cache_kill_switch')->trigger();
    }
  }
}

```

As far as I can tell, this stops the cache from working if the request is on the search page and there is a query parameter present named `keys`

# Answer
> 0 votes
I'd say that if you haven't been able to completely turn off cache then something is still preventing you from fully loading 'fresh' pages on every request, which may mean there's still some parameter deep down that you might consider reconfiguring. I'd suggest to follow this guide to Disable Drupal 8 caching during development on your local environment before going mad.

---
Tags: 8, caching
---


# Question
Title: How do I retrieve a plugin block field's translated value?
I created a module that installs a block with some fields when installed. I added a schema file, and altered the `blockSubmit()` function so that the translation is saved in the schema.

Here is my module.schema.yml:

```
block.settings.worldwide:
  type: block_settings
  label: 'Worldwide'
  mapping:
    overtitle:
      type: label
      label: 'Overtitle'

```

Here is the `blockSubmit()` function from my Block plugin:

```
public function blockSubmit($form, FormStateInterface $form_state) {
    parent::blockSubmit($form, $form_state);
    $values = $form_state->getValues();
    $block_name = $this->getPluginId();

    $this->blockConfigFactory->setBlockConfig($block_name, 'overtitle', $values['overtitle']);
    $this->setConfigurationValue('overtitle', $values['overtitle']);
}

```

When saving, I have no error, and can translate the field, which will keep the translation when updated. So everything seems to work. Additionnally, the website displays correctly what I saved for the default language.

Now, let's say that the default language is english and the alternative is french. My issue is that if I set the website in french, the default (english) value will keep displaying.

However, I can't figure out a way to displayed the saved translation when I want to look at the block in a language that has the block's translation saved. I have no idea where to look, and can't seem to find relevant stuff on internet.

Thank you in advance

# Answer
Little did I know, the translation was correctly loaded, but not used in the twig files. Both the fields' `content` and `configuration` were loaded, were `content` was *ie* an image and a link, and `configuration` the field's translation.

Somehow, still, the configuration needed several cache rebuilds to show up, but then went ok and kept being updated if I made any modifications.

The twig files were using variables such as `{{ content['field_worldwide_text'] }}`, so I needed it to use `config[]` instead.

Additional notes for future self, here is how to load `content` and `configuration`:

```
$content = $this->blockConfigFactory->getBlockConfig($this->getPluginId());
$config = $this->getConfiguration();

```
> 0 votes

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


# Question
Title: How do I add comments to a YAML webform?
I would like to add comments to the Sourcecode of my webforms in YAML.

`#` comment (without quotes).

But when I save this, it automatically gets removed.

```
20_e_mailadres:
  '#type': email
  '#title': E-mailadres
# write a comment here
21_werkmail:
  '#type': email
  '#title': werk E-mailadres

```

How do I add comments to a YAML webform so they are kept when I save?

# Answer
> 3 votes
## Context

* Drupal 8.x
* Webform module
* YAML comments

## Use-case

* developer KoenC wishes to add comments to a YAML file and have those comments retained upon save

## Problem

* Per the YAML specification, comments are specified as "throwaway" artifacts.
* This means that YAML commments are not required to be preserved by parsers that implement the YAML specification

## Workaround

# Answer
> 2 votes
Comments are not supported in the YAML source because the YAML is decoded and reencoded every time an element is updated.

On my todo list is to add support for '#admin\_notes' to each element which could be used to store 'comments'. For now, you could add a '#comment' property to any element.

@see Issue #3165328: Add support for #admin\_notes to webform elements

---
Tags: webforms
---


# Question
Title: Search is broken after updating search_api_solr from 8.x-2.7 to 4.1.4
My Drupal site has a search form, which connects to a Solr index. All of this was working smoothly.

But then I updated drupal/search\_api\_solr from 8.x-2.7 to 4.1.4 (which also required me to update drupal/search\_api from 1.13 to 1.17) – and now the search is broken. Specifically:

1. The "default" search results – the ones that are displayed when I first land on the search page, before entering any search keywords – are now different.
2. When I *do* enter keywords and submit the search form, it always returns no results. This happens with any keywords, even when there are definitely items in the index that should match.

Here's what I've already tried:

* Cleared the Drupal cache repeatedly (of course).
* From the Drupal configuration dashboard, I have:
    + Confirmed that the Solr server and index are configured correctly, and that Drupal is able to access them.
    + Deleted everything in the index, and re-indexed. (This appeared to complete successfully.)
    + Examined the AJAX response to the search submission, and compared it to the response on a working instance of the site. (The only difference is that HTML returned on the working site includes results, and the HTML returned on the broken site doesn't.)
* Looked for upgrade guides for the search\_api and search\_api\_solr modules. (I haven't been able to find any.)

Any suggestions? I'm running out of ideas here.

# Answer
> 0 votes
After the latest search\_api\_solr module update you need to update config files on your server, as there is a new field added.

If you look into the update log you will find the below message.

> A new Solr field type has been installed due to configuration changes. It is advisable to download and deploy an updated config.zip to your Solr server.

You can find the additional information on how to update server configs from the below link.

Upgrade Search API Solr

Even after checking above points if you are still getting issues, check whether it is due to varnish.

And also run cron once and clear drupal cache after cron and check results again.

---
Tags: 8, search, updating
---


# Question
Title: Scheduled unpublished content and media that is under content moderation
Let's say you have a need for the following:

* Content is created with content moderation, with various states.
* After a set amount of time, the content is deleted or archived.
* The user can set when media (using the media module) can be unpublished.
* When the media is unpublished, it's truly gone from the system. Meaning, if you already knew the path of the file before (like `example.com/site/default/files/blah.pdf`), then after it has been unpublished, it can no longer be accessed because it's gone from the file system.

Playing around with content moderation, I can get it to published in a scheduled manner, but unpublishing seems to not be as straight forward. And media, well, that seems to stick around forever unless you truly delete it.

What am I missing? If this isn't a part of the contributed modules, what other options are there?

# Answer
It should be no problem for a module to implement a cron hook to unpublish content and media after a set amount of time.

Concerning the media files, if you want that they can no longer be accessed after unpublishing the media entity you have store them in the private file system configured in settings.php. See

https://www.drupal.org/docs/8/modules/skilling/installation/set-up-a-private-file-path

The public file system `example.com/site/default/files` can be accessed through the web server directly without Drupal being involved.
> 1 votes

---
Tags: media
---


# Question
Title: How to create flagged nodes views that show up to colorbox using custom link
I Have flagged nodes, but because there are many flagged list with user, I want to show flagged list if user click on the text link as I describe on the picture. How to figure out this stuff?

# Answer
> 1 votes
Check the "Enable Colorbox load" option in Colorbox settings.

Create a page view that lists the flagged content with path of `/flagged/%`

Add Contextual filter of **Flags: User UID**

---

Now in your table view:

Add **User ID** field, and checkmark hide from display.

Add **Custom text** field to view

```
<a class="colorbox-load" href="/flagged/[uid]" width=300&height=150&top=40&right=20&iframe=true">Click here to show</a>.

```

---
Tags: 7, views
---


# Question
Title: Manually removing an orphaned entity type
I have been handed an older Drupal 8 site and asked to update it to run with composer. I didn't do it in the cleanest possible way but it is working. I have run into trouble updating it.

I am most of the way there. Have rebuilt it and it is now managed with composer. However, In trying to run the final DB updates I am stuck with the following error blocking update:

```
[notice] Update started: system_post_update_entity_reference_autocomplete_match_limit
[error]  The "support_ticket" entity type does not exist.
[error]  Update failed: system_post_update_entity_reference_autocomplete_match_limit
[error]  Update aborted by: system_post_update_entity_reference_autocomplete_match_limit
[error]  Finished performing updates.

```

The "support\_ticket" module was on the old site and in the DB but not enabled. I have tried adding and removing it and the "support" module that is its parent but the above error remains.

Is there a way for me to manually stop the system updating that entity type? Or inserting a placeholder? Or some other solution that lets me update the site.

MORE INFORMATION

The module Support and it's sub-module support ticket don't even appeat to be current drupal 8 projects. The last contribution to their d8-port github page is from 2015.

After some messing around I realise the sub-module support\_ticket does not only fail to uninstall but it can't be re-installed either. If you try to re-install it you get the following error:

```
Unable to install Support ticket, comment.type.support_ticket_update,
core.entity_form_display.comment.support_ticket_update.default,
core.entity_form_display.support_ticket.ticket.default,
core.entity_view_display.comment.support_ticket_update.default,
core.entity_view_display.support_ticket.ticket.default,
field.field.comment.support_ticket_update.comment_body,
field.field.comment.support_ticket_update.field_revision_changes,
field.field.comment.support_ticket_update.field_revision_reference,
field.field.support_ticket.ticket.body,
field.field.support_ticket.ticket.field_assigned_to,
field.field.support_ticket.ticket.field_priority,
field.field.support_ticket.ticket.field_related,
field.field.support_ticket.ticket.field_state,
field.field.support_ticket.ticket.field_ticket_update,
field.field.support_ticket.ticket.field_watchers,
field.storage.comment.field_revision_changes,
field.storage.comment.field_revision_reference,
field.storage.support_ticket.body,
field.storage.support_ticket.field_assigned_to,
field.storage.support_ticket.field_priority,
field.storage.support_ticket.field_related,
field.storage.support_ticket.field_state,
field.storage.support_ticket.field_ticket_update,
field.storage.support_ticket.field_watchers,
filter.format.support_ticket_diff, support_ticket.settings,
support_ticket.type.ticket, system.action.support_ticket_delete_action,
system.action.support_ticket_lock_action,
system.action.support_ticket_publish_action,
system.action.support_ticket_save_action,
system.action.support_ticket_unlock_action,
system.action.support_ticket_unpublish_action,
views.view.support_ticket_overview, views.view.users_support_tickets
already exist in active configuration.

```

I am guessing at this point I would need to manually delete entries from the DB?

# Answer
> 1 votes
In case it is of use to anyone else dealing with an old module that doesn't uninstall correctly. The solution to my problem was the following.

WARNING: Do this on a copy of your actual site and database. You could break a live site doing this.

Most of the troublesome database entries are in the config table.

You can use the error list produced above when trying to install the module to track down the rows to purge.

In the database a query such as:

`SELECT name FROM config WHERE name LIKE '%support_ticket%';`

should show you most of the problematic entries.

In my case that exactly matched the offending active configuration so i could just change the above to:

`DELETE FROM config WHERE name LIKE '%support_ticket%';`

I would be very careful about doing this with a `LIKE` query unless you are sure you won't accidentally delete something else.

I assume directly removing entries like this in the database is probably a bad idea but I really couldn't find another way to move forward.

Once the above is done `Drush updb` worked and the update completed.

---
Tags: entities, updating
---


# Question
Title: Failing to uninstall a module because "The website encountered an unexpected error. Please try again later."
It is something wrong with the Profile module I'm using together with the Commerce module and multilanguge module. I would like to uninstall all three modules and try to install them again, but it doesn't allow me as you can see below. How to proceed?

When I try to uninstall a module at /admin/modules/uninstall I get this error.

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

Detailed error message:

```
Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'pantheon.profile' doesn't exist: SELECT base_table.revision_id AS revision_id, base_table.profile_id AS profile_id FROM {profile} base_table LIMIT 1 OFFSET 0; Array ( ) in Drupal\Core\Entity\EntityStorageBase->hasData() (line 588 of /code/core/lib/Drupal/Core/Entity/EntityStorageBase.php).

```

I have clear all cash and run cron, still same issue. It asks me to run this update script:

> 15 PENDING UPDATES

> profile module

```
8003 - Removes the langcode key from the profile entity keys.
8004 - Add the uid entity key to profiles.
8005 - Rerun uid entity key addition after incorrect entity type fixed.
8006 - Install the `data` field.
8007 - Set the 'published' entity key.
8008 - Adds a storage schema for profile that adds a multi-column index.
8009 - Update revision fields.
8010 - Update the status field.
Add new revision settings to profile types.
Change the plugin ID of the delete action.
Change the plugin IDs of the publish and unpublish actions.
Show the profile form at user registration using the profile_form widget.
Replace the "profiles" view with the updated version.

```

> commerce\_tax module Add the tax\_number field to customer profiles. Add the tax\_number field to customer profile view displays.

I click on Apply pending updates. I get this error

```
An AJAX HTTP error occurred.
HTTP Result Code: 200
Debugging information follows.
Path: /update.php/start?id=44&op=do_nojs&op=do
StatusText: parsererror
ResponseText:

```

Detail error log:

```
Error: Call to a member function hasKey() on null in profile_update_8003() (line 82 of /code/modules/profile/profile.install)
#0 /code/core/includes/update.inc(246): profile_update_8003(Array)
#1 /code/core/includes/batch.inc(295): update_do_one('profile', 8003, Array, Array)
#2 /code/core/includes/batch.inc(137): _batch_process()
#3 /code/core/includes/batch.inc(93): _batch_do()
#4 /code/core/modules/system/src/Controller/DbUpdateController.php(185): _batch_page(Object(Symfony\Component\HttpFoundation\Request))
#5 [internal function]: Drupal\system\Controller\DbUpdateController->handle('start', Object(Symfony\Component\HttpFoundation\Request))
#6 /code/core/lib/Drupal/Core/Update/UpdateKernel.php(115): call_user_func_array(Array, Array)
#7 /code/core/lib/Drupal/Core/Update/UpdateKernel.php(76): Drupal\Core\Update\UpdateKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request))
#8 /code/update.php(28): Drupal\Core\Update\UpdateKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#9 {main}

```

# Answer
The uninstall & updated errors are like symptoms of the same problem; your profile module installation has corrupted DB storage so the module can't remove its DB tables, or retrieve its entity definitions to upgrade it.

You'll need to do a manual recovery on in a test environment so you can fully uninstall then reinstall so it has functional DB schema again. Manually restore the `profile` table (or any other DB schema) that the modules needs, then attempt uninstalling again. Repeat this process so you're able to successfully uninstall the module, then re-install it so it has a functional schema.

Once you've confirmed the process works, perform it on your live DB (after backing it up).
> 2 votes

---
Tags: users, commerce
---


# Question
Title: How do you add a PDF attachment to an email?
**Goal**: I need to send an email with a pdf attachment in Drupal 8.

## Progress

I am able to send an email with subject and message but have never been able to get the attachment. When I turn on the logic to attach the file to the email, the email never gets sent but the mail service returns True as if the email was sent anyway. There are no errors and the logs say nothing.

I have the following modules installed:

* SMTP
* MailSystem
* MimeMail

## What I've tried

* Tried using `$message['params']['files'][] = $params['attachments']` instead of `$message['params']['attachments'][] = $params['attachments']` like some examples have recommended
* Tried changing `$file->uri` to `$file->filepath`
* Tried attaching the file like so:

```
$params['attachments']['filecontent'] = $this->generatePDF($foa_list);
$params['attachments']['filename'] = 'MyFormsOfAssistance.pdf';
$params['attachments']['filemime'] = 'application/pdf';

```
* Tried attaching the file by path alone with an array:

```
$attachment = array(
    'filepath'=>'sites/default/files/MyFormsOfAssistance.pdf',
);

$params['attachments'] = $attachment;

```
* Tried attaching the file a different way:

```
$attachment = array(
    'filepath' => 'sites/default/files/MyFormsOfAssistance.pdf',
    'filename' => 'MyFormsOfAssistance.pdf',
    'filemime' => 'application/pdf'
);

$params['attachments'][] = $attachment;

```

## Setup

1. There is email landing page in which a user enters the recipient's email address, subject for the email, and message for the email.
2. When user clicks Send button, that data is routed to my Email Controller
3. Email controller creates the pdf file, attempts to attach the pdf to the email, and then sends the email.
4. I have the hook\_mail() function defined in my module file.

Here is the code for my Email Controller:

```
public function submit_email($foa_list = null) {
    $lang = "en";
    $email_to = "blah@blah.com";
    $params['subject'] = "Test subject";
    $params['body'] = "Test body";

    // -------------------- Attachment Logic -----------------------
    // Create pdf file and store file
    file_put_contents('sites/default/files/MyFormsOfAssistance.pdf', $this->generatePDF($foa_list));

    // Attach pdf file to email params
    $file = new \stdClass();
    $file->uri = 'sites/default/files/MyFormsOfAssistance.pdf';
    $file->filename = 'MyFormsOfAssistance.pdf';
    $file->filemime = 'application/pdf';
    $params['attachments'][] = $file;

    // Send email
    \Drupal::service('plugin.manager.mail')->mail('email', 'email', $email_to, $lang, $params);

    $response = new Response();
    $response->setContent("true");

    return $response;
}

```

Here is the hook\_mail() code in my Email module file:

```
// Note that print_and_email is what my module is called.
function print_and_email_mail($key, &$message, $params) {
    switch($key) {
        case 'email':
            $message['subject'] = $params['subject'];
            $message['body'][] = $params['body'];
            $message['headers'] = [
              'MIME-Version' => '1.0',
              'Content-Type' => 'text/html; charset=UTF-8; format=flowed; delsp=yes',
              'Content-Transfer-Encoding' => '8Bit',
              'X-Mailer' => 'Drupal',
            ];
            // $message['params']['files'][] = $params['attachments']; // Note: I have seen other examples implement attachments this way
            $message['params']['attachments'][] = $params['attachments'];
            break;
    }
}

```

The Drupal 8 documentation isn't really helpful and I would like to be able to figure this out without installing SwiftMailer, like some sources have recommended. Really not sure why this isn't working as it has worked for others. What am I missing?

# Answer
FINALLY! 4 weeks later...

So the following code ended up working for me:

```
    $attachment = array(
        'filepath' => 'sites/default/files/MyFormsOfAssistance.pdf',
        'filename' => 'MyFormsOfAssistance.pdf',
        'filemime' => 'application/pdf'
    );

```

BUT, the **key was that in the MailSystem Configuration I had to set the Formatter and Sender to "SMTP Mailer"**. MimeMail's config automatically pulled it's values from my SMTP's configuration.
> 3 votes

# Answer
Try the Email Attachment Helper module.

> This is a module for developers who want to attach files programmatically to emails send from Drupal 8. This module doesn't send emails but rather intercepts emails from other modules.
>
> If an 'attachment' or an 'attachments' key is present in the `$params` array, it will be converted into an actual MIME attachment. Otherwise, this module doesn't touch the mail.
>
> This module has no configuration options.

```
$params['context']['attachments'] = [
  'filecontent' => file_get_contents('sites/default/files/sample.pdf'),
  'filename' => 'Invoice.pdf',
  'filemime' => 'application/pdf',
];

```

Hook\_mail()

```
$context = $params['context'];
$message['params']['attachments'][] = $context['attachments'];

```
> 1 votes

# Answer
```
$invoice_pdf = File::load($fid); // the file id
$invoice_file = (object) [
  'filename' => 'invoice.pdf',
  'uri' => $invoice_pdf->getFileUri(),
  'filemime' => $invoice_pdf->getMimeType(),
];
$message['params']['files'][] = $invoice_file;

```

'files' must be an array, that's were I had the most difficulties with. Full code here: Send e-mail with managed file attachment in drupal 8
> -1 votes

---
Tags: 8, emails
---


# Question
Title: Since upgrading from 8.9.2 to 9.0.3 I cannot install custom modules
In Drupal 8.x I experimented with some modules and custom blocks, but whatever I do after upgrading to 9.0.3, the modules don't show up in the Extend menu. In the .info.yml file I changed the `core: 8.x` line to `core: 9`.

What am I doing wrong?

# Answer
Drupal 9 doesn't use the *core* key anymore. Instead, it uses the *core\_version\_requirement* key. If the module is compatible with both Drupal 8 and Drupal 9, it should use the following lines.

```
core: 8.x
core_version_requirement: ^8 || ^9

```

Notice that `core: 8.x` isn't necessary anymore for versions after Drupal 8.7.7. If the module is compatible with Drupal 8.8 and higher versions, the first line of the following code isn't necessary.

```
core: 8.x
core_version_requirement: ^8.8 || ^9

```

(To be compatible with Drupal 8.8 and higher versions, the module should not use any of the classes/methods/functions removed from Drupal 9, but this is a different story.)

### Reference
> 1 votes

---
Tags: upgrading, 9
---


# Question
Title: How can I programatically add a shipping method to a store?
I am using Commerce with Marketplace, and am using the Shipping module.

In my commerce marketplace, users become sellers via a custom form, where I create the store entity on submit. Currently, to attach a shipping method, it has to be done in commerce admin via a checkbox:

My marketplace can have an unlimited number of stores, making management of them via checkboxes unfeasible. How can I add a shipping method to a store? There's a table **commerce\_shipping\_method\__stores**:

Can I simply make an insert into this table and set the *stores\_target\_id* value to the new store id after the new store is created?

# Answer
With custom module code, you can add a new store like this:

```
function mymodule_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {

  if ($entity instanceof Drupal\commerce_store\Entity\StoreInterface) {

      $sm_id = 1; // I can see Shipping Method ID is 1 from your table screenshot
      $shipping_method = Drupal\commerce_shipping\Entity\ShippingMethod::load($sm_id);
      $store_ids = $shipping_method->getStoreIds(); // get existing IDs
      $new_store_id = $entity->id(); // get new id
      $store_ids[] = $new_store_id; // add new to existing
      $shipping_method->setStoreIds($store_ids); // set
      $shipping_method->save();

  }

}

```

In the above code, when a store is created, it automatically adds it to the shipping method.

---

But if your question is to add already existing stores to the shipping method, then run this code only once:

```
      $sm_id = 1; // I can see Shipping Method ID is 1 from your table screenshot
      $shipping_method = Drupal\commerce_shipping\Entity\ShippingMethod::load($sm_id);
      $store_ids = [1, 2, 3, 4, 5, 6]; // Array of all the store IDs that belong to this shipping method.
      $shipping_method->setStoreIds($store_ids); // set
      $shipping_method->save();

```

---

# The better API solution

Thanks to 4k4's answer I was able to commeup with a more efficient solution.

```
function mymodule_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {

  if ($entity instanceof Drupal\commerce_store\Entity\StoreInterface) {

      $sm_id = 1; // I can see Shipping Method ID is 1 from your table screenshot
      $shipping_method = Drupal\commerce_shipping\Entity\ShippingMethod::load($sm_id);
      $new_store_id = $entity->id(); // get new id
      $shipping_method->{'stores'}[] = $new_store_id; // appends new store to existing list.
      $shipping_method->save();

  }

}

```

---

# Manual Solution

> Quick follow up, do I have to load all the stores at once? **When I have** **1000+ stores** and more, that seems like it will be a little resource intensive. Is it possible to just add the new store?

At this point, you wouldn't want to use the entity API and do `Drupal\commerce_shipping\Entity\ShippingMethod::load` as this would contain all the 1000+ store IDs, you will have to manually DB query & insert:

```
function mymodule_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {

  if ($entity instanceof Drupal\commerce_store\Entity\StoreInterface) {

    $sm_id = 1; // Shipping Method ID
    $connection = \Drupal::database();

    $query = $connection->select('commerce_shipping_method__stores', 'csms');
    $query->range(0, 1)
      ->orderBy('delta', 'DESC')
      ->condition('csms.entity_id', $sm_id)
      ->addField('csms', 'delta');
    $last_delta = $query->execute()->fetchField();
    $new_delta = $last_delta + 1;
    $new_store_id = $entity->id(); // new store ID

    $insert = $connection->insert('commerce_shipping_method__stores')
      ->fields([
        'entity_id' => $sm_id,
        'stores_target_id' => $new_store_id,
        'revision_id' => $sm_id,
        'delta' => $new_delta,
        'bundle' => 'commerce_shipping_method',
        'langcode' => 'en',
      ])
      ->execute();

    $storage = \Drupal::entityTypeManager()
      ->getStorage('commerce_shipping_method');
    $storage->resetCache([$sm_id]); // Flush Cache

  }

}

```
> 2 votes

---
Tags: 8, commerce
---