# Question
Title: How to add captions to media library items?
Anyone know how to associate a caption to a image that gets uploaded into a media library field? I can get the name of the file to show up but I can't see how to associate a caption to the image. I have the image library filed set to allow unlimited items to be uploaded to it so I can have an array of images returned when I display it in my layout builder block. I got the css to style the image array in a grid format but now I need to somehow include a related field to the image which contains the caption text. I tried creating a view but I could only get all of the images in the image library from all the nodes that had uploaded images and not just the images uploaded to a specific node that was being viewed like a contextual or relationship in the advanced section of the view form. Because the image once uploaded to the media library dose not seem to have any relationship to the node it is uploaded into that I can filter or sort on for the context connection. Has some one written or know about a contributed module that does add the caption field association to a image or for that matter any other type of media uploaded to the media library?

# Answer
**Short answer:** yes, you can get Drupal to associate captions to Media Library images.

**Longer answer:** there are at least two different angles to approach this from.

**Approach #1:** Media entities are fieldable just like any other entities, so you can add a Caption field to the Media entity itself.

Go to `/admin/structure/media/manage/image/fields` and click "Add field" to add a caption for Media image entities.

Don't forget to adjust the Form display (`/admin/structure/media/manage/image/form-display`) and the Display (`/admin/structure/media/manage/image/display`) to your liking.

If necessary, you can set up different view modes with custom display settings, and you can override a Twig template to control the layout of the Media image entity.

**Caveats to Approach #1:** This approach means that the caption is bundled with the media image, so if you use the Media image entity on multiple pages, editing the caption will change the caption everywhere -- which is convenient if that is exactly what you want, but inconvenient if it causes unexpected side effects. It also means that the caption field may not be easily edited while editing the node that the Media image is used on.

**Approach #2:** One common workaround for these shortcomings is bundling the Media image entity reference field with a Caption field in a multi-field bundle using something like Paragraphs (other options include Field Collection or Entity Constructor Kit). This will allow users to edit the caption while editing the node that the Paragraph appears on. It also allows you to have a different caption each time the media image is used.

**Caveats to Approach #2:** This approach requires contributed modules; doing it in Drupal core is theoretically possible by creating a custom Content Type with the media entity reference field and the caption field, but the UX would not be quite as nice.

**Approach #3:** Finally, I should note that the two options can be combined. With savvy Twig conditionals, you can have your Paragraph template use the value provided in a "Caption Override" field in the Paragraph if it is available, or fall back on a global default caption provided by a field in the Media entity itself.
> 5 votes

---
Tags: media
---


title: Custom Migration Plugin MySQL Error

text:
# Question
Title: Custom Migration Plugin MySQL Error
I've run into the following error when running the command `drush migrate-import custom_spotlight` where `custom_spotlight` is the name of the plugin. I've been following along with this guide: https://www.metaltoad.com/blog/drupal-8-migrations-part-4-migrating-nodes-drupal-7 but I'm not exactly sure what went wrong here. It seems when the placeholder `:nid` is substituted with a value, there are quotes inserted as well which displays in the error log as the HTML entity code. Any tips on how to resolve this issue?

Drupal version: 9

mysql Ver 14.14 Distrib 5.7.35, for Linux (x86\_64) using EditLine wrapper

# Answer
> 0 votes
It looks like the issue stemmed from incorrect SQL syntax. The last column after the `SELECT` should not contain a comma.

---
Tags: nodes, database, drush, migrations, 9
---


# Question
Title: How can I assign custom field layouts using paragraphs?
For reference:

```
-modules
--contrib
---ds
--custom
---ds

```

I'm looking to add paragraph layouts using flexbox. I don't see a module specifically for this, so I realize I'm going to have to adapt an existing module.

Right now, I'm trying to add custom layouts in the Display Suite module by adding a template config to ds.layouts.twig with the appropriate html.twig and css files.

My concern is that any edits to these files will be overwritten with updates to the DS module. I tried adding a ds folder in the custom modules folder copying over the ds.layouts.twig file and the appropriate files, but it didn't work as I thought it would.

Does anyone have any recommendations to add layout functionality to paragraphs in which I can write my own layouts using grid/flexbox

# Answer
I've determined that the Layout API and associated modules are a better way to go for what I'm looking to do.

Thanks for reading this, though!
> 0 votes

---
Tags: theming, paragraphs
---


title: Login by email instead of username

text:
# Question
Title: Login by email instead of username
I can't find if it is possible or not to change the log in system by using the couple (email, password) instead of (username, password).

I think people never remember their usernames when not available as they wanted and so had to add a number at the end of it ...

# Answer
Both the Login Toboggan and Email Registration modules allow your users to use their email when logging in.
> 20 votes

# Answer
The developer has moved a module that meets your need from the sandbox to the project page: https://www.drupal.org/project/login\_email

The module exists as 7.x-1.x-dev It works as is...looks like a bit of assistance can turn this into an official release.
> 0 votes

# Answer
In order to allow both username and email: first add validator

```
function YOURMODULE_form_user_login_alter(&$form, &$form_state, $form_id) {
    $form['#validate'][1] = 'YOURMODULE_form_user_login_replace_email_validate';
    $form['#validate'][2] = 'user_login_authenticate_validate';
    $form['#validate'][3] = 'user_login_final_validate';
}

```

then check if looks like email address (contains @, letters before and after @ and at least 1 '.' after @). If it is, than replace email by username:

```
function YOURMODULE_form_user_login_replace_email_validate(&$form, &$form_state) {

    $name = $form_state['values']['name'];
    if (strpos($name, '@')) {
        $mailParts = explode('@', $name);
        if ((int)count($mailParts) === 2) {
            $extParts = explode('.', $mailParts[1]);
            if (count($extParts) > 1) {
                $query = db_select('users', 'u');
                $query->distinct();
                $query->fields('u', ['uid']);
                $query->fields('u', ['name']);
                $query->fields('u', ['mail']);
                $query->condition('u.mail', $name, '=');
                $result = $query->execute()->fetchAllAssoc('name');

                if (!empty($result)) {
                    $name = array_keys($result)[0];
                    $form_state['values']['name'] = $name;
                }
            }
        }
    }
}

```

I had a specific situation when I had to add email-based authentification to working site with a lot of users leaving the "old" authentification working, and I did it in such a way.
> 0 votes

# Answer
Here's how to let a user login with their email address in Drupal 7:

```
/**
 * Implements hook_form_alter().
 */
function MY_MODULE_form_alter(&$form, $form_state, $form_id) {

  // On the user login form...
  if ($form_id == 'user_login') {

    // OPTIONAL: Change the title on the user name input.
    $form['name']['#title'] = t('E-mail address');

    // OPTIONAL: Clear the descriptions on the user name and pass inputs.
    $form['name']['#description'] = '';
    $form['pass']['#description'] = '';

    // Prepend a custom validation handler.
    array_unshift($form['#validate'], 'MY_MODULE_user_login_form_validate');

  }

}

/**
 * A custom validation handler for the user login form.
 */
function MY_MODULE_user_login_form_validate(&$form, &$form_state) {

  // If they provided a valid email address for the user name...
  $name = $form_state['values']['name'];
  if (valid_email_address($name)) {

    // If an account exists for the email address...
    $account = user_load_by_mail($name);
    if ($account) {

      // Set the account's user name onto the form state.
      form_set_value($form['name'], $account->name, $form_state);

    }

  }

}

```
> 0 votes

---
Tags: 7, users
---


# Question
Title: Why is <my_entity>-content-add-list.html.twig template not being used?
I have generated a custom content entity via the Drupal Console. It has bundles. I would like to customise the screen which you get to when adding a new such entity - the screen which displays the list of bundles, to click on the type you want to add.

When I generated the entity, a bunch of template files were created, including one called `<my_entity>-content-add-list.html.twig`. I am certain this is intended to override the core template called `entity-add-list-html.twig`. However, changes I make to it do not take effect, and by putting twig in debug mode and viewing the source, I can see that it is not being overridden.

Do I need to add a theme suggestion hook? If so, what would the name of the function be? I feel like I must be missing something. Given that the console generated that template I am surprised it is not automatically used. But surely there must be a simple way of telling Drupal to use it.

EDIT: I've found what to name the function: it's `mymodule_theme_suggestions_entity_add_list`. But the machine name of the entity is nowhere in the $variables array that I can easily get at. I'm looking at parsing the route to get it out, which seems rather hacky

# Answer
> 0 votes
So I got there in the end (the machine name of the entity being `oc_activity`:

```
function opencase_entities_theme_suggestions_entity_add_list(array $variables) {
  $route_name = \Drupal::routeMatch()->getRouteName();
  $suggestions = [];
  if ($route_name == "entity.oc_activity.add_page") {
    $suggestions[] = 'oc_activity_content_add_list';
  }
  return $suggestions;
}

```

But it feels too hacky & hard-coded; it seems there ought to be a nicer way.

Also, the template file that was generate by the console assumed that the array of bundles was called `types` when actually it was `bundles`. So I had to change the generated code from `for type in types` to `for type in bundles`. Just putting that here in case it's useful to anyone...

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


# Question
Title: How can I replace the Home link with an image?
I want to replace the *Home* link shown in breadcrumbs with an icon.

>

>

How can I achieve this?

# Answer
> 0 votes
I’m not in the theme business but I suppose you can just override the twig template.

Assuming that the default template is in use:

```
[your_site]/core/themes/bartik/templates/classy/navigation/breadcrumb.html.twig

```

Just copy it to your theme templates folder and change it something like:

```
{#
/**
 * @file
 * Theme override for a breadcrumb trail.
 *
 * Available variables:
 * - breadcrumb: Breadcrumb trail items.
 */
#}
{% if breadcrumb %}
  <nav class="breadcrumb" role="navigation" aria-labelledby="system-breadcrumb">
    <h2 id="system-breadcrumb" class="visually-hidden">{{ 'Breadcrumb'|t }}</h2>
    <ol>
  {% for item in breadcrumb %}
      <li>
      {% if item.url %}
        {% if item.text == "Home" %}
          <a href="{{ item.url }}">
            <img src="some_src" alt="Some alt">
          </a>
        {% else %}
          <a href="{{ item.url }}">{{ item.text }}</a>
        {% endif %}
      {% else %}
          {{ item.text }}
      {% endif %}
      </li>
  {% endfor %}
    </ol>
  </nav>
{% endif %}

```

---
Tags: 8, breadcrumbs
---


# Question
Title: How to make custom fieldset collapsed by default in Drupal 8
In Drupal 7 there was option to have fieldset collapsible or not, and to restrict default state of this form element (collapsed, or uncollapsed). Example:

```
$form['contact_data'] = array(
        '#title' => t("Contact data"),
        '#type' => 'fieldset',
        '#collapsible' => TRUE,
        '#collapsed' => FALSE,
);

```

Now, in Drupal 8 I cannot find attributtes `#collapsible` and `#collapsed` in `Drupal\Core\Render\Element\Fieldset`. In official documentation of Fieldset element is not mentioned any new element, which should substitute the Fieldset element.

Also there is not Form API elements overview for Drupal 8, such as for Drupal 7. You have to manually search for all Render Elements definition in code, which is more time consuming (especially when you would like to see elements overview and compare them).

# Answer
> 35 votes
> All collapsible fieldsets have been replaced with HTML5 details elements.

Fieldset and legand are very hard to style and its not recommended to use with Drupal 8 any more. Instead its replaced with more cross browser way, which is the HTML5 Details & Summary tags.

```
'#type' => 'details'

```

https://www.drupal.org/node/1852020

Drupal 7

```
$form['advanced'] = array(
  '#type' => 'fieldset',
  '#title' => t('Advanced settings'),
  '#collapsible' => TRUE,
  '#collapsed' => FALSE,
  '#description' => t('Lorem ipsum.'),
);

```

Drupal 8

```
$form['advanced'] = array(
  '#type' => 'details',
  '#title' => t('Advanced settings'),
  '#description' => t('Lorem ipsum.'),
  '#open' => TRUE, // Controls the HTML5 'open' attribute. Defaults to FALSE.
);

```

# Answer
> 0 votes
Example using HereDoc notation to store the HTML Description:

```
$desc_html = <<<HTML
<p>
  <strong>Put the HTML to be displayed when open in here.</strong>
<p>
HTML;

$form['advanced'] = array(
  '#type' => 'details',
  '#title' => t('Advanced settings'),
  '#description' => t($desc_html),
  '#open' => TRUE, // Controls the HTML5 'open' attribute. Defaults to FALSE.
);

```

# Answer
> 0 votes
Drupal 8, change the form group default closed value to open programatically -

```
function hook_field_group_form_process_build_alter(array &$element, FormStateInterface $form_state, &$complete_form) {
      $node = $form_state->getFormObject()->getEntity();
      if ($node->hasField('field_pub_date') && !$node->get('field_pub_date')->isEmpty()) {
        $element['field_pub_date']['#attributes']['open'] = TRUE;
      }
}

```

---
Tags: forms, 8
---


# Question
Title: Loading content in a View via a sibling entity reference
I think what I need to do is use one Drupal View's results to filter the results of another view. Here is what I am trying to accomplish.

I have 3 content types (node types): Blog, Blog Post, Biography Page (aka Blog Author)

The blog post contains an entity reference to both the blog it should be in and one or more author's biography pages.

What I need to be able to do is take the ID for a given blog and get back all the authors that are associated via an associated blog post. Then remove any duplicates to show a list of all authors under a particular "blog".

I think I might be able to use a relationship. But still fuzzy on how that would work.

How can I accomplish this?

---

UPDATE: To clarify, I need to start with the Blog ID and using that find the authors of any blog posts that associate to said blog entity ID. Then take that resultset and dedupe it. I'm not worried about deduping. I just need help figuring out how to load the authors via that relationship.

Here is a diagram of this:

Thanks!

# Answer
I'm going to assume that this list of authors would appear, e.g., as a block on a blog post page, as in "Other authors associated with this post's blog." (I'm also assuming you're using Drupal 8 or 9)

You **can** do this with relationships:

1. The first relationship is through the blog post's blog ID field to get the blog
2. The next relationship uses the first with a "reverse" relationship through the same field to find all blog posts referencing that blog
3. The third relationship uses the second to get the authors through the Author ID

Here's a step-through I recommend using fields.

1. Add the first relationship. Give it a good readable "Administrative Title" because Drupal's built-in names become arcane very fast.
2. To check add the title field of the blog to confirm you've got what you expect. (You can always remove it later if you don't need it.)
3. Add the second relationship, being sure to use the first, and also give it a good name. Again use a field from the new relationship as a sanity check.
4. Add the third relationship being sure to use the second ...

You probably want to check the "require relationship" box in each case.

Yeah, I can see you getting a ton of duplicates that you'll have to remove. You *may* be able to get rid of some using Views' UI, but that's always dicey. You'll probably have to employ a view hook to clean up things.
> 1 votes

# Answer
Alright, so after dissecting Drupal Views a bit more and the query from it, I did this (which honestly was inspired by the suggestion in the answer from @beltouche).

So I setup a relationship using the blog post authors reference field. Set it as required. Then I setup a second required relationship via the field that referenced the blog and had it use the first relationship. This second relationship then gets used by a contextual filter that accepts the value of the blog ID and finds results that way.

Next, I found that the query was really close and just needed two joins modified. So I hacked it using query alter (details below). Finally, I set "Use aggregation" to "Yes".

**Here is my code:**

```
<?php
function my_module_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  if ($view->id() == 'authors' && $view->current_display == 'authors_eva') {
    /*
     * Basically what I did here is forced it to build the relationships in the way I know works
     * which I tested by manually rewriting the query and testing against the database.
     */
    $table_authors_field_data = $query->getTableInfo('blog_post_authors_node_field_data');

    if (!empty($table_authors_field_data)) {
      $table_authors_field_data['join']->leftField = 'blog_post_authors_target_id';
    }

    $table_node_blog = $query->getTableInfo('blog_post_authors_node_field_data__node__blog');

    if (!empty($table_node_blog)) {
      $table_node_blog['join']->field = 'entity_id';
      $table_node_blog['join']->leftField = 'entity_id';
      $table_node_blog['join']->leftTable = 'node__blog_post_authors';
    }
  }
}

```
> 0 votes

---
Tags: 8, views, entities
---


# Question
Title: Adding validation to existing forms using #element_validate
**Problem**

I'm using `#element_validate` to validate an input on a custom form which creates a node. I'm using `element_validate_integer_positive` as the function to validate. It works perfectly.

It partly works when I try to hook the same code into the existing node edit form. The form still breaks and displays the correct message but it also throws two errors due to missing values. How can I remove these errors?

**So far**

Here's the form code from my custom module. This works as expected.

```
$form['field_total_vacation'] = array(
  '#type' => 'textfield',
  '#title' => t('Total Vacation'),
  '#size' => 5,
  '#element_validate' => array('element_validate_integer_positive'),
);

```

Here's my hook into the node edit form:

```
function viewspagehack_form_alter(&$form, $form_state, $form_id) {
  if ($form_id === 'job_advert_node_form') {

    $form['field_total_vacation']['#weight']             = 19;
    $form['field_total_vacation']['#element_validate']   = array('element_validate_integer_positive');
    }
  }

```

If I enter a non-positive integer into `field_total_vacation` on the node edit form, it still breaks and throws the correct message: "Total Vacation must be a positive integer" but it also throws:

```
Notice: Undefined index: #value in element_validate_integer_positive() (line 4190 of C:\XAMPP\htdocs\drupal\includes\form.inc).
Notice: Undefined index: #title in element_validate_integer_positive() (line 4192 of C:\XAMPP\htdocs\drupal\includes\form.inc).

```

This is because `element_validate_integer_positive()` takes `$element` as it's first input and the function then calls:

```
$element['#value']
$element['#title']

```

But this error doesn't throw on my custom form which also doesn't take an input. What's going on?

**EDIT**

I moved #element\_validate to here, this means it now has access to `#title`:

```
$form['field_total_vacation']['und']['0']['#element_validate']   = array('element_validate_integer_positive');

```

This removes the title error but leaves the value error. I can't understand why this function takes `#value` from `$element`.

```
function element_validate_integer_positive($element, &$form_state) {
   $value = $element['#value'];

```

None of the form elements have `#value`, `#value` only seems to appear in `$form_state`. But yet it works in my custom form and not on the node edit.

# Answer
the method that work is this

```
function MYMODULE_form_NODE_FORMID_alter(&$form, &$form_state) {
  dpm($form);
  $form['body'][LANGUAGE_NONE][0][['#element_validate'][] = 'MYMODULE_validate_breads_node_form_alter';
}

/**
 * Implements callback function().
 * Specific alteration for views exposed forms
 */
function MYMODULE_validate_NODE_FORMID_alter($element, &$form, &$form_state) {
  if (empty($element['#value'])) {
    form_error($element, t('Text'));
  }
}

```
> 4 votes

# Answer
I ended up using the format of Jonathan's answer, although I added an extra validation function as opposed to putting it in `#element_validate`

```
function mymodule_form_alter (&$form, $form_state) {
  if ($form_id === 'node_edit_form_id') {
    $form['#validate'][] = 'mymodule_editjobadvert_validate';
  }
}

```

Two things to note about this. First `student_age` appears twice because the field can have multiple values and I need to check both.

Second each if checks if the value is a number or empty. Because empty is also ok.

```
function mymodule_editnode_validate ($form, $form_state) {
  /*element validate doesn't work when adding with form_alter for some reason. http://drupal.stackexchange.com/questions/86990/adding-validation-to-existing-forms-using-element-validate*/
  if(is_numeric($form_state['values']['field_total_vacation']['und']['0']['value']) || $form_state['values']['field_total_vacation']['und']['0']['value'] == NULL ) {
        } else {
          form_set_error('field_total_vacation', "Total Vacation must be a number");
    };
  if(is_numeric($form_state['values']['field_student_age']['und']['0']['value']) || $form_state['values']['field_student_age']['und']['0']['value'] == NULL ) {
        } else {
          form_set_error('field_student_age', "Student age must be a number");
    };
  if(is_numeric($form_state['values']['field_student_age']['und']['1']['value']) || $form_state['values']['field_student_age']['und']['0']['value'] == NULL ) {
        } else {
          form_set_error('field_student_age', "Student age must be a number");
    };
}

```
> 1 votes

# Answer
for Drupal 8 -9 here is an example of adding validation to all of a field type:

```
/**
 * Implements hook_field_widget_form_alter().
 */
function MYMOD_field_widget_form_alter(&$element, FormStateInterface $form_state, $context) {
  $field_definition = $context['items']->getFieldDefinition();
  $textarea_fields = [
    'text_with_summary',
    'text_long',
  ];
  if (in_array($field_definition->getType(), $textarea_fields)) {
    if (!empty($element['#element_validate'])) {
      $element['#element_validate'][] = '_MYMOD_textfield_validate';
    }
    else {
      $element['#element_validate']= ['_MYMOD_textfield_validate'];
    }
  }
}

/**
 * Implements hook_validate().
 */
function _MYMOD_textfield_validate($element, $form_state) {
  $max_length = 5000;
  if (!empty($element['#value'])) {
    $value = $element['#value'];
    if (strlen($value) > $max_length) {
      $form_state->setError($element, t('Sorry there is a max input value of 5000 characters'));
    }
  }
}

```
> 0 votes

---
Tags: 7, forms
---


title: Replace pages with static HTML pages

text:
# Question
Title: Replace pages with static HTML pages
I have a drupal 7 driven website. I need to replace a handful of pages on that website using static HTML without impacting the URLs of those pages.

For example I have a page accessible at: example.com/services/ That page is a proper drupal driven page. I want that page to display a proper HTML page I've written from scratch without any input from drupal engine but still retain the same URL so anything that leads to that page (internal & external links) would continue to work.

What's the correct way to set that up. Thank you!

# Answer
This is an old question, but the answer is still the same now as it would have been then. Drupal only kicks in if a file does not exist at the given URL and path. For example, if you try to access the following path on a Drupal instance, where nonexistentfile.html does not exist, Drupal will kick in and show a Drupal 404 message:

```
/[WEBROOT]/some/path/nonexistantfile.html

```

However, if you then create a file with that name at that location, that file wil be picked up rather than Drupal kicking in.

So the answer to the question is to create an .html file, and place it on the server at the required location, and it will be picked up.
> 1 votes

# Answer
lets say your url is : example.com/services , and services is 1 content type of drupal , and if you want to replace whole page with static html them create **services.html** page on root folder of your drupal and add whole html inside it and then run url it will display only html added in that html file.

Note : this html file name must be same as url , if url is **example.com/abc** then file name should be **abc.html**

Hope this helps you.
> 0 votes

---
Tags: 7
---


# Question
Title: Why is composer deleting and reinstalling core?
I am running Drupal 9.2.4 on Lando on Mac Big Sur. When I use composer to install a module it first deletes core.

```
Removing package drupal/core so that it can be re-installed and re-patched.
 - Removing drupal/core (9.2.4)

```

Then it reinstalls it.

```
 - Installing drupal/core (9.2.4): Extracting archive

```

If the module fails to install, no core!

I think these are the relevant lines from composer.json.

```
"drupal/core": "^9.2.4",
"drupal/core-composer-scaffold": "@stable",
"drupal/core-project-message": "9.2.4",
"drupal/core-recommended": "@stable",

```

Any ideas as to why this is happening and how to prevent it from happening?

# Answer
> 3 votes
When there is a patch set in your composer.json file or a composer.json file in one of your packages, composer will remove the package with a patch (in this case core) and reinstall it to apply all the patches. Look for a section that looks something like:

```
"patches": {
            "drupal/core": {
                "3035113 - EntityAccessChecker": "https://www.drupal.org/files/issues/2019-10-21/LatestRevisionCheck-13092187-24.patch",
                "2856823 - header links": "https://www.drupal.org/files/issues/2020-11-24/2856823-48__core-9.1.x.patch",
                "2784233 - Allow multiple vocabularies in the taxonomy filter": "https://www.drupal.org/files/issues/2021-05-28/2784233-193.patch"
            }
}

```

If not your composer.json file, check for a composer file of your distribution or profile. That’s the most likely place to find it.

---
Tags: composer
---


# Question
Title: Guzzle responses from POST on REST API are mixed
I develop a custom module to store and retrieve users data from an API. I used the user entity hooks to call the API on registration, edition and consultation of the Drupal users. It works well, and we use it on several website all using the same partner API.

To update or save the data, we use a POST method with the fields in the body and without URL parameters.

In some cases, when 2 users are registering or saving their account at the same time (max 3 seconds delay), then the information return in the POST response of the second call is the same as the first one.

\*** Edit \*** I forget to say, after each POST the page is reloaded and their is a GET on the API using the id\_contact that I store on the user data (states). I'm not sure if this is relevant. \*** /Edit \***

Here is the method I'm using to call the API:

```
/**
 * Make the Calls to the API.
 *
 * @param string $function
 *   The API endpoint to call.
 * @param string $method
 *   The method (GET / POST / ...).
 * @param array $data
 *   The data to POST to the API.
 *
 * @return array
 *   Array of data from the API, can be empty if error or no results.
 */
public static function callApi($function, $method = 'GET', array $data = []) {
  $srv_url = 'https://someapi.com/';

  if ($srv_url === '/') {
    return FALSE;
  }

  $headers = [
    'Content-Type' => 'application/json;charset=UTF-8',
  ];

  $token = self::getToken($srv_url);
  if ($token === FALSE) {
    return FALSE;
  }
  elseif ($token !== TRUE) {
    $headers['Authorization'] = 'Bearer ' . $token;
  }

  $options = [
    'headers' => $headers,
  ];
  $full_url = $srv_url . $function;

  if ($method === 'POST') {
    $options['body'] = Json::encode($data);
  }
  else {
    $full_url .= '?' . UrlHelper::buildQuery($data);
  }

  try {
    $client = \Drupal::httpClient();
    $mthd = strtolower($method);
    $response = $client->$mthd($full_url, $options);

    $statusCode = $response->getStatusCode();
    // Expected result.
    $jresp = Json::decode($response->getBody());

    // No result (GET).
    if ($statusCode == 204) {
      return [];
    }

    if (isset($jresp['code']) || !in_array($statusCode, [200, 201])) {
      // Something went wrong.
      $code = isset($jresp['code']) ? $jresp['code'] : $statusCode;
      if (isset($jresp['error'])) {
        $msg = $jresp['error'];
      }
      elseif (isset($jresp['message'])) {
        $msg = $jresp['message'];
      }
      else {
        $code = $statusCode;
        $msg = $response->getReasonPhrase() . '<br>' . $response->getBody()->getContents();
      }
      $message = "Response API {$method} - {$function} : {$code}<br>{$msg}<pre>" . print_r($response, TRUE) . '</pre>';
      \Drupal::logger('mymodule')->error($message);
      return [];
    }

    // Log posted result.
    if ($method === 'POST' && $function === 'contact') {
      AtixTools::debug('atix_crm_cible', ["Result API {$method} - {$function}" => ['options' => $options, 'resp' => $jresp]]);
    }
    if (isset($jresp['body'])) {
      return $jresp['body'];
    }
    return $jresp;
  }
  catch (RequestException $e) {
    watchdog_exception('mymodule', $e);
  }

  return [];
}

```

Here are an example of two calls where the data have been mixed. In the arrays are the options used for the POST request and the Body answered by the API.

```
Array
(
    [options] => Array
        (
            [headers] => Array
                (
                    [Content-Type] => application/json;charset=UTF-8
                    [Cache-Control] => no-cache
                    [Authorization] => Bearer XXXXXXX
                )

            [body] => @"email":ttf-test54@yopmail.com,"sms":"","nom":"ttf-test54","prenom":"ttf-test54","date_de_naissance":"","code_postal":"","ville":"","langue":"fr","id_filiale":9
        )

    [resp] => Array
        (
            [0] => Array
                (
                    [langue] => fr
                    [nom] => ttf-test54
                    [upd_date] => 2021-08-26 14:18:22
                    [id_contact] => 53550
                    [prenom] => ttf-test54
                    [email] => ttf-test54@yopmail.com
                )
        )
)

```

The second one has the same answer

```
Array
(
    [options] => Array
        (
            [headers] => Array
                (
                    [Content-Type] => application/json;charset=UTF-8
                    [Cache-Control] => no-cache
                    [Authorization] => Bearer XXXXXXX
                )

            [body] => @"email":ttf-test55@yopmail.com,"sms":"","nom":"ttf-test55","prenom":"ttf-test55","date_de_naissance":"","code_postal":"","ville":"","langue":"fr","id_filiale":9
        )

    [resp] => Array
        (
            [0] => Array
                (
                    [langue] => fr
                    [nom] => ttf-test54
                    [upd_date] => 2021-08-26 14:18:22
                    [id_contact] => 53550
                    [prenom] => ttf-test54
                    [email] => ttf-test54@yopmail.com
                )
        )
)

```

The people from the API assure me their is no cache on the server side, specially for a POST. The API is developed just for this purpose and is hosted on AWS (Amazon).

How is it possible that 2 calls to the API using Guzzle from two web pages are giving back the same set of data ? Is their a way Drupal or Guzzle are caching the response from the server ?

I looked a lot to find a solution to resolve this trouble, try using no cache header (like in this example), try reproducing it with Postman or a scenario in integromat without any success.

Thanks for some help.

\*** Edit2 \***

I had confirmation some data are mixed between 2 sites, which means it must come from the server side and the provider is working on a fix.

I choose to select the answer of @Yuseferi as good, even if it is not the case here, because it could have improve my code and I learn about ResourceResponse.

# Answer
> 1 votes
I think it's drupal cache,

instead of `return $jresp;`

try

```
$build = array(
  '#cache' => array(
    'max-age' => 0,
  ),
);

return (new ResourceResponse($jresp))->addCacheableDependency($build);

```

or

```
return new ModifiedResourceResponse($jresp, 200);

```

**note:** of course do not forget to add this classed in `use` section ;)

---
Tags: 8
---


# Question
Title: How do I fix this Configuration Directory sync error?
I can't get past this error while installing drupal on my localhost.

I've chmod'ed permissions on my core /default directory. I've:

```
/default on 755
/default/files including all subfolders and files on 744 (or 755)
/default/themes including all subfolders and files on 755
/default/modules including all subfolders and files on 755
/default/settings.php and /default/default.settings.php on 444

```

I've even double checked my apache configs to prepare for drupal8 install.

I'm stumped. I'm out of room to config everything. What's the proper course of action to fix this problem?

# Answer
> 4 votes
Create the directory specified in the error. This is fixed in an upcoming release.

# Answer
> 2 votes
Just put this

```
$config_directories['sync'] = "sites/default/files/config_acqTmp-2017-02-10T00.20.27-8325/sync";

```

on `settings.php` then Create that path with

```
   mkdir sites/default/files/config_acqTmp-2017-02-10T00.20.27-8325/sync

```

then rebuild the cache ( if you have drush, `drush cr` )

# Answer
> 2 votes
For beyond Drupal 8.8 versions you need to do the following

$settings\['config\_sync\_directory'\] = 'sites/default/files/\[your hash name\]';

# Answer
> 1 votes
I removed the settings.php file, copy the default.settings.php file (from the drupal 8 older version) to the /sites/default directory and changed it to settings.php On new setup I filled the details with the existing database name, username & password and it's gone. (It's not re-install your database, it uses the existing one)

# Answer
> 1 votes
Same error as others here. I don't use drush. So, I've been mucking around in the setttings.php file. I tried several fixes listed here, but none worked.

Aditya vardhan's trick worked for me :-)

A couple of tips: Your hash name should be the name of the folder in sites/default/files/ that contains the sync folder. If you have any other references in your settings.php to your sites/default/files/ config folder, that should be the same file name, too. (I had one upgrade attempt that had the wrong file name for the config folder)

You can copy that folder path from $config\_directories if you have that bit of code, or you can copy the config folder name from the sites/default/files path.

THIS worked for me: $settings\['config\_sync\_directory'\] = '**sites/default/files/config\_blah\_blah**';

(Replace config\_blah\_blah with whatever your folder name is, of course!)

This was an issue for me in upgrading from 8.9.13 to 9.1.4, but the above worked. For you non drush users or non-command line folks, you should be able to fix this with any editor + FTP/SFTP/SSH or CPanel File Editor. Good luck!

# Answer
> 0 votes
I had this issue when using Drupal 8.3.x, and found the procedure is a bit different. After installing Drupal and running the setup, I had this error. I went into sites/default/files, and found that the config folder already existed, so I copied that folder name, and added it to this string in settings.php:

```
$config_directories['sync'] = "sites/default/files/[your hash name]/sync";

```

This failed, so following the site instructions, did this:

```
$config_directories = array(
CONFIG_SYNC_DIRECTORY => 'sites/default/files/[your hash name]',
);

```

After this, running update.php and `drush cr` worked fine.

# Answer
> 0 votes
If you are interested, the config dir can be moved out of the web root. While I haven't had luck with providing a relative path, an absolute path works.

---
Tags: 8, installation
---


# Question
Title: entityQuery to get Nodes referenced by other nodes like an SQL JOIN
I have an entity query to get content of type `article` that has a field that matches a given value, which works as expected.

```
$query = \Drupal::entityQuery('node');
$query->condition('status', 1);
$query->condition('type', 'article');
$query->condition('field_some_field', 'some value');

```

Now I have a second content type `detail_page` that has an entity reference to a node of type `article`. I would like to get content of type `article`, *same as before*, but only those that have been referenced in the `field_detail_page_article_ref` field of a `detail_page` content type.

Is that possible with Entity Queries? Playing around with the raw SQL, what I basically need to do is an `INNER JOIN` or `LEFT JOIN` with the field `field_detail_page_article_ref` to see if the `nid` exists. But it doesn't seem like there is any sort of `join()` function available for entity queries.

# Answer
> 6 votes
I just had exactly the same problem with a Drupal 8 instance, and while I wasn't able to solve it with a single query as I'd've liked to, I did succeed with the following:

My goal was to get all the nodes of type A or B which meet certain criteria, one of which is that they are referenced by type C. (I've removed that other stuff here to focus on the issue.) Type has an entity reference field which allows multiple entries to either type A or B.

First we get all the nids that are referenced:

```
$connection = \Drupal::database();
$query = $connection->query("SELECT DISTINCT field_name_target_id  FROM {node__field_name}");
$referenced_nids = $query->fetchCol();

```

Note that you'll need to adjust your code to match the name of your reference field. See https://www.drupal.org/docs/8/api/database-api/static-queries, which is where I ripped that bit from.

Then my query to get the actual nodes/nids:

```
$storage = \Drupal::entityTypeManager()->getStorage('node');

$query = $storage->getQuery();

$nids = $query->condition('type', ['TypeA', 'TypeB'], 'IN')
  ->condition('status', 1)
  ->condition('nid', $referenced_nids, 'IN')
  ->sort('title')
  ->execute();

```

**UPDATE:** I learned today that the first step of my procedure is not considered proper by Drupal standards, as you shouldn't make direct queries on Drupal tables (see https://www.drupal.org/core/d8-bc-policy#schema). The following method is more brute force unfortunately, but caching the results should help.

Instead I refactored the first part using an EntityQuery.

```
// Get all the entities of type C, the referencing entity:
$query = \Drupal::entityQuery('node')
  ->condition('type', 'TypeC')
  ->condition('status', 1);
$typeC_nids = $query->execute();
$typeC_nodes = $storage->loadMultiple($typec_nids);

// Loop through the nodes and get all the references:
$referenced_nids = [];
foreach ($typeC_nodes as $node) {
 $references = array_column($node->field_name->getValue(), 'target_id');
 foreach ($references as $reference) {
   if (!in_array($reference, $referenced_nids)) {
     $referenced_nids[] = $reference;
   }
 }

```

}

Then use that list of the referenced NIDs in the second query.

# Answer
> 27 votes
You can use 'entity' field query

```
$query = \Drupal::entityQuery('node');
$query->condition('status', 1);
$query->condition('type', 'article');
$query->condition('field_some_field.entity:node.title', 'Referenced node title');

```

# Answer
> 2 votes
An example using `\Drupal::entityTypeManager()`:

```
$entityTypeManager = \Drupal::entityTypeManager();
$nodeStorage = $entityTypeManager->getStorage('node');
$nodeStorage->loadByProperties([
  'type' => 'mycontenttype',
  'field_entity_reference_field.entity:node.nid' => 3786,
]);

```

---
Tags: 8, database
---


# Question
Title: When there is a Drupal.org issue with patches on it already what is the best (most polite, easiest, most technically sound) way to make a GitLab fork?
Scenario: There is an issue with a patch. Perhaps the patch edits a module's `composer.json` for Drupal 9 compatibility such that the recommended way to use the patch is as an issue fork.

What is the best way (most polite, easiest, most technically sound) way to make a GitLab issue fork with the latest patch included? Or maybe more specifically i'm wondering:

1. There's no automated "Create issue fork from patch" button somewhere that i'm missing?
2. Applying the latest patch to an issue fork should be announced as identical to the latest patch in the issue? Or is it evident enough?
3. Are there plans or an effort to automate patch-to-fork (forks can already be used as patches)?

Thanks!

# Answer
> 1 votes
The user interface for an issue branch doesn't show, to users who can push code in it, a button to automatically apply a patch to the issue branch.

Supposing the issue branch doesn't exist, you can create it and apply the branch following these steps.

* Create the issue branch by clicking on the *Create issue fork* button that appears on the issue after the issue summary
* Follow the instructions given on Creating issue forks and merge requests » Cloning and committing code to an issue fork to set up the local repository for the issue branch
* Use `curl [patch-link] | git apply -` or `wget -q -O - [patch-link] | git apply -` to apply the patch to the issue branch local repository
* Push the changes in the issue branch

*\[patch-link\]*, for patches attached to issues on drupal.org is, for example, `https://www.drupal.org/files/issues/2021-08-28/2557319-17.patch`, not `https://www.drupal.org/files/2557319-17.patch` as Applying a patch in a feature branch seems to imply.

Posting a comment that explains you created the issue branch and applied the patch is fine. Users could find out the issue branch includes the patch, or assume you did that; commenting about what you did isn't wrong.

Looking at the issues for the project containing the drupal.org custom code, the ones for *Gitlab integration*, I don't see any issue for adding a button to apply a patch directly from the issue branch user interface, probably because it requires changing the Gitlab code, or it's not considered a necessary feature.

---
Tags: version-control, community-official-site
---


# Question
Title: How do I create an alias for the node edit page?
Pathauto can create path aliases for the node page. For example, it can change node/\[nid\] to project/\[nid\], where *project* is the content type. It doesn't change the path for the node edit page, which is still node/\[nid\]/edit, instead of project/\[nid\]/edit as I would expect it to be.

How could I set the path alias to project/\[nid\]/edit for the node edit page in Drupal 8, when the content type is project?

# Answer
There is a module for that: Sub-Pathauto

From the module page:

> The Drupal Path module matches only full URLs when creating SEO-friendly aliases. This module extends that behavior by also matching known sub-paths and replacing them with their respective alias. For example, if user/1 is aliased to users/admin, this module rewrites the link to the user contact page user/1/contact to use the aliased URL users/admin/contact instead.
> 2 votes

# Answer
Use a `src/Routing/RouteSubscriber.php` file in your module.

```
namespace Drupal\example\Routing;

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

/**
 * Listens to the dynamic route events.
 */
class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
    if ($route = $collection->get('entity.node.edit_form')) {
      $route->setPath('/project/{node}/edit');
    }
  }

}

```

Use a `example.services.yml` file in your module (if the module is named example).

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

```

https://www.drupal.org/docs/8/api/routing-system/altering-existing-routes-and-adding-new-routes-based-on-dynamic-ones
> 1 votes

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


# Question
Title: Is there a way to pass a value to a hidden field to multiple blocks printed from a template file?
The scenario is a template (tpl) file outputting a list of contact forms where each one is unique to a term ID in it section on the page. I need to generate a custom options list per printed Webform block using a tid passed from the section it's in in the template. So far I don't see any way to do this.

*sample.tpl.php*

```
<?php
   $block = module_invoke('webform', 'block_view', 'my-block-3581');
   print render($block['content']);
?>

```

The above is printed for each section (node) on the page and I have access to the tid where the Webform block is printed but I can't figure out any way to pass it to the form.

# Answer
you can always use `drupal_get_form` function to retrieve a form in drupal. this function allows you to send any needed arguments for example you can call it like this:

```
$form = drupal_get_form('SOME_FORM_ID', $argument1);

```

in this case `$argument1` value is passed and can be accessed in `hook_form_SOME_FORM_ID_alter` as follow:

```
if(isset($form_state['build_info']['args'][0]) {
  $form['SOME_ELEMENT']['#default_value'] = $form_state['build_info']['args'][0]; //as $arguments1 is passed as first parameter
}

```

now having this in mind, to get a webform using `drupal_get_form` you need this code snippet (better to use hook\_preprocess\_HOOK to add webform to your render array):

```
$nid = ; //YOUR WEBFORM NODE ID
$node = node_load($nid);
$submission = (object) array();
$enabled = TRUE;
$preview = FALSE;
$webform = drupal_get_form('webform_client_form_' . $nid, $node, $submission, $enabled, $preview, $YOUR_ADDITIONAL_ARGUMENT);

```

and then in your template file you can simply print your $webform:

```
print drupal_render($webform);

```

as I said you can use hook\_form\_alter to set default value of your hidden element using sent parameter.
> 1 votes

---
Tags: 7, webforms
---


# Question
Title: How to handle different output for a same block (Caching Problem)?
I have a theme which has two different appearance for main menu block, so I wrote a theme suggestion like this:

```
function MYTHEME_theme_suggestions_menu_alter(array &$suggestions, array $variables) {
  if ($variables['menu_name'] == 'main' and Drupal::service('path.matcher')
  ->isFrontPage()) {
    array_splice($suggestions, 1, 0, 'menu__main__front');
  }
}

```

so that I can theme main menu for front page in its own manner. The problem raises is about how Drupal caching system behaves about blocks so that when user navigates to other pages it uses the same block output which is produced for the first page. At first I thought that might be theme suggestion problem but then I realized that when I clear the caches it works fine.

Any suggestion for the case when we want a block be output in different manner based on some condition?

# Answer
> 0 votes
> Any suggestion for the case when we want a block be output in different manner based on some condition?

You want Cache Contexts: https://www.drupal.org/docs/drupal-apis/cache-api/cache-contexts

> Cache contexts provide a declarative way to create context-dependent variations of something that needs to be cached.

As hudri has stated, you need a cache context on `url.path`.

---
Tags: theming, blocks, caching, 9
---


title: Single form multiple submit

text:
# Question
Title: Single form multiple submit
I have one simple quick contact form (webform), it's working fine but sometimes when user fill form n submit it get submitted 2 times or 3 times.

I have checked the submission table that same data is submitted on same time 2 or 3 times.

This happens sometime but not for all submit .

If anybody have resolved this type of issue then please let me know how you have resolved it.

Thanks in advance.

# Answer
> 5 votes
You can try out a more general solution for all the forms by using Hide Submit Module

> Some users accidentally click the submit button more than once while waiting for their post to be saved. In some cases this may result duplicate postings or duplicate e-commerce orders.
>
> There are few ideas on how to solve duplicate postings but none is perfect. One of the solutions is a bit of jQuery to hide or disable the submit button after it has been clicked and replace it with an informative text such as "Processing..." .
>
> This module wraps that jQuery code and provides some options. Of course this, too, is not a perfect solution as it requires Javascript to be enabled. For browsers with Javascript disabled this module will have no effect at all.

# Answer
> 1 votes
Have you restricted the per user submission like below image.

Path for this perticular configuration is `node/%/webform/configure`.

# Answer
> 0 votes
You can prevent duplicate submissions for all webforms in /admin/structure/webform/config

It prevents someone from clicking submit twice and posting the exact same data.

If a user clicks submit and then back and submit again, you will get duplicate submissions.

If the user clicks submit twice (very fast) you will not get a duplicate submission.

---
Tags: forms, webforms
---


# Question
Title: Custom Submit Button On Inline Entity Form Triggers Gives Wrong Triggering Element
I have implemented `hook_field_widget_form_alter()` to add a new `#process` array item. E.g.

```
 hook_field_widget_form_alter() {
   $element['#process'][] = ['custom_process_function'];
 }

```

This part works fine to add in a new submit button that will save the contents of the current form send the user off to another page. E.g.\

```
custom_process_function(&$element) {
  $element['new_button'] = [
      '#type'                   => 'submit',
      '#value'                  => t('Upload new'),
      '#submit'                 => [
        [
          "Drupal\inline_entity_form\ElementSubmit",
          "trigger",
        ],
        [
          AddNewSubmitHandler::class,
          'handle',
        ],
      ],
      '#trigger'                => $this->fieldName,
      '#name'                   => $this->fieldName . '_add_new' . '_' . md5(json_encode($this->fieldParents)),
      '#ief_submit_trigger'     => TRUE,
      '#ief_submit_trigger_all' => TRUE,
      '#referenceType'          => $this->fieldReferenceType,
      '#referenceBundles'       => $this->fieldReferenceBundles,
      '#referenceEntityType'    => $this->entityType,
      '#referenceEntityBundle'  => $this->bundle,
      '#allowedFileTypes'       => $this->allowedFileTypes,
      '#validate'               => ['_custom_validate_function'],
    ];
}

```

However, the problem lies when it is loaded into Inline Entity Form field and then an ajax event is triggered. In my case, I am using an Entity Browser field within this form and when I click the `Remove` button and then click my custom button, the `$formState->getTriggeringElement()` is set to the next submit button that was on the original form, not even the next one in the Inline Entity Form.

Can anyone shed any light on why this is happening or how to fix it?

# Answer
The inline entity form element is not rendered at the moment the triggering element is being set to the $form\_state. See \Drupal\Core\Form\FormBuilder::doBuildForm for more details.

```
  // If a form contains a single textfield, and the ENTER key is pressed
  // within it, Internet Explorer submits the form with no POST data
  // identifying any submit button. Other browsers submit POST data as
  // though the user clicked the first button. Therefore, to be as
  // consistent as we can be across browsers, if no 'triggering_element' has
  // been identified yet, default it to the first button.
  $buttons = $form_state->getButtons();
  if (!$form_state->isProgrammed() && !$form_state->getTriggeringElement() && !empty($buttons)) {
    $form_state->setTriggeringElement($buttons[0]);
  }

```
> 0 votes

---
Tags: 8, ajax, entities
---


# Question
Title: How to create a view printing the latest 3 nodes with unique entity reference values
I have two content types, CAR and DRIVER. The DRIVER content type contains a CAR entity reference field. So each DRIVER node creation page can reference a specific CAR.

The goal is to build a view to print out 3 of the most recent unique CARs referenced from a DRIVER node (created by the logged-in user).

Example... here are 6 of the most recently created DRIVERS by a particular user.

* Driver 1 - BMW
* Driver 2 - BMW
* Driver 3 - Mercedes
* Driver 4 - BMW
* Driver 5 - Audi
* Driver 6 - Mercedes

The goal is to display 3 of most recent unique CARS referenced, like so...

* Driver 1 - BMW
* Driver 3 - Mercedes
* Driver 5 - Audi

The closest solution I've found is using Aggregation in views, but the sort order by Created Date doesn't actually sort them correctly.

I'm open to building this outside of views also. Any suggestions? Thanks!

# Answer
1. Create a view for Car content type
2. Add a relationship to Driver content referencing this content
3. Sort by created date using the Driver relationship
4. Use aggregation to show distinct values
5. Use pager settings to only show specific amount of items
> -1 votes

---
Tags: 8, views
---


# Question
Title: Why custom condition is not containing parent entity?
I'm using:

* Drupal 9.1.7
* Commerce 2.24

I'm trying to create my custom condition (based on https://docs.drupalcommerce.org/commerce2/developer-guide/core/conditions). However parent entity is always NULL. Seems like parent entity is only working when I specify `commerce_order` as `entity_type` only, but I need `commerce_order_item`. `ParentEntityAwareInterface` and `ParentEntityAwareTrait` are in use. Debugging show that:

```
  public function evaluate(EntityInterface $entity) {
    $this->assertEntity($entity);
    /** @var \Drupal\commerce_order\Entity\OrderItemInterface $order_item */
    $order_item = $entity;
    /** @var \Drupal\commerce_promotion\Entity\PromotionInterface $promotion */
    $promotion = $this->parentEntity;
    //$promotion is NULL
    // rest of the code
  }

```

`$promotion` is always null.

Annotation:

```
 * @CommerceCondition(
 *   id = "myproj_product_condition",
 *   label = @Translation("Product chooser"),
 *   category = @Translation("Product chooser"),
 *   entity_type = "commerce_order_item",
 *   parent_entity_type = "commerce_promotion",
 *   weight = 9,
 * )

```

# Answer
The docs note this:

> (If you want the Condition to apply to multiple parent entity types, you can leave this property unset; however, you will need to be careful in your evaluate() method implementation to check the type of the parent entity before accessing any of the parent entity's methods.)

So it seems the annotation would be:

```
 * @CommerceCondition(
 *   id = "myproj_product_condition",
 *   label = @Translation("Product chooser"),
 *   category = @Translation("Product chooser"),
 *   entity_type = "commerce_order_item",
 *   weight = 9,
 * )

```

and assert:

```
$promotion = $this->parentEntity;

if (check $promotion is a certain entity type) {
 ...
}

```

Clear your cache after updating the Annotation (and may have to re-create the Rule? unsure if it affects that). Beyond that it could be a bug in Drupal Commerce.
> 0 votes

---
Tags: commerce, 9, plugins
---


title: Display breadcrumbs on the front page

text:
# Question
Title: Display breadcrumbs on the front page
I installed Easy breadcrumb module and added Breadcrumbs block to my Block Layout. However, I can not make breadcrumbs appear on the front page. Block settings do not contain any that specify block display/hide on a specific pages. I have breadcrumbs on all other pages.

I am using a subtheme of Tara theme but I have no hooks that affect breadcrumbs. I have custom modules but they do not do anything to breadcrumbs.

I have checked the settings of Easy Breadcrumb and everything looks fine.

> Hide link to home page if it's the only breadcrumb item

This setting is OFF.

Can it be that the source of the problem is the front page path settings? Via Basic Site Settings it is set to /front, while all links to the front are actually just /.

Any help and assumptions will be appreciated.

# Answer
> 1 votes
In cases like this, it's often not worth spending any time trying to debug why a contributed module isn't behaving as expected, because the workaround is so simple.

The Block you want to see on the front page will always contain the same markup, so it does not need to be dynamically generated.

Copy the desired markup from another page that has the breadcrumbs, and place this markup in a custom Block.

It should be easy to create the desired Block either programmatically (with a very simple custom module) or via the Drupal UI. Make sure to edit the markup to remove the link from the word Home, and to remove any other breadcrumbs that follow.

Then place that block in the desired theme region, and set it to appear only on the front page.

---
Tags: breadcrumbs
---


# Question
Title: Prevent rendering of Layout Builder regions that have no content
Using Layout Builder, when you add a block to a layout that has access controls and a user visits a page without access, the layout is empty.

How does one prevent the layout from rendering at all if its contents are empty? While the `{% if content.foo|render|striptags|trim %}` trick works for block templates, I can't figure out how to get the same effect with layout templates.

The end result is I have extra markup in the page, which is classed and creating extra padding and vertical space between populated layout regions.

edit:

I have updated now with an event that Layout Builder needs:

```
class MyModuleEventSubscriber implements EventSubscriberInterface {

  /**
   * Layout Builder response event handler.
   *
   * @param SectionComponentBuildRenderArrayEvent $event
   *   Build render event.
   */
  public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) {
    $id = $event->getPlugin()->getPluginDefinition()['id'];

    if ($id == 'inline_block' && !$event->inPreview()) {
      $build = $event->getBuild();
      $build['#create_placeholder'] = FALSE;
      $event->setBuild($build);
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() : array {
    $events[LayoutBuilderEvents::SECTION_COMPONENT_BUILD_RENDER_ARRAY] = ['onBuildRender', 110];
    return $events;
  }

}

```

# Answer
This could be caused by placeholdering. Drupal formats placeholders as HTML tag. In your render test, `striptags` removes such placeholders, even if later, when the real rendering is happening, it is filled with a lazily-built block.

You can avoid it, at the expense of cache performance, by denying the block being placeholdered:

```
/**
 * Implements hook_block_build_BASE_BLOCK_ID_alter().
 */
function mymodule_block_build_example_block_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) {
  // Disable placeholdering of this block.
  $build['#create_placeholder'] = FALSE;
}

```

See Can BigPipe exclude certain blocks? This is not depending on BigPipe being enabled or not, but I think for both problems the solution is the same.
> 1 votes

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


# Question
Title: How do I add items from from the user module to a menu?
How do I add the core user module links such as *My account* and *Log out* to another menu?

# Answer
> 1 votes
The *My Account* and *Log Out* links are defined in `core/modules/user/user.links.menu.yml`

```
user.page:
  title: 'My account'
  weight: -10
  route_name: user.page
  menu_name: account
user.logout:
  weight: 10
  menu_name: account
  class: Drupal\user\Plugin\Menu\LoginLogoutMenuLink

```

As you can see they are hardcoded to the `account` menu. With this in mind, really the best thing to do is simply place both menus next to each other on the Block Overview page. This works for probably 95% of use cases. Your CSS should be written in a way to support that. For the other 5%, you could go as far as to piggyback your own links in a custom module. If you were to do so, it would/could look something like this:

`my_module.info.yml`

```
type: module
name: 'My Module'
description: 'Copy user links.'
core_version_requirement: ^8.8 || ^9
package: 'User'
dependencies:
  - user:user

```

`my_module.links.menu.yml`

```
my_module.user_page:
  title: 'My account'
  weight: -10
  route_name: user.page
  menu_name: YOUR_MENU_ID
my_module.user_logout:
  weight: 10
  menu_name: YOUR_MENU_ID
  class: Drupal\user\Plugin\Menu\LoginLogoutMenuLink

```

---
Tags: routes, navigation
---


# Question
Title: How to vary classes depending on content type?
In my `page.html.twig` template file, I'm looking to set classes depending on the content type the page is being viewed. I pretty much have two options, if the page being viewed is a program page, then I want one style applied to the div, if it's anything else, then the other style can be applied.

```
{%
  set aside_classes = [
    node.content-type is 'program' ? 'program',
    node.content-type is anything else ? 'standard'
  ]
%}

```

I know the above code is not proper but it's an example of what I'm trying to achieve.

I would then have the following code below on my div:

```
<div{{ content_attributes.addClass(aside_classes) }}>

```

Am I going about this right or is there a better way to achieve this?

EDIT: Here are my kint variables. Not sure if this helps at all?:

# Answer
> 2 votes
Not sure about page.html.twig. Would have to dig around...

In node.html.twig:

```
{%
  set newClassNameVar = [
    node.type.entity.label == 'Program' ? 'Program' : 'Not Program'
  ]
%}

<div{{ attributes.addClass(newClassNameVar) }}></div>

```

or:

```
{%
  set newClassNameVar = [
    node.bundle == 'content__type' ? 'set-yes-class' : 'set-no-class'
  ]
%}

<div{{ attributes.addClass(newClassNameVar) }}></div>

```

use debug such as `{{ dump(_context | keys) }}` to see what is available and best suits your use case.

# Answer
> 1 votes
Another way to do this is to add the class programmatically in your custom theme as discussed here.

```
/**
 * Implements template_preprocess_html().
 */
function MYTHEME_preprocess_html(&$variables) {
  if (isset($variables['node_type'])) {
    $node = \Drupal::routeMatch()->getParameter('node');

    // Add node-TYPE class to the element.
    $variables['attributes']['class'][] = 'page-node-' . $node->getType();
    $variables['attributes']['class'][] = 'page-node-' . $node->id();
  }
}

```

---
Tags: 8, theming
---


# Question
Title: Adding conditional comparison of two columns in relationship
I am trying to put value comparision while creating relationship. When i give direct value that works perfectly fine. but i wanted to pass column name with alias to get required results.

**This is working fine**

```
$this->query->add_where(
        $this->options['group'],
        db_and()
          ->condition("class.end_time", 1625047346 , '<=')
    );

```

**output**
WHERE ((( (class.end\_time \<= 1625047346) ))AND ...............

**This is not working. it takes alias.column as value**

```
$this->query->add_where(
        $this->options['group'],
        db_and()
          ->condition("class.end_time", "class1.end_time" , '<=')
    );

```

**output**
WHERE ((( (class.end\_time \<= 'class.end\_time') ))AND ...............

# Answer
I found a solution. I just passed all the conditions as an extra text after join and it works.

This is how I passed text while joining two tables. You can pass extra while constructing join as a fifth parameter.

```
class mymodule_booking_classes_relationship  extends views_handler_relationship {

    function query() {

        $extra = "class.end_time <=  class1.start_time  ";
        $extra .= " or class.start_time >= class1.end_time ";

        $join3 = new views_join;
        $join3->construct('class_table', 'node', 'nid', 'course_id', $extra, 'INNER');
        $this->alias = $this->query->add_relationship('class1', $join3, 'class1');

    }
}

```
> 0 votes

---
Tags: 7, views
---


title: Add action links in custom module page

text:
# Question
Title: Add action links in custom module page
I am writing a custom module for my project which handles a list of content (from custom db table) and content addition, following is my code.

```
function cp_menu() {
    $items = array();
    $items['admin/structure/package'] = array(
    'title' => t('Packages'),
        'page callback' => 'cp_packages_list',
        'access arguments' => array('administer access control'),
        'description' => t('Packages'),
        'type' => MENU_CALLBACK,
    );
    $items['admin/structure/package/add'] = array(
    'title' => t('Add package'),
        'page callback' => 'cp_form',
        'access arguments' => array('administer access control'),
        'description' => t('Add package'),
        'type' => MENU_CALLBACK,
    );
    return $items;
}

function cp_packages_list(){
    return 'this is a test page';
}
function cp_form() {
    return array('#markup'=>drupal_get_form('cp_my_form'));
}

```

it is working properly, but i want to show action links (add content type) at top of page like

How can i add action links on page?

my action links would be 'Add package' and 'View orders'

# Answer
```
$items['admin/structure/types'] = array(
    'title' => 'Content types',
    'description' => 'Manage content types, including default status, front page promotion, comment settings, etc.',
    'page callback' => 'node_overview_types',
    'access arguments' => array('administer content types'),
    'file' => 'content_types.inc',
  );
  $items['admin/structure/types/list'] = array(
    'title' => 'List',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -10,
  );
  $items['admin/structure/types/add'] = array(
    'title' => 'Add content type',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('node_type_form'),
    'access arguments' => array('administer content types'),
    'type' => MENU_LOCAL_ACTION,
    'file' => 'content_types.inc',
  );

```

This is what exist on node.module, modify to set the type to MENU\_LOCAL\_ACTION

Hope that help.
> 1 votes

# Answer
You can use hook\_menu\_local\_tasks\_alter() to add action links on any page.

Output that $root\_path to see what it is on a page, it is not the same as the actual path necessarily.

```
function YOURMODULE_menu_local_tasks_alter(&$data, $router_item, $root_path) {
  switch($root_path){
    case 'admin/structure/%':
      if ($router_item['original_map'][2] == 'path_arg') {
        $item = menu_get_item('admin/structure/types/add');
        if ($item['access']) {
          $data['actions']['output'][] = array(
            '#theme' => 'menu_local_action',
            '#link' => $item,
          );
        }
      }
    break;
  }
}

```

Credit to answer on d.o
> 0 votes

# Answer
Just change the type for the *admin/structure/package/add* from `MENU_CALLBACK` to `MENU_LOCAL_ACTION`. The purpose of `MENU_LOCAL_ACTION` is described in `hook_menu()`.

> `MENU_LOCAL_ACTION`: Local actions are menu items that describe actions on the parent item such as adding a new user or block, and are rendered in the action-links list in your theme.

In your case, the parent item of *admin/structure/package/add* is *admin/structure/package*, which is where you want the local action to appear.

Furthermore, there isn't any need to use a function that calls a form build as page callback: Just set `'drupal_get_form'` as page callback and set `array('cp_my_form')` as page arguments.

The code to use for `hook_menu()` is the following one.

```
function cp_menu() {
  $items = array();

  $items['admin/structure/package'] = array(
    'title' => 'Packages',
    'description' => 'Packages',
    'page callback' => 'cp_packages_list',
    'access arguments' => array('administer access control'),
    'type' => MENU_CALLBACK,
  );

  $items['admin/structure/package/add'] = array(
    'title' => 'Add package',
    'description' => 'Add package',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('cp_my_form')
    'access arguments' => array('administer access control'),
    'type' => MENU_LOCAL_ACTION,
  );

  return $items;
}

```

Also, the values for the menu title and the menu description are untranslated string. The description for those values given in the documentation for `hook_menu()` is clear about that.

> **"title"**: Required. The untranslated title of the menu item.
> **"description"**: The untranslated description of the menu item.
> 0 votes

---
Tags: 7, navigation
---


title: How to run check on each page load?

text:
# Question
Title: How to run check on each page load?
I would like to run a check on each page load. This only concerns the front end and not the admin dashboard.

Basically what I would like to do is: 1) User hits a URL in the drupal site. 2) A server-side check is ran. If the check passes, run some logic.

How would I accomplish this?

I'm guessing that I can use a hook, but what hook would that be?

Thanks.

# Answer
> 14 votes
`hook_init()` is run on every page load except for cached pages, so depending on your use case that might be an option.

```
function MYMODULE_init() {
  // Custom logic
}

```

`hook_boot()` is run on every page, including cached pages, so might be more useful (again depending on your use case). However if you have complex logic to process this will obviously slow down the build of every page, even those that are cached.

```
function MYMODULE_boot() {
  // Custom logic
}

```

If you want to check whether or not the current path falls under '/admin' you can use a check like this in either function:

```
if (arg(0) == 'admin') {
  // ...
}

```

This won't work for node edit pages, for example, who's path doesn't have '/admin' in it; but short of invoking `hook_admin_paths()` and testing the current URL against each of the paths returned, I'm not sure how you'd reliably test for that anyway.

# Answer
> 11 votes
I wanted to contribute something additionally to this. I am not an advocate of `hook_init()` or `hook_boot()` for doing tasks like this but tend to look for specific hooks that accomplish what you want. These two hooks are very broad and while they do they job they are also sometimes called multiple times per page load.

An alternative I would propose is `hook_page_build()`.

This will run on page builds and you don't have to worry about running things twice when you may not need to. I made a script for development sites where it would simply inject a bot restricting header line site-wide on pages. Likewise you could do the same as a check on each page load.

```
function my_module_page_build(&$page) {
  drupal_add_http_header('X-Robots-Tag', 'noindex,nofollow');
}

```

Similarly you could include a check for administrative pages

```
function my_module_page_build(&$page) {
  if (path_is_admin()) {
    foo();
  }
  else {
    bar();
  }
}

```

I prefer `path_is_admin()` as opposed to checking arbitrary arguments via `arg()`. Just my preference. Feels less hackish that way IMO.

# Answer
> 0 votes
Now with drupal 8 and 9, the approach outlined in this great blog post from chromatichq.com gives an excellent overview on how to execute code ignoring the cache.

If you require access to the user or session thou, it will also not help, as the `http_middleware` is very low level.

---
Tags: hooks
---


title: Frontpage slideshow not showing

text:
# Question
Title: Frontpage slideshow not showing
Here are the steps that I have taken:

1. Created a content type of "slide" with the following fields Title Body Link Image
2. Created 3 slides with "slide" content type.
3. Created a new view named "slideshow" using Views Slideshow (slideshow). The preview correctly displayed the slideshow.
4. Added the block "slideshow" in the theme's block "Featured"
5. Configured the block to show only slide content.
6. Saved the block.
7. Cleared the registry by typing "drush cr". Cleared.
8. Clicked Firefox refresh button.
9. Clicked the "Home". Only the "Welcome Text .." displayed. No slideshow.
10. Rechecked Views Slideshow to ensure that it is correctly displayed.
11. Update mariadb.
12. Refreshed. Still no slideshow.

Have I missed something?

Any help is greatly appreciated.

Thanks a lot.

M A Sani

# Answer
> 1 votes
Please clarify what you mean by "Configured the block to show only slide content."?

This seems off to me as you would instead configure the VIEW to only show slide content. When it comes down to block configuration, those settings are for *visibility* aka what urls and/or types of pages that block region will show that block.

If you wanted the block to be on the homepage only, you would add `<front>` in the *Pages* tab of the block visibility settings.

If you did indeed "configure the block to only show on slide content", then you told Drupal to show the block when you are actually viewing a slide node page aka "node/xx" where xx is a node id of a slide.

---
Tags: views
---


# Question
Title: Modify custom module's setting.yml without reinstalling
I have made a simple custom module in Drupal 8, in which I use a settings file (config/install/my\_module.settings.yml)

I have one entry, let's say

```
module:
  key: 'qsdqsd'

```

So when I install the module, I can use this entry in my controllers. But if I need to modify anything in this file (adding an entry, for instance...) I can't use it in my controllers (config-\>get(module.new\_entry) returns NULL) unless I uninstall then reinstall the module.

`drush cache-rebuild` did not help neither.

What am I missing?

# Answer
The correct way to handle this would be to write a hook\_update\_n() function and write the code out that would add those new config keys.

Then you would run `drush updb` and it would be added to the website.

The other answer is correct as well. I use both together and we can track everything in GIT from dev \> stage \> prod in case there are changes.
> 2 votes

# Answer
You can try the module config\_sync, there you can update the site's configuration from your custom module.

afaik there is no official way to update configuration from an updated module.
> 0 votes

---
Tags: 8, configuration
---


# Question
Title: What is the proper process to customize htaccess files?
We have custom redirect links that use the RedirectMatch rules that redirect based on a root path. We'd rather handle these at the web server level rather than using the Redirect module (if it can even do match based rules), so we put these rules in the `.htaccess` file, e.g.:

```
RedirectMatch 301 ^/computing/hpc[/]?(.*) https://hpc.our.domain/$1

```

Since the `.htaccess` file is updated with a composer install because of the scaffolding, what is the best process for adding our rules to the file? I’m not looking to prevent the scaffolding from updating the `.htaccess` file, but I may need to modify our patch from time to time so that it is applied to the newest version.

How do you go about editing and updating the patch when something needs to get added or removed?

# Answer
> 1 votes
Ryan Hartman's answer was great. We ended up taking a slightly different route. As with Drupal, there are often many ways of doing things.

We added this section to our `composer.json` file:

```
"scripts": {
        "post-drupal-scaffold-cmd": [
            "cd docroot && patch -p1 <../patches/htaccess.patch"
        ]
    }

```

Our `.htaccess` file is still part of our git repo. Each time we need to edit the rules, we make all the necessary changes to the `.htaccess` file and then we run a bash script (actually a Docksal custom fin command) that generates the patch file. The script looks like this:

```
mkdir temphtaccess
cd temphtaccess
git init
cp "${DOCROOT_PATH}/core/assets/scaffold/files/htaccess" "${PROJECT_ROOT}/temphtaccess/.htaccess"
git add .
git commit -m 'Scaffold htaccess commit'
cp "${DOCROOT_PATH}/.htaccess" "${PROJECT_ROOT}/temphtaccess/.htaccess"
git diff > ../patches/htaccess.patch
cd ${PROJECT_ROOT} && rm -rf temphtaccess

```

# Answer
> 1 votes
Depending on level of customization, there are two strategies you could employ.

* Patch drupal/core with a modified htaccess file including your customization.
* Override the htaccess file via scaffolding.

If you choose the first option here is a really easy way to do it.

1. Checkout the version of Drupal you are using to a folder.
2. Adjust the htaccess file in assets/scaffold.
3. Run `git diff > htaccess.patch`.
4. Go back to your project and create a patches folder, place the new file inside.
5. Add the following to composer.json `extra` section (make sure you have installed cweagans/composer-patches):

```
"patches": {
  "drupal/core": {
    "Add redirects": "patches/htaccess.patch"
  }
}

```

If you choose option two:

1. Create an assets/scaffold folder(s) in your project.
2. Copy the htaccess file inside of it.
3. Make your adjustments to the file.
4. Add the following to composer.json `extra` section:

```
"drupal-scaffold": {
  "locations": {
    "web-root": "web/"
  },
  "file-mapping": {
    "[web-root]/.htaccess": "assets/scaffold/.htaccess"
  }
}

```

---
Tags: composer, .htaccess
---


# Question
Title: Using the entity query API to identify entities with correlated values
Imagine two Drupal 9 custom entity types named `a` and `b`.

Entity type `a` has two fields `a_f1` and `a_f2`.

Entity type `b` has a field `b_a` which is an entity reference with a target type of `a` and unlimited cardinality.

How does one create an entity query which finds all entities of type `b` at least one of whose `b_a` entity references points to an `a` entity which has value 'v1' for its field `a_f1` and value 'v2' for its field `a_f2`?

It's not appropriate in this case to find a `b` which has one entity reference pointing to an `a` entity with `a_f1` of 'v1' but `a_f2` of 'something else', and another entity reference pointing to a different `a` entity with `a_f2` of 'v2' but `a_f1` of 'wrong value'.

I could do this in my sleep with direct SQL queries, but that's frowned on in the Drupal world. I'm having a hard time finding the guidance for doing this the *Drupal Way* in the official Drupal documentation.

Does the Drupal entity query API support this functionality?

# Answer
> 3 votes
The following code would achieve what described in the question.

```
$result = \Drupal::entityQuery('b')
  ->condition('b_a.entity:a.a_f1', 'v1')
  ->condition('b_a.entity:a.a_f2', 'v2')
  ->execute();

```

In the first string passed to `condition()`:

* *b\_a* is the field name
* *.entity:a* says that field is an entity reference for an *a* entity
* *a\_f1* and *a\_f2* are fields for the *a* entity

For more information about the values accepted for the first `condition()` argument, see `QueryInterface::condition()`.

In the case the *b\_a* field is a multi-value field, both the conditions would refer to the same delta, which means the value of the *a\_f1* and *A\_f2* fields are taken from the same *a* entity.
The code I wrote at the beginning of the answer returns all the entities for which both the conditions are met. If you want to get all the entities for which one of the conditions is true, the following code should be used.

```
$query = \Drupal::entityQuery('b');
$group = $query->orConditionGroup()
  ->condition('b_a.entity:a.a_f1', 'v1')
  ->condition('b_a.entity:a.a_f2', 'v2');
$result = $query->condition($group)->execute();

```

---
Tags: entities
---


# Question
Title: How can I have a custom block show different content on the front page?
I have a custom module, in Drupal 9, (showing a block in a region) that has an admin form with a checkbox for showing only on the "front page" or if unchecked on "all" pages.

In order for the block to show on the homepage or on all pages do I need some sort of preprocess function to run before the block loads? Does the build() only happen once and then is cached? If so, how do we let the block know what page it belongs on programmatically?

I have a simple build function to test this (build() is inside src/plugin/block), which doesn't work:

```
 public function build(){
        $alert_front = \Drupal::config('alert_front.settings')->get('front');
        $current_is_front = \Drupal::service('path.matcher')->isFrontPage();

      if ($current_is_front) {
        return [
          '#markup' => $this->t("Yes, Front Page Only"),
        ];
      }else{
       return [
        '#markup' => $this->t('@alert and @fp',[
          '@alert' => alertType($alert_type),
          '@fp' => $alert_front,
        ]),
       ];
     }
}

```

The Drupal block api isn't giving me much here, but I'll keep digging. Thanks for any ideas.

# Answer
Usually you restrict a block to a Content Type, Pages or Roles (or a mix of them) when placing the block in the block edit dialog - see https://www.drupal.org/docs/core-modules-and-themes/core-modules/block-module/managing-blocks

> Still, this will not handle caching for your dynamic block content.

If you want to make this "switch" in your build method, you definitely need to think about caching yourself, see fe. this answer from @Berdir https://drupal.stackexchange.com/a/199601/3218

You could use the `url.path.is_front` context - see https://www.drupal.org/docs/drupal-apis/cache-api/cache-contexts for more information

Maybe splitting your block into two different blocks will make it easier and clearer.
> 1 votes

---
Tags: blocks, caching, 9
---


# Question
Title: Migration of a custom Rest API using PATCH/POST
I had a custom REST API working with Drupal 8 perfectly. After upgrading to Drupal 9.2.X, the *Patch* and *Post* methods of this custom REST API stopped working. Now they throw the following exception.

> RuntimeException: Callable "Drupal\my\_module\Plugin\rest\resource\UpdateBoxes::patch" requires a value for the "$payload" argument. in Drupal\Component\Utility\ArgumentsResolver-\>handleUnresolvedArgument() (line 143 of /var/www/docroot/core/lib/Drupal/Component/Utility/ArgumentsResolver.php).

The code I am using is the following one.

```
namespace Drupal\my_module\Plugin\rest\resource;

use Drupal\rest\ModifiedResourceResponse;

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "update_boxes",
 *   label = @Translation("Update boxes"),
 *   uri_paths = {
 *     "canonical" = "/api/container/{container_id}/{type}/{product_id}/boxes"
 *   }
 * )
 */
class UpdateBoxes extends ResourceBase {

  /**
   * A current user instance.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  protected $boxesHandler;

  protected $event_dispacher;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $instance->currentUser = $container->get('current_user');
    $instance->boxesHandler = $container->get('boxes.handler');
    $instance->event_dispacher = $container->get('event_dispatcher');

    return $instance;
  }

  /**
   * Responds to PATCH requests.
   *
   * @param $container_id
   * @param $type
   * @param $product_id
   * @param $payload
   * @return \Drupal\rest\ModifiedResourceResponse
   *   The HTTP response object.
   */
    public function patch($container_id = null, $type = null, $product_id = null, $payload) {
      //My code here.

    }

}

```

In `patch()` I could read `$payload` and see the array sent in the request, but after upgrading the site, `$payload` is `NULL`.

The solution I found was changing the last argument of `patch()` and extract the payload from the `$request` object.

```
public function patch($container_id = null, $type = null, $product_id = null, Request $request) {
  // …
  $payload = json_decode($request->getContent(), TRUE);
}

```

I couldn't find any documentation about this change; I am not sure it was a good practice or the better implementation to get the payload working.

# Answer
I'm having the same issue with a *get* method. It seems to be related to the conversion of the parameters (see reported issue). I was able to work around the issue by using simple parameter names, for example, remove all the underscores in the comments and the method parameter names:

```
"canonical" = "/api/container/{containerid}/{type}/{productid}/boxes"

```

And in the method:

```
public function patch($containerid = null, $type = null, $productid = null, Request $request) {

```
> 3 votes

---
Tags: migrations, 9
---


# Question
Title: Webform address feilds are not populating from the querystring
I have a webform at http://safebuy.nz/New?your\_name=John%20Argent&your\_email\_address=grub@hotmail.com&address=28%20smith%20Rd&address2=&city=&state\_province=Northland&postal\_code=&phone\_number=0220492570&bank\_account\_number=

The address feilds are not populating from the querystring.

This page is also showing a date at top of form that shouldnt be there.

# Answer
You need to target the composite address element's sub-elements.

http://safebuy.nz/New?your\_address\[address\]=28%20smith%20Rd&your\_address\[address2\]=&city=&your\_address\[state\_province\]=Northland&your\_address\[postal\_code\]=&phone\_number=0220492570
> 1 votes

---
Tags: webforms
---


# Question
Title: How to add custom option value to select field in Webform and have them save with the submission?
I have a Drupal 7 webform when I need to dynamically populate a select field's options. I'm currently using hook\_form\_alter() and setting the values on the like so:

```
<?php
 $form['submitted']['left']['select_field_name']['#options'] = $new_options;
</php>

```

This works for displaying the new options on the webform creation but the values are not saved with the form.

I know there is a hook\_webform\_select\_options\_info() hook to create predefined options but it does not take any parameters so I have no way to pass a value from the webform to tell it how to dynamically create the options.

Is there any way to create a dynamic select option list and have it save the values that were not in the original Webform select values list?

# Answer
I solved this issue by populating all possible options through hook\_webform\_selection\_options() and then resetting the options in hook\_form\_alter() to remove the ones I don't need for that instance.
> 0 votes

# Answer
You also can use a text field element rather than an Select element , and then in hook\_form\_alter change the element type to select and apply your desired options to that, in this case webform won't ignore input value as there is no restriction for textfield (if no regex or ... is set)
> 0 votes

---
Tags: 7, webforms
---


title: How can I overwrite a hook from a theme

text:
# Question
Title: How can I overwrite a hook from a theme
I have a custom sub-theme of the Seven theme. The Seven theme makes some node alteration via `seven_form_node_form_alter()`. I would like to have `seven_form_node_form_alter()` not run at all or I would like to overwrite it. How can I accomplish this?

I tried `hook_module_implements_alter()` but there was no implementation of Seven in there. (I'm wondering if that only works with modules.)
Another thought was `hook_theme_registry_alter()` but I couldn't see anything there about form alters.

# Answer
> 2 votes
`hook_module_implements_alter()` allows just to alter the hooks implemented by modules, and `hook_theme_registry_alter()` alters only the theme functions, not hooks.

If you look at the code of `drupal_alter()`, the function that invokes all the alter hooks, you will see the following code, which deals with alter hooks implemented by themes.

```
// Allow the theme to alter variables after the theme system has been
// initialized.
global $theme, $base_theme_info;
if (isset($theme)) {
  $theme_keys = array();
  foreach ($base_theme_info as $base) {
    $theme_keys[] = $base->name;
  }
  $theme_keys[] = $theme;
  foreach ($theme_keys as $theme_key) {
    $function = $theme_key . '_' . $hook;
    if (function_exists($function)) {
      $functions[$cid][] = $function;
    }
    if (isset($extra_types)) {
      foreach ($extra_types as $extra_type) {
        $function = $theme_key . '_' . $extra_type . '_alter';
        if (function_exists($function)) {
          $functions[$cid][] = $function;
        }
      }
    }
  }
}

```

The alter hooks implemented by the base themes run first; if you have a sub-theme, and that is the current theme, its alter hook will run last. The only thing I see you could do is (in the implementation of the same hook done from your theme) to remove the changes introduced by `seven_form_node_form_alter()` that you don't want in your theme.

# Answer
> 1 votes
I'm a bit late for answering this but the solution is:

```
/**
 * Implements hook_form_alter().
 */
function mymodule_form_node_form_alter(&$form, FormStateInterface $form_state) {
 $form['#after_build'][] = '_mymodule_after_build';
}

/**
 * Form #after_build callback for hook_form_alter().
 */
function _mymodule_after_build(array $form, FormStateInterface $form_state) {
  $form['#theme'] = ['my_own_template'];
  return $form;
}

```

---
Tags: 8, hooks
---


# Question
Title: How to know if a batch process is still running?
I have a form with 5 buttons and each button run a different batch, some batch processes take several minutes. I want to block the button if the batch processes is already running, because other user admin can access to the same form and try to run the batch that is already running at this moment for other user.

How can i know what batch processes is running? i try using batch\_get(); but every time this function return an empty array.

# Answer
As per the API, once you define a batch, you provide the callback function that will be executed when the batch finishes, so until this callback is called, the batch is still ongoing.

So ideally your batch definition would perform an initial action to like setting a DB status that you can query and if it is blocked, you disallow the button, and once your finished callback is executed, you unlock the button again.
> 1 votes

---
Tags: 8, batch-operations
---


title: Libraries, CSS, and conditional loading

text:
# Question
Title: Libraries, CSS, and conditional loading
In looking at the attached screen shot from mytheme.libraries.yml, I see 'base:', 'component', 'layout', 'theme', and so on.

Do these designations represent/do anything in practice? Or is this just for organization of the libraries.yml file, or does this imply where/when these CSS files load? For example, form.css only loads when a form is present.

I can see this happening in modules, but in the theme.libraries file?

Also, why isn't a 'yml' or 'yaml' tag available here? y

# Answer
You should review the Adding stylesheets (CSS) and Javascript (JS) to a Drupal module and Drupal theme docs. Unfortunately, there's information in one that's not in the other, but *I believe* all of the information pertaining to defining a library, i.e. creating a libraries.yml file, applies to both modules and themes.

> Looking at mytheme.libraries.yml, I see 'base', 'component', 'layout', 'theme', and so on. **Do these designations represent/do anything in practice?**

Yes, they do stuff. Primarily, they change the order that the files are loaded (lower weights are loaded first). It's also a good way to organize your CSS (these keys only apply to CSS, not JS) conceptually so as to make it easier to find, debug, and fix any issues or make changes.

From the docs:

> \[base, layout, component, state, theme keys\] indicate the style type the CSS file belongs to.
>
> You can set CSS weights with 5 different levels of styling:
>
> * base: CSS reset/normalize plus HTML element styling. Key assigns a weight of `CSS_BASE = -200`
> * layout: macro arrangement of a web page, including any grid systems. Key assigns a weight of `CSS_LAYOUT = -100`
> * component: discrete, reusable UI elements. Key assigns a weight of `CSS_COMPONENT = 0`
> * state: styles that deal with client-side changes to components. Key assigns a weight of `CSS_STATE = 100`
> * theme: purely visual styling (“look-and-feel”) for a component. Key assigns a weight of `CSS_THEME = 200`
>
> This is defined by the SMACSS standard. So here if you specify theme it means that the CSS file contains theme related styling which is pure look and feel. More info here. You cannot use other keys as these will cause strict warnings.

These keys do not provide any conditional loading of the files. They're all always loaded when the library is included, the keys only change the order in which the individual files are loaded. (If you're using aggregation, they will all be in the one file, but the order will be preserved.) To conditionally load files, you'll need to create separate libraries (you can define multiple libraries in the same libraries.yml file) and then attach the individual libraries only when you need them.

There are a number of ways to attach a library to a page, see the Attaching a Library to Page(s) section of the module and theme docs noted above.
> 1 votes

# Answer
`base`, `components` etc. are SMACSS inspired categories, a method of organizing CSS in large scale projects (in Drupal this also means load order). And YAML in here makes no sense, you can't add YAML to a HTML document.
> 2 votes

---
Tags: theming
---