title: Form elements validation order

text:
# Question
Title: Form elements validation order
I have a custom autocomplete field widget, defined like below:

```
/**
 * Implements hook_field_widget_form
 */
function mymodule_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $element += array(
    '#id' => 'mymodule-field',
    '#type' => 'textfield',
    '#default_value' => '',
    '#autocomplete_path' => 'some/path',
    '#element_validate' => array('mymodule_autocomplete_validate'),
  );
  return $element;
}

```

I have a content type with 2 `Term reference` autocomplete fields: field `foo` with standard `Autocomplete term widget (tagging)` widget, and field `bar` with my custom autocomplete widget.

Field `bar` has a higher weight than field `foo` on a node form.

`mymodule` has weight `20` in `system` table. `taxonomy` module has weight `0`.

However, when I submit a node form which includes both fields, `mymodule_autocomplete_validate()` is invoked earlier than `taxonomy_autocomplete_validate()`, so `$form_state['values']['field-myfield-a']` is not processed yet.

The problem is I need to use the processed value of `foo` in `mymodule_autocomplete_validate()`.

I have another 2 fields with same widgets but another names, and they are processed in the right order.

So the question is: how the order of execution of these functions is defined? Is there a way to change it?

# Answer
> 1 votes
Order of execution of widget validation function is handled by the first foreach loop of `_form_validate()` function.

```
function _form_validate(&$elements, &$form_state, $form_id = NULL) {
  // Also used in the installer, pre-database setup.
  $t = get_t();

  // Recurse through all children.
  foreach (element_children($elements) as $key) {
    if (isset($elements[$key]) && $elements[$key]) {
      _form_validate($elements[$key], $form_state);
    }
  }

```

It looks like field weight could be used if `element_children($elements, TRUE)` was used to retrieve the fields for its recursive `_form_validate()` call (e.g. via a core patch).

The only other alternative would be to used `hook_form_alter()` to alter the `$form` element key order (different from field weight) so that `element_children($elements)` would produce the order that you want.

# Answer
> 1 votes
hook\_module\_implements\_alter() would seem to be the one you are looking for to change execution order.

However, I'm not sure It is exactly what you are looking for because it could have to do with the node edit form. One field could be higher on that form, and that could be causing the validation order issue. The weight of the fields on the form itself could be dictating the validation order. If that is the case, you can hook into the node form and run the validation in the order needed.

# Answer
> 1 votes
You're not making an apples-to-apples comparison here. `mymodule_autocomplete_validate()` is *widget* validation function, while `taxonomy_field_validate()` is a *field* validation function.

There is a good description of the difference on the docs for `field_attach_form_validate()`:

> There are two levels of validation for fields in forms: widget validation, and field validation.
>
> * Widget validation steps are specific to a given widget's own form structure and UI metaphors. They are executed through FAPI's `#element_validate` property during normal form validation.
> * Field validation steps are common to a given field type, independently of the specific widget being used in a given form. They are defined in the field type's implementation of `hook_field_validate()`.

As such, your module & field weights are irrelevant here; `_form_validate()` processes widget validation functions before any field validation functions.

If you want a guaranteed way to validate after any field validation, just append a form validation handler in your node form:

```
/**
 * Implements hook_form_alter().
 */
function mymodule_form_alter(&$form, &$form_state, $form_id) {
  // Append a custom handler to mynodetype forms
  if ($form_id == 'mynodetype_node_form') {
    $form['#validate'][] = 'mymodule_validation_handler';
  }
}
function mymodule_validation_handler($form, &$form_state) {
  // @TODO: Handle node form validation.
}

```

This will ensure that `mymodule_validation_handler()` is executed after all widget & field validation functions.

# Answer
> 0 votes
For those interested in Drupal 9's order of form validation and want a validation function to first before all the others - to for example, change a value but still want that value validated. (and as @Shawn Conn mentioned, the #element\_validate are run first, then the top level validations are run last).

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

/**
 * Implements hook_form_alter().
 */
function mymodule_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // Append a custom handler to media_image_add_form form.
  if ($form_id == 'media_image_add_form') {
    // Get the lowest #weight -1.
    $lowest_weight = call_user_func(function($form) {
      $lowest_weight = 0;
      foreach (Element::children($form) as $key) {
        if (isset($form[$key]['#weight']) && is_numeric($form[$key]['#weight'])) {
          if ($form[$key]['#weight'] < $lowest_weight) {
            $lowest_weight = $form[$key]['#weight'];
          }
        }
      }
      return $lowest_weight - 1;
    }, $form);
    $form['custom_first_validation_element'] = [
      '#type' => 'hidden',
      '#element_validate' => ['__custom_first_validation_element__validate'],
      '#weight' => $lowest_weight,
    ];
  }
}

/**
 * Validation handler for custom_first_validation_element.
 *
 * @param array $element
 *   The element the #element_validate is on.
 * @param Drupal\Core\Form\FormStateInterface $form_state
 *   The current form state.
 * @param array $complete_form
 *   The complete form - all the elements in the form.
 */
function __custom_first_validation_element__validate(array &$element, FormStateInterface $form_state, array &$complete_form) {
  // Force a image file to be used on the media form.
  $file_id = 6;
  // These values are used if form submission is successful.
  $media_image_values = $form_state->getValue('field_media_image');
  $media_image_values[0] = [
    'fids' => [
      $file_id,
    ],
    'focal_point' => '50,50',
  ] + $media_image_values[0];
  $form_state->setValue('field_media_image', $media_image_values);
  // These are used in valdation (and shown on the form if an error).
  $complete_form['field_media_image']['widget'][0]['fids']['#value'][0] = $file_id;
  $complete_form['field_media_image']['widget'][0]['focal_point']['#value'] = '50,50';
}

```

---
Tags: 7, forms
---


# Question
Title: can I set multiple JavaScript files on a custom module library?
I created a new module and I need to add multiple JavaScript files to my pageI.

Should I create a new library for each file, or is it possible to add multiple JavaScript files on the same library as in the following library definition?

```
organigram_admin_library:
  version: 1.0
  js:
    js/admin/jquery-1.10.2.min.js: {}
    js/admin/admin.js: {}

```

# Answer
> 0 votes
Yes, you can add multiple JS and CSS files to the same library. Here is an example you can follow.

```
custom-jbox-modal:
  version: 1.x
  css:
    theme:
      '//cdn.jsdelivr.net/gh/StephanWagner/jBox@v1.3.2/dist/jBox.all.min.css': {type: external, minified: true}
  js:
    '//cdn.jsdelivr.net/gh/StephanWagner/jBox@v1.3.2/dist/jBox.all.min.js': {type: external, minified: true}
    js/jbox-custom-modal.js: {}

```

# Answer
> 0 votes
Drupal doesn't put any limit on the number of JavaScript files a library can contain. This is how the *drupal.collapse* library is defined in core.libraries.yml.

```
drupal.collapse:
  version: VERSION
  js:
    misc/details-aria.js: {}
    misc/collapse.js: {}
  dependencies:
    - core/jquery
    - core/modernizr
    - core/drupal
    - core/drupal.form
    - core/jquery.once

```

It's not a common case in Drupal core, as most of the libraries contain a single JavaScript file, and adds the other files as dependencies, but that doesn't mean a library cannot contain more than a JavaScript file.

In the case of using a jQuery file different from the one used from Drupal core, I would be careful, and first verify it doesn't create issues.

---
Tags: 8, javascript
---


# Question
Title: How to get File entity in media_presave hook?
I want to get the file entity out of an media image bundle to the get the filename to check if the image is cmyk or not.

```
/**
 * Implements hook_ENTITY_TYPE_presave().
 */
function hook_media_presave(MediaInterface $entity) {
  if ($entity->bundle() == 'image') {
    $field_definitions = $entity->getFieldDefinitions();
    foreach ($field_definitions as $field_definition) {
      if ($field_definition->getType() 'image') {
        // get File entity here.
      }
    }
  }
}

```

How do I do this?

# Answer
> 1 votes
I've found a solution.

```
/**
 * Implements hook_ENTITY_TYPE_presave().
 */
function hook_media_presave(MediaInterface $entity) {
  if ($entity->bundle() == 'image') {
    $field_definitions = $entity->getFieldDefinitions();
    foreach ($field_definitions as $field_definition) {
      if ($field_definition->getType() == 'image') {
        /** @var FieldItemListInterface $field_value */
        $field_values = $entity->get($field_definition->getName())->getValue();
        if (is_array($field_values)) {
          foreach ($field_values as $field_value) {
            if ($field_value['target_id']) {
              /** @var File $file */
              $file = File::load($field_value['target_id']);
              $image = getimagesize($file->getFileUri());
              // If the image has channels '4' it is cmyk.
              if ($image['channels'] == '4') {
                $imagick = new Imagick($file->getFileUri());
                $imagick->setImageColorspace(Imagick::COLORSPACE_RGB);
                $imagick->writeImage($image);
                $imagick->destroy();
              }
            }
          }
        }
      }
    }
  }
}

```

# Answer
> 1 votes
To set the image alt text as name.

```
use Drupal\media\MediaInterface;

/**
 * Implements hook_ENTITY_TYPE_presave().
 */
function MODULE_NAME_media_presave(MediaInterface $entity) {
  if ($entity->bundle() == 'image' && $entity->hasField('image') && !$entity->get('image')->isEmpty()) {
    $image = $entity->get("image")->getValue();
    if (empty($image[0]['alt'])) {
      $image[0]['alt'] = $entity->get('name')->value;
      $entity->set('image', $image);
    }
  }
}

```

---
Tags: 8, files, media
---


title: How do I print the display name?

text:
# Question
Title: How do I print the display name?
I have a view with multiple pages. In the Views interface, I can set a display name for each display.

>

Is there anyway I can print this name in the view itself, for example adding a *Global Text* field to the views header?

# Answer
> 0 votes
In Drupal 7, the "Global: Result summary" field in Views header gives you a few tokens to get access to some of the view information (e.g. it has a token named `@name -- the human-readable name of the view`  to print the View name).

For fetching the View display name, though, you need to create a custom Views handler to define your own tokens:

* Create a new module. In your `my_module_name.info` file, add the lines :

```
    dependencies[] = views

    files[] = handlers/views_handler_my_custom_handler.inc

```
* In your `my_module.module` file, add a hook\_views\_data():

```
    function my_module_views_data() {
        // Definition of your custom handler
        $data['views']['my_module_custom_handler'] = array(
            'title' => t('My custom handler'),
            'help' => t('Custom tokens to access View information'),
            'area' => array(
                'handler' => 'views_handler_my_custom_handler',
            ),
        );
        return $data;
    }

```
* Finally, create the `handlers/views_handler_my_custom_handler.inc` file. The most basic content based on your needs would be something like:

```

/**
 * @file
 * Definition of views_handler_area.
 */

/**
 * Views area handler to display some configurable result summary.
 *
 * @ingroup views_area_handlers
 */
class views_handler_my_custom_handler extends views_handler_area {

    function option_definition() {
        $options = parent::option_definition();
        $options['content'] = array(
            'default' => 'Displaying view tokens',
            'translatable' => TRUE,
        );
        return $options;
    }

    function options_form(&$form, &$form_state) {
        parent::options_form($form, $form_state);

        $variables = array(
            'items' => array(
                '@display_name -- the name of the View display'
            ),
        );
        $list = theme('item_list', $variables);
        $form['content'] = array(
            '#title' => t('Display'),
            '#type' => 'textarea',
            '#rows' => 3,
            '#default_value' => $this->options['content'],
            '#description' => t('You may use HTML code in this field. The following tokens are supported:') . $list,
        );
    }

    /**
     * Find out the information to render.
     */
    function render($empty = FALSE) {
        $format = $this->options['content'];
        // Replace "@display_name" with view current display value
        $output = filter_xss_admin(str_replace("@display_name", $this->view->current_display, $format));
        return $output;
    }

```

That's it. Your custom views handler should now be available in any View.

I recommend you to have a look at view\_handler\_area\_result.inc file (code for "Global: Result summary" field) in Views module if you wish to extend it to have its tokens available in your custom handler.

---
Tags: 7, views
---


# Question
Title: "PHP Notice: Constant DATE_RFC7231 already defined in /ext/vhosts/public/includes/bootstrap.inc on line 258"
After moving my Drupal site to a new host, I got the following error in the error logs.

> \[error\] 8707#0: \*1 FastCGI sent in stderr: "PHP message: PHP Notice: Constant DATE\_RFC7231 already defined in /ext/vhosts/public/includes/bootstrap.inc on line 258

How can I fix it?

My site currently says "The website encountered an unexpected error. Please try again later"

My setup is as follows:

* Debian 8
* PHP 7.0.21
* MySQL 5.6
* Drupal 7.54

# Answer
> 2 votes
Are you *certain* you're running PHP 5 and not a version of PHP 7? I've only ever seen that error when running PHP 7, and it was due to DATE\_RFC7231 already defined in PHP 7.0.19 and 7.1.5.

Either way, the patches in that issue were committed and released with 7.55, so it might be worth trying a core update before anything else.

# Answer
> 0 votes
I solved following this tutorial:
https://webocreation.com/blog/notice-constant-date\_rfc7231-already-defined-in-includes-bootstrap-inc-on-line-258/

Open **/includes/bootstrap.inc**
Go to line number 258
Comment out the following line:

```
//define(‘DATE_RFC7231’, ‘D, d M Y H:i:s \G\M\T’);

```

Then add following line:

```
if (!defined(‘DATE_RFC7231’)) {
define(‘DATE_RFC7231’, ‘D, d M Y H:i:s \G\M\T’);
}

```

---
Tags: 7, debugging
---


# Question
Title: Remove All Unwanted js and css files from theme
I create a website based on Drupal. When I look at the JavaScript and CSS files loaded from Drupal, I see many unwanted files loaded. I want to force Drupal to load only those files added to the .info file and remove everything else. I think I can achieve it by using `hook_js_alter()` but I want to know if there is a better solution.

# Answer
Drupal only has one sanctioned mechanism for removing specific assets, regardless of the motivation for doing so.

For CSS:

`hook_css_alter`

For JS:

`hook_js_alter`

**To remove all style and scripts except `.info` style and script use below codes:**

```
function hook_css_alter(&$css) {
    $themes=list_themes();
          foreach($css as $key=>$item) {
            if (!in_array($key, $themes['yourthemename']->stylesheets['all'])) {
                unset($css[$key]);
            }
        }
}

function hook_js_alter(&$js) {
    $themes=list_themes();
    foreach($js as $key=>$item) {
        if (!in_array($key, $themes['yourthemename']->scripts)) {
            unset($js[$key]);
        }
    }
}

```

If the theme/module is custom, then obviously you can just remove the offending code manually if that makes more sense.
> 6 votes

# Answer
This code works for removing the CSS from frontend:

```
libraries-override:
  system/base: false

```

Just use the above in yourtheme.info.yml
> 0 votes

---
Tags: 7, theming, javascript
---


# Question
Title: Views showing quizzes and content sharing taxonomy term
I have a Drupal 9 site, with a lot of quizzes and content pages. Both have the same vocabulary attached (Category), and want to create a view showing all quizzes and nodes sharing same category.

Is that possible, or is it better to create a custom page and do the magic my self ?

# Answer
You can achieve this by creating using views. Create a view with view settings set to `taxonomy`. Go to relationship and add the taxonomy field that is added to your node. Add another field in the relationship `Taxonomy term referenced from your-taxonomy-field` and select relationship from dropdown.

Add title and taxonomy name in the field and you can group using format settings, selecting the field you want to group.
> 2 votes

---
Tags: views
---


# Question
Title: The website encountered an unexpected error. Please try again later. as shown in body
I tried to set up my drupal 8 full project on localhost but after set up when I run project getting error as shown below:-

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

Drupal\Component\Plugin\Exception\PluginNotFoundException: The "node" entity type does not exist. in Drupal\Core\Entity\EntityTypeManager-\>getDefinition() (line 150 of core\lib\Drupal\Core\Entity\EntityTypeManager.php). Drupal\Core\Entity\EntityTypeManager-\>getHandler('node', 'storage') (Line: 208) Drupal\Core\Entity\EntityTypeManager-\>getStorage('node') (Line: 187) Drupal\Core\Entity\EntityRepository-\>getCanonicalMultiple('node', Array, Array) (Line: 180) Drupal\Core\Entity\EntityRepository-\>getCanonical('node', '1', Array) (Line: 149) Drupal\Core\ParamConverter\EntityConverter-\>convert('1', Array, 'node', Array) (Line: 100) Drupal\Core\ParamConverter\ParamConverterManager-\>convert(Array) (Line: 45) Drupal\Core\Routing\Enhancer\ParamConversionEnhancer-\>enhance(Array, Object) (Line: 260) Drupal\Core\Routing\Router-\>applyRouteEnhancers(Array, Object) (Line: 131) Drupal\Core\Routing\Router-\>matchRequest(Object) (Line: 92) Drupal\Core\Routing\AccessAwareRouter-\>matchRequest(Object) (Line: 113) Symfony\Component\HttpKernel\EventListener\RouterListener-\>onKernelRequest(Object, 'kernel.request', Object) call\_user\_func(Array, Object, 'kernel.request', Object) (Line: 111) Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher-\>dispatch('kernel.request', Object) (Line: 127) Symfony\Component\HttpKernel\HttpKernel-\>handleRaw(Object, 1) (Line: 68) Symfony\Component\HttpKernel\HttpKernel-\>handle(Object, 1, 1) (Line: 57) Drupal\Core\StackMiddleware\Session-\>handle(Object, 1, 1) (Line: 47) Drupal\Core\StackMiddleware\KernelPreHandle-\>handle(Object, 1, 1) (Line: 47) Drupal\Core\StackMiddleware\ReverseProxyMiddleware-\>handle(Object, 1, 1) (Line: 52) Drupal\Core\StackMiddleware\NegotiationMiddleware-\>handle(Object, 1, 1) (Line: 23) Stack\StackedHttpKernel-\>handle(Object, 1, 1) (Line: 708) Drupal\Core\DrupalKernel-\>handle(Object) (Line: 20)

# Answer
If the "node" entity type does not exist, you have a fundamentally broken installation, but it's not possible to say exactly how it's broken based on the information given.

There are a couple things I would inspect at this point:

* Is your local database complete? Did the import perhaps fail?
* Is the cache out-of-date? Try truncating every database table with a name that starts with `cache_`, or if you have Drush, running `drush cr`
> 2 votes

---
Tags: nodes, migrations
---


# Question
Title: Is it possible to use libraries-extend from a module (instead of theme)?
**Problem/Motivation**

I'm interested in altering/overriding the little bit of HTML markup that's output by core, in my case `Drupal.theme.mediaEmbedEditButton` (from `core/modules/media/js/media_embed_ckeditor.theme.js`), but without hacking core, of course. It seems I could do this in a custom theme by adding:

```
libraries-extend:
  media/media_embed_ckeditor_theme:
    - my_theme/my_library

```

(plus the info for `my_library` in `my_theme.libraries.yml`, and the JS file in my theme with the function that would return the new markup).

However, since this shows up in places like /node/add/page that only uses the admin theme (we're using Seven), such additions to `my_theme` wouldn't apply. While it seems like I could make a bare-bones `my_admin_theme`, pulling in Seven as base, I'd like to keep this override near other related customizations in a custom module (I also ran into other cans of worms when I tried this as a proof of concept).

**What (else) I've tried**

I tried putting in `libraries-extend:` from above in `my_module.info.yml` (plus the addition to `my_module.libraries.yml` and the new JS, of course), but this didn't seem to work (kinda not surprising, since the docs I'm finding only seem to reference `libraries-extend` in the same breath as themes). I also tried using `hook_field_widget_form_alter()` in `my_module.module` to attach my override library via `$element['#attached']['library'][]` but didn't have luck there either.

Am I stuck with with making a custom admin theme if I want to use `libraries-extend`? (I'm guessing this is also a problem for `libraries-override`.) Or am I missing some hook or something I could instead add to my custom module to accomplish overriding the output made by `Drupal.theme.mediaEmbedEditButton`?

# Answer
It's not possible, read this: https://www.oreilly.com/library/view/drupal-8-development/9781788290401/080b0131-1b64-4900-8535-55c82dba4200.xhtml

> # Manipulating libraries from hooks
>
> Modules have the ability to provide dynamic library definitions and alter libraries. A module can use the `hook_library_info()` hook to provide a library definition. This is not the recommended way to define a library, but it is provided for edge use cases.
>
> Modules do not have the ability to use `libraries-override` or `libraries-extend`, and need to rely on the `hook_library_info_alter()` hook. You can check out this hook in `core/lib/Drupal/Core/Render/theme.api.php` or at https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api.php/function/hook\_library\_info\_alter/8.
>
> source: **Drupal 8 Development Cookbook - Second Edition** by Matt Glaman
> 3 votes

---
Tags: 8, theming, media, .info
---


# Question
Title: Trouble with the upgrade of core 8.9 to 9.2
We are in the process of migrating to Drupal 9, and I am having nothing but problems with composer and trying to get Drupal core updated.

I have provided my composer.json file, and a HUGE list of errors it's spitting out at me, and I have absolutely no idea how to fix it.

The command I have been running is `composer update`

```

Gathering patches for root package.
No patches supplied.
Loading composer repositories with package information
Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - drupal/core 8.0.0-beta6 requires doctrine/common dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5 -> no matching package found.
    - remove drupal/admin_menu 3.x-dev|keep drupal/admin_menu dev-3.x
    - Conclusion: remove drupal/admin_menu dev-3.x
    - drupal/core-recommended 9.2.6 requires drupal/core 9.2.6 -> satisfiable by drupal/core[9.2.6].
    - Conclusion: don't install drupal/core 9.2.6
    - drupal/core-recommended 9.2.5 requires drupal/core 9.2.5 -> satisfiable by drupal/core[9.2.5].
    - Conclusion: don't install drupal/core 9.2.5
    - drupal/core-recommended 9.2.4 requires drupal/core 9.2.4 -> satisfiable by drupal/core[9.2.4].
    - Conclusion: don't install drupal/core 9.2.4
    - drupal/core-recommended 9.2.3 requires drupal/core 9.2.3 -> satisfiable by drupal/core[9.2.3].
    - Conclusion: don't install drupal/core 9.2.3
    - drupal/core-recommended 9.2.2 requires drupal/core 9.2.2 -> satisfiable by drupal/core[9.2.2].
    - Conclusion: don't install drupal/core 9.2.2
    - drupal/core-recommended 9.2.1 requires drupal/core 9.2.1 -> satisfiable by drupal/core[9.2.1].
    - Conclusion: don't install drupal/core 9.2.1
    - drupal/core-recommended 9.2.0 requires drupal/core 9.2.0 -> satisfiable by drupal/core[9.2.0].
    - Conclusion: don't install drupal/core 9.2.0
    - drupal/core-recommended 9.2.0-rc1 requires drupal/core 9.2.0-rc1 -> satisfiable by drupal/core[9.2.0-rc1].
    - Conclusion: don't install drupal/core 9.2.0-rc1
    - drupal/core-recommended 9.2.0-beta3 requires drupal/core 9.2.0-beta3 -> satisfiable by drupal/core[9.2.0-beta3].
    - Conclusion: don't install drupal/core 9.2.0-beta3
    - drupal/core-recommended 9.2.0-beta2 requires drupal/core 9.2.0-beta2 -> satisfiable by drupal/core[9.2.0-beta2].
    - Conclusion: don't install drupal/core 9.2.0-beta2
    - drupal/core-recommended 9.2.0-beta1 requires drupal/core 9.2.0-beta1 -> satisfiable by drupal/core[9.2.0-beta1].
    - Conclusion: don't install drupal/core 9.2.0-beta1
    - drupal/core-recommended 9.2.0-alpha1 requires drupal/core 9.2.0-alpha1 -> satisfiable by drupal/core[9.2.0-alpha1].
    - Conclusion: don't install drupal/core 9.2.0-alpha1
    - Installation request for drupal/admin_menu 3.x-dev -> satisfiable by drupal/admin_menu[3.x-dev].
    - drupal/core-recommended 9.3.x-dev requires drupal/core 9.3.x-dev -> satisfiable by drupal/core[9.3.x-dev].
    - Conclusion: don't install drupal/core 9.3.x-dev
    - drupal/admin_menu 3.x-dev requires drupal/core ~8.0 -> satisfiable by drupal/core[8.9.17, 8.0.0, 8.0.0-beta10, 8.0.0-beta11, 8.0.0-beta12, 8.0.0-beta13, 8.0.0-beta14, 8.0.0-beta15, 8.0.0-beta16, 8.0.0-beta6, 8.0.0-beta7, 8.0.0-beta8, 8.0.0-beta9, 8.0.0-rc1, 8.0.0-rc2, 8.0.0-rc3, 8.0.0-rc4, 8.0.1, 8.0.2, 8.0.3, 8.0.4, 8.0.5, 8.0.6, 8.0.x-dev, 8.1.0, 8.1.0-beta1, 8.1.0-beta2, 8.1.0-rc1, 8.1.1, 8.1.10, 8.1.2, 8.1.3, 8.1.4, 8.1.5, 8.1.6, 8.1.7, 8.1.8, 8.1.9, 8.1.x-dev, 8.2.0, 8.2.0-beta1, 8.2.0-beta2, 8.2.0-beta3, 8.2.0-rc1, 8.2.0-rc2, 8.2.1, 8.2.2, 8.2.3, 8.2.4, 8.2.5, 8.2.6, 8.2.7, 8.2.8, 8.2.x-dev, 8.3.0, 8.3.0-alpha1, 8.3.0-beta1, 8.3.0-rc1, 8.3.0-rc2, 8.3.1, 8.3.2, 8.3.3, 8.3.4, 8.3.5, 8.3.6, 8.3.7, 8.3.8, 8.3.9, 8.3.x-dev, 8.4.0, 8.4.0-alpha1, 8.4.0-beta1, 8.4.0-rc1, 8.4.0-rc2, 8.4.1, 8.4.2, 8.4.3, 8.4.4, 8.4.5, 8.4.6, 8.4.7, 8.4.8, 8.4.x-dev, 8.5.0, 8.5.0-alpha1, 8.5.0-beta1, 8.5.0-rc1, 8.5.1, 8.5.10, 8.5.11, 8.5.12, 8.5.13, 8.5.14, 8.5.15, 8.5.2, 8.5.3, 8.5.4, 8.5.5, 8.5.6, 8.5.7, 8.5.8, 8.5.9, 8.5.x-dev, 8.6.0, 8.6.0-alpha1, 8.6.0-beta1, 8.6.0-beta2, 8.6.0-rc1, 8.6.1, 8.6.10, 8.6.11, 8.6.12, 8.6.13, 8.6.14, 8.6.15, 8.6.16, 8.6.17, 8.6.18, 8.6.2, 8.6.3, 8.6.4, 8.6.5, 8.6.6, 8.6.7, 8.6.8, 8.6.9, 8.7.0, 8.7.0-alpha1, 8.7.0-alpha2, 8.7.0-beta1, 8.7.0-beta2, 8.7.0-rc1, 8.7.1, 8.7.10, 8.7.11, 8.7.12, 8.7.13, 8.7.14, 8.7.2, 8.7.3, 8.7.4, 8.7.5, 8.7.6, 8.7.7, 8.7.8, 8.7.9, 8.7.x-dev, 8.8.0, 8.8.0-alpha1, 8.8.0-beta1, 8.8.0-rc1, 8.8.1, 8.8.10, 8.8.11, 8.8.12, 8.8.2, 8.8.3, 8.8.4, 8.8.5, 8.8.6, 8.8.7, 8.8.8, 8.8.9, 8.8.x-dev, 8.9.0, 8.9.0-beta1, 8.9.0-beta2, 8.9.0-beta3, 8.9.0-rc1, 8.9.1, 8.9.10, 8.9.11, 8.9.12, 8.9.13, 8.9.14, 8.9.15, 8.9.16, 8.9.18, 8.9.19, 8.9.2, 8.9.3, 8.9.4, 8.9.5, 8.9.6, 8.9.7, 8.9.8, 8.9.9, 8.9.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.0-beta1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.0-beta2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.0-beta3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.10].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.11].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.12].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.13].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.14].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.15].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.16].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.17].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.18].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.19].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.9].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta10].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta11].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta12].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta13].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta14].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta15].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta16].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-beta9].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-rc2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-rc3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.0-rc4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.0.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.0-beta1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.0-beta2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.10].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.9].
    - Can only install one of: drupal/core[9.2.x-dev, 8.1.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.0-beta1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.0-beta2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.0-beta3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.0-rc2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.2.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.0-alpha1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.0-beta1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.0-rc2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.9].
    - Can only install one of: drupal/core[9.2.x-dev, 8.3.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.0-alpha1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.0-beta1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.0-rc2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.4.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.0-alpha1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.0-beta1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.10].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.11].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.12].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.13].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.14].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.15].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.9].
    - Can only install one of: drupal/core[9.2.x-dev, 8.5.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.0-alpha1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.0-beta1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.0-beta2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.10].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.11].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.12].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.13].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.14].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.15].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.16].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.17].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.18].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.6.9].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.0-alpha1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.0-alpha2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.0-beta1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.0-beta2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.10].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.11].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.12].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.13].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.14].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.9].
    - Can only install one of: drupal/core[9.2.x-dev, 8.7.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.0].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.0-alpha1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.0-beta1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.0-rc1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.1].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.10].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.11].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.12].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.2].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.3].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.4].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.5].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.6].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.7].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.8].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.9].
    - Can only install one of: drupal/core[9.2.x-dev, 8.8.x-dev].
    - Can only install one of: drupal/core[9.2.x-dev, 8.9.17].
    - drupal/core-recommended 9.2.x-dev requires drupal/core 9.2.x-dev -> satisfiable by drupal/core[9.2.x-dev].
    - Installation request for drupal/core-recommended ^9.2.0 -> satisfiable by drupal/core-recommended[9.2.0, 9.2.0-alpha1, 9.2.0-beta1, 9.2.0-beta2, 9.2.0-beta3, 9.2.0-rc1, 9.2.1, 9.2.2, 9.2.3, 9.2.4, 9.2.5, 9.2.6, 9.2.x-dev, 9.3.x-dev].

Potential causes:
 - A typo in the package name
 - The package is not available in a stable-enough version according to your minimum-stability setting
   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.
 - It's a private package and you forgot to add a custom repository to find it

Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.

```

and my composer.json

```
{
  "name": "acquia/drupal-minimal-project",
  "description": "Minimal Acquia-compatible Drupal application based on the Drupal Recommended Project",
  "license": "GPL-2.0-or-later",
  "authors": [
    {
      "name": "Acquia Engineering",
      "homepage": "https://www.acquia.com",
      "role": "Maintainer"
    }
  ],
  "repositories": {
    "drupal": {
      "type": "composer",
      "url": "https://packages.drupal.org/8"
    }
  },
  "require": {
    "composer/installers": "^1.9",
    "cweagans/composer-patches": "^1.6",
    "dompdf/dompdf": "^1.0",
    "drupal/acquia_connector": "^3.0",
    "drupal/admin_menu": "3.x-dev",
    "drupal/admin_toolbar": "^3.0",
    "drupal/autologout": "^1.3",
    "drupal/better_exposed_filters": "^5.0@beta",
    "drupal/block_exclude_pages": "^2.0",
    "drupal/bootstrap4": "^2.1",
    "drupal/config_devel": "^1.8",
    "drupal/config_distro": "^1.0@alpha",
    "drupal/config_distro_filter": "^1.0@alpha",
    "drupal/config_filter": "2.2.0",
    "drupal/config_ignore": "^2.3",
    "drupal/config_merge": "^1.0@RC",
    "drupal/config_normalizer": "^1.0@alpha",
    "drupal/config_provider": "^2.0@RC",
    "drupal/config_snapshot": "^1.0@RC",
    "drupal/config_split": "^2.0",
    "drupal/config_sync": "^2.0@beta",
    "drupal/config_update": "^1.7",
    "drupal/console": "^1.9",
    "drupal/content_sync": "^2.1",
    "drupal/core-composer-scaffold": "^9.2.0",
    "drupal/core-project-message": "^9.2.0",
    "drupal/core-recommended": "^9.2.0",
    "drupal/custom_add_another": "^1.0@beta",
    "drupal/devel": "^4.1",
    "drupal/externalauth": "^1.4",
    "drupal/fast_404": "^2.0@alpha",
    "drupal/field_group": "^3.1",
    "drupal/fontawesome": "^2.19",
    "drupal/httpswww": "^2.0",
    "drupal/jquery_ui_accordion": "^1.1",
    "drupal/memcache": "^2.3",
    "drupal/multiple_fields_remove_button": "^1.0@alpha",
    "drupal/paragraphs": "^1.12",
    "drupal/password_policy": "^3.0",
    "drupal/select_or_other": "^1.0@alpha",
    "drupal/shield": "^1.4",
    "drupal/simplesamlphp_auth": "^3.2",
    "drupal/siteimprove": "^1.11",
    "drupal/theme_switcher": "^1.2",
    "drupal/toolbar_anti_flicker": "^9.3",
    "drupal/toolbar_menu": "^2.2",
    "drupal/twig_tweak": "^2",
    "drupal/views_bulk_operations": "^4.0",
    "drupal/views_conditional": "^1.4",
    "drupal/views_data_export": "^1.0",
    "drush/drush": "^10.5",
    "picqer/php-barcode-generator": "^2.2",
    "scriptotek/google-books": "^0.2.5",
    "tecnickcom/tcpdf": "^6.4",
    "zaporylie/composer-drupal-optimizations": "^1.2"
  },
  "minimum-stability": "dev",
  "prefer-stable": true,
  "config": {
    "sort-packages": true
  },
  "extra": {
    "drupal-scaffold": {
      "locations": {
        "web-root": "docroot/"
      },
      "file-mapping": {
        "[web-root]/sites/default/default.services.yml": {
          "mode": "replace",
          "path": "docroot/core/assets/scaffold/files/default.services.yml",
          "overwrite": false
        },
        "[web-root]/sites/default/default.settings.php": {
          "mode": "replace",
          "path": "docroot/core/assets/scaffold/files/default.settings.php",
          "overwrite": false
        }
      },
      "gitignore": true
    },
    "installer-paths": {
      "docroot/core": [
        "type:drupal-core"
      ],
      "docroot/libraries/{$name}": [
        "type:drupal-library"
      ],
      "docroot/modules/contrib/{$name}": [
        "type:drupal-module"
      ],
      "docroot/profiles/contrib/{$name}": [
        "type:drupal-profile"
      ],
      "docroot/themes/contrib/{$name}": [
        "type:drupal-theme"
      ],
      "drush/Commands/contrib/{$name}": [
        "type:drupal-drush"
      ],
      "docroot/modules/custom/{$name}": [
        "type:drupal-custom-module"
      ],
      "docroot/themes/custom/{$name}": [
        "type:drupal-custom-theme"
      ]
    },
    "enable-patching": true,
    "patchLevel": {
      "drupal/core": "-p2"
    },
    "patches": {}
  },
  "require-dev": {
    "drupal/core-dev": "^9.2.0"
  }
}

```

Is there anybody that can assist me with this?

Please and thank you.

# Answer
> 1 votes
You may have heard that upgrading from Drupal 8 to Drupal 9 is the easiest Drupal core upgrade yet (and that is true!) but there are still a few steps to upgrading.

Hopefully, you are using `git` or another form of version control, because you should start by rolling back your site to the last stable state, when you were running Drupal 8. Then you can address some prerequisites, and run some tests, before upgrading to Drupal 9.

You are still using Composer 1. You should start the upgrade by preparing your site for Composer 2. (There's a lot of info at the linked page. Usually, link-only answers are frowned upon, but it's beyond the scope of this answer to include all that info here. Besides, it's part of the official Drupal documentation on Drupal.org, so I think that's fair game for linking, unlike a blog post that might disappear.)

Once you have that straightened out, make certain that you have upgraded Drupal core and contributed modules to the very latest versions available, and then install the Upgrade Status module to test your site for Drupal 9 readiness. If it detects any problems, you'll need to fix them before upgrading.

Here's a link to the official Drupal docs on Upgrading a Drupal 8 site to Drupal 9:

> Short summary
>
> 1. Ensure your hosting environment matches the platform requirements of Drupal 9.
> 2. Update to Drupal 8.8.x or 8.9.x (if not already on that version)
> 3. Update all contributed projects and ensure they are Drupal 9 compatible
> 4. Make custom code Drupal 9 compatible
> 5. Update core codebase to Drupal 9
> 6. Run update.php
>
> If you're looking for step by step directions, you'll find more details in the upgrading section.

After you have followed all these steps, come back and update your question if you are still seeing a Composer-related error.

**LATER:**

OK, I'll take your word for it that you have followed all the prerequisites above.

My hunch is that you are having trouble upgrading because you are using the `acquia/drupal-minimal-project`, but I can't be sure.

Please create a new Drupal 8.9 project:

```
composer create-project drupal/recommended-project:^8.9 $SITE_NAME

```

Substitute your desired project name for `$SITE_NAME`.

Then use `composer require` to add all the packages from your `composer.json` (there are not too many, so it should not take too long.) If you have any custom modules and themes in your site, move them into the new 8.9 site at this time.

Since your site is hosted on Acquia, the one change you should make from the `recommended-project` is to change the docroot directory from `web` to `docroot`:

```
        "drupal-scaffold": {
            "locations": {
                "web-root": "docroot/"
            }
        },
        "installer-paths": {
            "docroot/core": [
                "type:drupal-core"
            ],
            "docroot/libraries/{$name}": [
                "type:drupal-library"
            ],
            "docroot/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "docroot/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "docroot/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ],
            "docroot/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "docroot/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ]
        },

```

Then import the database from your site into the new 8.9 site and make sure that it runs as expected. (If you are using something like Lando, DDEV, or Docksal, this should be pretty easy. Actually I recommend setting up Lando with the new Acquia recipe, which is pretty sweet.)

After that, you should be able to complete the Drupal 9 upgrade by following the instructions I linked to above:

https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-to-drupal-9-or-later#s-upgrading-a-composer-based-drupal-8-site

Note: this is not as simple as manually updating a `composer.json` file and running `composer update`. In particular:

> Temporarily add write access to protected files and directories:
>
> ```
> chmod 777 web/sites/default
> chmod 666 web/sites/default/*settings.php
> chmod 666 web/sites/default/*services.yml
>
> ```
>
> Next, you'll need to pull in both the Drupal 9 version of core-recommended and dev-dependencies packages as dependencies. We use `--no-update` to avoid a chicken-and-egg problem with mutual dependencies:
>
> ```
> composer require 'drupal/core-recommended:^9' 'drupal/core-composer-scaffold:^9' 'drupal/core-project-message:^9' --update-with-dependencies --no-update
>
> ```
>
> If you have drupal/core-dev installed:
>
> ```
> composer require 'drupal/core-dev:^9' --dev --update-with-dependencies --no-update
>
> ```
>
> Now, actually perform the update to the code itself:
>
> ```
> composer update
>
> ```

That's all the advice I have! Good luck!

---
Tags: composer, 9, upgrading
---


# Question
Title: error The website encountered an unexpected error. Please try again later
The website encountered an unexpected error. Please try again later. My drupal version is 9.2.5. How to open dev mode

# Answer
> 2 votes
To show all error messages with backtrace information, update `<drupal_root>/sites/default/settings.php`. Change the following line to `verbose`

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

```

Remember to change it back for production.

---
Tags: 9
---


# Question
Title: Render custom field from user registration form
I'm trying to render a custom field that shows up on the user registration form on a separate new form that creates users of a particular role with specific permissions.

I have everything working except being able to render this custom field.

When I view the field under the user registration form settings page, it says it's an entity reference field. When it renders it has 4 check boxes.

I've figured out how to kint out the fields that are on the user registration form from my new form, but I can't figure out how to render the specific one that I need.

```
$entityTypeManager = \Drupal::service('entity_field.manager');
$fields = $entityTypeManager->getFieldDefinitions('user', 'user');

foreach ($fields as $field_name) {
  kint($field_name);
}

```

That gives me a listing of all of the fields in the user registration.

I feel like I'm missing something very obvious.

# Answer
A form mode is configuration which you can roll out via CMI (drush cex/cim) or install with the module by including the YAML files in the modules config folder.

Implementing a new register form mode is not very intuitive. The basics:

1. Create the form mode:

```
/admin/structure/display-modes/form

```
2. Enable and configure it like in this questions for the pre-installed *Register* form mode:

How to hide custom fields on the registration form?
3. To place the new form mode on a page you need either a contrib module

https://www.drupal.org/project/form\_mode\_manager

or custom code:

How do I load a form with a specific form display (form mode)?

or a custom route:

*mymodule.routing.yml*

```
mymodule.register2:
  path: '/admin/people/ch-create'
  defaults:
    _entity_form: 'user.register2'
    _title: 'Create new account'
  requirements:
    _permission: 'register certain users'

```

`register2` needs to be registered as form handler in the entity type:

*mymodule.module*

```
function mymodule_entity_type_build(array &$entity_types) {
  $entity_types['user']->setFormClass('register2', 'Drupal\user\RegisterForm');
}

```
> 2 votes

---
Tags: 8, forms
---


title: How can I bulk delete users?

text:
# Question
Title: How can I bulk delete users?
My site got hacked and I had an online service clean it out. However, it now has over 150,000 user accounts, the bulk of which have no role assignment. How do I delete these accounts and their content?

PS: Drush solutions are appreciated and welcome, but for now I would prefer non-Drush answers.

I tried suggestion 1 at How to delete 'blocked' users in bulk? but both options are time consuming and the VBO module seemed to hang. Suggestion 2 seems to be the fastest option, but the */core/modules/user/user.admin.inc* file doesn't exist in Drupal 8.7.

# Answer
I just had to do this recently. I found the easiest thing was to build a list of the emails addresses to remove in a text file.

**\_remove\_user\_emails.txt**

```
test1@test.com
test2@test.com
test3@test.com

```

Then process them with the simple script below:

**remove\_users.sh**

```
IFS="
"
pwd
for user in `cat _remove_user_emails.txt`
do
  echo "Cancelling user: $user"
  ./vendor/bin/drush -y user-cancel ${user}
done

```

You can derive your list however you'd like. I often use phpmyadmin and just write a query for what I need and export it. Something like this:

```
SELECT DISTINCT u.mail
FROM users u
LEFT JOIN users_roles ur on u.uid = ur.uid
WHERE u.uid > 1
AND u.status <> 0
AND ur.rid IS NULL

```
> 4 votes

---
Tags: 8, users
---


title: Best upgrade path?

text:
# Question
Title: Best upgrade path?
One of my Drupal sites has been languishing on Drupal 5.

It has a lot of content, so I can't just start from scratch. I'm considering to finally upgrade it to Drupal 9.

What would be the best and easiest path to getting all caught up?

Should I make a clone of my most recent 5 on a development machine, then install each of the next version using its upgrade method?

Can I just install Drupal 9 over my ancient Drupal 5 site on the development machine, and hammer through all of the errors until I (hopefully) get them all sorted out?

Is there a much better way?

# Answer
> 1 votes
5 is so old I would treat it as "migrating from a generic website to Drupal 9."

I would try to approach this using the Feeds module, which allows you to import content from one site into another.

There was no version of Feeds for Drupal 5 (started with 6), but you should be able to find some way to export the content with Views in 5 (perhaps to CSV?) and then you can import it with Feeds.

Feeds has great support for the "core" Drupal entities-- users, nodes, taxonomy terms. But, I'm not sure about "forum posts"-- the forum module has been a bit neglected compared to other modules, so this may be a pain point (or it may magically work-- no need to be unnecessarily negative). So if you do decide to go the Feeds route, I would test something relatively easy (users) and then test the forum posts next to evaluate the difficulty of the upgrade.

# Answer
> 0 votes
No matter what you do, you're going to have to do a lot of work. Going forward, Drupal has changed the way major upgrades are done so from now on instead of major efforts to go from D5 to D6 to D7 etc. there should be only a small amount of ongoing work necessary to keep your site up-to-date. But you have to get to at least D8 to take advantage of that ...

Using Migrate to go from Drupal 6 to Drupal 8/9 is pretty well documented, and the problems you will encounter are mostly known and also documented. But this Migrate process doesn't work for Drupal 5, so I suggest trying to update from D5 to D6 first. This is also a pretty simple process. See for example Upgrading from Drupal 5.x to Drupal 6.x - Tutorial

How well this all works out will depend on a lot of things specific to your site, mostly whether the contributed modules you rely on have been ported to D6/D9 and whether they support Migrate for going from D6 to D9. Another problem is going to be your theme - theming has changed substantially between D5 and D9 so you might have to do a lot of work to get the look you want. You will not be able to keep the same look as you have now, but that's probably a good thing because D5 sites look really dated.

If your main goal is to preserve your content, then I think your chances of success are much better if you stay with Drupal than if you try to move to some other CMS / software because even though D9 is quite different from D5, the jump is less than the difference between Drupal and WordPress.

---
Tags: migrations, 9, upgrading
---


# Question
Title: How to solve “Query failed” error in drush sql-sync output 2?
I have the exact same problem as in How to solve "Query failed" error in drush sql-sync output?, exact same output. That user found the answer as the password in settings.php was wrong, but my password is correct and it still doesn't work. Can anyone please help?

```
drush sql-query --strict=0 --file=/tmp/mob_20191203_224013.sql.gz --file-delete --uri=mob --root=/home/fc/1/de/mob/web -vvv
 [preflight] Config paths: /home/fc/1/de/mob/vendor/drush/drush/drush.yml,/home/fc/1/de/mob/drush/drush.yml
 [preflight] Alias paths: /home/fc/1/de/mob/web/drush/sites,/home/fc/1/de/mob/drush/sites
 [preflight] Commandfile search paths: /home/fc/1/de/mob/vendor/drush/drush/src,/home/fc/1/de/mob/drush
 [bootstrap] Starting bootstrap to max [0.04 sec, 8.57 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalRoot() [0.04 sec, 8.57 MB]
 [bootstrap] Change working directory to /home/fc/1/de/mob/web [0.04 sec, 8.57 MB]
 [bootstrap] Initialized Drupal 8.7.10 root directory at /home/fc/1/de/mob/web [0.04 sec, 8.76 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalSite() [0.04 sec, 9.06 MB]
 [bootstrap] Initialized Drupal site mob at sites/default [0.04 sec, 9.29 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalConfiguration() [0.04 sec, 9.29 MB]
 [debug] Add service modifier [0.04 sec, 9.45 MB]
 [info] Executing: command -v mysql [0.05 sec, 9.91 MB]
 [info] Executing: mysql --defaults-file=/tmp/drush_IsKDek --database=mob --host=localhost --silent -A < /tmp/mob_20191203_224013.sql.gz [0.05 sec, 9.96 MB]

In SqlCommands.php line 199:

  [Exception]
  Query failed.

```

/tmp/mob\_20191203\_224013.sql.gz exists, /tmp/drush\_IsKDek does not Drush is 9.7.1, Mint 19.2, alias

```
loc:
  root: /home/fc/1/de/mob/web
  uri: mob
  options:
    command-specific:
      sql-sync:
        sanitize: true
        structure-tables:
          common:
            - cache_advagg
            - cache_bootstrap
            - cache_config
            - cache_container
            - cache_data
            - cache_default
            - cache_discovery
            - cache_dynamic_page_cache
            - cache_entity
            - cache_menu
            - cache_page
            - cache_render
            - cache_toolbar
            - watchdog
            - history
            - sessions
    os: Linux
  paths:
    dump-dir: /tmp
    files: sites/default/files

```

# Answer
Same issue with Drush 10.6.x. https://github.com/drush-ops/drush/issues/4319#issuecomment-649223069 is outdated as the function has been moved elsewhere but the problem persists.

Solution is to manually set PHP CLI to a lower version, for example

```
sudo update-alternatives --set php /usr/bin/php7.3

```
> 1 votes

# Answer
At the time of writing this comment, there is a problem in drush 9 with php7.4 as mentioned here: https://github.com/drush-ops/drush/issues/4319#issuecomment-649223069

I solved it in my case (I have multiple PHP versions installed) by switching to php7.2 using this command: `sudo update-alternatives --set php /usr/bin/php7.2`

I think it will work also with php7.0 and php7.1
> 0 votes

---
Tags: 8, database, drush
---


# Question
Title: Decoupled site as a presentation (display) layer for external microservices?
I understand that Drupal 9 out of box is very capable as a decoupled aka headless Drupal serves as a back-end for other apps (the core REST, JSONAPI capability).

However, I am thinking about the reverse way: having Drupal 9 as a pure presentation layer that pulls and displays data from various external micro-service APIs. For example, an external API outputs a product list JSON and a Drupal page requests that data to shown it on its page.

It might not need to map the pulled data into Drupal entities, but simply display them to Drupal page. (The reason I don't want to map data and store into Drupal is that it would create duplicated dataset, which probably isn't a good practice for micro-services architecture set up.)

Are there existing recommended approaches, modules for such case in the market for Drupal 9? If no modules are suitable for this case, what are the parts of dev I can further look into (for example hooks used by the Views module)?

---

UPDATED @ 26th Sep 2021

For reference and anyone may be interested in such situation, I end up with Feeds ecosystem.

Below are contributed modules work together for this:

* Feeds
* Extensible Parsers
* Feeds Tamper

Feeds (main) doesn't have JSON format parsing, Feeds Extensive Parsers (feeds\_ex) add JSON support, utilize the JsonPath libraries. Always use 'composer' to install these as lots of dependencies to solve. Use Ludwig module to check if any required libraries missing.

A great reference here: https://www.mediacurrent.com/blog/drupal-8-feeds-import-external-json-api/

---

Updated: Also

https://www.drupal.org/project/views\_json\_source

# Answer
> 1 votes
> It might not need to map the pulled data into Drupal entities, just simply display them to Drupal page.

If you are pulling from an external source, and not using entities, why even use Drupal at all? The function of the JSON:API module is to expose Drupal entities via JSON:API; that's all it does. So if you go the JSON:API route, you will need to use entities.

Anyway, Views + most other Drupal modules rely heavily on the concept of entities. Entity API was a contrib module in D7, but it is part of core and one of the fundamental concepts of D8/D9.

So if building a display layer, I would start with figuring out how to map your external data into Drupal entities. Then experiment with JSON:API first before REST, because if you already have entities, JSON:API is very fast to set up (since it exposes all entities by default) and give you some space to experiment with.

Some potentially useful modules:

* Feeds to pull in data externally and Feeds Tamper to tweak it (pre-process)
* JSON Field or JSONB Field to store external JSON data as JSON, alleviating the need to parse it right away (limited to databases that support JSON)
* JSON:API Explorer, PHPMyAdmin for JSON:API
* JSON:API Extras-- despite the name, this module is probably essential. It lets you rename JSON:API resources instead of using the default core names and it also lets you easily disable access to groups of entities (which you want, because exposing everything like JSON:API does by default is probably too much)
* JSON:API Include to merge (pull in entity references automatically)
* JSON:API Resources to define your own endpoints to do whatever you want (for all custom processing)

---
Tags: views, feeds, 9, http-request
---


# Question
Title: Custom block plugin does not show in Layout Builder options
Newish to Layout Builder - we made a custom block plugin that renders a custom form. When I go to a page with Layout Builder and try to add that block... it is not in the list of blocks.

```
/**
 * Provides a form block.
 *
 * @Block(
 *   id = "my_block",
 *   admin_label = @Translation("My Block with Form"),
 *   category = @Translation("Custom")
 * )
 */
class MyBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * The form builder.
   *
   * @var \Drupal\Core\Form\FormBuilderInterface
   */
  protected $formBuilder;

  /**
   * Constructs a new MyBlock instance.
   *
   * @param array $configuration
   *   The plugin configuration, i.e. an array with configuration values keyed
   *   by configuration option name. The special key 'context' may be used to
   *   initialize the defined contexts by setting it to an array of context
   *   values keyed by context names.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
   *   The form builder.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, FormBuilderInterface $form_builder) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->formBuilder = $form_builder;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('form_builder')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    $build['access_form'] = $this->formBuilder->getForm('Drupal\mymodule\Form\MyForm');
    return $build;
  }

}

```

Is there something I need to add to the annotation or class to make it an option for Layout Builder? It works fine as a normal Drupal block.

edit: I notice in one random custom module, they have to alter Layout Builder to get this functionality. Is that correct??

https://git.drupalcode.org/project/layout\_builder\_block/-/blob/1.x/src/EventSubscriber/LayoutBuilderBlockAddControllerSubscriber.php

# Answer
This project has Layout Builder Browser installed. After adding that block to a category, it is now an option in Layout Builder. Drupal core only seems to otherwise recognize block\_content blocks.
> 1 votes

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


# Question
Title: Is it a valid approach to have a different CSP based on login state and browser?
I'm currently working on improving the security of a Drupal 8 site by implementing a Content Security Policy. As this is still new to me, I would like to get some input on my strategy.

# Relevant base setup

# Preliminary considerations

I would like to not use `'unsafe-inline'` for scripts if possible, but I finally figured that this would only work for certain browsers. I would also like to have an adequate CSP for different situations (different browsers, logged-in vs not logged-in).

This leads me to this idea for `script-src`:

* using `nonce` and `'strict-dynamic'` for browsers that support CSP v3 and non-cachable pages
* using hashes for browsers that support CSP v3 and cachable pages
* using `'unsafe-inline'` together with a domain-based list for all other browsers

The main reason for having a browser distinction is that I couldn't find a way of creating the CSP directives backward-compatible without an unreasonable amount of changes to core and contrib modules.

# What I have done so far on my local test site

I have added logic that uses a `nonce` and `'strict-dynamic'` for chrome based browsers for logged in users, for which pages are not cached, assuring that the nonces are new and unique for every request. That logic is based on the User Agent string (which I know is unsafe, but don't see a better solution).

So basically, for chrome based browser, logged in users will get a CSP header with those script related CSP policies (`'unsafe-inline'` in the script-src will be ignored by browsers that support `'strict-dynmic'`):

```
script-src 'self' 'unsafe-inline' *.googletagmanager.com  *.google-analytics.com 'nonce-SECURENONCE' 'strict-dynamic';
script-src-attr 'unsafe-inline';

```

Anonymous users will get a CSP that looks roughly like this:

```
script-src 'self' 'unsafe-inline' *.googletagmanager.com *.google-analytics.com 'sha256-HASH_1' 'sha256-HASH_2' 'sha256-HASH_3' 'sha256-HASH_4' 'sha256-HASH_5' ...;
script-src-attr 'unsafe-inline';

```

Non chrome based browsers get a CSP header that looks like this:

```
script-src 'self' 'unsafe-inline' *.google-analytics.com *.googletagmanager.com;

```

I have also added logic, that, based on the above selection criteria, adds either `nonce` attributes to every script tag (non-cached pages), or hash codes for every script tag (cached pages). This also allows me to have CKEditor working fine in the backend.

It seems to be working well on the different browsers I have tested with: Brave, Chrome, Edge, Firefox and Safari. Only the three former have a CSP that I would consider safe (also checked with https://csp-evaluator.withgoogle.com/).

Is it a valid approach to have:

1. different CSPs for logged-in vs anonymous users?
2. different CSPs for different browsers (or different "reported browsers" actually)?

# Answer
> 3 votes
1. Relying on the user agent is not reliable - for example I changed the user agent in my old browser, otherwise YouTube refuses to work. If, based on the results of the analysis of the violation reports, you change the CSP for such of my user agent, legitimate users of this browser may suffer.
2. Using of `script-src-attr 'unsafe-inline';` will open door for XSS in Chromium based browsers, because it allows event handlers in the tags (like `onckick="alert('XSS')"`).
3. Using of `'sha256-HASH'` is **not** supported for **external** scripts in Safari/Firefox. If you do use it for inline `<script>` tags only, it is easier to use `'hash-value'` for both logged and non-logged users (and not to use `'nonce'`).
You can use mix `'nonce-'` and `'sha256-'` but in case of XSS `'nonce-'` can be reused in the browser-cashed pages (this is difficult and unlikely).

Briefly, you can use CSP in browsers backward compatibility mode:

```
script-src 'self' 'strict-dynamic' *.googletagmanager.com *.google-analytics.com
  'sha256-HASH_1' 'sha256-HASH_2' ...;

```

or

```
script-src 'self' 'strict-dynamic' *.googletagmanager.com *.google-analytics.com 'nonce-SECURENONCE';

```
* Chrome/Edge/Firefox supports `'strict-dinamic'` (which cancels any host-based sources), therefore actual CSP will be `script-src 'strict-dynamic' 'sha256-HASH_1' 'sha256-HASH_2' ...;` or `script-src 'strict-dynamic' 'nonce-SECURENONCE';` respectively.
* Safari does not supports `'strict-dinamic'`, therefore actual CSP will be `script-src 'self' *.googletagmanager.com *.google-analytics.com 'sha256-HASH_1' 'sha256-HASH_2' ...;` or `script-src 'self' *.googletagmanager.com *.google-analytics.com 'nonce-SECURENONCE';` respectively.
* you do not need to use `'unsafe-inline'` at all because it's cancelled by `'nonce-value'` or `'hash-value'` anyway. As for now there is not browsers that does not support `'nonce-value'` / `'hash-value'`.

The above CSP above does not allow an inline event handlers in the tags, but:

1. CKEditor-5 does not requre `'unsafe-inline'` and can be allowed with nonce/hash. The `'unsafe-inline'` is required for CKEditor-4 only.
2. Google Analytics does not require `'unsafe-inline'` and can be allowed with nonce/hash.
3. Google Tag Manager itself does not require `'unsafe-inline'` and can be allowed with nonce/hash. The `'unsafe-inline'` for GTM is required only if you use custom inline scripts in the "Custom HTML tags".
Using a `'nonce-value'` may be preferred because if the GTM script is inserted with the *nonce=* attribute, it will be redistributed to all scripts inserted by the Tag Manager, except "Custom HTML tags".
4. If you use inline event handlers in the tags - an `'unsafe-inline'` is mandatory so forget about `'nonces'`, `'hashes'` and `'strict-dynamic'` tokens. Since an `'unsafe-hashes'` is not supported by Safari, you have no way safely allow inline event handlers in the tags.

---
Tags: 8, security
---


# Question
Title: How do I plot a graph or chart on the confirmation message?
How do I plot a graph on the confirmation message, on a webform and Drupal 8?

I searched a lot, but did not find anything useful, but these results.

1. There are several modules involved in graphing, including the Charts module.
2. There is a programming solution (Display webform results data in a Google Chart), but I don't think it works, since the site will contain dozens of questionnaires. Drawing charts should be easy, something similar to Twing or only in the confirmation message textBox area.
3. images files can be displayed if uploaded to the site via the questionnaire in this way (from How to Display Image after submitting webform in the confirmation message page).

```
<img src="[submission:values:image_key]"/>

```
4. There are previous attempts at Drupal 7, such as the Webform Charts module. I don't know how it worked.

# Answer
> 0 votes
After trying several solutions, I found that the best way is an easy forgotten one. i used

> **webform-confirmation--\[webform\_id\].html.twig**

in the theme. you can use java script directly, same as provided by source (like google charts), just replace Webform variable like this:

```
{% set H_Axis =  webform_submission.data.H_Axis  %}

```

# Answer
> 1 votes
Since there doesn't seem to be a solution for this, I would define a webform handler that would preprocess the confirmation page with the chart that you generate.

There are plenty of D8 module for charting, and in the handler you have access to the webform submission values. You could even use a different method and save the chart image into a hidden image field on the submission. Handlers are sweet like that.

Check out `WebformHandlerBase` class/interface for the full method list. Checkout this other answer involving webform handlers to get you started. Once you have your handler, check out these examples for your methods.

**Acting on presave()**

```
/**
 * The example below demonstrates:
 * - retrieving a submission value
 * - processing it
 * - setting a field value to that result
 *
 * @param WebformSubmissionInterface $webform_submission
 *   A webform submission.
 */
public function preSave(WebformSubmissionInterface $webform_submission)
{
  $age = $webform_submission->getElementData('age');
  $ageChart = $this->someInjectedFooChartingService($age);
  $webform_submission->setElementData('age_chart', $ageChart->BarExportPng());
}

```

**Acting on preprocessConfirmation()**

```
/**
 * The example below demonstrates:
 * - retrieving a submission value
 * - processing it
 * - passing data to the confirmation template
 *
 * @param array $variables
 * @throws Exception
 */
public function preprocessConfirmation(array &$variables)
{
  /** @var WebformSubmissionInterface $webform_submission */
  $webform_submission = $variables['webform_submission'];
  $age = $webform_submission->getElementData('age');
  $ageChart = $this->someInjectedChartingService($age);
  // Add data to the confirmation template
  $variables['agechart'] = $ageChart;
}

```

# Answer
> 0 votes
thank you Ryan Hartman for your answer. There is no solution other than writing a new module to perform this task. I might do this, But I'll collect some resources here for future readers. This is another approach to plot a chart. (Overriding a Webform Confirmation Message in Drupal 8)

```
    /**
 * Implements hook_preprocess_HOOK().
 */
function mymodule_preprocess_webform_confirmation(&$vars) {
  if ($vars['webform']->id() == 'rate_workshop') {
    $request = \Drupal::request()->query;
    $display_mode = $request->get('display_mode');
    $rate_type = $request->get('rate_type');
    if ($rate_type === 'complete' && $display_mode === 'overlay') {
      $markup = t('Thank you for your feedback.') . '<br/><br/>';
      $markup .= '<button class="overlay-only">';
      $markup .= t('Explore more of this workshop');
      $markup .= '</button>';
      $vars['message']['#allowed_tags'] = ['br', 'button'];
    }
    else {
      $markup = t('Thank you for your feedback.');
    }

    $vars['message']['#markup'] = $markup;
  }
}

```

Thank you @kiamlaluno for editing my post.

---
Tags: webforms, charts
---


# Question
Title: How to programmatically enable and set taxonomy access control for role
I want to be able to programmatically enable and set taxonomy access control for the anonymous and authenticated roles. Specifically, I want to deny anonymous and authenticated users from being able to view or edit nodes tagged with a particular term. I know how to do this through the admin interface. But I'd like to be able to do this programmatically.

I can see functions to get the grants for a particular role, but not set them.

Thanks!

# Answer
> 1 votes
```
/**
 * Implements hook_node_access().
 */
function accommodation_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Session\AccountInterface $account) {
  if ($node->bundle() == 'accommodation' && \Drupal::currentUser()->isAuthenticated())  {
    if ($node->get('field_accommodation_category')->entity->getName() == 'Category 1') {
      return \Drupal\Core\Access\AccessResult::allowed();
    }

    return \Drupal\Core\Access\AccessResult::forbidden();
  }

  return \Drupal\Core\Access\AccessResult::neutral();
}

```

# Answer
> 1 votes
Check these two modules, both do your task.
Permissions by Term (Drupal 8/9)
Taxonomy Access Control Lite (D7 & D8/9)

# Answer
> 0 votes
Check out this page: http://drupalcontrib.org/api/drupal/contributions!taxonomy\_access!taxonomy\_access.module/group/tac\_grant\_api/

I'm currently attempting to implement the same functionality and it seems that this provides everything I need.

---
Tags: taxonomy-terms
---


# Question
Title: Is there a way to strip field set and description from [submission:values] in the emails tab?
I have a very long form. I would like to use the simple *\[submission:values\]* token in the email, but I'm hoping there is a way to add something that will leave out all the extraneous information like field set labels and descriptions.

# Answer
> 1 votes
my English is not very good but you can follow these steps to solve your problem.

1 -add email, 2 -select custom body and the values you want to include, 3 -exclude empty values and boxes that are not checked,

you can personalize even better by writing your text and adding the value you want.

for example: "yourText": \[webform\_submission:values:Element\_key\]

I hope I have helped you and excuse me for my bad English

---
Tags: 7, webforms
---


title: How to calculate a field in webform?

text:
# Question
Title: How to calculate a field in webform?
We recently implemented a site on the Drupal environment.

We make considerable use of the amazing Webform system. However, we encountered a need for which we did not see a solution in the existing elements in the Webform.

We need an element that can perform a simple calculation (+ - * /) between other numerical fields and\or pre-set numbers as we choose. So that the person filling out the form will see the result of the calculation while filling out the form. Something like entering a number and multiply by X number or another number field.

Is there a solution for that?

# Answer
> 3 votes
You probably want to use a computed element. Check out this video.

# Answer
> 2 votes
you can use Computed twig field. In this example it calculates the result of 5 fields (a2 + b2 + c2 + d2 + f2) only if all the fields are complete

---
Tags: webforms
---


# Question
Title: Webform Computed Data Display Grade and Text based on result
I am building a quiz using webforms and the computed data twig and have a question if something is possible and if there is documentation on how to build this.

The quiz is 20 questions and each answer has a value of 1-5, I have all of the computed data working and it is able to show the final score properly, but was wonder if I could assign a grade and give short text feedback based on the score.

For example:

A user scores less than 70 they would receive a grade of "Below Average", 70-80 Average and 81-100 "Above Average" and then some text giving them feedback on their score depending on this range they scored in. Is this possible to do in webforms?

# Answer
Yes, this is possible. Computed elements can trigger condition logic. In your use case, you could hide/show a text field based on the score. You might need to trim the computed element's whitespace to get the condition to trigger properly
> 1 votes

# Answer
I was able to solve it like that, I hope it helps you
> 2 votes

---
Tags: webforms
---


title: Ckeditor inline images path

text:
# Question
Title: Ckeditor inline images path
I am running a Drupal 9 site and I expect my users to upload a lot of files with the ckeditor functionality. All of those files will be stored in a single folder.

I heard that this will cause performance issue once there are a lot of files. To avoid this, I would like to include a timestamp in to the path where to file will be stored, similar to what Drupal does to regular file uploads.

Is there a way to achieve this?

I found this question but it's 5 years old and there is no real answer.

# Answer
> 0 votes
Although stock Drupal may be OK with tons of files in a single directory, some Drupal hosts (e.g., Pantheon) have limits:

From their docs:

> ## Highly Populated Directories
>
> If you have individual directories with tens of thousands of files (e.g. an image repository) it may be necessary to refactor this file structure to see good performance on Pantheon. The danger zone begins at around 50,000 files in a single directory, and performance drops off suddenly at over 100,000 files.
>
> Drupal itself is capable of managing uploaded content into different directories based on the date or user, which is preferable to dumping all uploads into a single place. Refactoring an existing large-scale site with this issue is usually simply a matter of re-arranging the files and then updating the files table in Drupal.

If you did need to implement this, you might look at what the Filefield Paths module does.

---
Tags: files, wysiwyg
---


# Question
Title: Actions form array overriding to set HTML id attribute
I extend the `EntityForm` class and I try to override a submission button, to set its HTML ID attribute (try #1). Since it doesn't work, I tried to wrap the button in a wrapper `<div>`. I tried to wrap with two different ways (try #2 and try #3), but they don't work. The only way I can override the submision button is to set `'#attributes'` to set the HTML attribute `class` and to add my own CSS class, but my wish was to set a HTML `id` attribute. And I wanted to do this overriding in actions() method (not form()).

```
use Drupal\Core\Entity\ContentEntityForm;

class MyForm extends ContentEntityForm {

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

    $actions['submit'] = [
      '#type' => 'submit',
      '#id' => 'save-button', // <-- try #1
      '#value' => t('Save'),
      '#ajax' => [
        'callback' => '::ajaxCallback',
        'event' => 'mousedown',
        'wrapper' => 'bar-wrapper-1',   // <-- try #2
      ],
      '#prefix' => '<div id="bar-wrapper-2">',  // <-- try #3
      '#suffix' => '</div>',
      '#attributes' => [
        'class' => ['foo'],   // <-- try #4
      ],
    ];

    $actions['submit_wrapper'] = [
      '#type' => 'markup',
      '#markup' => '<div id="bar-wrapper-1"></div>'
    ];

    return $actions;
  }

}

```

I suppose I can only override the HTML ID within `form()`, but it looks a little inconsistent because I can override/add a CSS class.

# Answer
a sample here :

```
$form['submit'] = [
  '#type' => 'submit',
  '#value' => $this->t('Submit'),
  '#weight' => 99,
  '#attributes' => ['class' => ['ex-black'], 'id' => ['testId']],
  '#prefix' => '<div id="testIdWrapper">',
  '#suffix' => '</div>',
];

```
> 1 votes

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


# Question
Title: How to alter image style based on product custom attribute?
I'm building a webshop based on Ubercart, and products have a custom attribute "sold out". When this attribute is checked, all product images should be displayed with a semitransparent overlay textbox: SOLD OUT. Theoretically, I found a couple of promising options, but none of them seems to me satisfying:

1. Using node--product.tpl.php to insert a custom overlay div around the rendered image. This is a very fragile solution, because I cannot put the overlay div inside the main-product-image div. Therefore, it's hard to make it responsive, and on the other hand, cross-browser issues might raise because of the opacity...
2. Adding a new image style and overriding theme\_uc\_product\_image function. Since style\_name is hardcoded here as 'uc\_product', it is obvious to override this. But no node array is available here to decide whether to override image\_style or not. Maybe a custom sql query?
3. Manipulating the default uc\_product image style from code with hook\_image\_styles\_alter function. Same problem: no node array here.

Any idea?

# Answer
You could use ImageCache Actions module and write your PHP field condition right on the generation of the image.

Custom Actions effect is what you need.
> 0 votes

# Answer
Finally I managed to solve the problem.
Steps are as follows:
1. Create a distinct image style for the overlay text (you'll need imagecache actions module). You can also add background png for the text with the watermark effect.
2. Add a custom action effect for **uc\_product** style. This is a built-in style used for ubercart product display.
3. Put the code into the custom action:

> ```
> if ($image_context['entity']->field_product_sold_out['und']['0']['value']) { // this is my custom node attribute
>   if ($preset = image_style_load('sold_overlay')) { //sold_overlay is my image style for the overlay text
>     foreach ($preset['effects'] as $effect) { //cycle through all effects of the style
>       image_effect_apply($image, $effect); //apply the style
>     }
>   }
> }
> $style = image_style_load('uc_product');
> image_style_flush($style); //you'll also need to flush the media cache
> return TRUE;
>
> ```

Note that you'll need PHP Filter module enabled to put the code in the textarea.

And that's all. From now on, all images displayed with **uc\_product** style will run the code above.

Perhaps this is not the most brilliant solution, but works. ;-) Comments are welcome.
> 0 votes

# Answer
Check this, I have an image field with a default image style. How to alter that style:

```
/**
 * Implements gc_histories_paragraph_view().
 */
function gc_histories_paragraph_view(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {
  if ($entity->bundle() == 'one_image' && $view_mode == 'default') {
    $build['field_oi_image'][0]['#image_style'] = "history_1140_{$entity->get('field_paragraph_image_height')->value}";
    // ksm("history_1140_{$entity->get('field_paragraph_image_height')->value}");
  }
  else if ($entity->bundle() == 'one_image_with_text' && $view_mode == 'default') {
    $build['field_oiwt_image'][0]['#image_style'] = "history_560_{$entity->get('field_paragraph_image_height')->value}";
    // ksm("history_1140_{$entity->get('field_paragraph_image_height')->value}");
  }
  else if ($entity->bundle() == 'two_images' && $view_mode == 'default') {
    $imageStyle = "history_560_{$entity->get('field_paragraph_image_height')->value}";
    $build['field_ti_images'][0]['#image_style'] = $imageStyle;
    $build['field_ti_images'][1]['#image_style'] = $imageStyle;
    // ksm($imageStyle);
  }
  else if ($entity->bundle() == 'two_images_with_text' && $view_mode == 'default') {
    $imageStyle = "history_370_{$entity->get('field_paragraph_image_height')->value}";
    $build['field_tiwt_images'][0]['#image_style'] = $imageStyle;
    $build['field_tiwt_images'][1]['#image_style'] = $imageStyle;
    // ksm($imageStyle);
  }
  else if ($entity->bundle() == 'three_images' && $view_mode == 'default') {
    $imageStyle = "history_370_{$entity->get('field_paragraph_image_height')->value}";
    $build['field_th_images'][0]['#image_style'] = $imageStyle;
    $build['field_th_images'][1]['#image_style'] = $imageStyle;
    $build['field_th_images'][2]['#image_style'] = $imageStyle;
    // ksm($imageStyle);
  }
}

```
> 0 votes

---
Tags: ubercart, media
---


# Question
Title: Update FieldStorageConfig for a field in an update hook properly?
I need to update the allowed values option on an list\_integer field. For reasons at the moment, I can't just update and export the configuration and import it on production until we implement config\_ignore. I also do not want to edit several block types to update a few field(s) coming up across several environments - so if I can script it and save time that is what I want to do.

In an update hook, I am trying this:

```
/**
 * Update the result options for the Result Count field.
 */
function mymodule_update_8001(&$sandbox) {
  $allowed_values = [];

  for ($x = 1; $x < 16; $x++) {
    $allowed_values[$x] = (string) $x;
  }

  $allowed_values[50] = '50';
  $allowed_values[75] = '75';
  $allowed_values[100] = '100';

  $old_config = FieldStorageConfig::load('block_content.field_result_count');
  $new_config = $old_config->createDuplicate();
  $new_config->original = $new_config;
  $new_config->enforceIsNew(FALSE);
  $new_config
    ->setSetting('allowed_values', $allowed_values)
    ->save();
}

```

It appeared to add the new values to the field, but the terminal spit this out when running the database update:

```
>  [warning] assert(): Cannot load the "field_storage_config" entity with NULL ID. failed EntityStorageBase.php:249
>  [warning] array_flip(): Can only flip STRING and INTEGER values! EntityStorageBase.php:266

```

Is this the proper way to update an existing field?

# Answer
Was almost there initially, but thanks to 4k4 this is one way to amend an allowed value list with new values:

```
/**
 * Implements hook_install().
 *
 * The first action updates the result options for the Result Count field.
 * Options should be 1-15, 50, 75 and 100.
 */
function mymodule_update_8001(&$sandbox) {
  $allowed_values = [];

  for ($x = 1; $x < 16; $x++) {
    $allowed_values[$x] = (string) $x;
  }

  $allowed_values[50] = '50';
  $allowed_values[75] = '75';
  $allowed_values[100] = '100';

  $config = FieldStorageConfig::load('ENTITY_TYPE.FIELD_ID');
  $config
    ->setSetting('allowed_values', $allowed_values)
    ->save();
}

```
> 3 votes

---
Tags: 8, entities
---


# Question
Title: How do I programmatically delete a reference field value?
I have a multi-valued taxonomy reference field named `field_classrooms` in a node type. I use below code to delete the value in the field.

```
$node = Drupal\node\Entity\Node::load('1512');
unset($node->field_classrooms[0]);
$node->save();

```

I can't figure out what I am doing wrong here.

# Answer
Maybe something like this could help you out

```
// Get the list of the associated classrooms ...
$classrooms = $node->get('field_classrooms')->getValue();
// ... if there are any associated classrooms ...
if(!empty($classrooms)) {
  foreach($classrooms as $classroom) {
    // ... get the key of the classroom
    $key = array_search(current($classroom), array_column($classrooms, key($classroom)));
    // ... remove the relationship ...
    $node->get('field_classrooms')->removeItem($key);
  }
  // ... and save the node.
  $node->save();
}

```

If you want to remove a single classroom from the list and you already know the tid

```
private function removeClassroomFromNode($node, $tid) {
  if(null != $node) {
    // ... get the list of associated classrooms
    $classrooms = $node->get('field_classrooms')->getValue();
    // ... get the key of the classroom
    $key = array_search($tid, array_column($classrooms, 'target_id'));
    // ... remove the classroom
    $node->get('field_classrooms')->removeItem($key);
    // ... save the node.
    $node->save();
  }
}

```
> 12 votes

# Answer
You can use below code for removing items in the reference field in Drupal 8 :

```
/** @var \Drupal\Core\Entity\ContentEntityBase $entity */
$entity = \Drupal::entityTypeManager()->getStorage('node')->load($nid);

$tids = $entity->get('field_classrooms')->getValue();

$updatedTerms = [];
foreach($tids as $term) {
  if ($term['target_id'] != 35)
    $updatedTerms[] = ['target_id' => $term['target_id']];
}

$entity->field_notifications = $updatedTerms;

$entity->save();

```
> 4 votes

# Answer
You can simply set to empty

```
$node->set('field_classrooms', []);

```
> 3 votes

# Answer
You can remove the first item of a list just calling

```
$node->get('field_classrooms')->removeItem(0);

```
> 2 votes

# Answer
You can remove a particular referenced entity by id with this code:

```
    $entity->get('my_field')->setValue(array_filter($entity->get('my_field')->getValue(), function ($value) use ($id) {
      return ($value['target_id'] != $id);
    }));

```
> 2 votes

# Answer
Another way of bulk or selective delete is elegant `filter()` method.

Example:

```
use Drupal\Core\TypedData\TypedDataInterface;

$nodeStorage = \Drupal::service('entity_type.manager')->getStorage('node');
/**
 * @var \Drupal\node\Entity\Node $node
 */
$node = $nodeStorage->load($nid);
$classrooms = $node->get('field_classrooms');
$classrooms->filter(function (TypedDataInterface $item) {
  // You can do some operations on field item like: $item->getValue();
  // Returning TRUE in an iteration will remove the item.
  return TRUE;
});
$node->save();

```
> 2 votes

# Answer
Meanwhile you can take help from this code -

```
$node = \Drupal\node\Entity\Node::load('1512');
// Removes '0' index element.
$node->set('field_classrooms', array_slice($node->get('field_classrooms')->getValue(), 1));
$node->save();

```
> 1 votes

# Answer
the item is removed based on the index number of the list, so you need to figure out the index you want to remove,

1.- get all the referenced items

`$array_of_referenced_items = $node->get('field_SOMETHING_ref')->getValue();`

2.- search on the array for the index of the item you are trying to remove.

`$index_to_remove = array_search(['target_id' => ID_TO_SEARCH], $array_of_referenced_items);`

3.- Remove the reference by the index.

`$node->get('field_SOMETHING_ref')->removeItem($index_to_remove);`
> 0 votes

---
Tags: 8, entities
---


# Question
Title: How to use hook_block_access() with custom block created in UI
I have a custom block created using Drupal 9 Custom block library. I want to use hook\_block\_access() to control access to it, but, as it is a custom block, it does not have a block machine name. The only ID I can find (using Devel variables) is:

stdClass Object ( \[**CLASS**\] =\> Drupal\block\_content\Entity\BlockContent \[theme:protected\] =\> \[values:protected\] =\> Array
( **\[id\] =\> Array ( \[x-default\] =\> 4 )**

```
        [revision_id] => Array
            (
                [x-default] => 4
            )

        [type] => Array
            (
                [x-default] => basic
            )

        [uuid] => Array
            (
                [x-default] => f0c17429-584a-4221-995c-c00f4c41c714
            )

        [langcode] => Array
            (
                [x-default] => en
            )

        [revision_user] => Array
            (
                [x-default] =>
            )

        [revision_created] => Array
            (
                [x-default] => 1632243859
            )

        [revision_log] => Array
            (
                [x-default] =>
            )

        [revision_default] => Array
            (
                [x-default] => 1
            )

        [isDefaultRevision] => Array
            (
                [x-default] => 1
            )

        [status] => Array
            (
                [x-default] => 1
            )

        [info] => Array
            (
                [x-default] => Add Content
            )

        [changed] => Array
            (
                [x-default] => 1632261438
            )

        [default_langcode] => Array
            (
                [x-default] => 1
            )

        [revision_translation_affected] => Array
            (
                [x-default] => 1
            )

        [reusable] => Array
            (
                [x-default] => 1
            )

        [body] => Array
            (
                [x-default] => Array
                    (
                        [0] => Array
                            (
                                [value] =>

```

etc...

I get to the block edit by going to: http://mysite.com/block/4

How can I use **hook\_block\_access(Block $block, $operation, AccountInterface $account)** to control access to this block? How do I identify this block in the **$block** variable?

# Answer
After you've created the custom block in UI you can place it in different regions. Each of these instances gets a machine name and `hook_block_access()` works as intended.

If you want to control access on content entity level, this makes sense because you can use block content not only in block layout, implement an access hook for the entity type `block_content`:

```
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;

/**
 * Implements hook_ENTITY_TYPE_access().
 */
function mymodule_block_content_access(EntityInterface $entity, $operation, AccountInterface $account) {
  if ($operation == 'view') {
    if ($entity->id() == 4) {
      return AccessResult::forbidden();
    }
  }
  return AccessResult::neutral();
}

```
> 3 votes

---
Tags: blocks, hooks
---


# Question
Title: What method should I use instead of Drupal\Core\Entity\Query\Sql\Query::addExpression()?
I am using Entity Query to select nodes of two different types. The fetching seems to be working, but I want to sort the returned values. Both the content types have different date fields. I know I could do this with

```
$query->addExpression('COALESCE( field_date_1, field_date_2)', 'Date');
$query->sort('Date', 'DESC');

```

but `addExpression()` isn't an existing method, and the code throws this exception.

> Error: Call to undefined method Drupal\Core\Entity\Query\Sql\Query::addExpression()

How can I sort on two or more date fields?

# Answer
Entity queries don't support expressions. To get it around it, add a tag to the query:

```
$query->addTag('mymodule');

```

Then implement `hook_query_alter()`, check for the tag, and add the expression there instead:

```
function mymodule_query_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  if ($query instanceof Drupal\Core\Database\Query\SelectInterface && $query->hasTag('mymodule')) {
    $query->addExpression('...');
  }
}

```
> 6 votes

---
Tags: entities, 9
---