# Question
Title: Optimal way to get a content type's field definition
When I need a content type's field definition in Drupal 8+, I used to run the following code (for getting 'body' field in content type 'page'):

```
$page_fields = \Drupal::getContainer()->get('entity_field.manager')
               ->getFieldDefinitions('node', 'page');
$body_definition = $page_fields['body'];

```

I learned, that it is also possible by running the following code:

```
$body_definition = \Drupal::entityTypeManager()
                  ->getStorage('field_config')
                  ->load('node.page.body');

```

Now my question is, what's an advantage of one over the other? The latter is of course only one line, but that can't be the end of the story, I guess. Is one of these ways the "Drupal way"?

# Answer
> 3 votes
Field definitions can be defined in different places. The first code examples gets all definitions, the second code example only a specific field definition and it finds only configured fields.

The service `entity_field.manager` is responsible for discovering fields in multiple locations, configuration and a lot of different methods in code, which might be extended in future to find even more. So using this service is the most generic way to get field definitions.

Use `\Drupal` only in hooks, not in classes. And then you can reference services via `\Drupal::service('entity_field.manager')`, you don't need to get the container.

---
Tags: entities, 9
---


# Question
Title: Is there an easy way to get the image derivatives links?
I'm working with complex image styles, and I'd like to be able to load all the different derivatives quickly to check they're being processed correctly.

But I don't see how to easily get the links. The best I can come up with is opening the node in JSONAPI and, with the patch from https://www.drupal.org/project/drupal/issues/2825812, getting the URLs for derivatives from that.

It there something easier?

Back in the Drupal 6 days, the Image module showed the links to all the sizes on the image node itself.

# Answer
You can get that info with the following code:

```
$original_uri = 'public://images/image.jpg';

$styles = \Drupal::entityTypeManager()->getStorage('image_style')->loadMultiple();

$urls = array_map(function($style) use ($original_uri) {
  return $style->buildUri($original_uri);
}, $styles);

```

`$urls` should now contain a list of URLs based on the original, one for each image style in the system.
> 1 votes

# Answer
To get the image derivative URI for an image to which is applied a specific image style, you can use the following code.

```
// Load the ImageStyle instance in $image_style, for example with
// $image_style = ImageStyle::load($id).
// $image_uri is the path/URI for the image to which the style is applied.
if ($image_style->supportsUri($image_uri)) {
  $derivative_uri = $style->buildUri($image_uri);
}

```

Keep in mind that image derivatives are created only when the URL returned from `$image_style->buildURL($image_uri)` is requested (from a browser). Building the URI (or the URL) doesn't generate the derivative image; it returns the URI (URL) for an image that couldn't exist, yet.

To check an image derivative could be created, code similar to the one used from `ImageStyleDownloadController::deliver()` should be used.

```
if ($image_style->supportsUri($image_uri)) {
  $derivative_uri = $style->buildUri($image_uri);

  if (!file_exists($image_uri)) {
    $path_info = pathinfo($image_uri);
    $converted_image_uri = $path_info['dirname'] . DIRECTORY_SEPARATOR . $path_info['filename'];
    if (file_exists($converted_image_uri)) {
      $image_uri = $converted_image_uri;
    }
  }

  $success = file_exists($derivative_uri) || $image_style->createDerivative($image_uri, $derivative_uri);

  if ($success) {
    $image = Drupal::service('image.factory')->get($derivative_uri);
    $uri = $image->getSource();
  }
}

```
> 1 votes

---
Tags: 8, media
---


# Question
Title: How do I enable CkEditor for a textarea form element?
I have a custom form and the following textarea element.

```
$form['fieldset']['email_template'] = array(
  '#type' => 'textarea',
  '#title' => t('E-mail template content'),
  '#default_value' => '',
  '#description' => t('A valid template for email trigger.<b>Please type ":" for variable suggestions</b>'),
  '#required' => TRUE,
  '#cols' => 60,
  '#resizable' => TRUE,
  '#rows' => 5,
);

```

After I installed the *CkEeditor* module and enabled it, the following text appeared under that form element.

>

I added *sky:notification/addTemplate.edit-email-template* in the *CkEditor* module settings as element ID that should use the CkEditor, but the editor is still not used for that element.

How can I enable CkEditor for the *email\_template* element?

# Answer
> 0 votes
You need to add `'#wysiwyg' => TRUE` and use `'text_format'` for `'#type'`.

The form element definition would then be the following one, instead of the one you are using.

```
$form['fieldset']['email_template'] = array(
  '#type' => 'text_format',
  '#wysiwyg' => TRUE,
  '#title' => t('E-mail template content'),
  '#default_value' => '',
  '#description' => t('A valid template for email trigger.<b>Please type ":" for variable suggestions</b>'),
  '#required' => TRUE,
  '#cols' => 60,
  '#resizable' => TRUE,
  '#rows' => 5,
);

```

# Answer
> 0 votes
You can just do that by adding `'#format' => 'filtered_html'` and `'#type' => 'text_format',`.

---
Tags: 6, forms, wysiwyg
---


# Question
Title: How to add html tags to account setting emails?
I am working on a project where I need to add some custom headers to the email which we send to the user on registration. Is there a module which support this functionality?

# Answer
> 0 votes
Have a look at Mail Headers project. As says doc, it allows you to control and modify any (almost any) mail header.

# Answer
> 0 votes
You can add a custom header to the email by using a custom module that uses hook\_mail\_alter() to set the custom email headers.

You can also use these contrib modules:

---
Tags: emails, users
---


# Question
Title: Creating a view with an exposed filter for "is not empty" where all results are shown by default
I'm creating a view. By default, I want all results shown, with an exposed filter for 'has a value' (aka is not empty) and 'is empty'.

I cannot figure out how to make the exposed filter work for this. If I make the exposed filter on either 'is empty' or 'is not empty', it filters the values initially based on that section. I only want the exposed filter to take effect when the value is in the URL.

Can anyone point me how to do that?

# Answer
You can configure your exposed filter with these configurations to show all the content in the initial state:

* Check: Expose this filter to visitors, to allow them to change it
* Filter type to expose: Single filter
* Operator: Is one of
* Selection in the RHS: Do not select anything.

Once you save this, your view should show all the results when view output is rendered, and filter the results based on the exposed filter selection.

Hope this helps.
> 1 votes

---
Tags: views, 9
---


title: Site branding not displaying correctly

text:
# Question
Title: Site branding not displaying correctly
I'm working on a new theme for the Rain distribution (Drupal 9), but I'm having a hard time showing site branding correctly. This is the first time I'm trying to make a theme, so sorry if I ask stupid.

Site\_logo, site\_name and site\_slogan are displayed on top of each other.

Here are excerpts from cloud\_theme.theme:

```
/**
 * Implements hook_preprocess_HOOK().
 */
function cloud_theme_preprocess_block(array &$variables) {
  // Use inline svg in the branding block.
  if ($variables['plugin_id'] == 'system_branding_block') {
    $variables['attributes']['class'][] = 'clearfix';
    if (isset($variables['site_logo'])) {
      $logo_path = DRUPAL_ROOT . $variables['site_logo'];
      // If logo is a SVG lets load it content so we can inline it.
      if (strlen($logo_path) - strpos($logo_path, '.svg') === 4) {
        $variables['site_logo_svg'] = file_get_contents($logo_path);
      }
    }
  }
}

```

Here are excerpts from cloud\_theme.libraries:

```
site-branding:
  css:
    component:
      dist/css/site-branding.css: {}

```

Here is my site-branding.css file:

```
/**
 * @file
 * Visual styles for the site branding block in Cloud theme.
 */

.site-logo {
  display: inline-block;
  margin-right: 1em; /* LTR */
  margin-bottom: 0.286em;
  border-bottom: 0;
}
[dir="rtl"] .site-logo {
  margin-right: 0;
  margin-left: 1em;
}
.site-text {
  display: inline-block;
  vertical-align: top;
}

@media all and (min-width: 461px) {
  .site-text {
    margin-bottom: 1.857em;
  }
}

@media all and (min-width: 901px) {
  .site-text {
    padding: 1.286em 0 0;
  }
}
.site-name {
  color: #686868;
  font-size: 1.6em;
  line-height: 1;
}

@media all and (min-width: 901px) {
  .site-name {
    font-size: 1.821em;
  }
}
.site-slogan {
  margin-top: 7px;
  word-spacing: 0.1em;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 0.929em;
  font-style: italic;
}

```

Here is my block--system-branding-block.html.twig file:

```
{% extends "block.html.twig" %}
{#
/**
 * @file
 * Cloud's theme implementation for a branding block.
 *
 * Each branding element variable (logo, name, slogan) is only available if
 * enabled in the block configuration.
 *
 * Available variables:
 * - site_logo: Logo for site as defined in Appearance or theme settings.
 * - site_name: Name for site as defined in Site information settings.
 * - site_slogan: Slogan for site as defined in Site information settings.
 */
#}
{% set attributes = attributes.addClass('site-branding') %}
{% block content %}
  {% if site_logo %}
    <a href="{{ path('<front>') }}" rel="home" class="site-logo">
      <img src="{{ site_logo }}" alt="{{ 'Home'|t }}" />
    </a>
  {% endif %}
  {% if site_name or site_slogan %}
    <div class="site-text">
      {% if site_name %}
        <div class="site-name">
          <a href="{{ path('<front>') }}" title="{{ 'Home'|t }}" rel="home">{{ site_name }}</a>
        </div>
      {% endif %}
      {% if site_slogan %}
        <div class="site-slogan">{{ site_slogan }}</div>
      {% endif %}
    </div>
  {% endif %}
{% endblock %}

```

I can not really figure out what I am missing.

# Answer
> 0 votes
If the name of your theme is 'cloud\_theme' then your hook should be called 'cloud\_theme\_theme\_preprocess\_block'. You can see how Bartik theme did it here: https://api.drupal.org/api/drupal/core%21themes%21bartik%21bartik.theme/function/bartik\_preprocess\_block/8.8.x

EDITED: Assuming that you have named your preprocess function as `cloud_theme_theme_preprocess_block` (based on the name of your theme), also make sure that you include the library in your 'cloud\_theme.info.yml' file:

```
libraries:
  - cloud_theme/site-branding

```

---
Tags: theming, 9
---


# Question
Title: How to allow for files of any extension to be uploaded?
I'm surprised this hasn't been asked before like this.

I want to allow users to upload files of all file extensions, without enabling each extension by hand. How do I do it?

# Answer
> 3 votes
You can use Allow all file extension Module

> This module reverts Drupal 7's file upload widget to the Drupal 6 behavior, and trusts the site administrator to be smart enough to allow uploads with any file extension. It also lengthens the allowed file extensions box from 128 characters to 2048, allowing you to specify a larger number of extensions.
>
> While I realize this is somewhat insecure and would have liked to add more functionality to this module, this isn't something I should have needed to do at all, and I don't have a whole lot of time to spend on it. If there are any bugs, I'll try to fix them, but beyond that, I won't be adding new features to it. If you would like add new features to this module, I would gladly accept a co-maintainer (or even transfer ownership to someone else).
>
> Warning: The ability to leave the allowed file extensions box blank was removed for a reason. If you leave it blank and allow random users to upload files of any type, you'll have an insecure site. As such, you are strongly cautioned only to allow trusted users to do this.

# Answer
> 0 votes
You can override the `required = true` in `file_field_instance_settings_form` function that returns and form array and then remove the extensions from your ui config so that drupal use with out the validate function that also checks the resource suffixes.

Same for Drupal 8.

e.g.

`use Drupal\Core\Form\FormStateInterface;`

`/**
 * Implements hook_form_form_id_alter().
 */
function my_module_file_upload_config_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
 if($form['settings']['file_extensions']['#required']) {
 $form['settings']['file_extensions']['#required'] = FALSE;
 }
}`

# Answer
> 0 votes
For Drupal \>= 8. **( I mean Drupal 8, Drupal 9 )**

use Allow All File Extensions for file fields module

it lets you make the "Allow extensions" field be empty. it means you can upload any file type.

# Answer
> -1 votes
you just need to define any file extension that user need to upload it in file field that attached to content type example: add new file field to any content type and in field setting add the approved extension

---
Tags: 7, files
---


title: Place text below exposed filter

text:
# Question
Title: Place text below exposed filter
I have a Drupal view where I would like to enter some text in between 'Exposed Filter' and 'Content' sections. What is the safest of doing this? Attached image shows exact location I need text inserted.

Thanks

# Answer
You need to create a custom template for your view.

Go to `/sites/all/themes/YourTheme/templates` folder

create a file called **views-view--\[view-name\]--\[machine-name\].tpl.php**

> For example if you view name is "Hello World" and machine name is "block\_1"
>
> It would be: `views-view--hello-world--block-1.tpl.php`

Inside your custom template file put:

```
<?php

/**
 * @file
 * Main view template.
 *
 * Variables available:
 * - $classes_array: An array of classes determined in
 *   template_preprocess_views_view(). Default classes are:
 *     .view
 *     .view-[css_name]
 *     .view-id-[view_name]
 *     .view-display-id-[display_name]
 *     .view-dom-id-[dom_id]
 * - $classes: A string version of $classes_array for use in the class attribute
 * - $css_name: A css-safe version of the view name.
 * - $css_class: The user-specified classes names, if any
 * - $header: The view header
 * - $footer: The view footer
 * - $rows: The results of the view query, if any
 * - $empty: The empty text to display if the view is empty
 * - $pager: The pager next/prev links to display, if any
 * - $exposed: Exposed widget form/info to display
 * - $feed_icon: Feed icon to display, if any
 * - $more: A link to view more, if any
 *
 * @ingroup views_templates
 */
?>
<div class="<?php print $classes; ?>">
  <?php print render($title_prefix); ?>
  <?php if ($title): ?>
    <?php print $title; ?>
  <?php endif; ?>
  <?php print render($title_suffix); ?>
  <?php if ($header): ?>
    <div class="view-header">
      <?php print $header; ?>
    </div>
  <?php endif; ?>

  <?php if ($exposed): ?>
    <div class="view-filters">
      <?php print $exposed; ?>
    </div>
  <?php endif; ?>

  HERE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

  <?php if ($attachment_before): ?>
    <div class="attachment attachment-before">
      <?php print $attachment_before; ?>
    </div>
  <?php endif; ?>

  <?php if ($rows): ?>
    <div class="view-content">
      <?php print $rows; ?>
    </div>
  <?php elseif ($empty): ?>
    <div class="view-empty">
      <?php print $empty; ?>
    </div>
  <?php endif; ?>

  <?php if ($pager): ?>
    <?php print $pager; ?>
  <?php endif; ?>

  <?php if ($attachment_after): ?>
    <div class="attachment attachment-after">
      <?php print $attachment_after; ?>
    </div>
  <?php endif; ?>

  <?php if ($more): ?>
    <?php print $more; ?>
  <?php endif; ?>

  <?php if ($footer): ?>
    <div class="view-footer">
      <?php print $footer; ?>
    </div>
  <?php endif; ?>

  <?php if ($feed_icon): ?>
    <div class="feed-icon">
      <?php print $feed_icon; ?>
    </div>
  <?php endif; ?>

</div><?php /* class view */ ?>

```

> **Note:** The above code is an exact copy of **views-view.tpl.php** located in the `/sites/all/modules/views/theme` folder. I just added the HERE \<\<\<\<\<\<\<\<\<\<\<\<\<\<\< part after the exposed filter php.

**Don't forget to clear/flush the cache to see changes.**
> 1 votes

# Answer
For anyone arriving here for Drupal 8/9 (may apply to D7, not sure):

If it is appropriate, you can enter a table caption to describe the table, which is located within the `table` element but above the `thead` and `tbody`. The caption is editable at (Edit) View \> Format \> (Table) Settings \> Caption (in D8.9).
> 0 votes

---
Tags: 7, views
---


# Question
Title: Add HTML markup to a new paragraph text field
I'm creating a new paragraph item within a hook\_node\_presave() function.

The paragraph item is fairly simple, just a title and body text written into a text field with full html text editing. When I attempt to html elements within the body text, I'm unable to get the content to render the HTML tags.

Is there a way to do this using a render array, or another technique?

This is my initial attempt to build the paragraph, putting my html tags directly into the field that contains the body content.

```
$summary_paragraph = Paragraph::create([
  'type' => 'paragraph_text', //this is the paragraph type
  'field_title' => 'Title text',
  'field_content' => '<p>Sentence one.</p><p>Sentence two</p>.',
]);

```

The title appears correctly and *field\_content* prints the tags along with the text.

I also tried with a render array.

```
$content_text = [
  '#type' => 'processed_text',
  '#text' => '<p>Paragraph one.</p><p>Paragraph two.</p>',
  '#format' => 'full_html',
];

$summary_paragraph = Paragraph::create([
  'type' => 'paragraph_text', //this is the paragraph type
  'field_title' => 'Title text',
  'field_content' => $content_text,
]);

```

In this case, only the title was printed.

# Answer
> 1 votes
To store a formatted text field you need a field array with two properties `value` and `format`:

```
$summary_paragraph = Paragraph::create([
  // ...
  'field_content' => [
    'value' => '<p>Paragraph one.</p><p>Paragraph two.</p>',
    'format' => 'full_html',
  ],
]);

```

---
Tags: 8
---


# Question
Title: How can I open a node edit form in an overlay (modal window)?
I have a view with nodes of type 'tasks'. I want to easily view and edit these tasks by using a minimized overlay. When I click on a task title in the view, it needs to open in an overlay.

In Drupal 7 this was possible with the core overlay module, in combination with the Overlay Paths module. The core overlay has been discontinued in Drupal 8, in favor of a 'back to site' link, which does not serve my purpose to show a minimized popup block. It also needs to be used by authenticated users, not only administrators.

How can this be done in Drupal 8?

# Answer
> 2 votes
You can just add css class `use-ajax` and `data-dialog-type="modal"` to the link. For example:

```
<a href="/node/add/task" class="use-ajax" data-dialog-type="modal">
  Create new task
</a>

```

https://www.drupal.org/docs/drupal-apis/ajax-api/ajax-dialog-boxes

Or better you can use twig variables and functions in Views like this:

```
<a href="{{ path('node.add', {'node_type': 'task'}) }}" class="use-ajax" data-dialog-type="modal">
  Create new task
</a>

```

# Answer
> 0 votes
You can do that by constructing special links with the help of Colorbox and Colorbox Inline. You'll probably have to create your own style for the "minimized" overlay.

There are other libraries that do the same or similar thing as Colorbox, also integrated into Drupal through a module, so you might want to search and investigate others too (Shadowbox, for example).

These modules are also worth checking out: Modal Configuration, Simple Modal Entity Form, Entity Overlay.

---
Tags: 8, modal-dialogs
---


# Question
Title: Why is single quote sign escaped inside render element attribute?
When attribute text contains a single quote, like "It's a nice day" that single quote when rendered is escaped to "It's a nice day". Why is that happening and can it be prevented? Is twig doing that escaping?

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Template%21Attribute.php/class/Attribute/8.2.x

it says:

"The attribute keys and values are automatically escaped for output with Html::escape()."

and also:

"The attribute values are considered plain text and are treated as such. If a safe HTML string is detected, it is converted to plain text with PlainTextOutput::renderFromHtml() before being escaped."

Neither of those should do that conversion.

# Answer
> 0 votes
Attributes built via the `Attribute` class are escaped.

The `Attribute::__toString()` code is the following one.

```
$return = '';

/** @var \Drupal\Core\Template\AttributeValueBase $value */
foreach ($this->storage as $name => $value) {
  $rendered = $value->render();
  if ($rendered) {
    $return .= ' ' . $rendered;
  }
}
return $return;

```

In a class that extend `AttributeValueBase`, for example `AttributeString`, `render()` contains the following code.

```
value = (string) $this;
if (isset($this->value) && static::RENDER_EMPTY_ATTRIBUTE || !empty($value)) {
  return Html::escape($this->name) . '="' . $value . '"';
}

```

`AttributeString::__toString()` contains the following code.

```
return Html::escape($this->value);

```

`Html::escape()` is called for the attribute name and its value. That's why an attribute built using code similar to the following one single quotes inside the attribute name and value are escaped.

```
$attributes = new Attribute(array());
$attributes['id'] = 'socks';
$attributes['style'] = 'background-color:white';
echo '<cat ' . $attributes . '>';

```

`AttributeArray::__toString()` uses the following code.

```
// Filter out any empty values before printing.
$this->value = array_unique(array_filter($this->value));
return Html::escape(implode(' ', $this->value));

```

This means that for an attribute built using code similar to the following one, the attribute value is escaped.

```
$attributes = new Attribute();
$attributes['class'] = array();
$attributes['class'][] = 'cat';

```

---
Tags: 8
---


title: Return Table and Form in page callback

text:
# Question
Title: Return Table and Form in page callback
I have a problem returning table and form in page callback at the same time it only works if one of them only returned.

```
function _table_maps(){
$query = db_select('maps','m');

$result = $query->fields('m')
                ->extend('TableSort')
                ->extend('PagerDefault')
                ->limit(50)
                ->execute();

$header = array('Title','Longitude','Latitude','Description');

$rows = array();
while($data = $result->fetchAssoc())
{
    $rows[] = array(
        $data['maps_title'],
        $data['maps_long'],
        $data['maps_lat'],
        $data['maps_desc']
    );
}

$output = theme_table(
            array(
                "header" => $header,
                "rows" => $rows,
                "attributes" => array(),
                "sticky" => true,
                "caption" => "",
                "colgroups" => array(),
                "empty" => t("Table has no row!")
                )
            ).theme("pager");

return $output;

```

}

```
function aieadmin_map_form($form_state){

$form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#size' => 30,
    '#maxlength' => 64,
    '#description' => t('Enter the Title For the Location'),
);

$form['long'] = array(
    '#type' => 'textfield',
    '#title' => t('Longitude'),
    '#size' => 30,
    '#maxlength' => 64,
    '#description' => t('Enter the Longitude For the Location'),
);

$form['lat'] = array(
    '#type' => 'textfield',
    '#title' => t('Latitude'),
    '#size' => 30,
    '#maxlength' => 64,
    '#description' => t('Enter the Latitude For the Location'),
);

$form['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Describe it'),
    '#cols' => 60,
    '#rows' => 5,
    '#description' => t('Location description.'),
);

$form['submit'] = array('#type' => 'submit', '#value' => t('Save'));

return $form;
}

```

/*****\*****\******Page Callbacks******\*****\********/

```
function aieadmin_callback_mod(){
$page = _table_maps();
$page .= drupal_get_form('aieadmin_map_form');
return $page;
}

```

# Answer
> 0 votes
try this in the form

```
$custom_table = _table_maps();

$form['some_information'] = array(
  '#markup' => $custom_table,
  '#prefix' => '<div class="custom-class">',
  '#suffix' => '</div>',
);

```

# Answer
> 0 votes
I wrote a tutorial on how to do this in Drupal 8/9: https://www.jaypan.com/tutorial/drupal-form-api-ajax-form-and-results-same-page

---
Tags: forms, routes
---


title: Error with creating custom fieldtype

text:
# Question
Title: Error with creating custom fieldtype
I am creating a custom multi-value fieldtype for some functionality that I need.

I have been using the drupal core 'telephone' module and the contrib 'address' module as reference, but am running into some issues.

In the src/Plugins/Field/FieldType.php definition, there is a `propertyDefinitions()` method used to define the properties of a field.

The default value provided in the scaffolding provided by Drupal Console provides it as

`$properties['value'] = DataDefinition::create('string')->setLabel(t('Default value));`

However, 'value' isn't the correct property.

The field is setup to be a select list of available options, and a textfield that takes a value.

In the schema() method, I have this:

```
public static function schema(FieldStorageDefinitionInterface $field_definition) {
  $schema = [
    'columns' => [
      'format' => [
        'type' => 'varchar',
        'length' => 3,
      ],
      'aph_number' => [
        'type' => 'varchar',
        'length' => 255,
      ],
    ],
  ];

  return $schema;

```

Where as 'format' is a property of one of the fields (stored as 'field\_name\__format' in the database), and 'aph\_number' (stored as field\_name\__aph\_number' in the database).

My property definitions I am using are these:

```
 public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
   $properties = [];

   $properties['format'] = DataDefinition::create('string')
     ->setLabel(t('Format'));

   $properties['aph_number'] = DataDefinition::create('string')
     ->setLabel(t('APH Number'));

   return $properties;
 }

```

Which, whe looking at the 'address' field is how you define properties for a field.

When I enable the module and add the newly created field to a piece of content, I get a Drupal error, and in watchdog, it gives me this:

`InvalidArgumentException: Property value is unknown. in Drupal\Core\TypedData\TypedDataManager->getPropertyInstance()`

If I change 'format' and 'aph\_number' to 'value' in the $properties array, the error goes away, but I don't want the 'value' property to be available on this field, I want the ones I provided.

I have been unable to find any information online regarding this, and in looking at the two modules I am using as reference, this is correct.

Could somebody possibly help me with this?

# Answer
> 0 votes
I had a similar problem when trying something that looks a lot like the code you posted and I got the same error. The culprit for this error, for me, was my "isEmpty" function was still calling 'value', which was the original name of the property I used as a template. You might check the other functions in your FieldType file, like the isEmpty one, and make sure they aren't trying to access a property named 'value'.

---
Tags: 8, entities
---


# Question
Title: What value should the $bundle_name parameter for fileld_info_instances() get?
In a module, I need to get the list of fields for a content type. I used the following code, but `$instances` does not contain any helpful value.

```
$instances = field_info_instances('node', 'indicatorsheet_page');

```

Which value should I use for `$content_type`? Isn't it the content type machine name?

# Answer
What you're doing here seems correct to me, bear in mind that you can leave the bundle parameter empty and then you'll get an array of results keyed by bundle so you can evaluate if there's a problem with the machine name of the bundle you're using:

```
  $instances = field_info_instances('node');

```

You can also access admin/reports/fields and take a look to fields and content types available in your site.
> 0 votes

# Answer
The second argument required from `field_info_instances()` is the machine name for a content type. If the function doesn't return any information when `'node'` and `'indicatorsheet_page'` are passed as arguments, that could mean:

* The content type name isn't correct
* The content type name is correct, but that isn't a node content type
* The content type name is correct, and that is a node content type, but it doesn't have any field that isn't marked as deleted

Since the field information is cached, it could also be the *cache\_field* cache has been corrupted.

For debugging purposes, you can check what `field_read_fields(array('entity_type' => 'node'), array('include_deleted' => TRUE, 'include_inactive'))` and `field_read_instances(array('entity_type' => 'node'), array('include_deleted' => TRUE, 'include_inactive'))`. Both the function calls return information for fields of every node content type, including information for those fields have been marked as deleted or inactive fields.
> 0 votes

---
Tags: nodes
---


# Question
Title: How to access paragraph fields from a webform's form?
I have a webform (*contact\_info*) which is attached to a paragraph's field (*field\_contact\_info*). The paragraph has other fields as well.

I implemented `hook_form_alter()` to change some attributes inside the webform's form.

Is there any way to access the values of other paragraph fields value in `hook_form_alter()`?

I can pass them inside the webform object, but those aren't available in `hook_form_alter()` or the form array.

Any help on this?

# Answer
> 0 votes
This question is answered by @hudri

inside the hook\_form\_alter() get the entity first:

```
if ($form_state->getFormObject() instanceof \Drupal\Core\Entity\EntityFormInterface) {
  $entity = $form_state->getFormObject()->getEntity();
}

```

Then get the parent paragraph using this

```
$entity->getSourceEntity()

```

This will return the paragraph instance with all the fields.

---
Tags: webforms, 9, paragraphs
---


title: Uninstalling Lightning causes an error

text:
# Question
Title: Uninstalling Lightning causes an error
I am trying to uninstall Lightning. When I run `drush pm:uninstall lightning`, it throws this error.

> In PmCommands.php line 196:
>
> lightning: The Lightning module is required

How can I resolve this?

# Answer
Lightning is a distribution, not a module. Distributions and installation profiles cannot be uninstalled, once used to create a site. That's why the Lightning distribution hooks into the `drush pm:uninstall` command to make it possible.

If you aren't getting any *Welcome to the $profile name uninstaller!* message, it means the installed Lightning distribution needs to be first updated, as Uninstalling Lightning suggests.

> * If you're using Lightning 3, use the latest 3.4.x version.
> * If you're using Lightning 4, use the latest 4.1.x version.
> * If you're using Lightning 5, use the latest 5.2.x version.
> * If you're using Headless Lightning, use the latest 1.9.x version.

That page gives also other suggestions, for example the following one, for the commands that need to be executed before `drush pm:uninstall lightning`.

> If you're using BLT and `drush status --fields=install-profile` reports that you're directly using the *lightning* or *headless\_lightning* profiles, edit *blt/blt.yml* and change the profile key to *minimal*. **Do NOT** do this if you're using a sub-profile of Lightning or Headless Lightning.

As for running `drush pm:uninstall lightning`, these are the suggestions given for that.

> Run `drush pm:uninstall lightning` to use the automated uninstall tool, which will ensure that Lightning can be uninstalled safely by making the necessary code and configuration changes. If you're using a sub-profile of Lightning, you can allow the uninstaller to decouple all sub-profiles automatically by answering the prompt, or see "Decoupling a sub-profile from Lightning" below to do it manually (all sub-profiles, in use or not, must be decoupled from Lightning before you continue). **IMPORTANT**: If you're using Headless Lightning or a sub-profile of it, run `drush pm:uninstall headless_lightning` **BEFORE** running `drush pm:uninstall lightning`.

After running `drush pm:uninstall lightning`, the next step is the following one.

> Export config, then commit all changes and deploy them to your hosting. At a minimum, you should expect to see changes in your project-level *composer.json* and *core.extension* config.

When Lightning hooks into the `drush pm:uninstall` command, it executes the following commands, which essentially switch the profile from Lightning to another one.

* `drush pm:enable profile_switcher`
* `drush switch:profile $profile`

I didn't find any reference to the Profile Switcher module, in the Lightning distribution, despite it is necessary to switch the installation profile, which makes possible to uninstall the distribution. (Otherwise, `drush pm:uninstall lightning` would return the *The Lightning module is required* error.)
If updating the distribution doesn't install it, I would manually install it.

Also, the Lightning hook adds a required option to `drush pm:uninstall`, *profile*, which the installation profile to use instead of the distribution. If after updating the Lightning distribution and following the suggestions given in Uninstalling Lightning, you get an error about the *profile* option not found or required, try running `drush pm:uninstall lightning --profile='default'` instead of `drush pm:uninstall lightning`, which would pass the *profile* option to the command and the hook added by the distribution.
> 4 votes

---
Tags: 8, drush
---


# Question
Title: How to add twig code in View 'global custom text' field?
I want to show a link when a node is published.

I added the *Content: Publishing status* field and hid it. In *global custom text*, I added the following code.

```
{% if status == 0 %}
  <div class="apply_job"><a href="/appy-job" target="_blank">Apply</a></div>
{% endif %}

```

The replacement pattern for the published status is `{{ status }}`, which shows 0 or 1.

I am using Drupal 8.2.0.

Can anybody help me to make this work?

# Answer
> 0 votes
I tried that and it worked for me.

>

Just make sure to set the output format to 0/1.

```
{% if  status  %}
  <div class="apply_job"><a href="/appy-job" target="_blank">Apply</a></div>
{% endif %}

```

>

# Answer
> 0 votes
The correct code to use for the *Global: Custom text* field is the following one.

```
{% if status == '1' %}
  <div class="apply_job"><a href="/appy-job" target="_blank">Apply</a></div>
{% endif %}

```

>

(I left the *Status* field visible just to check the link was only shown for published nodes.)

I first tried the following code, which didn't work.

```
{% if status == 1 %}
  <div class="apply_job"><a href="/appy-job" target="_blank">Apply</a></div>
{% endif %}

```

>

I then noticed this error in the Drupal log, which made me understand that the code I entered was converting `status` to an integer.

> Notice: Object of class Drupal\Core\Render\Markup could not be converted to int in \__TwigTemplate\_0e6762666bfbb9311bd9151c5ea0be83db756ef416475732470b4e0d9f6604e6-\>doDisplay() (line 32 of /var/www/html.original/sites/default/files/php/twig/61222d7b5a923\___string\_template\__3f0751\_iIyQMmqa7AXU9cjNTkh8j\_Ed3/jVctGpgldXY6pQdNOz4-EYc-iwQbJzqU8T1VgO6g32E.php)

Notice that also the following code wouldn't work.

```
{% if  status  %}
  <div class="apply_job"><a href="/appy-job" target="_blank">Apply</a></div>
{% endif %}

```

It would show the link also for unpublished nodes.

As side note, if the view is only shown to users who don't have access to unpublished nodes, or to whom information about unpublished nodes should not be shown, adding *Published (=Yes)* to the filter criteria is what I would do.

---
Tags: views, 8
---


# Question
Title: Change priority of different aliases with the same aliases
There is vocabulary, let's call it forum tags which contain all forum tags, Also, in Forum, the link for the Forum container using a similar tag pattern for the forums. for example,

```
Term name : windows
term alias: /forum/windows

Forum container: windows
forum alias:     /forum/windows

```

if I open `/forum/windows` always term page will be loaded which means it has a higher priority.

at the moment all request handled by taxonomy handler which shows term page.

any thoughts on how can change the aliases priority?

(there are some other solutions to achieve what I'm doing without the same aliases but I'm wondering how we can do this on Drupal).

# Answer
The forum shown on /admin/structure/forum/add/container (to create a forum container) or on /admin/structure/forum/add/forum (to create a forum) is the form to create a taxonomy term.

In fact, the controller method called for /admin/structure/forum/add/container (ForumController::addContainer()) contains the following code.

```
$vid = $this->config('forum.settings')->get('vocabulary');
$taxonomy_term = $this->termStorage->create([
  'vid' => $vid,
  'forum_container' => 1,
]);

return $this->entityFormBuilder()->getForm($taxonomy_term, 'container');

```

There aren't two path aliases: There is only a taxonomy term path alias shown in two different pages that allow to edit it.
This is could be confusing, as /admin/structure/forum/add/container (and /admin/structure/forum/add/forum) doesn't give any hint that the submitted data are for a taxonomy term.
> 3 votes

---
Tags: path-aliases, 9
---


# Question
Title: Where is the maintenance mode value in the database?
I know the maintenance mode value used to be in the variables table, but in D8 that table is replaced by (or joined with) the config table, but I couldn't find any row with that name.

Where is it located now?

# Answer
> 1 votes
It's no longer a part of the config system; it's a part of the state system which is stored in the `key_value` table as a part of the `state` `collection`.

# Answer
> 3 votes
For Drupal 8 and 9:

First check the system.maintenance\_mode value:

```
SELECT `value` FROM `key_value`
WHERE `name` = 'system.maintenance_mode'

```

Then update the value:

```
UPDATE `key_value`
SET `value` =   'b:0;'
WHERE `name` = 'system.maintenance_mode' AND `value` =  'b:1;'

```

Then empty all tables starting with "cache":

```
TRUNCATE `cachetags`;
TRUNCATE `cache_bootstrap`;
TRUNCATE `cache_config`;
TRUNCATE `cache_container`;
TRUNCATE `cache_data`;
TRUNCATE `cache_default`;
TRUNCATE `cache_discovery`;
TRUNCATE `cache_dynamic_page_cache`;
TRUNCATE `cache_entity`;
TRUNCATE `cache_menu`;
TRUNCATE `cache_page`;
TRUNCATE `cache_render`;
TRUNCATE `cache_toolbar`;

```

# Answer
> 0 votes
An alternative (depending on your use case) is to use drush:

```
drush sset system.maintenance_mode 0
drush cr

```

---
Tags: 8, maintenance-mode
---


# Question
Title: Drush fails with PHP 8 due to padraic/humbug_get_contents requirements
I'm sure there is a simple fix, but I can't figure it out. This is my error every time I try to run drush updatedb

```
$ drush updatedb

Box Requirements Checker
========================

> Using PHP 8.0.9
> PHP is using the following php.ini file:
  /etc/php/php.ini

> Checking Box requirements:
  ..E.........

 [ERROR] Your system is not ready to run the application.

Fix the following mandatory requirements:
=========================================

 * The package "padraic/humbug_get_contents" requires the version "^5.3 || ^7.0
   || ^7.1 || ^7.2" or greater.

```

So far, the only way I have been able to bypass this is by forcing drupal/drush to use php7.4, but that doesn't seem like it's a good long-term solution.

If I could figure out where the requirement for padraic/humbug\_get\_contents comes from, I would try to modify it to add || ^8.0 or something like that, but I can't determine which package requires that package using `composer show --tree` or `composer depends padraic\humbug_get_contents`

I can't seem to find other people having the same issue despite searching. It may also be worth noting that the issue occurs across multiple sites on the same machine, so it is not likely to be some kind of mis-configuration of that site or installation. Other commands work fine on the install, as does running update.php through the web browser, it seems like it's just drush that doesn't work.

Does anyone have any suggestions that I may be able to use to solve this issue without rolling back to a previous version of php?

# Answer
This was simple to find an answer for, by searching on "padraic/humbug\_get\_contents drush".

See https://github.com/drush-ops/drush-launcher/issues/84, where your exact problem is described.

This appears to be fixed in the current version of drush launcher.
> 2 votes

---
Tags: drush
---


# Question
Title: How can I make revision log message required based on revision checkbox by node_form_alter?
My goal is to make the "**revision log message**" required if "**Create new revision**" is checked on create/edit node.

I do able to add the visible and required mark based on the "**create new revision**" field.

```
function hook_form_node_form_alter(&$form, &$form_state, $form_id) {

  $form['revision_information']['log']['#states'] = [
    'required' => [
      ':input[name="revision"]' => ['checked' => TRUE],
    ],
    'visible'  => [
      ':input[name="revision"]' => ['checked' => TRUE],
    ],
  ];
}

```

I also able to make the "**revision log message**" as required.

```
function hook_form_node_form_alter(&$form, &$form_state, $form_id) {

  $form['revision_information']['log']['#required'] = [
    'required' => [
      ':input[name="revision"]' => ['checked' => TRUE],
    ],
  ];
}

```

But I don't know how to make the field required based on the "**create new revision**" checkbox.

PS: I want to make this simple and don't want to use the "Enforce revision log message" module.

// update 1: I found it require a custom hook validate and Im searching for it

# Answer
I found an answer after hours of searching. Basically, I just need to add a custom hook validation for revision log. See below for my code.

```
function MYMODULENAME_form_node_form_alter(&$form, &$form_state, $form_id) {
    // change revision log status based on revision checkbox
    $form['revision_information']['log']['#states'] = array(
        'required' => array(
          ':input[name="revision"]' => array('checked' => TRUE),
        ),
        'visible' => array(
          ':input[name="revision"]' => array('checked' => TRUE),
        ),
    );
}
function MYMODULENAME_node_validate($node, $form, &$form_state) {
    // add revision log validation
    if (empty($form_state['values']['log']) && ($form_state['values']['revision'])) {
        form_set_error('log', 'Revision log message cannot be empty!');
    }
}

```

I hope this helps someone who needs revision log message required.
> 2 votes

# Answer
In Drupal 8 and 9 i just do this sort of thing.

```
$form['revision_log']['#required'] = TRUE;
$form['revision_log']['widget']['#required'] = TRUE;
$form['revision_log']['widget'][0]['#required'] = TRUE;
$form['revision_log']['widget'][0]['value']['#required'] = TRUE;

```
> 0 votes

# Answer
I created a simple module that does this. Note, it will require the log message on any revision of a node, but not on initial creation. Also, it currently affects all node types without regard to if the create new revision is clicked on the content type configuration.

https://www.drupal.org/project/require\_revision\_log\_message/
> -1 votes

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


# Question
Title: How can I tell, in hook_form_alter(), if a node form is for the node in its default language or a translation?
I'm implementing hook\_form\_BASE\_FORM\_ID\_alter() in a custom module. I'd like to know if my form is for the node in its default language, or a translation of that original node.

# Answer
> 3 votes
It looks like I can get it from the form's object, i.e. the form's node, and then use the node's isDefaultTranslation() method.

For example:

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

function MY_MODULE_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  /** @var \Drupal\node\NodeInterface $node */
  $node = $form_state->getFormObject()->getEntity();
  if ($node->isDefaultTranslation()) {
    // The node form is for the node in its default language.
  }
  else {
    // The node form is for a translation of the node.
  }
}

```

---
Tags: forms, i18n-l10n
---


title: Botton webform change bootstrap class

text:
# Question
Title: Botton webform change bootstrap class
Maybe someone knows why when you change the name of the button, its class changes from btn-primary to btn-default. btn-primary only if there is a submit in the button name (Without spaces before or after).

# Answer
Thank you so much for Clive help. As it turned out, the \_bootstrap\_colorize\_button function is responsible for choosing which class will be assigned depending on the label. To add a new word to this function, you need to implement hook\_bootstrap\_colorize\_text\_alter(). My code.

```
function myTheme_bootstrap_colorize_text_alter(array &$texts){
  $texts['contains'][t('Register')] = 'primary';
}

```

Instead of t ('Register'), you need the word and assign the bootstrap class you need.
> 2 votes

---
Tags: 7, webforms, bootstrap-theme
---


# Question
Title: How to set a validation constraint for base fields like the taxonomy term name?
I'm having trouble setting a validation constraint on the name of the taxonomy term.

```
function MYMODULE_entity_bundle_field_info_alter(&$fields, $entity_type, $bundle) {
  if ($entity_type->id() === 'taxonomy_term' && $bundle === 'my_taxonomy_type') {
    kint($fields['name']);
    if (isset($fields['name'])) {
      kint('found name');
    }
  }
}

```

When I rebuild the cache with drush, `kint()` outputs the value of `$fields['name']` as `null`.

When I use `kint()` to output the value of `$fields`, I see this:

```
array (4) [
    'parent' => Drupal\Core\Field\BaseFieldDefinition (7) (
        protected 'type' -> string (16) "entity_reference"
        protected 'propertyDefinitions' -> null
        protected 'schema' -> null
        protected 'indexes' -> array (0) []
        protected 'itemDefinition' -> Drupal\Core\Field\TypedData\FieldItemDataDefinition (3) (
            protected 'fieldDefinition' -> Drupal\Core\Field\BaseFieldDefinition (7) RECURSION
            protected 'definition' -> array (2) [
                'type' => string (27) "field_item:entity_reference"
                'settings' => array (3) [
                    'target_type' => string (13) "taxonomy_term"
                    'handler' => string (7) "default"
                    'handler_settings' => array (1) [
                        'target_bundles' => array (1) DEPTH LIMIT
                    ]
                ]
            ]
            protected 'typedDataManager' -> null
        )
        protected 'definition' -> array (7) [
            'label' => Drupal\Core\StringTranslation\TranslatableMarkup (5) (
                protected 'translatedMarkup' -> null
                protected 'options' -> array (0) []
                protected 'stringTranslation' -> null
                protected 'string' -> string (12) "Term Parents"
                protected 'arguments' -> array (0) []
            )
            'description' => Drupal\Core\StringTranslation\TranslatableMarkup (5) (
                protected 'translatedMarkup' -> null
                protected 'options' -> array (0) []
                protected 'stringTranslation' -> null
                protected 'string' -> string (25) "The parents of this term."
                protected 'arguments' -> array (0) []
            )
            'cardinality' => integer -1
            'provider' => string (8) "taxonomy"
            'field_name' => string (6) "parent"
            'entity_type' => string (13) "taxonomy_term"
            'bundle' => string (18) "my_taxonomy_type"
        ]
        protected 'typedDataManager' -> null
    )
    'field_int_count' => Drupal\field\Entity\FieldConfig (35) (
        protected 'deleted' -> boolean false
        ... cut
        protected 'id' -> string (56) "taxonomy_term.card_group_private.field_term_date_created"
        protected 'field_name' -> string (23) "field_term_date_created"
        protected 'field_type' -> string (8) "datetime"
        ... cut

```

"taxonomy\_term.card\_group\_private.field\_term\_ref\_author" protected 'field\_name' -\> string (21) "field\_term\_ref\_author" protected 'field\_type' -\> string (16) "entity\_reference" \]

The `name` field is nowhere to be found. How can I add a constraint to taxonomy term names?

# Answer
> 4 votes
Try a different hook for base fields:

```
/**
 * Implements hook_entity_base_field_info_alter().
 */
function mymodule_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
  if ($entity_type->id() === 'taxonomy_term') {
    $fields['foo']->addConstraint('Length', ['min' => 5]);
  }
}

```

If the field has bundle specific overrides you might need to use both hooks. See https://www.drupal.org/project/drupal/issues/3193351

Example for both hooks found in a contrib module https://git.drupalcode.org/project/node\_title\_validation/-/blob/8.x-1.x/node\_title\_validation.module

# Answer
> 2 votes
Field name in taxonomy is a baseField not a bundleField so you should rather use HOOK\_entity\_base\_field\_info\_alter instead to add custom definition to it

---
Tags: entities, forms, taxonomy-terms
---


# Question
Title: How to make taxonomy term names unique per user?
I have a taxonomy vocabulary, **Groups**.

Requirements

* Different users can create groups with the same name. (User A can make an `apples` group, and User B can also make an `apples` group.)
* The same user cannot make two groups with the same name (User A cannot make two `apples` groups.)

How can I implement this?

D8/9 offers a field constraint as explained in this answer and this blog post, but this makes a field unique for all users.

I want to make the **taxonomy term name** unique **per user**. Also, this needs to work with JSON:API. How can I do this?

# Answer
> 4 votes
You are allowed to add a custom validation constrains using this steps:

1. Step 1: Define the constraint:

The constraint definition will go in the namespace Drupal\[MODULENAME\]\Plugin\Validation\Constraint, and will extend Symfony\Component\Validator\Constraint. In this class, the types of constraint violations are defined, along with the error messages that will be displayed for the given violations.
2. Step 2: Create the validation for the constraint

The next step is to create the class that will validate the constraint. The constraint validation will go in the namespace Drupal\[MODULENAME\]\Plugin\Validation\Constraint, and will extend Symfony\Component\Validator\ConstraintValidator. In this class, the submitted values will be returned, and any violations will be registered.

Please note, that the name of your validator class is expected to be ${ConstraintClassName}Validator by default. If you want to use a different name, you may overwrite the validatedBy() method of your Constraint class, that you created in step 1.

and for the final step you can add the new constrain to your field just like the answer you have mentioned

now having this information you can add a user reference field to your taxonomy so each term will hold info about the author, you can use hook\_Entity\_Type\_presave to set this field programmatically

then you can create a custom constrain called `notUniquePerArthor` (or any name you like) then in step 2 where you define isUniquePerUser method, you can run a query and get a list of taxonomy term which have the label equal to value and author equal to current user, if this query return a value then this means that this term is not unique (user has defined this term before) and you can raise an error

# Answer
> 3 votes
Thanks to @Alireza Tabatabaeian for this. I'm simply posting my code that I used based on that answer.

To the taxonomy that I wanted to apply the constraint, I added a **field\_term\_ref\_author** entity reference to the user.

**mymodule.php**

```
function MYMOUDLE_taxonomy_term_presave(TermInterface $term) {
  $vocabulary = $term->bundle();
  switch ($vocabulary) {
    case 'my_vocab_type':
      if ($term->isNew()) {
        // Set the author (via custom field).
        $current_user = \Drupal::currentUser()->id();
        $term->set('field_term_ref_author', $current_user);
      }
    break;

function MYMODULE_entity_base_field_info_alter(&$fields, $entity_type) {
  if ($entity_type->id() === 'taxonomy_term') {
    if (isset($fields['name'])) {
      $fields['name']->addConstraint('TermNameUniquePerUser');
    }
  }
}

```

**mymodule/src/Plugin/Validation/Constraint/TermNameUniquePerUser.php**

```
<?php

namespace Drupal\MYMODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;

/**
 * Checks that the submitted value is unique to the user.
 *
 * @Constraint(
 *   id = "TermNameUniquePerUser",
 *   label = @Translation("Term Name Unique Per User", context = "Validation"),
 *   type = "string"
 * )
 */
class TermNameUniquePerUser extends Constraint {
  // The message that will be shown if the value is not unique.
  public $notUnique = 'You already created a term named %value.';

}

```

**mymodule/src/Plugin/Validation/Constraint/TermNameUniquePerUserValidator.php**

```
<?php

namespace Drupal\MYMODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Validates the TermNameUniquePerUser constraint.
 */
class TermNameUniquePerUserValidator extends ConstraintValidator {

  /**
   * {@inheritdoc}
   */
  public function validate($items, Constraint $constraint) {
    foreach ($items as $item) {
      // Next check if the value is unique.
      if (!$this->isUnique($item->value)) {
        $this->context->addViolation($constraint->notUnique, ['%value' => $item->value]);
      }
    }
  }

  /**
   * Is unique?
   *
   * @param string $value
   */
  private function isUnique($value) {
    $uid = \Drupal::currentUser()->id();
    $term_name_query = \Drupal::entityQuery('taxonomy_term')
      ->condition('name', $value, '=')
      ->condition('field_term_ref_author', $uid);
    // If the query has any results, then it is not unique.
    // So we should return the opposite of whether there are any results.
    return !($term_name_query->execute());
  }

}

```

The good thing about writing the entity query like this is that if the taxonomy vocabulary does not have a `field_term_ref_author` field, there will never be any results, so the constraint will evaluate correctly with terms that are in bundles not subject to the constraint (although this will result in a wasted database query.)

---
Tags: forms, taxonomy-terms
---


# Question
Title: How to add image field to main navigation menu item
I am having a problem using MYTHEME.theme file to add image field in the menu item object. I need to be able to specify an image for each menu link/item!

---

```
function HOOK_entity_base_field_info(EntityTypeInterface $entity_type) {
  $fields = [];

  if ($entity_type->id() == 'menu_link_content')
  {
   $fields['menu-image'] = BaseFieldDefinition::create('image')
   ->setLabel(t('Image shown next to menu name'))
   ->setComputed(TRUE);
  }
  return $fields;
}

```

---

I don't think that this code actually runs, I cannot see any effects!

# Answer
There are a few contrib modules that can offer this functionality.
> 2 votes

# Answer
Here's how I added a custom image field to my main menu link items. I added this to my custom module.

```
function my_custom_module_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
  if ($entity_type->id() === 'menu_link_content') {
    $fields['menu_link_image'] = BaseFieldDefinition::create('image')
      ->setLabel(t('Menu link image'))
      ->setDescription(t('Upload the image related to this menu item'))
      ->setDisplayOptions('form', array('type' => 'string', 'weight' => 0));

    return $fields;
  }
}

```

Flush the caches and the field should appear in the Menu Item form.

The only issue I had was that I was getting a MySQL error `Column not found: 1054 Unknown column 'menu_link_image'` when submitting the form. One solution to that was to add the column `menu_link_content` to the `menu_link_content_data` table but this is not a very good solution since you are altering a core Drupal db table.

I am still working on finding a better solution (e.g. using hook\_form\_alter to save that field to a different/custom db table). Any feedback/comment is appreciated.
> 0 votes

---
Tags: theming, 8, navigation
---


# Question
Title: Web Form Submission customizations of Email Handler
The webform provides the \[webform\_submission:values\] but when sent through emails, the layout is not very readable. All values are not separated for readablitity where I can use paragraph tags to separate it.
I am assuming something like the below would be the way to do this but I cant find the right syntax to make it work.

I would like something like that I can wrap html around to create readability. I have tried different references:

\[webform\_submission:values\[0\]\]

\[webform\_submission:values\['first\_name'\]\] where first\_name is part of values

and I tried \[webform\_submission:name\] -- similar to the provided

Submitted by: \[webform\_submission:user\]

How do I access my fields to do this?

Thank you!

Please Note: I have spent two days searching and watching videos of the support developer - who is awesome but I have had no luck finding syntax other than twig template php code. Sometimes simple items are difficult to sift through.

# Answer
> 1 votes
Webform shows this as the option available:

```
Use [webform_submission:values:ELEMENT_KEY:raw] to get plain text values.

```

So if you want to format `first_name` then you can do this:

```
<p>User first name: [webform_submission:values:first_name:raw]</p>

```

---
Tags: webforms
---


# Question
Title: drupal custom callback in node edit form is not firing
i am fairly new to drupal , i have custom button added to one the content type edit page , when i click on that button i want to call a function but it seems like it is not calling function when i see the console i see drupa ajax error coming whenever i click the button . please let me know what i am doing wrong here .

```
function mymodule_form_node_program_edit_form_alter(&$form, FormStateInterface $form_state) {
  $form['apply'] = array(
    '#type' => 'submit',
    '#value' => t('Apply'),
    '#weight' => '9',
    '#executes_submit_callback' => FALSE,
    '#limit_validation_errors' => array(),
    '#ajax'                     => array(
      'callback' => 'button_test_callback',
    ),
  );
}
    function button_test_callback(array &$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  echo '<script>alert("Welcome")</script>';
  return $form;
}

```

error i am getting :

Uncaught Drupal.AjaxError {message: "\nAn AJAX HTTP error occurred.\nHTTP Result Code: 50…\Core\DrupalKernel-\>handle(Object) (Line: 19)\n", name: "AjaxError"} message: "\nAn AJAX HTTP error occurred.\nHTTP Result Code: 500\nDebugging information follows.\nPath: /node/680911/edit?destination=/admin/content&ajax\_form=1\nStatusText: error\nResponseText: The website encountered an unexpected error. Please try again later.Symfony\Component\HttpKernel\Exception\HttpException: The specified #ajax callback is empty or not callable. in Drupal\Core\Form\FormAjaxResponseBuilder-\>buildResponse() (line 67 of core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php). Drupal\Core\Form\EventSubscriber\FormAjaxSubscriber-\>onException(Object, 'kernel.exception', Object)\ncall\_user\_func(Array, Object, 'kernel.exception', Object) (Line: 111)\nDrupal\Component\EventDispatcher\ContainerAwareEventDispatcher-\>dispatch('kernel.exception', Object) (Line: 227)\nSymfony\Component\HttpKernel\HttpKernel-\>handleException(Object, Object, 1) (Line: 79)\nSymfony\Component\HttpKernel\HttpKernel-\>handle(Object, 1, 1) (Line: 67)\nDrupal\simple\_oauth\HttpMiddleware\BasicAuthSwap-\>handle(Object, 1, 1) (Line: 57)\nDrupal\Core\StackMiddleware\Session-\>handle(Object, 1, 1) (Line: 47)\nDrupal\Core\StackMiddleware\KernelPreHandle-\>handle(Object, 1, 1) (Line: 106)\nDrupal\page\_cache\StackMiddleware\PageCache-\>pass(Object, 1, 1) (Line: 85)\nDrupal\page\_cache\StackMiddleware\PageCache-\>handle(Object, 1, 1) (Line: 49)\nAsm89\Stack\Cors-\>handle(Object, 1, 1) (Line: 50)\nDrupal\ban\BanMiddleware-\>handle(Object, 1, 1) (Line: 47)\nDrupal\Core\StackMiddleware\ReverseProxyMiddleware-\>handle(Object, 1, 1) (Line: 52)\nDrupal\Core\StackMiddleware\NegotiationMiddleware-\>handle(Object, 1, 1) (Line: 23)\nStack\StackedHttpKernel-\>handle(Object, 1, 1) (Line: 708)\nDrupal\Core\DrupalKernel-\>handle(Object) (Line: 19)\n"

# Answer
You're using an D7 callback definition. It needs to be defined as a D8+ callback. So this:

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

```

Should be this:

```
function button_test_callback(array &$form, \Drupal\Core\Form\FormStateInterface $form_state) {

```
> 0 votes

---
Tags: nodes, hooks, ajax
---


# Question
Title: How I can insert some help text on the ckeditor media embed "Create embed" tab?
How I can insert some help text on the ckeditor media embed "Create embed" tab? Oddly, I can't even find those words together in code. I have a user confused about its use, so I want to specify that this is for video URLs only. She is trying to "embed" an image that she already has on the site, but she gets an error message "input did not match any media types." If I do a form alter of "entity\_embed\_dialog" then the message displays on all tabs of media embed dialog window. I have several contrib modules on the site. Any of these may/may not affect this process: embed, entity, entity\_browser, entity\_embed, lightning\_media, video\_embed\_field

# Answer
> 0 votes
Drupal is actually rendering the media create form for that bundle of 'embed', so that is why your alter affecting all the tabs.

What you want to do is actually edit the 'embed' media type field settings.

1. Open up /admin/structure/media and select your 'embed' media type.
2. Select the "Manage Fields" tab.
3. Edit the video embed field and add some help/description text.

You can also go to "Manage form display" and see the form configuration if there are settings there you would like to adjust.

---
Tags: media
---


# Question
Title: Perform a query with an entity field condition with multiple values
I have a content type that has a entity reference field that allows users to add multiple taxonomy terms in that field. I'm attempting to perform queries that grab nodes that have a specific set of taxonomy terms within that field.

Using one value in that field works fine, like so.

```
    $query = \Drupal::entityQuery('node')
        ->condition('status', NODE_PUBLISHED)
        ->condition('type', 'custom_type')
        ->condition('custom_taxonomy', 2)
        ->sort('field_last_name', DESC);

```

Where 2 is the id of the term I'm searching for. However when I attempt to search for nodes that contain two specific terms like so,

```
    $query = \Drupal::entityQuery('node')
        ->condition('status', NODE_PUBLISHED)
        ->condition('type', 'custom_type')
        ->condition('custom_taxonomy', [2,8])
        ->sort('field_last_name', DESC);

```

I receive the error

> Invalid parameter number: number of bound variables does not match number of tokens:

I've also attempted

```
    $query = \Drupal::entityQuery('node')
        ->condition('status', NODE_PUBLISHED)
        ->condition('type', 'custom_type')
        ->condition('custom_taxonomy', [2,8], 'IN')
        ->sort('field_last_name', DESC);

```

Which doesn't fail, but doesn't provide the intended results. It displays every node that has either term 2 **OR** term 8. Instead of term 2 **AND** term 8 as intended. How would I perform a query that checks if a node has multiple specific values in an entity reference field?

# Answer
Use two separate `andConditionGroup()`:

```
$query = \Drupal::entityQuery('node')
  ->condition('status', NODE_PUBLISHED)
  ->condition('type', 'custom_type');
$and = $query->andConditionGroup();
$and->condition('custom_taxonomy', 2);
$query->condition($and);
$and = $query->andConditionGroup();
$and->condition('custom_taxonomy', 8);
$query->condition($and);
$result = $query->execute();

```

This works no matter how many terms are in the field or in which delta they are.

**Edit**

This results in this SQL:

```
SELECT base_table.vid AS vid, base_table.nid AS nid
FROM
{node} base_table
INNER JOIN {node_field_data} node_field_data ON node_field_data.nid = base_table.nid
INNER JOIN {node__custom_taxonomy} node__custom_taxonomy ON node__custom_taxonomy.entity_id = base_table.nid
INNER JOIN {node__custom_taxonomy} node__custom_taxonomy_2 ON node__custom_taxonomy_2.entity_id = base_table.nid
WHERE  (node_field_data.status = '1') AND (node_field_data.type = 'custom_type') AND( (node__custom_taxonomy.custom_taxonomy_target_id = '2') )AND( (node__custom_taxonomy_2.custom_taxonomy_target_id = '8') )

```
> 34 votes

# Answer
To do complex queries as you asked, you will need to use a condition group and to query the delta.

```
$query = \Drupal::entityQuery('node');
$query->condition('status', NODE_PUBLISHED)
  ->condition('type', 'custom_type')
  ->condition('custom_taxonomy', [2, 8], 'IN')
  ->condition('custom_taxonomy.%delta', 2, '=')
  ->sort('field_last_name', DESC);
$or = $query->orConditionGroup();
$or->condition('custom_taxonomy.0.target_id', 2);
$or->condition('custom_taxonomy.0.target_id', 8);
$query->condition($or);

```

See QueryInterface::condition documentation.
> 9 votes

# Answer
```
$taxonomy_term = 'taxonomy_term';
    $vid = 'name_taxon';
    $terms = $this->entity_type_manager->getStorage($taxonomy_term)
      ->loadTree($vid);

foreach ($terms as $term) {
  $term_data[] = [
    "vid" => $term->vid,
    "name" => $term->name,
  ];
}

```
> 1 votes

# Answer
Drupal 9 looks like this

```
$userStorage = $this->entityTypeManager->getStorage('user');

$userQuery = $userStorage->getQuery();
$result_user_ids = $userQuery->accessCheck(FALSE)
  ->condition('field_user_nodes.target_id', [1,2,4], 'IN')
  ->condition('status', 1)
  ->execute();
// Above ^^
return $userStorage->loadMultiple($result_user_ids);

```
> 1 votes

---
Tags: 8, entities, database
---


# Question
Title: How can I fix an "Access Denied" error on image styles, despite the correct filesystem permissions being set?
On a Drupal 8 site, image styles are no longer generating correctly.

The sample.png used in the image styles configuration page is generated fine (including when I manually delete the file from the image styles directory). I have recursively set to 0775 and 0664 the directory and file permissions for the entire sites/default/files directory, but the error persists. The log just shows *access denied*.

The Drupal version is 8.1.9.

How can I fix this error?

# Answer
> 2 votes
I have at last worked out what is causing the issue - but not why it suddenly started happening.

Going through our hosting cPanel, I stumbled across xVarnish, which is enabled across the board. Disabling it on our website immediately made the image styles generate correctly.

It may be that I can configure it to ignore image styles (thoughts welcome!) but for now, I have so much caching enabled Drupal-side that I think I can do without Varnish.

However, unless someone has suddenly turned on Varnish without consulting me (unlikely, but hard to ascertain in my org) then I'm totally at sea as to why it suddenly started being a problem.

# Answer
> 2 votes
I have had issues in the past where derivatives weren't generating correctly intermittently and it was due to disc space running out. When logs were purged the image derivatives would generate, but otherwise, the server was running out of space. So that's one idea.

# Answer
> 0 votes
Sometimes this problem can be caused by wrong or absent of the image token. Try to insert config line in the settings.php to check:

```
$config['image.settings'] = ['allow_insecure_derivatives' => true];

```

If after this change your picture style is showing correctly, your picture URL has wrong parameter "itok", for example:

```
/sites/default/files/styles/your_style_name/public/post-images/2021-07/photo_2021-06.webp?itok=0I_xdyI7

```

---
Tags: 8, media
---


title: Insert Record Using db_insert in Block

text:
# Question
Title: Insert Record Using db_insert in Block
I have created a block whose content uses the PHP as input filter. What I want to do is inserting a record into a separate database.

The code I am using is the following one.

```
$tracker = array(
  'database' => 'tracker',
  'username' => 'tracker',
  'password' => 'PASSWORD',
  'host' => 'localhost',
  'driver' => 'mysql',
);

Database::addConnectionInfo('tracker', 'default', $tracker);
db_set_active('tracker');

$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$finish = $time;
$total_time = round(($finish - $start), 4);
$t = $total_time;
$url = $_GET['url'];
$current_ip = $_SERVER['REMOTE_ADDR'];
$user_agent = $_SERVER['HTTP_USER_AGENT'];
$date = date("Y-m-d");
$time =  date("h:i:s");

function is_bot() {
  $botlist = array(
    "Teoma", "alexa", "froogle", "Gigabot", "inktomi",
    "looksmart", "URL_Spider_SQL", "Firefly", "NationalDirectory",
    "Ask Jeeves", "TECNOSEEK", "InfoSeek", "WebFindBot", "girafabot",
    "crawler", "www.galaxy.com", "Googlebot", "Scooter", "Slurp",
    "msnbot", "appie", "FAST", "WebBug", "Spade", "ZyBorg", "rabaz",
    "Baiduspider", "Feedfetcher-Google", "TechnoratiSnoop",
    "Rankivabot", "Mediapartners-Google", "Sogou web spider",
    "WebAlta Crawler", "TweetmemeBot",
    "Butterfly", "Twitturls", "Me.dium", "Twiceler"
  );

  foreach ($botlist as $bot) {
    if(strpos($_SERVER['HTTP_USER_AGENT'], $bot) !== false)
      return true;
    }
    return false;
  }
}

if (is_bot()) {
  $isbot = 1;
}
else {
  $isbot = 0;
}

db_insert('ap_visits')
  ->fields(array(
    'id' => NULL,
    'length' => $t,
    'url' => '$url',
    'current_ip' => '$current_ip',
    'user_agent' => '$user_agent',
    'date_start' => date("Y-m-d H:i:s"),
    'is_bot' => $isbot,
  ))
  ->execute();
db_set_active();

```

When executed, the code returns the following error.

> PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE\[42S02\]: Base table or view not found: 1146 Table 'c1tracker.semaphore' doesn't exist' in /var/www/clients/client1/web2/web/includes/database/database.inc:2168
> Stack trace:
> #0 /var/www/clients/client1/web2/web/includes/database/database.inc(2168): PDOStatement-\>execute(Array)
> #1 /var/www/clients/client1/web2/web/includes/database/database.inc(680): DatabaseStatementBase-\>execute(Array, Array)
> #2 /var/www/clients/client1/web2/web/includes/database/database.inc(2347): DatabaseConnection-\>query('SELECT expire, ...', Array, Array)
> #3 /var/www/clients/client1/web2/web/includes/lock.inc(167): db\_query('SELECT expire, ...', Array)
> #4 /var/www/clients/client1/web2/web/includes/lock.inc(146): lock\_may\_be\_available('schema:runtime:...')
> #5 /var/www/clients/client1/web2/web/includes/bootstrap.inc(420): lock\_acquire('schema:runtime:...')
> #6 /var/www/clients/client1/web2/web/includes/bootstrap.inc(442): DrupalCacheArray-\>set(Array)
> #7 \[internal function\]: DrupalCache in /var/www/clients/client1/web2/web/includes/database/database.inc on line 2168
> PDOException: SQLSTATE\[HY000\]: General error: 1364 Field 'is\_logout' doesn't have a default value: INSERT INTO {ap\_visits} (id, length, url, current\_ip, user\_agent, date\_start, is\_bot) VALUES (:db\_insert\_placeholder\_0, :db\_insert\_placeholder\_1, :db\_insert\_placeholder\_2, :db\_insert\_placeholder\_3, :db\_insert\_placeholder\_4, :db\_insert\_placeholder\_5, :db\_insert\_placeholder\_6); Array
> ( \[:db\_insert\_placeholder\_0\] =\> \[:db\_insert\_placeholder\_1\] =\> 1375693838.8169 \[:db\_insert\_placeholder\_2\] =\> $url \[:db\_insert\_placeholder\_3\] =\> $current\_ip \[:db\_insert\_placeholder\_4\] =\> $user\_agent \[:db\_insert\_placeholder\_5\] =\> 2013-08-05 17:10:38 \[:db\_insert\_placeholder\_6\] =\> 0 )
> in eval() (line 61 of /var/www/clients/client1/web2/web/modules/php/php.module(80) : eval()'d code).

It seems that the code is trying to access 'semaphore' table when using the external database.

How can I fix that error?

# Answer
> 0 votes
I could be wrong, but looking at the database code, there is not manual locking going on, so most likely you have a contrib module that causes the above error.

Regardless, you'll need to debug the `lock_acquire` function to find out which lock is being attempted, and work back from there to understand why the lock is needed.

# Answer
> 0 votes
Essentially, what happens is that the code executes the following query, which doesn't set a value for the *is\_logout* database field which has been defined without a default value.

```
db_insert('ap_visits')->fields(array(
  'id' => NULL,
  'length' => $t,
  'url' => '$url',
  'current_ip' => '$current_ip',
  'user_agent' => '$user_agent',
  'date_start' => date("Y-m-d H:i:s"),
  'is_bot' => $isbot,
))
  ->execute();

```

An internal function in the /includes/database/database.inc file (line 2168) tries to get the database schema, probably to show it in the error message. The function tries to populate the cache containing the database schema data, and that causes the call to `lock_may_be_available()`, which tries to access a database table that doesn't exist in that database.

It's impossible to know which function causes that without knowing the exact Drupal 7 version. It would require to find a version where line 2168 the /includes/database/database.inc file is inside a function/method and, between all those versions, the exact version.

Since the main cause is the query that doesn't set a value for a database field that doesn't have the default value, the fix doesn't require to know exactly which function is calling `lock_may_be_available()`. Rather, it requires to either:

* Change the database table definition for *ap\_visits* and add a default value for the *is\_logout* field
* Change the query to set a value for the *is\_logout* field in the *ap\_visits* database table

---
Tags: 7, database
---


# Question
Title: Prompt user to download file via AJAX form submission
I have a file that is generated when an AJAX button is clicked. I want to immediately have a file download prompt come up. The file is being generated and has the correct data in the file. I just don't know how to force the download prompt to come up.

**Edit#1**

I have updated the `generateCSV()` code to include:

```
$response = new BinaryFileResponse($path . $filename);
$response->setContentDisposition(
  ResponseHeaderBag::DISPOSITION_ATTACHMENT,
  $filename
);

$form_state->setResponse($response);

```

This is not invoking a download.

**AJAX Button**

```
$form['comp_card_dl'] = [
  '#type' => 'button',
  '#value' => $this->t('Download'),
  '#ajax' => [
    'callback' => '::generateCSV',
    'progress' => [
      'type' => 'throbber',
    ],
  ],
  '#name' => 'comp_card_download',
];

```

**CSV File Creation**

```
public function generateCSV($form, FormStateInterface $form_state) {
  $trigger = $form_state->getTriggeringElement();
  if ($trigger['#name'] == 'gift_card_download') {
    $filename = $form['#gift_card_filename'];
    $data = $form['#gift_card_data'];
  }
  else if ($trigger['#name'] == 'comp_card_download') {
    $filename = $form['#comp_card_filename'];
    $data = $form['#comp_card_data'];
  }

  $path = \Drupal::service('file_system')->realpath(file_default_scheme() . "://") . '/';
  $csv = fopen($path . $filename, 'w');

  foreach ($data as $id => $value) {
    array_unshift($value, $id);
    fputcsv($csv, $value);
  }

  fclose($csv);

  $response = new BinaryFileResponse($path . $filename);
  $response->setContentDisposition(
    ResponseHeaderBag::DISPOSITION_ATTACHMENT,
    $filename
  );

  $form_state->setResponse($response);
}

```

# Answer
I had same issue, its is not working by just jQuery but working by JavaScript click on a link.

First you need a html element with the download attribute

```
<a id="download-csv" target="_blank" href="" download="file.csv"></a>

```

Write an a js code to add `href` and then a javascript to click the element by its ID.

```
  $.fn.ajaxDownlaodHistory = function($path) {
    $("#download-csv").attr('href', window.location.origin + '/' + $path);
    document.getElementById("download-csv").click();
  };

```

In you PHP code, I consider you create your file successfully. Then you need to InvokeCommand that calls the recent js function created.

```
// Response to download the file directly
$response = new AjaxResponse();
$response->addCommand(new InvokeCommand(NULL, "ajaxDownlaodHistory", [$path]));
return $response;

```

You need to import

> use Drupal\Core\Ajax\AjaxResponse;
>
> use Drupal\Core\Ajax\InvokeCommand;
> 0 votes

---
Tags: 8, files
---


title: Do I need the trusted host setting?

text:
# Question
Title: Do I need the trusted host setting?
Do I need the trusted host setting for a Drupal 7 site? If so how do I configure it?

I noticed that Backdrop CMS has it in their settings file.

# Answer
Drupal 7 only limits the length of the host name to 1000 bytes to prevent DoS attacks, and it doesn't accepts host names containing slashes, but it doesn't restrict the allowed host names basing on a value set in the *settings.php* file, as Drupal 8 and Drupal 9 do.

The code checking the value of the *HTTP\_HOST* header is contained in `drupal_valid_http_host()`.

```
// Limit the length of the host name to 1000 bytes to prevent DoS attacks with
// long host names.
return strlen($host) <= 1000 && substr_count($host, '.') <= 100 && substr_count($host, ':') <= 100 && preg_match('/^\\[?(?:[a-zA-Z0-9-:\\]_]+\\.?)+$/', $host);

```

The function is called by `drupal_environment_initialize()`.

```
if (!isset($_SERVER['HTTP_REFERER'])) {
  $_SERVER['HTTP_REFERER'] = '';
}
if (!isset($_SERVER['SERVER_PROTOCOL']) || $_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.0' && $_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.1') {
  $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0';
}
if (isset($_SERVER['HTTP_HOST'])) {
  // As HTTP_HOST is user input, ensure it only contains characters allowed
  // in hostnames. See RFC 952 (and RFC 2181).
  // $_SERVER['HTTP_HOST'] is lowercased here per specifications.
  $_SERVER['HTTP_HOST'] = strtolower($_SERVER['HTTP_HOST']);
  if (!drupal_valid_http_host($_SERVER['HTTP_HOST'])) {
    // HTTP_HOST is invalid, e.g. if containing slashes it may be an attack.
    header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
    exit;
  }
}
else {
  // Some pre-HTTP/1.1 clients will not send a Host header. Ensure the key is
  // defined for E_ALL compliance.
  $_SERVER['HTTP_HOST'] = '';
}

```

There is a patch that should add to Drupal 7 the same code used by Drupal 8, in HTTP\_HOST header cannot be trusted. At the moment, the development of Drupal 7 slowed down, especially since when Drupal 8 and Drupal 9 has been developed at the same time.
Since that is considered a security improvement (with, apparently, low chances to happen to be considered a security issue, or the issue would not be discussed publicly), you could apply the patch provided in that issue (the latest one is, at the moment I posted this answer, https://www.drupal.org/files/issues/2021-02-04/http\_host\_header\_cannot\_bet\_trusted-2221699-151.patch) and start using `$conf['trusted_host_patterns']`.
> 4 votes

# Answer
Trusted host patterns were introduced in Drupal 8. There's nothing to configure for Drupal 7.
> 1 votes

---
Tags: 7, security
---


# Question
Title: How to invalidate Breadcrumbs cache for child nodes on graphQl
I have for example **Node A** with alias ***node-a*** and **Node B** with alias ***node-a/node-b*** so on my **Node B** i have this breadcrumb ***Home \> Node A \> Node B***

GraphQl result:

```
"breadcrumb": [
                {
                    "text": "Home",
                    "url": {
                        "path": "/",
                        "routed": true
                    }
                },
                {
                    "text": "Node A",
                    "url": {
                        "path": "http://example.com/node-a",
                        "routed": true
                    }
                },
                {
                    "text": "Node B",
                    "url": {
                        "path": "",
                        "routed": true
                    }
                }
            ]

```

But when i change ***Node A*** title i get always the same result (breadcrumbs not changed), but when i re-save the **node A** or clear cache the graphQl result change.

Here is what i have tried:

1. Clear graphQl cache (results and definitions)on node update:

```

     /**
     * Implements hook_ENTITY_TYPE_update().
     */
    function MYMODULE_node_update(EntityInterface $entity) {
      // Clear graphql cache.
      /** @var \Drupal\Core\Cache\CacheBackendInterface $graphql_results_cache */
      $graphql_results_cache = \Drupal::service('cache.graphql.results');
      $graphql_results_cache->invalidateAll();
      /** @var \Drupal\Core\Cache\CacheBackendInterface $graphql_definitions_cache */
      $graphql_definitions_cache = \Drupal::service('cache.graphql.definitions');
      $graphql_definitions_cache->invalidateAll();
    }

```

it doesn't work !

2. Clear cache of all child node on node update like this:

```

    /**
     * Implements hook_ENTITY_TYPE_update().
     */
    function MYMODULE_node_update(EntityInterface $entity) {
      $database = \Drupal::database();
      // Get the current node path alias.
      $alias = \Drupal::service('path_alias.manager')
        ->getAliasByPath('/node/' . $entity->id());
      // Get all node child of the current node.
      $child_nodes_alias = $database->select('path_alias', 'pa')->fields('pa', [
        'path',
        'alias',
      ])->condition('path', '/node/%', 'LIKE')
        ->condition('alias', $alias . '%', 'LIKE')
        ->execute()
        ->fetchAll();
      // Invalidate cache for each node child of current node.
      foreach ($child_nodes_alias as $alias_data) {
        $nid = explode('/', $alias_data->path)[2] ?? NULL;
        if ($nid && $nid != $entity->id()) {
          $tags = ['node:' . $nid];
          Cache::invalidateTags($tags);
          \Drupal::entityTypeManager()->getStorage('node')->resetCache([$nid]);
        }
      }
    }

```

it doesn’t work also

3. I combined the two previous ways it doesn't work too.

When i clear all caches on node update it works, but it's not the best way it impact site cache.

```

/**
 * Implements hook_ENTITY_TYPE_update().
 */
function MYMODULE_node_update(EntityInterface $entity) {
  drupal_flush_all_caches();
}

```

What is the best way to clear breadcrumbs cache, or child nodes without clear all site cache ?

**Edit:** Thank you @4K4 for your comment, i did tried to add CacheTags too breadcrumb but i didn’t work either !

```

/**
 * Implements hook_system_breadcrumb_alter().
 */
function MYMODULE_system_breadcrumb_alter(Breadcrumb &$breadcrumb, RouteMatchInterface $route_match, array $context) {
  // Append the current page title to the breadcrumb for non-admin routes.
  if ($breadcrumb && !\Drupal::service('router.admin_context')->isAdminRoute()) {
    $links = $breadcrumb->getLinks();
    foreach ($links as $link) {
      $parameters = $link->getUrl()->getRouteParameters();
      if ($parameters) {
        // Make sure the breadcrumb is updated when node title changes.
        $breadcrumb->addCacheTags(['node:' . $parameters['node']]);
        $breadcrumb->addCacheContexts(['url']);
      }
    }
  }
}

```

**Note:** Easy Breadcrumb module installed.

# Answer
I don't know the caching implementation of GraphQL 3.x field plugins, but as far as I can tell this code (even after the latest update from 2018) doesn't collect the breadcrumb metadata because it only gets the links:

```
protected function resolveValues($value, array $args, ResolveContext $context, ResolveInfo $info) {
    if ($value instanceof Url) {
      $resolve = $this->subRequestBuffer->add($value, function () {
        $links = $this->breadcrumbManager->build($this->routeMatch)->getLinks();
        return $links;
      });

      return function ($value, array $args, ResolveContext $context, ResolveInfo $info) use ($resolve) {
        /** @var \Drupal\graphql\GraphQL\Cache\CacheableValue $response */
        $response = $resolve();
        $links = $response->getValue();

        foreach ($links as $link) {
          yield new CacheableValue($link, [$response]);
        }
      };
    }
  }

```

Shouldn't it get the breadcrumb object to add its cacheable metadata?

```
protected function resolveValues($value, array $args, ResolveContext $context, ResolveInfo $info) {
    if ($value instanceof Url) {
      $resolve = $this->subRequestBuffer->add($value, function () {
        $breadcrumb = $this->breadcrumbManager->build($this->routeMatch);
        return $breadcrumb;
      });

      return function ($value, array $args, ResolveContext $context, ResolveInfo $info) use ($resolve) {
        /** @var \Drupal\graphql\GraphQL\Cache\CacheableValue $response */
        $response = $resolve();
        $breadcrumb = $response->getValue();
        $links = $breadcrumb->getLinks();

        foreach ($links as $link) {
          yield new CacheableValue($link, [$response, $breadcrumb]);
        }
      };
    }
  }

```
> 1 votes

---
Tags: caching, 9
---


# Question
Title: What is the insecure orange tag in the modules release pages?
I was checking today the release page for the Admin Toolbar module and see an orange tag with the text **Insecure** I tried to find an explanation about it without luck, anyone knows what this means?

# Answer
> 5 votes
It's a tag that is automatically added when a more recent release for the same branch has been tagged as release that fixes security issues. In the case of the 3.0.1 release, it's the 3.0.2 release.

>

The *Security update* tag is manually added from the Security Team, and it cannot be removed once added. (Actually, the release type cannot be anymore changed, once *Security update* is selected.)

>

---
Tags: community-official-site
---


# Question
Title: Custom block is still caching for anonymous users despite getCacheMaxAge() being set to 0 and can't figure out why
I have a custom Drupal 8 block with class with build() and getCacheMaxAge() functions. getCacheMaxAge() is set to 0 but it is still being cached for anonymous users.

If I put debug code in the build() function I can see it being called when I'm logged in but not for anonymous users.

My code is below. We do have Memcached installed. Would that be causing the issue?

The only other caching modules are core.

```
<?php
class HeaderPhone extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() {

    $info = geo_location_blocks_get_region();
    $region = $info['region'];
    $tid = $info['tid'];

    return array(
        '#theme' => 'geo_location_header_phone',
        '#region' => $region,
        '#view' => views_embed_view('locations', 'block_3', $tid),

    );
  }

  /**
   * @return int
  */
  public function getCacheMaxAge() {
    return 0;
  }
}?>

```

# Answer
Setting cache max-age to 0 doesn't work if you still have the core module *Internal Page Cache* enabled.

Read the documentation why you probably want to disable this module or deliver the block with a different method:

> Websites that serve personalized content to anonymous users (dynamic, per-session, e.g. a shopping cart) will want to disable the Internal Page Cache module. This module assumes pages are identical for all anonymous users. Those websites can still take advantage of the Dynamic Page Cache module though, or can alternatively do their personalization using JavaScript + AJAX.

https://www.drupal.org/docs/administering-a-drupal-site/internal-page-cache
> 5 votes

---
Tags: caching
---


title: Hide a view programatically D8

text:
# Question
Title: Hide a view programatically D8
I am trying to hide a view block if it has one or less results, i am doing this using the MYTHEME\_preprocess\_views\_view function.

Here is the code

```
// Removes product range if only one product is availiable!
if($variables['view']->id() == 'brand_product_range') {
  if(count($variables['view']->result) < 2) {
    // $variables['view']->destroy();
    // $variables['view']->setDisplay(false);
    // I want to hide block here!
  }
}

```

I managed to get the id of view block and number of results in the view, but I don't know how to hide the block, I tried the above methods but they are not working.

# Answer
I assume your view is using a block display and you don't want the block to display at all if there is only 1 result.

In my opinion you are hooking in too late in the process to hide the view there. It is possible to hide it in the theme layer but I don't think it is the optimal approach.

There are a number of ways you can do it but here are a couple of ways using a hook in a custom module, not in a theme. (This is not an exhaustive list of options that you have.)

**Option 1**

1. Hook into the view execution process and tell the process that execution has failed, so it will not render the view.

For example:

```
use Drupal\views\ViewExecutable;

function MODULE_NAME_views_post_execute(ViewExecutable $view) {
  // If there is only 1 result set the failure condition so that
  // execution will not continue and the view will not display.
  if ($view->id() == 'VIEW_NAME') {
    if (count($view->result) == 1) {
      $view->build_info['fail'] = TRUE;
    }
  }
}

```

**Option 2**

1. Configure your view to have 'Hide block if the view output is empty' = Yes
2. Hook into the view execution process and clear the results when you don't want it to display.

For example:

```
use Drupal\views\ViewExecutable;

/**
 * Implements hook_views_post_execute().
 */
function MODULE_NAME_views_post_execute(ViewExecutable $view) {
  // Clear the results if there is only 1 result.
  // The view will then hide as it is configured to hide the
  // block if empty.
  if ($view->id() == 'VIEW_NAME') {
    if (count($view->result) == 1) {
      $view->result = array();
    }
  }
}

```

Note: Depending on how you decide to hide the view, if your views block is the only block in your region then be aware of this outstanding bug, which may cause your region to still display even though your block doesn't: https://www.drupal.org/project/drupal/issues/953034
> 8 votes

# Answer
Build on @rooby's answer but for themes only.

It is possible to use `MYTHEME_views_post_render()` to hide the views block when `Hide block if the view output is empty' = Yes`. Note that any additional cache metadata is not bubbled for entities such as a block in the views header (if a change in the block should trigger a cache refresh).

```
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\cache\CachePluginBase;
use Drupal\views\Plugin\views\area\Entity as ViewsAreaEntity;

/**
 * Implements hook_views_post_render().
 */
function mytheme_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) {
  if (mycondition()) {
    // Hide the block.
    $view->result = [];
  }
  foreach ($view->header as $views_area_entity) {
    if ($views_area_entity instanceof ViewsAreaEntity) {
      $entity_type = $views_area_entity->definition['entity_type'];
      $target = $views_area_entity->options['target'];
      // Note: `$output` is a render array for views blocks,
      // but for REST/JSON display applying to `$view->element`
      // is required as `$output` is string
      // (Drupal\views\Render\ViewsRenderPipelineMarkup).
       $block_entity = \Drupal::entityTypeManager()->getStorage($entity_type)->load($target);
      $block_entity = $block_entity ? $block_entity : \Drupal::service('entity.repository')->loadEntityByConfigTarget($entity_type, $target);
      if ($block_entity && ($block_view = \Drupal::entityTypeManager()->getViewBuilder($entity_type)->view($block_entity))) {
        CacheableMetadata::createFromRenderArray($output)
          // OR use the block entity directly if required.
          // However view() will have a #lazy_builder for blocks & an un-rendered node #theme so shouldn't be any performance impact.
          // ->merge(CacheableMetadata::createFromObject($block_entity))
          // ->merge(CacheableMetadata::createFromObject($block_entity->getPlugin()))
          ->merge(CacheableMetadata::createFromRenderArray($block_view))
          ->applyTo($output);
      }
    }
  }
}

```
> 2 votes

---
Tags: 8, theming, hooks
---


# Question
Title: How do I avoid a template get rendered from a preprocess function?
I have a multilingual site with two view blocks, and a custom template for them.

I want to render both blocks in language A, but only one in language B.
Is it possible to avoid that one of them is rendered on a language basis, from the preprocess function?

# Answer
> 5 votes
Why preprocess?

Blocks have language visibility. Just configure that block to be shown only in a specific language.

# Answer
> 1 votes
To anyone coming here from a search:

As Berdir says, for the problem described in the question we don't need to use preprocess.

However, if you need this for some other reason, the following hack does the trick, for whichever theme hook you want to target:

```
function mymodule_preprocess_HOOK(array &$variables, string $hook, array &$info): void {
  if (...) {
    $info['function'] = '';
  }
}

```

The `$info` array is a local variable in `ThemeManager::render()` that is loaded from the theme registry, and then passed to preprocess functions in a way that supports treating it as a by-reference parameter.

Setting `$info['function']` overrides any template that would otherwise be rendered. If we use a function name that does not exist, we get an empty string as output.

In `\Drupal\Core\Theme\ThemeManager::render()`:

```
    // Generate the output using either a function or a template.
    $output = '';
    if (isset($info['function'])) {
      if (function_exists($info['function'])) {
        // Theme functions do not render via the theme engine, so the output is
        // not autoescaped. However, we can only presume that the theme function
        // has been written correctly and that the markup is safe.
        $output = Markup::create($info['function']($variables));
      }
    }
    else {
      $render_function = 'twig_render_template';

```

Disclaimer: You need to determine case by case whether doing this in preprocess is the correct solution. This answer only describes a technical possibility.

# Answer
> 0 votes
+1 from me for the answer from @Berdir.

If you really need to do this in preprocess, this depends, for which template the preprocess is:

In page you can remove a block from a region:

```
unset($variables['page']['myregion']['mytheme_myblock']);

```

In block template you can remove the content and if necessary the label to prevent any further rendering.

```
$variables['content'] = [];
$variables['label'] = [];

```

There should be similar solutions at any point in preprocess.

# Answer
> 0 votes
If the blocks are in a view, you can use `Hide block if the view output is empty' = Yes` & then set `$view->result = [];` in `hook_views_post_render()`.

You can use nest other blocks in the views header to get this ability for the inner block too.

Example & detailed code:

Hide a view programatically D8

---
Tags: theming, 8
---