# Question
Title: How to modify the subfields of a custom field in hook presave
I have a custom field in a custom module that consists of 4 varchar type values. Each of these subfields are called 'prefix', 'suffix', 'body' and 'header'.

In the hook presave, I want to modify only one of them, 'prefix', however, I can't do it:

```
function custom_field_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
  switch ($entity->bundle()) {
    case 'custom_object':
      //This seems to modify all de field instead only the subfield 'prefix'
      $entity->set('field_multifield', ['prefix' => '55555']);
      break;
  }
}

```

# Answer
As @sonfd commented you could get the field content as array:

```
$values = $entity->get('field_multifield')->getValue();

```

modify this array

```
$values[0]['prefix'] = '55555';

```

and then replace the entire field content:

```
$entity->set('field_multifield', $values);

```

Much easier though would be accessing a single property directly:

```
$entity->field_multifield->prefix = '55555';

```
> 1 votes

---
Tags: entities
---


# Question
Title: What is the encoding for JSON:API operators?
I'm trying to filter JSON:API results based on the "greater than" operator (`>`).

The filtering documentation lists the operators:

```
\Drupal\jsonapi\Query\EntityCondition::$allowedOperators = [
  '=', '<>',
  '>', '>=', '<', '<=',
  'STARTS_WITH', 'CONTAINS', 'ENDS_WITH',
  'IN', 'NOT IN',
  'BETWEEN', 'NOT BETWEEN',
  'IS NULL', 'IS NOT NULL',
];

```

But it also notes that the symbol operators need to be encoded:

```
&filter[a-label][condition][operator]=%3D  <- encoded "=" symbol

```

Which "encoding" is this referring to? What is the encoding for the other operators (`>`, `>=`, etc.)? How do I look them up?

# Answer
Thanks to Hudri, here's the list:

* `=` `%3D`
* `<>` `%3C%3E`
* `>` `%3E`
* `>=` `%3E%3D`
* `<` `%3C`
* `<=` `%3C%3D`
> 1 votes

---
Tags: 8
---


# Question
Title: Migrate date time field using migrate source csv
I am trying to migrate a datetime field from csv file but only few are being migrating and other are being failed.I am using migrate

I have created two datetime fields called as Activation Date and Expiry Date in article content type. Attached field type images for reference.

I am writing a custom migration yml file to migrate data from csv file. But only the date values from id 6-10 are being imported but not the date values from 1-5 .

While import I am getting error stating **article\_csv\_import Migration - 5 failed.**

I have included sample data and yml file for reference.

Can anyone please let me know what causing the first 5 dates import failing ? Any pointers for a way to debug migration process is greatly appreciated.

**migration\_examples/migrations/article\_csv\_import.yml**

```
id: article_csv_import
label: Import Articles
migration_group: default
migration_tags:
  - Article CSV Migration

source:
  plugin: 'csv'
  # Full path to the file.
  path: public://subscription-list-small-copy.csv
  # Column delimiter. Comma (,) by default.
  delimiter: ','
  enclosure: '"'
  header_offset: 0
  ids:
    - id
  fields:
    0:
      name: id
      label: 'Id'
    1:
      name: title
      label: 'Title'
    2:
      name: body
      label: 'Post body'
    3:
      name: field_activation_date
      label: 'Activation Date'
    4:
      name: field_expiry_date
      label: 'Expiry Date'
process:
  title: title
  body: body
  #activation date of the account.
  field_activation_date:
    -
      plugin: format_date
      from_format: Y-m-d H:i:s
      to_format: 'Y-m-d\TH:i:s'
      from_timezone: 'America/Managua'
      to_timezone: 'UTC'
      source: field_activation_date
  # expiry date of the account.
  field_expiry_date:
    -
      plugin: format_date
      from_format: Y-m-d H:i:s
      to_format: 'Y-m-d\TH:i:s'
      from_timezone: 'America/Managua'
      to_timezone: 'UTC'
      source: field_expiry_date
  type:
    plugin: default_value
    default_value: article

destination:
  plugin: entity:node

```

Sample CSV Data : **subscription-list-small-copy.csv**

```
id,title,body,field_activation_date,field_expiry_date
1,Title 1,Body 1,2012-12-22 2:36:03,2013-01-03 0:00:00
2,Title 2,Body 2,2013-08-16 0:00:00,2013-09-15 0:00:00
3,Title 3,Body 3,2013-09-14 0:00:00,2013-10-14 0:00:00
4,Title 4,Body 4,2014-04-08 0:00:00,2014-04-07 23:59:59
5,Title 5,Body 5,2014-09-30 0:00:00,2015-03-29 11:00:00
6,Title 6,Body 6,2014-12-09 12:29:00,2015-01-09 12:29:00
7,Title 7,Body 7,2014-12-31 11:08:00,2015-06-26 23:59:59
8,Title 8,Body 8,2015-02-25 19:12:00,2015-08-10 23:59:59
9,Title 9,Body 9,2015-03-01 11:19:00,2015-02-28 23:59:59
10,Title 10,Body 10,2015-03-02 18:01:00,2015-08-20 23:59:59

```

image-1 image-2

# Answer
`from_format: Y-m-d H:i:s` means hours with leading zeroes, but there are no leading zeroes in your source. Use `from_format: Y-m-d G:i:s` (capital `G`) for 24-hour-format without leading zeroes

see https://www.php.net/manual/function.date.php
> 3 votes

---
Tags: 8, migrations, datetime
---


# Question
Title: How can I implement paging for a custom query plugin which displays data from an external API?
Hi I have a requirement to display the data from external api but should not be imported into any entities. What I did is I have written a custom view query plugin which displays the data from external api. What I did is I have used the GuzzleHttp Client to get the data. Here is how my service looks like

```

namespace Drupal\***_services;

use Drupal\Component\Serialization\Json;

class NewsBlogsClient {

  /**
   * @var \GuzzleHttp\Client
   */
  protected $client;

  /**
   * NewsBlogsClient constructor.
   *
   * @param $http_client_factory \Drupal\Core\Http\ClientFactory
   */
  public function __construct($http_client_factory) {
    $this->client = $http_client_factory->fromOptions([
      'base_uri' => 'https://****************/',
    ]);
  }

  /**
   * Get all the news.
   *
   * @return array
   */
  public function getNews() {
    $response = $this->client->get('****');

    $data = Json::decode($response->getBody());

    return $data;
  }

  /**
   * Get all the blogs.
   *
   * @return array
   */
  public function getBlogs() {
    $response = $this->client->get('****');

    $data = Json::decode($response->getBody());

    return $data;
  }

}

```

I called the service into my plugin query and mapped it to the view fields that I have created using hook\_views\_data(). Here is how my plugin query looks like.

```
namespace Drupal\****\Plugin\views\query;

use Drupal\views\ViewExecutable;
use Drupal\views\ResultRow;
use Drupal\views\Annotation\ViewsQuery;
use Drupal\Core\Annotation\Translation;
use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Datetime\DrupalDateTime;

/**
 * Views query plugin which wraps calls to the *** API in order to
 * expose the results to views.
 *
 * @ViewsQuery(
 *   id = "news",
 *   title = @Translation("News"),
 *   help = @Translation("Query against the API.")
 * )
 */
class News extends QueryPluginBase implements ContainerFactoryPluginInterface {

  /**
   * @var \Drupal\*****\NewsBlogsClient
   */
  protected $newsBlogsClient;

  /**
   * FeaturedNews constructor.
   *
   * @param array $configuration
   * @param $plugin_id
   * @param $plugin_definition
   * @param $newsBlogsClient \Drupal\****\NewsBlogsClient
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, $news_blogs_client) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->newsBlogsClient = $news_blogs_client;
  }

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

  /**
   *
   * {@inheritdoc}
   */

  public function execute(ViewExecutable $view) {
    $index = 0;
    if ($news_items = $this->newsBlogsClient->getNews()) {
      foreach ($news_items as $news_item) {
        $row['title'] = $news_item['title'];
        $row['link'] = $news_item['view_node'];
        $date = $news_item['field_published_date'];
        $dateTime = new DrupalDateTime($date);
        $timestamp = $dateTime->format('U');
        $row['pubdate'] = $timestamp;
        $row['summary'] = $news_item['field_short_description'];
        $row['thumbnail'] = $news_item['uri'];
        // 'index' key is required.
        $row['index'] = $index++;
        $view->result[] = new ResultRow($row);
      }
    }
  }

  /**
   * Ensures a table exists in the query.
   *
   * This replicates the interface of Views' default SQL backend to simplify
   * the Views integration of the API. Since the API has no
   * concept of "tables", this method implementation does nothing. If you are
   * writing API-specific Views code, there is therefore no reason at all
   * to call this method.
   * See https://www.drupal.org/node/2484565 for more information.
   *
   * @return string
   *   An empty string.
   */
  public function ensureTable($table, $relationship = NULL) {
    return '';
  }

  /**
   * Adds a field to the table. In our case, the API has no
   * notion of limiting the fields that come back, so tracking a list
   * of fields to fetch is irrelevant for us. Hence this function body is more
   * or less empty and it serves only to satisfy handlers that may assume an
   * addField method is present b/c they were written against Views' default SQL
   * backend.
   *
   * This replicates the interface of Views' default SQL backend to simplify
   * the Views integration of the API.
   *
   * @param string $table
   *   NULL in most cases, we could probably remove this altogether.
   * @param string $field
   *   The name of the metric/dimension/field to add.
   * @param string $alias
   *   Probably could get rid of this too.
   * @param array $params
   *   Probably could get rid of this too.
   *
   * @return string
   *   The name that this field can be referred to as.
   *
   * @see \Drupal\views\Plugin\views\query\Sql::addField()
   */
  public function addField($table, $field, $alias = '', $params = array()) {
    return $field;
  }
}

```

Everything is working great. I can display and control the data through views. The only missing thing is paging. The API is also from another Drupal application which supports pagination. I also need to setup a pager for this query. Tried lot of things but didn't work. I don't know how actually a view pager works. Can anyone explain and provide me any example snippet or code to work with.

# Answer
You're missing some pager handling that's required. There isn't a great example of this, except to try to follow along with what `\Drupal\views\Plugin\views\query\Sql` does, translating the things that are SQL specific into things that are relevant for your API.

In your implementation of `\Drupal\views\Plugin\views\query\QueryPluginBase::execute` you need to first trigger the preExecute phase of the pager setup. Looking at the `\Drupal\views\Plugin\views\query\Sql` implementation, here's what that class does:

```
// Let the pager modify the query to add limits.
$view->pager->preExecute($query);

if (!empty($this->limit) || !empty($this->offset)) {
  // We can't have an offset without a limit, so provide a very large limit instead.
  $limit = intval(!empty($this->limit) ? $this->limit : 999999);
  $offset = intval(!empty($this->offset) ? $this->offset : 0);
  $query->range($offset, $limit);
}

```

Obviously the line `$query->range($offset, $limit);` isn't applicable to your use case, b/c here `\Drupal\views\Plugin\views\query\Sql` is concerned with building up a SQL query. The rest is applicable almost verbatium. With the above code you have a `$limit` and `$offset` per the configuration (and/or active query string / exposed pager) of your view that you can then apply to your API call to get back a paged result. That's the key, the views module won't page the `$view->result` array for you. It's up to you to use the `$offset` and `$limit` to apply paging yourself. Ideally your API supports paging and you can translate `$offset` and `$limit` to match what the API wants, or if your lucky just use them directly. Alternatively, you would need to `array_slice` your full array of results back from the API.

Hope that helps.
> 1 votes

---
Tags: 8, views, paging, plugins
---


# Question
Title: How do I display a modal dialog on page load, with working title and dialog options, using OpenModalDialogCommand?
I'm trying to display a modal dialog containing some simple markup on page load. I'm getting the expected markup to load, and the dialog appears. However, the dialog title always displays "Loading..." and the options (width, specifically) don't appear to work.

I've got the following in my controller:

```
public function modal() {
  $config = \Drupal::config('popup.settings');
  $title = $this->t('Fnord');
  $content = [
    '#type' => 'processed_text',
    '#text' => $config->get('content')['value'],
    '#format' => $config->get('content')['format'],
  ];
  $options = [
    'dialogClass' => 'popup-dialog-class',
    'width' => '75%',
  ];
  $response = new AjaxResponse();
  $response->addCommand(new OpenModalDialogCommand($title, $content, $options));

  return $response;
}

```

...and the following javascript:

```
(function ($, Drupal, drupalSettings) {
  $(document).ready(function () {
    var ajaxSettings = {
      url: '/popup/modal'
    };
    var myAjaxObject = Drupal.ajax(ajaxSettings);
    myAjaxObject.execute();
  });
})(jQuery, Drupal, drupalSettings);

```

The result:

The width should be about 1152px on my screen, but is instead an even 600px; I assume that's a default, and that my $options array isn't overriding it as I would expect.

On the theory that this is only expected to work if the dialog is opened by a click event, I tried setting the dialog options in the javascript:

```
var ajaxSettings = {
  url: '/popup/modal',
  dialogType: 'modal',
  dialog: { width: 300 }
};

```

...however, the result was identical. What am I doing wrong?

# Answer
It turns out the code above was working fine -- the problem was that the site was using a Bootstrap subtheme, and Bootstrap was configured to override the standard dialog behavior. Turning off Bootstrap's dialogs solved the problem, enabling both width and title settings.
> 2 votes

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


title: Custom module causes an AJAX error

text:
# Question
Title: Custom module causes an AJAX error
I created a custom module which creates a content type (*FAQs*) with a paragraph field whose type is *FAQ Item* (with 2 fields, title and text).

After installing the module, I have a new content type as expected.

I add this new content type (which works), but when I want to add more paragraphs, I get this error.

>

**edit start**

```
↵An AJAX HTTP error occurred.↵HTTP Result Code: 200↵Debugging information follows.↵Path: /node/add/faq?ajax_form=1↵StatusText: OK↵ResponseText:

```

**edit end**

Is there any missing configuration the module should provide?

The YAML files are inside faq/config/optional. They have been created from the UI on another site and exported.

**edit 2 start**

My module files and structure

*.info.yml* file I have basic info link name, type, description, core\_version\_requirement and package.

*.libraries.yml* Am importing a JS file, inside "src-js"

*.module* is empty, without any php code.

*.routing.yml* also have basic stuff:

```
faq:
path: '/faqs'
defaults:
  _controller: 'Drupal\faq\Controller\GetFaqController::getFaq'
  _title: 'FAQs Page'
requirements:
  _permission: 'access content'

```

Inside config-optional folder I have my YML to create content type, fields and paragraph. Those .yml files I exported from another website where I create all of this and deleted "uuid" line.

Then in my controller I also have basic stuff (for now).

```
class GetFaqController extends ControllerBase {
public function getFaq() {

    echo '<h1>FAQs</h1>';

    return [
        '#title' => 'test'
    ];
}

```

}

This is my module structure/files.

Have very basic configs, that's why I am a bit lost with this error and what I search online I found same error but it is not related.

It seems something is missing with paragraphs and ajax request to add more.

**edit 2 end**

**edit 3 start**

I have created another module, this new module only creates a paragraph type with 2 fields (title and text), then I add manually this paragraph to "Article" content type and I get same error.

Another thing I have notice, in a clean drupal site with paragrpahs module installed, when I create a paragraph type manually via backoffice and then add it to any content type works correctly, when I install my module all paragraphs fields stop working and give this error.

If I uninstall my module and delete paragraph type created by my module, other paragraphs type start working again.

Here a repository of my custom module if someone want to test.

https://gitlab.com/drase15/custom-module

**edit 3 end**

# Answer
After a lot of digging I just need to change a folder name -.- Changed from "optional" to "install", after that everything works as expected.

Thanks for your help.
> 0 votes

---
Tags: paragraphs, 9
---


# Question
Title: How can I get the Operations Link Field back?
I have a custom entity created in code which displays list in collection route. I decided to use a view to show this collection.

1. I created a new view of type 'Product' (Views shows my custom entity)
2. I added the fields I need to display
3. then searched for Operations Links (to add the edit, delete menu)

but it wasn't showing. I can confirm I've used this before in a view of custom entities.

Wat magic do I need to do here?

# Answer
I had deleted the "list\_builder" handler from my custom entity's annotations - thinking I didn't need a list builder since I was using a Views handler. Well, turns out that was the problem. The "Operations" link in views came back after I reinserted the list builder handler in my custom entity.
> 0 votes

---
Tags: 8, views
---


# Question
Title: How do I print line breaks and HTML in a watchdog message?
I am trying to log emails to watchdog for testing in my local dev environment.

```
function MYMODULE_mail_alter(&$message) {
  // First: Prevent the mail from being sent.
  $message['send'] = FALSE;

  // Next: Log the mail so it can be debugged if necessary
  ksm($message);
  $logemail = $message['subject'] .'\nThe following email was not sent: \n<pre>Subject:<br>' . $message['subject'] . '<br>Body:<br>'  . $message['body'][0] . '</pre>';
  watchdog('MYMODULE', '@logemail', array('@logemail' => $logemail), WATCHDOG_ALERT);
}

```

However, this gives me a value for **Message** that doesn't have any line breaks and ignores my HTML `<br>` and `\n`:

```
Patrick K, new members for the week of April 23\nThe following email was not sent: \n<pre>Subject:<br>Patrick K, new members for the week of April 23<br>Body:<br><p>Dear Patrick K,</p> <p>We haven't seen you in awhile. Hundreds of people have joined since you last logged in.</p> <p><a href="">Log in now and say hello to our newest members!</a></p></pre>

```

How can I get the line breaks and HTML to be rendered in the watchdog message?

# Answer
> However, this gives me a value for Message that doesn't have any line breaks and ignores my HTML `<br>` and `\n`

As well it should :)

You've wrapped the HTML message in a `<pre>` tag, whose job is simply to preserve everything within as literal text, so that the browser won't interpret it as HTML. To fix, just remove the `<pre>` tags. If there's a possibility the email content could have been user-submitted, run it through `filter_xss()` first with an appropriate list of permitted tags, to avoid pain when you view the log message.

At the same time, `\n` isn't an escape char in HTML, so that's treated literally and rendered as text. It's an escape char in PHP, but it won't affect the outcome here as browsers collapse multiple whitespace chars into a single space anyway.

You could use PHP's `nl2br` to convert `\n` to `<br>` automatically if the message content was dynamic, but since you're using a literal string, you might as well just be explicit and use `<br>` instead of `\n` when you want a line break.

This is a basic working example:

```
$message = [
  'subject' => 'test subject',
  'body' => ['<div class="test">some content<br />On a new line</div>'],
];

$allowed_tags = array('div', 'a', 'table', 'br', 'etc...');
$output = '!subject <br />The following email was not sent: <br />Subject:<br />!subject<br />Body:<br />!body';
$args = array('!subject' => filter_xss($message['subject'], $allowed_tags), '!body' => filter_xss($message['body'][0], $allowed_tags));
watchdog('MYMODULE', $output, $args, WATCHDOG_ALERT);

```

It's worth noting that the list view of the watchdog messages strips out HTML, so without the spaces after the first `!subject` and `not sent:`, some of the message will run together and make it harder to read at a glance.
> 4 votes

# Answer
Can you try with the below.

```
watchdog("my_module", '<pre>' . print_r( $my_array_or_object, true) . '</pre>');

```
> 1 votes

# Answer
I can't believe no one mentioned this before, but `\n` will be interpreted by PHP as char `\` and char `n` when the string is delimited by **single quotes**. You need to use **double quotes**.

```
$logemail = $message['subject'] . "\nThe following email was not sent...";

```
> 0 votes

---
Tags: log-messages
---


# Question
Title: What is the right way to implement google_analytics with the eu_cookie_compliance and categories?
I'm having difficulty configuring eu\_cookie\_compliance with multiple categories on a website with Google Analytics tracking. The GA tracking depends on selection of one of the categories.

When the category 'analytics' is enabled, google analytics cookies should be allowed and vice versa.

This comment in a thread for google\_analytics shows how to implement the hasAgreed() check within the google\_analytics module; in the '**Code Snippet (before)**' field:

```
document.addEventListener('DOMContentLoaded', function(){
    if (!Drupal.eu_cookie_compliance.hasAgreed()) {
        window['ga-disable-UA-0000000-00'] = true;
    }

```

and in the '**Code Snippet (after)**' field:

```
});

```

several others in the thread have confirmed that this works for them. In my case however, google analytics is never triggered.

I added the following before the 'if' statement to debug it:

```
console.log("General: " + Drupal.eu_cookie_compliance.hasAgreed());
console.log("Analytics: " + Drupal.eu_cookie_compliance.hasAgreed('analytics'));

```

The console shows false for both of the above, no matter what I select, and the google analytics is never triggered.

What could I be doing wrong?

# Answer
As far as I know, it is not yet possible to activate individual 3rd party services with the EU Cookie compliance module. An update is planned, the concept will be completely revised.

I would recommend using the module "COOKiES Consent Management" https://www.drupal.org/project/cookies, which supports various 3rd party integration modules out-of-the-box, such as https://www.drupal.org/project/google\_analytics is supported.
> 2 votes

---
Tags: 8, cookies, google-analytics
---


# Question
Title: EntityQuery PHP issue when assigning the query to a variable
I am very confused about this behavior of EntityQuery, or maybe I am just missing something basic about PHP.

Here is the query I am working with:

```
$entity_query_points1 = \Drupal::entityQuery($entity_type_id)
  ->condition($entity_type->getKey('bundle'), $entity_type_bundle)
  ->condition($entity_type->getKey('uid'), $uid)
  ->condition('field_int_points', 1, '=');
return $entity_query_points1;

```

This is fine.

But if this query returns no results, I wanted to immediately execute another query. So I made a `switch` statement and wrote code like this:

```
$entity_query_points1 = \Drupal::entityQuery($entity_type_id)
  ->condition($entity_type->getKey('bundle'), $entity_type_bundle)
  ->condition($entity_type->getKey('uid'), $uid)
  ->condition('field_int_points', 1, '=');
$entity_query = $entity_query_points1;
$count = $entity_query->count()->execute();
if ($count >= 1) {
  return $entity_query_points1;
}

```

This fails with a WSOD (I am using this code with the JSON:API Resources module):

```
TypeError: Argument 2 passed to Drupal\jsonapi_resources\Resource\EntityQueryResourceBase::loadResourceObjectsByEntityIds() must be of the type array, string given, called in /app/web/modules/contrib/jsonapi_resources/src/Resource/EntityQueryResourceBase.php on line 97 in Drupal\jsonapi_resources\Resource\EntityQueryResourceBase->loadResourceObjectsByEntityIds() (line 125 of modules/contrib/jsonapi_resources/src/Resource/EntityQueryResourceBase.php).

```

If I use the following code, it works (query resolved correctly, no WSOD):

```
$entity_query_points1 = \Drupal::entityQuery($entity_type_id)
  ->condition($entity_type->getKey('bundle'), $entity_type_bundle)
  ->condition($entity_type->getKey('uid'), $uid)
  ->condition('field_int_points', 1, '=');
$entity_query = $entity_query_points1;
$count = $entity_query->count()->execute();
if ($count >= 1) {
  $entity_query_score1 = \Drupal::entityQuery($entity_type_id)
    ->condition($entity_type->getKey('bundle'), $entity_type_bundle)
    ->condition($entity_type->getKey('uid'), $uid)
    ->condition('field_int_points', 1, '=');
  return $entity_query_points1;
}

```

But... why? I executed the count on `$entity_query`, but I have to redefine `$entity_query_score1` to return the query as expected. I know having to redefine the query means I have screwed up somehow, but I don't know what my mistake is.

# Answer
> 2 votes
Objects work differently than regular variables in PHP. They are "assigned by reference", generally speaking. The Objects and References page in the PHP manual goes into some detail about this. Basically, your `=` is not working as you expect. `$entity_query` and `$entity_query_points1` are "the same object".

As noted by @baikho in the comments, you'll need to use `clone` to achieve what you're trying to do.

```
$entity_query = clone $entity_query_points1;

```

---
Tags: 8, database
---


# Question
Title: What's the best way to assign variables for use in multiple form modules?
We have multiple custom form modules in our Drupal 8 site, and there are variables that are common across them -- like arrays for year, semester and campus, as well as lists of courses (so it's quite a few values, and they have to be updated from time to time). What's the best (most correct) way to define these common variables in a single place so they can be accessed by any module that needs them?

# Answer
It's hard to say what is the "best", but you can write a class, add the variables as constants, and then import the class wherever you need it.

For example, in `MYMODULE/src/MyVariables.php`:

```
<?php

namespace Drupal\MYMODULE\SharedStuff;

/**
 * Defines variables that need to be shared throughout the site.
 */
class MyVariables {

  // Seconds in an hour.
  const HOUR = 60 * 60;
  // Seconds in a day.
  const DAY = 24 * self::HOUR;
  // Seconds in a week.
  const WEEK = 7 * self::DAY;
}

```

And then in the PHP files where you need the variables:

`use Drupal\MYMODULE\SharedStuff\MyVariables;`

And then for the variable: `MyVariables::HOUR`
> 0 votes

---
Tags: forms
---


# Question
Title: Uncaught PHP Exception: Query tagged for node access but there is no node table, specify the base_table using meta data
Can anyone give me a hint where this error could come from?

When a user tries to access a specific node in the login-area of my Drupal 8 website, he randomly gets a white screen with the message "The website encountered an unexpected error. Please try again later."

I look at the apache error logs on the server and see the following error message:

> Uncaught PHP Exception Exception: "Query tagged for node access but there is no node table, specify the base\_table using meta data." at /mywebsite.com/html\_d8tst/core/modules/node/node.module line 1107, referer: http://mywebsite.com/user/251

node.module line 1107 says:

```
// Bail out if the base table is missing.
if (!$base_table) {
  throw new Exception(t('Query tagged for node access but there is no node table, specify the base_table using meta data.'));
}

```

I don't understand what exactly goes wrong when the error occurs. And unfortunately, I don't even see any pattern in which use cases the error occurs.

It's only on this specific node. Sometimes it works, sometimes not. The node is of a specific content type which only logged-in users have access to. It contains several views, some of them are user-specific.

This https://www.drupal.org/project/drupal/issues/2664748 seemed to be a similar problem, but the post was about Drupal 8.0.x-dev and was fixed. I'm working with Drupal 8.6.13

I would be glad of any hints!

# Answer
For anyone else running into this, I was able to get it to go away by checking all my blocks' permissions, especially the ones related to user information, and for me, the culprit was the **User Activity Log block**. Once I added the **Visibility setting** that only authenticated users had access to the block, the error went away.

Looks like the Drupal devs aren't having this module fail gracefully for unauthenticated users.
> 0 votes

---
Tags: 8
---


title: Error when creating custom form

text:
# Question
Title: Error when creating custom form
I am trying to create a custom form in drupal 8. for that I created my custom module called hello , and i've put inside the hello.routing.yml file the folllowing route:

```
hello.my_special_form:
  path: '/my-form'
  defaults:
    _title: 'My new form'
    _form: '\Drupal\hello\Form\Test.php'
  requirements:
    _permission: 'access content'

```

Inside Test.php , I have only written :

```
<?php
/**
 * @file
 * Contains \Drupal\hello\Form\Test.
 */
   namespace Drupal\hello\Form;
   use Drupal\Core\Form\FormBase;
   use Drupal\Core\Form\FormStateInterface;
   class Test extends FormBase {

}

```

I have no errors in my recent log messages, but when I clear cache , the website crashes.I have no idea why specially that I have not written anything yet.

Debugging: If I comment all the Test.php file, the clear cache works fine ! In addition to that, If I only comment the class Test extends FormBase line , the clear cache works as well. so the problem is in the class declaration. Any idea why?

# Answer
> 3 votes
`FormBase` is `abstract`; it implements `FormInterface`, but doesn't contain methods for:

* `getFormId`
* `buildForm`
* `submitForm`

You need to provide those in your class or PHP will reject it.

```
...
class Test extends FormBase {

  public function getFormId() {
    return 'foo';
  }

  public function buildForm(array $form, FormStateInterface $form_state) {
    // Build form then
    return $form;
  }

  public function submitForm(array $form, FormStateInterface $form_state) {
    // Perform submission tasks
  }

}

```

---
Tags: forms
---


# Question
Title: How to show a block on pages with url parameters?
I have a block that I want to show on pages matching `news` and `news?page=1`. In the 'only show on these pages' section I have `news` and `news/*` but it doesn't match the second url. Is there a way to do this?

**Update 1**: I have also tried this:

`<?php
 $url = request_uri();
 if (strpos($url, "news")) {
 return TRUE;
 }
 ?>`

But even after clearing all the caches it doesn't seem to have worked either.

I also tried the pattern `news?page=*` but that doesn't work either! Surely somebody considered being able to show blocks on paginated pages?

**Update 2**: Found the answer Restrict block to specific pages is broken when using view pagination

Turns out the block I was trying to display was a View which was also set to display a pager (even though one doesn't appear). Turning the pager off resolved the issue.

# Answer
Found the answer Restrict block to specific pages is broken when using view pagination

Turns out the block I was trying to display was a View which was also set to display a pager (even though one doesn't appear). Turning the pager off resolved the issue.
> 2 votes

# Answer
You can ajaxify the views using Ajax option in the view settings. So that page won't reload with parameters like ?page=1.

If you dont want to use ajax then you can select PHP code as visibility settings and write below php code. You need to enable php filter module to see the php code setting in the block configuration.

```
<?php
if (arg(0) == "news") {
  return TRUE;
}
else {
  return FALSE;
}
?>

```

Have a look at here: http://drupal.org/node/1208488
> 1 votes

# Answer
The solution as described in your own answer seems to be like a workaround for your original question, it doesn't answer the question for those case where you cannot (or do not want to) "*turn the pager off to resolve the issue*". To actually *show blocks on paginated pages* (as in your original question), you can use the Rules block visibility module for this. Here is a quote from its project page:

> The Rules block visibility module allows Rules components to be used to control block visibility. This provides Drupal administrators and developers extreme flexibility in controlling when blocks should be displayed on their websites, in addition to the default visibility options provided by Drupal.
>
> The general idea is that if you can do it with Rules, you can use it to control block visibility, so the possibilities are limitless.
>
> Need to show a block only for users registered more than a month ago?
>
> Perhaps you have a block that must be shown only between 8am-5pm on weekdays?
>
> What about displaying or hiding a block based on current weather conditions?
>
> All of this can be done by using Rules block visibility.

With that, and as per the "*if you can do it with Rules, you can use it to control block visibility*" above, you've reduced your question to making Rules "***check the path of the current page***" (so that the block is only shown on pages with a path either **matching** "`news`" or **starting with** "`news?page=`").

For an illustration of how to use this module, refer to my answer to "How to stop a Views block from displaying to admins, such as user/1?". It includes a Rules Component (in Rules export format), which you should replace by this variation of it to make it match your specific question):

```
{ "rules_show_block_on_pages_with_url_parms" : {
    "LABEL" : "Show block on pages with url parms",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "USES VARIABLES" : {
      "module" : { "label" : "Module", "type" : "text" },
      "delta" : { "label" : "Delta", "type" : "text" },
      "result" : { "label" : "Result", "type" : "boolean", "parameter" : false }
    },
    "IF" : [
      { "OR" : [
          { "data_is" : { "data" : [ "site:current-page:path" ], "value" : "news" } },
          { "text_matches" : {
              "text" : [ "site:current-page:path" ],
              "match" : "news?page=",
              "operation" : "starts"
            }
          }
        ]
      }
    ],
    "DO" : [ { "data_set" : { "data" : [ "result" ], "value" : "1" } } ],
    "PROVIDES VARIABLES" : [ "result" ]
  }
}

```

To further enhance the above Rules Component (to make it more generic), just replace the 2nd Rules Condition in it with something using an appropriate regular expression (ie to check if the current path contains a number to indicate the page id).
> 0 votes

# Answer
To be able to configure blocks to show up or not show up based on URL parameters (same as you can for the URL path in Drupal core) use condition query module for Drupal 8 or block query for Drupal 7.
> 0 votes

---
Tags: 7, blocks
---


# Question
Title: How to apply patches that are created in core-dev
Noob here. I'm trying to apply patches to my website, but it's keeps skipping because the version of the patch is for DEV. For example, I want to apply a patch to Core like this issue: https://www.drupal.org/project/drupal/issues/2579343.

How should I apply patches that are in core-dev?

Thanks!

# Answer
If the patch weren't already committed, you would need to reroll the desired patch against your Drupal Core version. This can be done by cloning the git repository of Drupal Core and generating a patch against the relevant revision of your version of Drupal.

The Drupal Core git repository can be found at https://www.drupal.org/project/drupal/git-instructions

See Making a patch on how to create a patch.

However in this case we can see that the issue has already been marked as "Fixed" and the patch of comment #19 was committed, so if you are on Drupal Core `8.1.x` or up, you should already have the changes from that patch on your Drupal site.
> 1 votes

---
Tags: 8, version-control
---


# Question
Title: How to inherit base class dependencies without redefining theme in child class service arguments?
## The current system

I have a set of services classes that extends the same base class ex:

```
class NodeHandler extends ContentEntityHandlerBase {}
class ParagraphHandler extends ContentEntityHandlerBase {}

```

and this base class receives these dependencies:

```
class ContentEntityHandlerBase extends ControllerBase {

 public function __construct(EntityTypeManager $entityTypeManager, RequestStack $requestStack, PermissionsService $permissionsService, LoggerChannelFactoryInterface $loggerChannelFactory) {
    $this->entityTypeManager = $entityTypeManager;
    $this->request = $requestStack->getCurrentRequest();
    $this->permissionsService = $permissionsService;
    $this->loggerChannelFactory = $loggerChannelFactory;
  }

```

So for each child class ex:(NodeHandler , ParagraphHandler) I need always to inject the parent class dependencies ex:

```
services:
  sacd_rest_api.node_handler:
    class: 'Drupal\sacd_rest_api\service\NodeHandler'
    arguments: ['@entity_type.manager','@request_stack','@sacd_user.permissions','@logger.factory']
  sacd_rest_api.parapgraph_handler:
    class: 'Drupal\sacd_rest_api\service\ParapgrapHandler'
    arguments: ['@entity_type.manager','@request_stack','@sacd_user.permissions','@logger.factory']

```

## The problem

I don't want to re-inject the parent dependencies each time I create a service class that extends it unless I want to inject a new dependencies that is not inherited from the Base Class for ex:

```
services:
  sacd_rest_api.node_handler:
    class: 'Drupal\sacd_rest_api\service\NodeHandler'
  sacd_rest_api.parapgraph_handler:
    class: 'Drupal\sacd_rest_api\service\ParapgrapHandler'

```

So in order to prevent re-injecting the base class dependencies for all baseClass child service ex: (NodeHandler and ParagraphHandler) so I have use the create() factory method but this doesn't work:

```
class ContentEntityHandlerBase extends ControllerBase {
 public function __construct(EntityTypeManager $entityTypeManager, RequestStack $requestStack, PermissionsService $permissionsService, LoggerChannelFactoryInterface $loggerChannelFactory) {
    $this->entityTypeManager = $entityTypeManager;
    $this->request = $requestStack->getCurrentRequest();
    $this->permissionsService = $permissionsService;
    $this->loggerChannelFactory = $loggerChannelFactory;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity_type.manager'),
      $container->get('request_stack'),
      $container->get('sacd_user.permissions'),
      $container->get('logger.factory')
    );
  }
}

```

# Question ?

is there any way to ineject the Base Class service , when defining a child class service (NodeHnadler , ParagraphHandler) wihout using the arguments: part in the service definiton ?

# Answer
The question asks:

> Is there any way to inject the Base Class service , when defining a child class service (NodeHandler , ParagraphHandler) without using the arguments: part in the service definition

Yes. For example, look in core.services.yml to see how this is done in core Drupal. Most core Drupal plugin managers have a parent service named default\_plugin\_manager. The default\_plugin\_manager service is defined like this:

```
  default_plugin_manager:
    abstract: true
    arguments: ['@container.namespaces', '@cache.discovery', '@module_handler']

```

As you can see, there are three services injected into the default\_plugin\_manager service. Because it is declared as "abstract", this service definition is more like an alias or a placeholder - it's simply there to define a set of arguments. Note there's no class associated with this service.

A concrete plugin manager, for example the plugin.manager.block service, is then defined like this:

```
  plugin.manager.block:
    class: Drupal\Core\Block\BlockManager
    parent: default_plugin_manager
    arguments: ['@logger.channel.default']

```

This service has FOUR arguments injected; the three defined by the parent default\_plugin\_manager plus the addition argument defined here.

When you look at the concrete class BlockManager that implements this service, you see that BlockManager has a constructor that looks like this:

```
public function __construct(\Traversable $namespaces, CacheBackendInterface $cache_backend, ModuleHandlerInterface $module_handler, LoggerInterface $logger) {
...
}

```

As you can see, this constructor takes four arguments. The first three defined by the default\_plugin\_manager service and the last one defined by the plugin.manager.block service.

Core Drupal defines a DefaultPluginManager base class which is extended by BlockManager and other plugins. BlockManager accepts all four arguments in its constructor. Note that if the parent (DefaultPluginManager in this case) has a constructor then you need to call that from the subclass constructor. This way many different plugin managers can extend DefaultPluginManager and inherit those three injected services.

In your specific case, your services.yml file might look like this:

```
  my_parent_service:
    abstract: true
    arguments: ['@entity_type.manager', '@request_stack', '@sacd_user.permissions', '@logger.factory']

  sacd_rest_api.node_handler:
    class: Drupal\sacd_rest_api\service\NodeHandler
    parent: my_parent_service
  sacd_rest_api.parapgraph_handler:
    class: Drupal\sacd_rest_api\service\ParagraphHandler
    parent: my_parent_service

```

You do not need a create() method anywhere, and you do not need to use ControllerBase at all.
> 1 votes

---
Tags: 8, dependency-injection, symfony-services
---


# Question
Title: Does a third-party module need to implement hook_help()?
After having spent hours reading through (very old) coding standards and best practices threads on drupal.org, and even trying to revive the Contrib Development Best Practices group on groups.drupal.org which seems to having been abandoned for years, I'm still struggling to getting an answer to whether a third-party module needs to implement `hook_help()` to comply with the Module Documentation Guidelines or not.

Above guidelines state

> **All but the most trivial modules should implement hook\_help().**

Yet, **should** is not **must**, which sometimes leads to discussions within the Security Advisory Application Issues Queue.

I was not able to identify someone to ask, whether it is a requirement or a (strong?) suggestion.

As we're currently reworking the PAReview (pareview.sh) tool, it would be great to know for having a distinct severity for a missing hook\_help(). That's why I'm hoping to getting a hint from the grey-bearded Drupalists here, on where to address this inquiry.

Don't get me wrong, I don't want to start a discussion here, nor subjective answers on whether there should be a hook\_help or not. I just want to know which board is deciding such issues and where to ask when it comes to contrib module coding standards and best practices.

# Answer
Modules should implement `hook_help()` even for just giving a short description of the purpose of the module (an overview help page). The standard structure of that page is described in Help text standards / Help page. `hook_help()` is the hook used from the core Help module.

In Drupal 8.8.x, a new experimental core module has been added: the Help Topics module. Its purpose is allowing modules to write their help pages as Twig template files with an embedded YAML header, for example like ban.banning\_ips.html.twig.

```
---
label: 'Banning IP addresses'
related:
  - user.overview
---
{% set ban = render_var(url('ban.admin_page')) %}
<h2>{% trans %}Goal{% endtrans %}</h2>
<p>{% trans %}Ban visitors from one or more IP addresses from accessing and viewing your site.{% endtrans %}</p>
<h2>{% trans %}Steps{% endtrans %}</h2>
<ol>
  <li>{% trans %}In the <em>Manage</em> administrative menu, navigate to <em>Configuration</em> > <em>People</em> > <a href="{{ ban }}"><em>IP address bans</em></a>{% endtrans %}</li>
  <li>{% trans %}Enter an <em>IP address</em> and click <em>Add</em>.{% endtrans %}</li>
  <li>{% trans %}You should see the IP address you entered listed under <em>Banned IP addresses</em>. Repeat the above steps to ban additional IP addresses.{% endtrans %}</li>
</ol>

```

Since the module is experimental, third-party modules should not depend on that and use those files for their help text, especially because the module is going to be merged with the Help module. The plan is also to deprecate `hook_help()`.

Third-party modules should:

* Drupal 7
Implement `hook_help()` even to show a short overview page
* Drupal 8
Implement `hook_help()` even to show a short overview page; consider writing integration with the Tour module to add additional contextual help to any page in the shape of a tour, which can have multiple steps, each one describing part of a page (such as different form elements in an administrative form)
* Drupal 9 (or 10, depending from when the *Help Topics* module will be merged into the *Help* module)
Write topics pages even to show a short overview page; consider writing integration with the *Tour* module to add additional contextual help
> 1 votes

# Answer
I never found anything about it, but I think that is highly recommended implement this hook.

The reason, I remember when I started with Drupal that many modules did not have a README.txt file and did not have the help page, even in the module page you did not find any information about how to use the module.

So, this is not required for a module, but I think that you should show a suggestion to implement the hook with some information about how to use the module.
> 0 votes

---
Tags: coding-standards
---


# Question
Title: How to load a webform via ajax inside custom JS?
I'm trying to load a webform block via ajax.

Right now I have:

```
$.ajax({
    url: '/form/contact-us',
    success: function (response) {
        console.log(response);
    },
    error: function (error) {
        console.log(error);
    }
});

```

How do i get the form as a block and not by the full page/node?

# Answer
Try the following steps :

1. Create follow this how to create contact form block
2. Create route for example `form/contact-us-block` :

**custom\_module.routing.yml**

```
custom_module.get_contact_form_block:
  path: '/form/contact-us-block'
  defaults:
    _controller: '\Drupal\custom_module\Controller\TutorialController::getContactFormBlock'

```

**getContactFormBlock Action in your controller**

```
public function getContactFormBlock() {
    //- Set your block id here
    $bid = 4;
    $block = \Drupal\block_content\Entity\BlockContent::load($bid);
    $build = \Drupal::entityTypeManager()
      ->getViewBuilder('block_content')
      ->view($block);
    return render($build)->__toString();
  }

```
3. Get the block html in your Js.

```

    (function ($, Drupal) {
      $(document).ready(function ($) {
        $.ajax({
          url: 'form/contact-us-block',
          success: function (response) {
            console.log(response);
          },
          error: function (error) {
            console.log(error);
          }
        });
      });
    })(jQuery, Drupal);

```
> 1 votes

# Answer
If you check `/admin/structure/webform/config` you will find a Site-wide webform support library inclusion option.

You will get the dialogue-library of the webform will be loaded. You can use that or customize the code to meet your own need.

UPDATE:

Use `class='use-ajax'` might help you load webform in modal.
> 0 votes

---
Tags: 8, webforms
---


# Question
Title: What should be used instead of raw filter?
Drupal 9 theming documentation indicates that the Twig raw filter is deprecated in favor of `verbatim`.

The ds-field-expert.html.twig template uses `raw` to render the input in the prefix and suffix field, which is often HTML.

```
{{- settings['prefix']|raw -}}

```

`verbatim` in the Twig 2 documentation is not a filter, but instead wraps around content in the template, so wrapping the line of code does not actually go and get the prefix/suffix content. It just renders the twig.

What should I use instead of `raw` in this case so the markup I enter into the prefix and suffix field of a Display Suite expert field template renders as HTML and not plain text?
Will this template break in Drupal 9?

# Answer
The raw *filter* is still fine to use. The filter is not deprecated, only the raw *tag*.

From the Drupal 9 theming documentation:

> As of Twig 1.x, the raw **tag** is deprecated in favor of verbatim.

Looking at the Twig 2.x documentation, you'll notice that the raw *filter* is not deprecated.

However, in the Twig 1.x documentation for the verbatim tag you can see that it replaced the raw *tag* in Twig 1.12. This is the cause of the deprecation in the Drupal 9 theming guide.

Ironically, there’s a notice at the bottom of that page that says the change was to help prevent confusion between the raw tag and raw filter.

> The verbatim tag works in the exact same way as the old raw tag, but was renamed to avoid confusion with the raw filter.
> 7 votes

---
Tags: theming, display-suite, 9
---


title: Command "generate-votes" is not defined

text:
# Question
Title: Command "generate-votes" is not defined
I'd like to use `Drush 10.3.6` to generate votes on my development server.

Based on these instructions for a previous Drush version (8.x), there is some kind of module/extension for this.

```
drush generate-votes

```

However, when I try it, it doesn't work for me. The error message I get is the following one.

> Command "generate-votes" is not defined.

Has this feature been removed or deprecated? Is there any other way I can generate votes from the command line?

# Answer
This command doesn't come from Drush core but from the Voting API module. This command simply doesn't exist yet in the currently latest Voting API release: 8.x-3.0-beta2. See, the directory `/src/Commands` where Drush commands since Drush version 9 get registered now simply isn't there yet.

You need to get the latest Voting API dev:

```
$ composer require 'drupal/votingapi:3.x-dev@dev'

```

There the `/src/Commands` directory contains a VotingApiCommands.php file with all the commands in it. The module needs to be enabled to use them, of course.

---

Voting API version 3.0-beta2 only contains the legacy `votingapi.drush.inc` file for Drush commands up to Drush version 8.
> 3 votes

---
Tags: 8, drush
---


# Question
Title: How do I get all the options of a field?
In Drupal 7, we are using the following code.

```
$field = field_info_field('field_name');
$allowed_values = list_allowed_values($field);

```

What can we use in Drupal 8?

# Answer
Drupal 8.9.x still has the `options_allowed_values()` (a function implemented in the *Options* module). If the field uses a selection, check box, or a radio button widget, you could use the following code. The same function is still implemented in Drupal 9.3.x, the latest Drupal version under development, at the time I am posting this answer.

```
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('entity', 'bundle');
if (isset($field_definitions['field'])) {
    $allowed_options = options_allowed_values($field_definitions['field']->getFieldStorageDefinition());
}

```

Replace `'entity'` with the entity type ID (for example, `'node'` for nodes), `'bundle'` with the bundle machine name (for example, `'article'` for Article nodes), and `'field'` with the field machine name.

Keep in mind that this code requires the *Options* module; the module using the code I shown should declare its dependency from it.

Using `options_allowed_values()` has the benefit that, if the field has a function returning the allowed values, that function is called. The following is the code used by `options_allowed_values()` to achieve that.

```
if (!isset($allowed_values[$cache_id])) {
  $function = $definition->getSetting('allowed_values_function');
  $cacheable = TRUE;
  if (!empty($function)) {
    $values = $function($definition, $entity, $cacheable);
  }
  else {
    $values = $definition->getSetting('allowed_values');
  }
  if ($cacheable) {
    $allowed_values[$cache_id] = $values;
  }
  else {
    return $values;
  }
}

```

Using `options_allowed_values()` also allows to cache the allowed values. In this way, calling `options_allowed_values()` for the same field (and same entity type) multiple times has a minimal impact on performance.

`options_allowed_values()` is defined also in Drupal 9.x and Drupal 10.x.
> 7 votes

# Answer
To get list of allowed values of field of select list try with:

```
    $options_array = [];
    $field_name = 'field_name';
    $definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('custom_entity_name', 'bundle');

    if (isset($definitions[$field_name])) {
      $options_array = $definitions[$field_name]->getSetting('allowed_values');
    }

```
> 4 votes

# Answer
Try directly from field:

```
    $allowedVals = $entity->get('field_name')->getSettings()['allowed_values'];

```
> 1 votes

---
Tags: 8, entities
---


# Question
Title: How to add an Ajax call to an element that already has callback set?
I want to add an ajax callback to a form element inside a form\_alter, but it already has 2 callbacks assigned to it.

When I review:

```
$form['payment_information']['payment_method']['#ajax']['callback']

```

it has 2 callbacks already assigned to it.

If I do this:

```
$form['payment_information']['payment_method']['#ajax'] = [
  'callback' => '_sia_general_get_fee',
  'event' => 'click',
];

```

My callback is hit on click; but of course, the other 2 callbacks are wiped out and do not work.

If I add something like this:

```
$form['payment_information']['payment_method']['#ajax']['callback'][] = '_sia_general_get_fee';

```

then the other callbacks are called; but mine is not - I suspect since I no longer of an event defined.

I am also not sure how the other ajax calls work when they have no events defined for them.

Is there any way to do this?

# Answer
> 1 votes
I doubt that the array you've found really assigns 2 callbacks. It's rather an array defining a class and a method for a single callback:

```
'callback' => ['Drupal\foo\BarClass', 'ajaxCallback']

```

In fact, you can only set one callback in an #ajax element. If you want to override a callback you have to include the overridden callback in your code:

```
Drupal\foo\BarClass::ajaxCallback($form, $form_state)

```

and add your ajax commands to the returned ajax response (or in case the original method returns a render array you can either add your own content to the array or transform the render array into an ajax command which you return with your own commands in an ajax response).

Caveat: This only works if the overridden callback is static. If it runs in an instantiated object you have to override the class method itself.

---
Tags: 8, forms, ajax
---


# Question
Title: error SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry
I'm currently migrating my website to D8 and I'm having some issues updating my NEW nodes to match with my live D7 site.

I get a few of these for each content type. I think it's from creating "test page" and the node ID is taken.

I get a few of these warnings:

```
 [error]  SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'e0891884-4da7-45c9-a1b5-808c8f821cfa' for key 'node_field__uuid__value': UPDATE {node} SET vid=:db_update_placeholder_0, type=:db_update_placeholder_1, uuid=:db_update_placeholder_2, langcode=:db_update_placeholder_3
WHERE nid = :db_condition_placeholder_0; Array
(
 [:db_update_placeholder_0] => 61287
 [:db_update_placeholder_1] => festival
 [:db_update_placeholder_2] => e0891884-4da7-45c9-a1b5-808c8f821cfa
 [:db_update_placeholder_3] => und
 [:db_condition_placeholder_0] => 3943
)

```

I tried `drush migrate-import upgrade_d7_node_festival --update` , but that didn't work. Is there a way to overwrite my test nodes when migrating? Do I have to go and delete all the table nodes in my DB then rerun the migration?

Thank!

# Answer
> 0 votes
sadly there is no "vanilla" way in migrate / migrate\_tools / migrate\_plus, to achieve this, at least that i know of.

I think the best solution is to create a custom plugin and append it to your yml file at the uuid field.

I should probably look something like this. **Disclaimer: The following snippet is derived from https://www.drupal.org/project/migrate\_plus/issues/3060320 and modified to suit your case specifically. It is not tested though.**

```
<?php

namespace Drupal\your_module\Plugin\migrate\process;

use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\MigrateSkipRowException;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Skips processing the current row when a same entity already exists.
 *
 * Examples:
 *
 * @code
 * process:
 *   name:
 *     plugin: skip_on_duplicate_entity_exists
 * @endcode
 *
 * @MigrateProcessPlugin(
 *   id = "skip_on_duplicate_entity_exists"
 * )
 */
class SkipOnDuplicateEntityExists extends ProcessPluginBase implements ContainerFactoryPluginInterface {

  /**
   * The entity storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $storage;

  /**
   * EntityExists constructor.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin ID.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Entity\EntityStorageInterface $storage
   *   The entity storage.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityStorageInterface $storage) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->storage = $storage;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      // Use configuration instead of "node" for a mode generic solution
      $container->get('entity_type.manager')->getStorage('node')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $entityQuery = $this->storage->getQuery();

    $existingEntities = $entityQuery
      ->condition('uuid', $value)
      ->execute();

    /* The result is either an entity id string,
    or an array of entity id strings.
    If either one is not empty, there's a duplicate. */
    if (!empty($existingEntities)) {
      throw new MigrateSkipRowException();
    }

    return $value;
  }

}

```

*You can find more on custom migrate plugins here https://www.drupal.org/docs/8/api/migrate-api/migrate-process/writing-a-process-plugin.*

Let me know it it helped, or if you need any further assistance / clarification.

---
Tags: 8, migrations
---


# Question
Title: Select in a first form / menu, the choices of other fields in other forms
I have three types of content, which represents categories.

In each type of content, I have a first field which offers to select a subcategory (different subcategories depending on the type of content).

To simplify the creation of a node for my users, I would like them to be able to select in a first form field directly the subcategory (therefore among all the subcategories of the different types of content).

For example:

Three types of content: A, B and C.

A has as subcategories: A1, A2, A3; B has as subcategories: B1, B2, B3; and C has as subcategories: C1, C2, C3.

When the user creates a node, the first field of the form offers to choose from all the sub-categories, namely: A1, A2, A3, B1, B2, B3, C1, C2, C3.

Do you know how to do it ?

I thought about creating a first page with a menu with all the subcategories allowing to redirect to the corresponding form with the first pre-filled field, but in this case it would be necessary that the links contain the information of the first field

# Answer
> 0 votes
Based on your comment, it sounds like you want a list of 9 links, and clicking a link sends the users to the **node add** form for the relevant content type with the **Subcategory** field already filled in.

As you noted in your question, you can use a menu for this. The challenge is how to pre-fill the first field.

For that, you can use the Prepopulate module.

As noted on the project page, this allows you to make a link like this to automatically set the value of fields. For example, to set the title:

```
http://www.example.com/node/add/page?edit[title][widget][0][value]=My awesome page

```

Also note the security warning on the page:

> For security reasons, Drupal 8 version of this module does not support radios/checkboxes.

Since subcategories are probably a taxonomy entity reference or text list, I assume this module will be fine for your case.

---
Tags: 8, forms
---


# Question
Title: How to loop through a database table to save every column as a single node?
I have a module, which loads company data from an external db to save this as content.

```
function example_create_nodes() {
// Get Data from external DATABASE
  db_set_active('db_wirdfit');
  $result = db_query('SELECT * FROM wirdfit.wirdfit_data');
  db_set_active();

 foreach ($result as $row) {
  $node->language = LANGUAGE_NONE;
  $node->type = "page";
  $node->title = $row->post_title;
  node_object_prepare($node);  //Set some default values

 // Try to set your custom field
  $node->field_id[$node->language][0]['value'] = $row->id;
  $node->field_post_content[$node->language][0]['value'] = $row->post_content;
  $node->field_post_author[$node->language][0]['value'] = $row->post_author;

  $node->date = 'complaint_post_date';
  $node->created = strtotime('complaint_post_date');

  $path = 'content/mytest-' . date('YmdHis');
  $node->path = array('alias' => $path);
  print_r($row);
  node_save($node);

  }

```

That works but saved only one node from the the last row of my table. How can I loop through the table and save every row as a single content page?

Thanks for help

# Answer
> 0 votes
The code shown in the question would cause a warning (*Creating default object from empty value*) when PHP executes `$node->language = LANGUAGE_NONE;` since `$node` isn't first initialized. PHP 8.0 would throw fatal error (*Fatal error: Uncaught Error: Attempt to assign property "language" on null*).

The code needs to first initialize `$node`.
After the call to `node_save()`, when the node object isn't necessary anymore, it should set `$node->is_new` to `TRUE` and unset `$node->nid`. Differently, Drupal would think you are saving the same node.

```
$node = (object) array();

foreach ($result as $row) {
  $node->language = LANGUAGE_NONE;
  $node->type = "page";
  $node->title = $row->post_title;
  node_object_prepare($node);

  $node->field_id[$node->language][0]['value'] = $row->id;
  $node->field_post_content[$node->language][0]['value'] = $row->post_content;
  $node->field_post_author[$node->language][0]['value'] = $row->post_author;

  $path = 'content/mytest-' . date('YmdHis');
  $node->path = array('alias' => $path);
  node_save($node);
  $node->is_new = TRUE;
  unset($node->nid);
}

```

I didn't set `$node->created`, which should be a Unix timestamp (and it's already set by `node_object_prepare()`), nor `$node->date`, which `node_object_prepare()` already sets to `$node->date = format_date($node->created, 'custom', 'Y-m-d H:i:s O')`;\`. If you need to set those fields, you need to set them to the values Drupal expects (a timestamp and a date string).

# Answer
> 1 votes
This is essentially PHP - you are not initiating a new variable with each iteration of the loop. Start a new $node - otherwise you are writing to it over and over.

```
foreach ($result as $row) {
  $node = new stdClass();
  $node->type = 'page';
  ...
  $node = node_submit($node);
  node_save($node);
}

```

---
Tags: 7, nodes
---


# Question
Title: Exposed date filter against >= "today" fails until 5pm Mountain time
* I added a `Date only` date field named `expires` to the user profile.
* The `expires` field has the value **2021-01-08** for a certain user (I checked the database; it has no time component).
* In a view, I have an exposed filter that tests the `expires` field using Operator=`Is greater than or equal to` with Value type=`An offset from the current time` and Value=`today`.
* On **2021-01-09** up until 5pm Mountain time, the user with `expires` = **2021-01-08** is improperly included in the view.
* When I refresh the view at 5pm Mountain time or thereafter, the user is dropped from the view.
* I tried switching to Value type=`A date in any machine readable format` and Value=`today`. This also has a problem, but in this case users aren't included when they should be sometimes (the problem is sort of reversed).
* If, as a test, I edit the exposed filter and use Value type=`A date in any machine readable format` and Value=**2021-01-09** (i.e. hardcode the date) then the user with `expires`=**2021-01-08** is not included in the view at any time, as expected.

It appears that `today` isn't giving me today's date until 5pm Mountain Time. What am I missing?

SOLUTION: Inspired by @Patrick Kenny below, I added this to MYMODULE.views\_execution.inc:

```
function MYMODULE_views_query_alter($view, $query)
{
    if (!empty($query->where[1]['conditions'])) {
        foreach ($query->where[1]['conditions'] as $key => &$value) {
            error_log($value['field']);
        }
    }
}

```

Testing on 2021-01-13 at 10:17 am Mountain Time with Operator=`Is greater than or equal to` and Value type=`An offset from the current time` and Value=`today`, the output is

`DATE_FORMAT(user__field_expire.field_expire_value, '%Y-%m-%d') >= DATE_FORMAT('2021-01-12T17:00:00', '%Y-%m-%d')`

Notice the `today` value of 2021-01-12T17:00:00. **WRONG DAY**. Off by 7 hours. This confirms the answer by @Patrick Kenny.

HOWEVER, if I change to Value=`now` (instead of Value=`today`) and test again, the output is

`DATE_FORMAT(user__field_expire.field_expire_value, '%Y-%m-%d') >= DATE_FORMAT('2021-01-13T10:17:02', '%Y-%m-%d')`

Notice the `today` value of 2021-01-13T10:17:02. **CORRECT DAY** and time.

In my case, switching to `now` seems adequate to fix the problem because the Y-m-d format is applied, making the comparison work correctly. But I still subscribe to @Patrick Kenny's solution as a general fix.

# Answer
Since the server timezone, Drupal timezone, and `\Drupal::time()->getCurrentTime()` are all pointing to the same time, you have probably been bitten by the same bug in Views that I was, Date/time Views filter tries strotime() relative to Unix epoch.

Basically, all relative values like "today" "yesterday - 5 hours", etc. can have timezone issues in Views. There's another related issue I reported as well. This bug has yet to be fixed.

In my case, I needed to filter by "midnight of the current day", and Views was giving me incorrect results depending on the timezone.

I fixed it like this (code more or less pasted directly from my site, but it should give you an idea of what you can do):

```
function MYMODULE_views_pre_view(ViewExecutable $view, $display_id, array &$args) {
  if (($view->id() === 'VIEW_MACHINE_NAME') &&
    ($display_id === 'page_1')) {
    $filters = $view->display_handler->getOption('filters');
    if ($filters['field_MY_FIELD']) {
      $user_timezone = date_default_timezone_get();
      $current_timestamp = \Drupal::time()->getCurrentTime();
      $midnight_usertimezone_datestring = MYMODULE_get_midnight_datestring("$current_timestamp", MYMODULE_get_utc_offset($user_timezone));

      $filters['field_MY_FIELD']['value']['value'] = $midnight_usertimezone_datestring;
    }
    $view->display_handler->overrideOption('filters', $filters);
  }
}

```
> 2 votes

---
Tags: 8, views, datetime
---


title: How to redirect comment form?

text:
# Question
Title: How to redirect comment form?
I want to redirect to a node after comment form submit.
But I tried using hook\_form\_alter hook,the redirect not happen.

```
function pf_core_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id){
 if($form_id=='comment_comment_form'){
   $form['#submit'][] = 'pf_core_comment_comment_form_submit';
 }
}

function pf_core_comment_comment_form_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  $form_state->setRedirectUrl('<front>');
}

```

Please help me to fix this issue.

# Answer
```
$nid = 1; // lets pretend the node ID you want to redirect is 1.

$url = \Drupal\Core\Url::fromRoute('entity.node.canonical', ['node' => $nid]);
$form_state->setRedirectUrl($url);

```
> 0 votes

# Answer
If you ever need to redirect to a URL with parameters (rather than a fixed URL as in the example), a custom submit handler won't work because the $form object gets rebuilt, but you *can* append:

`?destination=` to `$form['#action']`

and it will redirect to that afterwards.

See question I asked.
> 0 votes

# Answer
A simple way to redirect to the same page, where the comment was submitted.

```
function mytheme_form_alter(&$form, FormStateInterface $form_state, $form_id) {
   if($form_id == 'comment_simple_form') {
      $form['#action'] .= '?destination=' . Drupal::service('path.current')->getPath();
   }
}

```
> 0 votes

---
Tags: 8
---


# Question
Title: How do I attach a single-use block through a field?
I am working on a project that has a lot of custom block types (about 35). They are complex and have a lot of fields. They are being used with Layout Builder so all the blocks that get created are mostly single-use and hidden. The block plugin that is applicable here is the `InlineBlock` class provided by Layout Builder.

I want to re-use some of these block types in a node field. This usage is identical to how paragraphs are used on a field. The main module I would turn to in this sort of situation is block\_field. Unfortunately it does not work with `InlineBlock`s, I've created an issue about this.

Is there a solution for this problem? Are there other patterns or techniques I'm missing? At this stage my only obvious solution is to convert these types to paragraphs which I know how to use in Layout Builder.

# Answer
The block\_field module is designed to reference block plugins rather than block content. I think what you want here is an entity reference field with an inline entity form or entity browser.

It's likely block field has never been tested with layout\_builder enabled (where the InlineBlock plugin comes from) so that's where this confusion is coming from!
> 1 votes

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


# Question
Title: Batch delete users and the content they created
When I received this Drupal 7 site to manage, it has had years of being open for people to make accounts and now I have ~ 300 PAGES of users with names like ismehacker1234568 and such, with under a dozen legitimate accounts I need to keep.

Once, on another site long ago I tried removing the users from the database table using a SQL query. That was a disaster and broke the entire site. I want to avoid that this time around.

I also need to delete any content they made, but not anything the legitimate users made.

# Answer
> 1 votes
As stated in the comments, Views Bulk Operations provides helpful functionality. You can use the "select all" checkbox on the /admin/people page to select all the users, then deselect the few you want to keep. From the dropdown, you can then choose "Cancel user account". After submitting, you will select the method by which to cancel the accounts in bulk (such as *Delete the account and its content*, or *Delete the account and make its content belong to Anonymous*).

# Answer
> 0 votes
My suggestion is to prepare a text file with 1 username per line and use Drush in a shell script (assuming Drush 8), do this:

```
IFS="
"
for user in `cat users.txt`
do
echo "Cancelling user: $user"
drush -y user-cancel --delete-content ${user}
done

```

This way you will loop over your file and delete one user at a time.

Another approach is to massive delete all of them using a comma-separated approach:

```
drush -y user-cancel --delete-content `cat users.txt | paste -d ',' -`

```

---
Tags: 7, users
---


title: add Bundle field to a custom entity

text:
# Question
Title: add Bundle field to a custom entity
I am trying to add a new bundle field into my custom entity, I added the following code into the MyCustomEntity.php file, I uninstalled my module, so, I installed it again, the field is showing up on the view, but in my data base the field is not added.

Could you please support me?

```
$fields['new_name'] = BaseFieldDefinition::create('text_long')
  ->setLabel(t('New Name'))
  ->setDisplayOptions('form', [
    'type' => 'text_textarea',
  ])
  ->setRevisionable(TRUE)
  ->setTargetBundle($bundle);

```

Thank you, I will really appreciate your support.

# Answer
> 1 votes
For the Entity base field update, You'll need to also add an update hook to apply it

For example:

**Installing a new field storage definition**

```
use Drupal\Core\Field\BaseFieldDefinition;

/**
 * Implements hook_update_N
 */
function example_update_8701() {
  $bundle = 'article';
  $field_storage_definition = BaseFieldDefinition::create('text_long')
  ->setLabel(t('New Name'))
  ->setDisplayOptions('form', [
    'type' => 'text_textarea',
  ])->setRevisionable(TRUE)
  ->setTargetBundle($bundle);

  \Drupal::entityDefinitionUpdateManager()
    ->installFieldStorageDefinition('new_name', 'node', 'EXAMPLE_MODULE', $field_storage_definition);
}

```

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

---
Tags: entities
---


# Question
Title: Correct way to get field definitions for entity types
I'm still pretty new to D8 so I'm getting to grips with the new way it deals with fields and the OOP way of doing it etc.

I've got a hook in my module which I'm trying to add a submit handler to different types of form submission (user registration, comment forms, webforms etc) and I'm trying to write something which will go through each of the admin added fields (eg, all fields that start with field\_ ) and deal with each field type so that I can do something additional with it at the end

In pseudo terms

```
foreach ($fields as $field_name => $field) {
    if (substr($field_name, 0, 6) === "field_") {
      switch ( //field type ) {
        case 'boolean':
          // if it's a boolean, do this
          break;

        case 'entity_reference':
          // if it's an entity reference, do this
          break;

        default:
          // for everything else, do this

          break;
      }
    }
  }

```

But where my switch statement is, I'm basically having to check against the field definition to determine what type of field I'm checking against, because if I just check against the submit handler answers, it only gives me the response.

Currently I'm getting the definitions by doing this

```
$definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('entity_type', 'bundle');

```

Is that the best method to do it? When I tried to run dpm() on this for a custom comment form type, it just seems to kill my site, not like a requirement error, but it just seems to have a memory leak when I try to do it or something.

# Answer
Think this is an OOP question... so the correct answer is to switch by the type of the instance. In PHP you do this with "instanceof", like here in MappingTest.php:

```
protected function filterNumericFields(&$fields) {
    foreach ($this->view->field as $id => $field) {
      if (!($field instanceof NumericField)) {
        unset($fields[$id]);
      }
    }
  }

```

Note: dpm is bad with nested objects... you should set up a debugger like xdebug.

Another Note: Each content entity has a getFieldDefinitions method:

```
   /**
   * {@inheritdoc}
   */
  public function getFieldDefinitions() {
    if (!isset($this->fieldDefinitions)) {
      $this->fieldDefinitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($this->entityTypeId, $this->bundle());
    }
    return $this->fieldDefinitions;
  }

```
> 0 votes

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


title: identify author of an entity

text:
# Question
Title: identify author of an entity
Using Drupal 8 and hooks, I am able to send an email to the current user, thanks to How to send mail programmatically in Drupal 8 and BCC For drupal mail function.

So, I define my message in `hook_entity_update()` and send it in `hook_mail()`.

I am trying to send emails in the following case.

1. user U1 consult a node created by user U2 (the aim is to permit to U1 to give his impression to U2 thanks to a select field). When U1 gave his impression, content is registered.
2. I need to send a email to U2 (the node author), but since he isn't the current user, I cannot use `\Drupal::currentUser()`.

In `hook_entity_update()`, how can I identify the author of the current entity, knowing that "author" is not provided by `Drupal\Core\Entity\EntityInterface`?

Is there a specific service?

# Answer
Afaik, there's no requirement that a Content Entity **must** store the id of the user who created/edited it. However, many entity types do use a common method to store the owner information - Drupal core's *user* module provides an EntityOwnerTrait that many entity types use. (At least Node, Media, etc, all use this trait.)

For example, if you're looking for the owner of an entity that uses this trait, you can use the `getOwner()` method like:

```
$owner_user_object = $entity->getOwner();

```

---

It's unclear if user *U2*, in your example, would be the owner of the entity or just the author of a particular revision. If your entity is storing revision information, and the entity extends EditorialContentEntityBase (Note that they probably do. Node, Media, etc, all extend this base class) then it's also possible to load the author of a particular revision.

First, load the revision. See @baikho's comment pointing to Preferred way of loading a specific entity revision.

```
$entity_revision = \Drupal::entityTypeManager()
  ->getStorage('MY_ENTITY_EYPE')
  ->loadRevision($MY_REVISION_ID);

```

Once you'd loaded the revision, you can get the author of that revision with the `getRevisionUser()` method like:

```
$revision_user_object = $entity_revision->getRevisionUser()

```
> 4 votes

# Answer
`EntityInterface` doesn't have any method for getting the user who created an entity because not all the entities have the concept of owner. For example, the User entity is one of those entities.

The entities for which is defined an owner implement `EntityOwnerInterface`.

> An owner is someone who has primary control over an entity, similar to owners in Unix file system access. This may or may not be the entity's original author. The owner may also have less permissions than other users, such as administrators.

If you are implementing `hook_entity_update()` for a generic entity and you want to check if it has an owner, you should use code similar to the following one.

```
use \Drupal\Core\Entity\EntityInterface;
use \Drupal\user\EntityOwnerInterface;

function hook_entity_update(EntityInterface $entity) {
  if ($entity instanceof EntityOwnerInterface) {
    // The entity has an owner (a.k.a. an author).
    $author_id = $entity->getOwnerId();
    $autor = $entity->getOwner();
  }
}

```

If the entity implements `RevisionLogInterface` (which means it supports revisions, and it usually extends `RevisionableContentEntityBase`), then it also defines a revision author, returned from `getRevisionUser()`.
> 2 votes

---
Tags: 8, emails
---


# Question
Title: Add #ajax event to a custom composite element
I have created a custom composite element for Webform (6.0) that has a date field and a select field. The idea is when a user picks a date, an API call is made that returns available time slots to make a booking.

I am familiar with how this is normally done in FormBase forms and inspecting form\_state to inform build values, but I am stuck here.

```
class WebformTourAvailabilityComposite extends WebformCompositeBase {

  /**
   * {@inheritdoc}
   */
  public static function getCompositeElements(array $element) {
    $date_format_entity = DateFormat::load('html_date');
    $date_format = $date_format_entity->getPattern();

    $elements = [];

    $elements['tour_date'] = [
      '#type' => 'date',
      '#title' => t("Tour Date"),
      '#date_date_format' => $date_format,
      '#date_year_range' => '0:15',
      '#attributes' => [
        'min' => '[webform_submission:created:html_date]',
        'onkeydown' => 'return false'
      ],
      #'#datepicker' => TRUE,
      '#datepicker_button' => TRUE,
      '#date_label_position' => 'invisible',
      '#required' => TRUE,
      '#ajax' => [
        'callback' => 'mymodule_get_date_options',
        'wrapper' => 'available-times'
      ]
    ];

    $elements['tour_time'] = [
      '#type' => 'select',
      '#title' => t('Tour time'),
      '#prefix' => '<div id="available-times">',
      '#suffix' => '</div>',
      #'#options' => [],
    ];

    return $elements;
  }

}

```

in mymodule.module:

```
function mymodule_webform_submission_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  $selected = $form_state->getValues();

  if (isset($selected["select_appointment"]["tour_date"])) {
    $response = \Drupal::httpClient()->get('https://nestiolistings.com/api/v2/appointments/group/123/available-times');
    $options = json_decode($response->getBody()->getContents(), TRUE);
    #$form["elements"]["step_1"]["select_appointment"]["tour_time"]["#options"] = $options['data'];
    $form["elements"]["step_1"]["select_appointment"]["#webform_composite_elements"]["tour_time"]["#options"] = $options['data'];
  }
}

function mymodule_get_date_options(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  return $form;
}

```

Which method I should override or use in the Webform ecosystem, or if this needs to be a composite at all and I can do this some other way?

# Answer
Turns out I was pretty close, an external module was causing interference while authenticated (was getting a post max size exceeded error when submitting the form) on the front end. Unrelated to Webform.

You can add ajax to composite elements and react to them in afterBuild like so (or in your own custom form elements, added to the composite):

```
class WebformTourAvailabilityComposite extends WebformCompositeBase {

  /**
   * {@inheritdoc}
   */
  public static function getCompositeElements(array $element) {
    $date_format_entity = DateFormat::load('html_date');
    $date_format = $date_format_entity->getPattern();

    $elements = [];

    $elements['tour_date'] = [
      '#type' => 'date',
      '#title' => t("Tour Date"),
      '#date_date_format' => $date_format,
      '#date_year_range' => '0:15',
      '#attributes' => [
        'min' => '[webform_submission:created:html_date]',
        'onkeydown' => 'return false'
      ],
      '#datepicker_button' => TRUE,
      '#date_label_position' => 'invisible',
      '#required' => TRUE,
      '#ajax' => [
        'callback' => ['\Drupal\mymodule\Element', 'refreshTimes'],
        'wrapper' => 'available-times'
      ],
      '#prefix' => '<div id="available-times">',
    ];

    $elements['tour_time'] = [
      '#type' => 'select',
      '#title' => t('Tour time'),
      '#suffix' => '</div>',
      '#after_build' => [[get_called_class(), 'afterBuild']],
      '#validated' => TRUE,
    ];

    return $elements;
  }

  public static function refreshTimes($form, FormStateInterface $form_state) {
    return $form['elements']['tour_time'];
  }

  /**
   * Performs the after_build callback.
   */
  public static function afterBuild(array $element, FormStateInterface $form_state) {
    $client = \Drupal::service('mymodule.client');
    $selected = $form_state->getValues();

    if (isset($selected['tour_date']) && strlen($selected['tour_date'])) {
      $times = $client->getAvailableTourTimes($selected["tour_date"]);
      $element['#options'] = count($times) ? $times : ['' => '- Select -'];
      $element['#description'] = count($times) ? '' : 'There were no available times found for the date you selected. Please choose another date.';
    }

    return $element;
  }

}

```

Note that your form keys will vary depending on your form, what you name fields, etc. On afterBuild, in this case, if the date picker has a value submitted, it will call a remote API and replace the options in the select with values.
> 1 votes

---
Tags: 8, webforms
---


# Question
Title: How to use .schema.yml definition for two entities avoiding duplicated code
What is the yml syntax in drupal .schema.yml files for specifying the same config for two entities? Something like this is what I need:

```
node.type.*.third_party.my_module:
media.type.*.third_party.my_module:
  type: mapping
  label: 'My Module'
  mapping:
    lots more lines here ...
    which I do not want to duplicate ...

```

I want the same settings for both `node.type.*` and `media.type.*` and there should be a way to avoid repeating all the definition and just having those two rows at the top.

# Answer
## Solution

Here is a very good way to do this, with thanks to @sonfd for the link.

```
node.type.*.third_party.my_module: &third_party_settings_alias
  type: mapping
  label: 'My Module'
  mapping:
    lots more lines here ...
    which I do not want to duplicate ...

# Use saved alias to repeat the same settings for media.type
media.type.*.third_party.my_module:
  *third_party_settings_alias

```

That's all there is to it. All the settings for `node.type` are repeated for `media.type`
> 0 votes

---
Tags: 8, configuration
---


# Question
Title: How to check if an item exists in a Queue?
While inserting items in a Queue how can I check if the item I am trying to insert is already present in the Queue?

# Answer
The queue API doesn't have a method for this. It is very limited on purpose, as some queue systems might not be able to provide information like this.

The update module has its own wrapper to do this, by additionally storing all the task names in key value as well. See `\Drupal\update\UpdateProcessor::createFetchTask`:

```
public function createFetchTask($project) {
  if (empty($this->fetchTasks)) {
    $this->fetchTasks = $this->fetchTaskStore->getAll();
  }
  if (empty($this->fetchTasks[$project['name']])) {
    $this->fetchQueue->createItem($project);
    $this->fetchTaskStore->set($project['name'], $project);
    $this->fetchTasks[$project['name']] = REQUEST_TIME;
  }
}

```
> 6 votes

# Answer
Add this function:

```
/**
 * Adding item to queue.
 *
 * @param string $queue_id
 *   The name of the queue to work with.
 * @param array $item_data
 *   Arbitrary data to be associated with the new task in the queue.
 * @param bool $find_identical
 *   Checking exist item in the queue or not.
 *   If exists, new item wouldn't be added in queue.
 */
function MY_MODULE_add_to_queue($queue_id, array $item_data, $find_identical = FALSE) {
  $queue_item_exists = FALSE;

  if ($find_identical) {
    $query = \Drupal::database()->select('queue', 'q');
    $query->condition('name', $queue_id);
    $query->condition('data', serialize($item_data));
    $query->condition('expire', 0);
    $query->fields('q', ['item_id']);

    $queue_item_exists = !empty($query->execute()->fetchAll());
  }

  if (!$queue_item_exists) {
    \Drupal::queue($queue_id)->createItem($item_data);
  }
}

```

And in place where you adding new items in queue use this:

```
MY_MODULE_add_to_queue('YOUR_QUEUE_WORKER', $item_to_add, TRUE);

```
> 4 votes

# Answer
It depends on how your implementation. How do you define uniqueness? By a duplicate queue item object (e.g. all properties are equal), by a specific property on your queue item object, or something else?

The Queue interfaces `QueueInterface` & `ReliableQueueInterface` don't define any method for uniqueness. It's up to you to define what unique means and to enforce it when using the `createItem()` method.

To have a concrete example, take a look at the Queue Unique project (it's D7 but the premise is the same this has releases for D7 and D8/D9 now). It's creating it's own implementation of `DrupalQueueInterface` (`QueueInterface` in D8) and adding a table where it MD5ing a serialized queue object to determine if an item is unique (if the MD5 hash of the serialized object is the same, it's a duplicate which is rejected).
> 2 votes

# Answer
Here you can find a nice D7 solution: https://www.webomelette.com/overriding-queues-drupal-7-or-how-not-create-duplicate-queue-items
> 1 votes

---
Tags: 8, cron, queue
---


title: Entity Print PDF Layout for Views page

text:
# Question
Title: Entity Print PDF Layout for Views page
My requirement is to convert a views page into a PDF. I have created the views page with table formatting and a PDF plugin attached to the header that allows one to download the views page as PDF. I created an entity-print.html twig template and an HTML structure copied from the answer in this post How to customize entity print pdf and created a twig variable 'footer' in THEME\_preprocess\_page function in the theme's .theme file but the calls {{ footer }} to that variable in the template returns nothing.

In other to at least test CSS formatting, I placed these in the respective files:

ENTITY-PRINT.HTML.TWIG

```
<html>
<head>
    <meta charset="utf-8">
    <title>{{ title }}</title>
    {{ entity_print_css }}
</head>
<body>
{# The footer is repeated on all pages and must be printed first. #}

<footer>
    {{  footer  }}
</footer>
{%  if cover_page  %}
<div class="cover-page">
    {{ cover_page }}
</div>
{%  endif  %}
{# The header is repeated after the cover page for all pages. #}
<header>
    {{  header  }}
</header>
<div class="page">
    {{ content }}
</div>
</body>
</html>

```

THEMENAME.THEME

```
function THEMENAME_preprocess_page(&$variables) {
  $variables['footer'] = "HERE IS YOUR FOOTER";
  $variables['header'] = "HERE IS YOUR HEADER";
}

```

IN .INFO.YML

```
entity_print:
 views:
   views_page_machine_name: 'theme_name/result-pdf'

```

IN .LIBRARIES.YML

```
result-pdf:
  css:
    theme:
      styles/result-pdf.css: {}

```

IN CSS FILE (i.e. result-pdf.css)

```
* {
    color: red;
}

div {
    background: blue;
}

```

and then created result-pdf.css but the styles did not change anything in the generated pdf.

One of the answers in another post Entity print get variable in twig template pointed to creating an entity specific template for layout of the PDF with HTML as required. For example, for the article content type you have node--article--pdf.html.twig. What is the template suggestion for a views as described in my case?

The question is how do I achieve:

1. create a HTML layout format that is fed all the fields from the views page
2. rightly set the footer/header variable for output in the entity-print.html template mentioned above
3. turn bullet into A pdf (so that the download link on the views page generates the formatted html as pdf).

Perhaps bullet 1-3 is irrelevant, a step by step direction on how to have a views page formatted as required and converted to PDF using the entity print module will be appreciated.

# Answer
> 1 votes
The solution came down to replacing "views" with "view" - without the s and "views\_page\_machine\_name" with "all", such that this:

```
entity_print:
 views:
   views_page_machine_name : 'theme_name/result-pdf'

```

became:

```
entity_print:
 view:
   all: 'theme_name/result-pdf'

```

---
Tags: theming, 8
---


# Question
Title: Composer keeps reinstalling the same core version
I manually updated a Drupal 9 installation to 9.1.2. I need to install the Real AES module, which depends on the Defuse PHP-Encryption library.

I attempted to install it using Composer, but it tries to update Drupal to 9.1.2 again, which breaks it, and I have to restore from a backup.

Any help would be greatly appreciated!

Running `composer --no-plugins --no-scripts require defuse/php-encryption` causes the following error.

> PHP Warning: Module 'pdo\_mysql' already loaded in Unknown on line 0
> Do not run Composer as root/super user! See https://getcomposer.org/root for details
>
> Continue as root/super user \[yes\]?
>
> Using version ^2.2 for defuse/php-encryption
> ./composer.json has been updated
> Running composer update defuse/php-encryption
>
> Loading composer repositories with package information
>
> Updating dependencies
>
> Lock file operations: 2 installs, 0 updates, 0 removals
>
> * Locking defuse/php-encryption (v2.2.1)
> * Locking paragonie/random\_compat (v9.99.100)
>
> Writing lock file
>
> Installing dependencies from lock file (including require-dev)
> Package operations: 3 installs, 0 updates, 0 removals
>
> * Installing paragonie/random\_compat (v9.99.100): Extracting archive
> * Installing defuse/php-encryption (v2.2.1): Extracting archive
> * Installing drupal/core (9.1.2): Extracting archive
>
> 1 package suggestions were added by new dependencies, use `composer suggest` to see details.
>
> Package doctrine/reflection is abandoned, you should avoid using it. Use roave/better-reflection instead.
>
> Generating autoload files

# Answer
> 0 votes
The issue is resolved. I was running Composer as root and disabling scripts and plugins because of that.

In my over concern for security, I didn't think to just enable my servers "www" user to allow for access via "su www". Sometimes you just need a good SHAKE!

> "Don't run the command with that flag. You say you're using these flags because composer says to use them if you run as root, so don't run as root. – sonfd 12 hours ago"

Thank you for your feedback. I was able to modify my "www" user and su to my "www" user and then run the composer without the -- arguments and... ...it worked. – bforest 11 hours ago

@bforest If you found the answer, you can write an answer to your own question; this is helpful for future visitors to the site who may have a similar problem. – Patrick Kenny 5 hours ago.

---
Tags: composer
---


# Question
Title: How do I add a view between display fields of a node?
I have a view that displays a table at the bottom of every node. It's part of the content of the node so I want to have the "comments" section below the view.

However, the comments are a display field, which means they have to be in the same block as the node content. Since the view is a separate block I can't place the view between the node content and the comment section.

Is there a workaround for this?

Note that my content is created by the website community, so I can't use any solution that involves changing the contents of the nodes manually.

# Answer
> 3 votes
This can be done with Drupal 8's Layout Builder.

Layout Builder is a module in Drupal 8 core that does much of what Panels did in Drupal 7 and before-- it allows you to create arbitrary layouts consisting of fields and blocks for content types and even individual pieces of content.

Since its part of core, this should be a safe long-term solution to rely on.

In this case, the rough steps would be:

1. Enable Layout Builder.
2. Go to Structure -\> Content types -\> MY CONTENT TYPE -\> Manage Display.
3. Under **Layout options**, check *Use Layout Builder* and save.
4. Click the new **Manage layout** button that appears.
5. Your fields will be arranged as before. Now, though, you can click **Add block** to add any block you want, including Views blocks. You can then put the Views block between your page body and your comments.

This is just scratching the surface of what you can do but it should get you started.

---
Tags: 8, views, blocks, comments
---


title: How do I turn off notices only?

text:
# Question
Title: How do I turn off notices only?
I want to show only warnings and errors but I want to turn-off notices. How can I turn off notices?

In my settings.php, I have this code:

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

```

What value should I put there?

# Answer
> 3 votes
This configuration aligns with the options at Manage \> Configuration \> Development \> Logging and Errors (/admin/config/development/logging).

There are 4 error level options available. The levels with their corresponding values, i.e. the actual value for `$config['system.logging']['error_level']` are:

1. None: `hide`
2. Errors and warnings: `some`
3. All messages: `all`
4. All messages, with backtrace information: `verbose`

For example, to only display errors and warnings, replace your current line with:

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

```

---
Tags: 8
---


# Question
Title: How to remove non breaking space from body/value in migration process?
I am successfully migrating the content from Drupal 7 to Drupal 9. However, I am getting some extra non-breaking spaces I'd like to remove.

>

I tried using a basic *str\_replace* plugin, but that doesn't work.

>

What am I doing wrong? What else should I look into?

# Answer
By taking a look into the StrReplace class I see that you are missing the source key, which should be the name of the field/column/whatever you are importing from.

If it does not work, try to also remove the "regex" key and if it still does not, try to use a simpler search, to ensure that the problem does not lie with your data.
> 2 votes

---
Tags: migrations, plugins
---