# Question
Title: Drupal 7 Form API - AJAX updates for multiple file uploads
I have a Drupal 7 custom module form that uploads then processes multiple images.

I have an ajax callback that updates page content with the processed images. BUT, the page update happens when all uploaded files are finished and I would like to alter this to update when each uploaded file is processed.

Form creation:

```
function awsImage_form($form, &$form_state) {
  $form = [];

  $form['file'] = [
    '#type' => 'file',
    '#name' => 'files[]',
    '#title' => t('Upload files to test'),
    '#description' => t('TIFF\'s, JPG\'s, GIF\'s, and PNG\'s only, 20MB Max Size'),
    '#attributes' => ['multiple' => 'multiple'],
  ];

  $form['submit'] = [
    '#type' => 'submit',
    '#value' => t('Upload'),
    '#ajax' => [
      'callback' => 'awsImage_form_callback',
      'wrapper' => 'results',
      'method' => 'append',
    ],
  ];
  $form['results'] = [
    '#markup' => '<div id="results">Results:</div>',
  ];
  return $form;
}

```

Form validation \[error checking & save location \[$destination\] removed to keep it brief\]:

```
function awsImage_form_validate($form, &$form_state) {
  //Save multiple files
  $num_files = count($_FILES['files']['name']);

  for ($i = 0; $i < $num_files; $i++) {
    $file = file_save_upload($i, [
      'file_validate_extensions' => ['tif tiff png gif jpg jpeg'],
    ]);
    if ($file) {
      file_prepare_directory($destination, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
      if ($file = file_move($file, $destination, FILE_EXISTS_REPLACE)) {
        $form_state['values']['file'][$i] = $file;
      }
    }
  }
}

```

AJAX callback \[image processing removed to keep it brief\]:

```
function awsImage_form_callback($form, $form_state) {
  $form_state['rebuild'] = TRUE;
  $processed_out = '';
  if (is_array($form_state['values']['file'])) {
    foreach ($form_state['values']['file'] as $file) {
     // image processing stuff which builds and array: $img_reponse_details
      $output = '';
      foreach ($img_reponse_details as $key => $img_details) {
        // build front end $output
      }
      $processed_out .= $output;
  }
  // push output back to form.
  $element = $form['results'];
  $element['#markup'] = $processed_out;
  return $element;
}

```

Ideally, I would like to update the front end in the foreach loop in the ajax callback:

```
function awsImage_form_callback($form, $form_state) {
  foreach ($form_state['values']['file'] as $file) {
      // deal with each image
      // push output back to form.
      $element = $form['results'];
      $element['#markup'] = $processed_out;
      return $element;
    }
}

```

But as soon as I return the current result, that's the loop over and only the first file is displayed - which is correct as it is a return... but what I am really after is 'do the AJAX update and carry on with the rest' and I am not sure how to go about that part?

# Answer
> 0 votes
The AJAX updates I wanted was to provide some progress updates which I found out I can achieve form api #ajax\['progress'\]. I guess if I had mentioned that in the original question it would have made life a bit simpler :) :

first create a url for the ajax progress update to call:

```
function awsImage_menu() {
  $items = [];

  $items['path/to/page'] = [
    'title' => t('Import progress'),
    'page callback' => 'import_progress',
    'access callback' => 'user_access',
    'access arguments' => ['access awsImage'],
    'type' => MENU_CALLBACK,
  ];

  return $items;
}

```

then update the form to use the progress path created in the hook\_menu - note the type MUST be 'bar' and the url MUST have the starting forward slash

```
function awsImage_form($form, &$form_state) {
.....

  $form['submit'] = [
    '#type' => 'submit',
    '#value' => t('Upload'),
    '#ajax' => [
      'callback' => 'awsImage_form_callback',
      'wrapper' => 'results',
      'method' => 'append',
      'progress' => [
        'type' => 'bar',
        'url' => '/path/to/page',
        'interval' => 1000,
      ],
    ],
  ];
....

}

```

then create your progress function. In my original awsImage\_form\_callback function I created and updated a session variable: $\_SESSION\['awsImage'\]\['import\_status'\]

```
function import_progress() {
  // set up default progress status message
  $progress = [
    'message' => t('Starting import...'),
    'percentage' => -1,
  ];

  // check if there is any status data

    $completed = (isset($_SESSION['awsImage']['import_status'])) ? $_SESSION['awsImage']['import_status'] : false; // calculate progress percentage here

    if ($completed) {
      // there is status data, so build the status message
      $completed = unserialize($completed);
      $total_files = $completed['total'];
      $current_file = $completed['current'];
      $current_file_name = $completed['current_filename'];
      $completed_percentage = ($current_file / $total_files) * 100;

      $progress['message'] = t('Processing:' . $current_file_name);
      $progress['percentage'] = (int) $completed_percentage;
    }

  drupal_json_output($progress);
}

```

Now when I upload & process multiple files, I get an update every second on which file I am uploading and how much there is left to go... Most of the time, sometimes the progress bar does not do any updates then just shows 100% and completes... but that may be down to local files uploading to a local server and there is not enough time!

---
Tags: forms, ajax
---


title: webform libraries dir location

text:
# Question
Title: webform libraries dir location
The webform status report states several libraries are needed. After downloading the zip file.. and extracting it. Where does '/libraries/' directory belong? ie: /modules/webform/libraries Or ???

# Answer
It's literally /libraries in your web root, not in a subfolder. This is from the *Base-Level Directories* section of the Directory Structure docs (which began life here):

> **/libraries** \- All third party external libraries leveraged by Drupal, such as a WYSIWYG editor. This folder is not included by core, but used with many contributed modules.
> 5 votes

# Answer
It's written inside `webform.libraries.yml` where these 3rd party libraries are supposed to be located.

Their paths all start with `/libraries/...` (`/` means Drupal web root) whereas Webform's own libraries paths all start with just `js/...` (which means relative to the `webform.libraries.yml` file).
> 2 votes

# Answer
You can use `drush webform-libraries-download`.
> 0 votes

---
Tags: 8, webforms
---


# Question
Title: Call another field inside preprocess_views_view_field
how can I access the value of another field inside the preprocess\_views\_view\_field. This is an example:

```
function THEMENAME_preprocess_views_view_field(&$variables) {
  $view = $variables['view'];
  $field = $variables['field'];

  if ($view->id() == 'VIEW_NAME' && $view->current_display == 'DISPLAY_NAME') {
    if ($field->field == 'FIELD_NAME') {
      $my_output = manipulation(ANOTHER_FIELD_NAME_IN_VIEW);
      $variables['output'] = $my_output;
    }
  }
}

```

It's possible or should i use it \_preprocess\_views\_view?

# Answer
> 2 votes
Ok, I solved it like this:

```
function THEMENAME_preprocess_views_view_field(&$variables) {
  $view = $variables['view'];
  $field = $variables['field'];
  $rows = $variables['rows'];

  if ($view->id() == 'VIEW_NAME' && $view->current_display == 'DISPLAY_NAME') {
    if ($field->field == 'FIELD_NAME') {
      foreach ($view->field as $fieldId => $field) {
        if ($fieldId === 'ANOTHER_FIELD_NAME_IN_VIEW') {
          $my_output = $view->style_plugin->getFieldValue($row->index, $fieldId);
        }
      }
      $variables['output'] = $my_output;
    }
  }
}

```

---
Tags: views, 8, theming
---


title: How can I show a field on click?

text:
# Question
Title: How can I show a field on click?
In node.html.twig, I want to show a field when I click on it, as what the Field Value Loader (Show field on click) module does, but this module doesn't have releases for Drupal 8.

How can I do this?

# Answer
> 1 votes
**node.html.twig**

```
<div class = "field-something">
{{ content.field_something.value }}
</div>

<div class = "show">
Show
</div>

```

**custom.js**

```
(function ($) {

$('.field-something').hide();
$('.show').show();

$('.show').click(function(){
    $('.field-something').fadeIn(2000);
    $('.show').hide();
});

}(jQuery));

```

Your Theme's **style.css**

```
.field-something { float: left; padding-right: 5px; }
.show { color: blue; cursor: pointer; display: none; }

```

Example DEMO

# Answer
> 0 votes
```
var notificationList = false;
$('.show').click(function(){
    if(notificationList) {
       notificationList = false;
       $('.field-something').hide();
    } else {
       notificationList = true;
       $('.field-something').show();
    }
});

```

---
Tags: 8
---


# Question
Title: How to show a block between the body and a paragraphs field?
For a larger article content type on a Drupal 8 page, I want to have the following structure:

### Title Image/Video

### Body (the normal node body with the title and some text)

# A contanct block

### Paragraphs

For the title image/video I'm not sure yet whether I want to simply create 2 different article types or find some magic to do either the one or the other, but that's fine.

The body that comes next, will just follow as is and contain some introductional text. I guess, I have to write my own template to be able to place the image before the title, but that'll work.

**Then**, I want a simple block that contains some simple contact information (probably the same block in every article).

**Then**, there should follow a paragraphs field that'll hold several paragraphs for the rest of the article.

Do you have any ideas how I could place this block?

Thank you in advance for your help :)

# Answer
Enable "Layout builder" module first. On "Manage display" in entity config Default "Custom display" enable "Full content", then go there and enable "Use Layout builder" and "Allow each content item to have its layout customized."

This will give you "Layout" tab in each node (of this type where you enable this in config) for ex. - how to arrange each field of this entity, also ability to add custom block, user fields, etc. If you want Contact form there you should probably have to write custom block in custom module and put the form inside - just to have it for placement from the Layout builder.
> 2 votes

# Answer
1. Install the Block field module
2. Create a paragraph type "Drupal block"
3. In that paragraph type, create a new field using the field type from the new module

Now you can place any block within the main content area just like an ordinary paragraph.
> 1 votes

---
Tags: 8, nodes, blocks, paragraphs
---


# Question
Title: How to customize message in maestro mail notification
I am working on Maestro module. we have interactive tasks in the Maestro which are executed by the users to whom task is assigned. In Maestro, we can intimate the user by mail about the task assigned to him. Message in the mail is one paragraph. I want to customize this mail. I need to add table and send message in multiple pargagraphs.

I have tried adding br(I tried adding angular brackets but text after that is going to next line) in the message but message is being displayed along with br instead of going to new line.

I think html tags doesn't work there.

How to make html tags work in the custom mail or customise the message? P.S: I am attaching the screenshot where I am writing the message

# Answer
I know this has been up for a while but thought I would answer. Up until recently, Maestro was removing any HTML from that textbox using Drupal's checkPlain.

I added a patch which was accepted into the development branch so it should be sorted in the next release of Maestro. If you wanted a fix in the meantime, use the patch file here: https://www.drupal.org/project/maestro/issues/3076536
> 0 votes

---
Tags: emails
---


title: How do I re-save all users?

text:
# Question
Title: How do I re-save all users?
I need to re-save about 300 user to initialize geo-coding on their address fields. On /admin/people, I don't see any bulk action that would fit my needs. I have tested the update path-alias but with no luck.

Also, the VBO module for Drupal 8 doesn't offer a solution for users, AFAIK.

Any help is appreciated.

# Answer
I don't know how comfortable you are with code. I would suggest writing an update hook in a custom module. Something like:

```
MYMODULE_update_8100(&$sandbox) {
  // On the initial run, set up the update.
  if (empty($sandbox)) {
    // Get all user ids.
    $sandbox['items'] = \Drupal::entityQuery('user')
      ->accessCheck(FALSE)
      ->execute();
    $sandbox['max'] = count($sandbox['items']);

    if (!$sandbox['max']) {
      // Prevent division by zero if there are no users.
      $sandbox['#finished'] = 1;
      return;
    }
  }

  $iteration = 0;
  while ($iteration < 25 && $sandbox['items']) {
    $iteration ++;

    // Resave each user.
    \Drupal::entityTypeManager()
      ->getStorage('user')
      ->load(end($sandbox['items']))
      ->save();

    // Remove the end of the items list when the item has finished
    // processing.
    array_pop($sandbox['items']);
  }

  // Update the completion status as a number between 0 and 1.
  $sandbox['#finished'] = ($sandbox['max'] - count($sandbox['items']) / $sandbox['max'];
}

```

See `hook_update_N` for more information.
> 2 votes

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


# Question
Title: Calling a JS function after managed file has completed uploading
How can I call a JavaScript function after a file has completed uploading using the Drupal Form API (FAPI) `managed_file` element?

# Answer
> 8 votes
This is tricky in D8, as the ajax code does not offer any hooks or callbacks after the function has run. The solution is to override the ajax callback function that the managed\_file element uses, adding an additional custom command that is triggered when the file upload is complete.

First, we create a custom AJAX command, that will be used to trigger the code we want to execute. Details on creating custom ajax commands can be found here.

First, the Ajax command on the PHP side. This will go into `[MODULE]/src/Ajax`:

```
<?php

namespace Drupal\[MODULE]\Ajax;

use Drupal\Core\Ajax\CommandInterface;

/**
 * Command to trigger an event when managed file upload is complete.
 */
class ManagedFileUploadCompleteEventCommand implements CommandInterface {

  /**
   * Implements Drupal\Core\Ajax\CommandInterface:render().
   */
  public function render() {
    return [
      'command' => 'triggerManagedFileUploadComplete',
    ];
  }

}

```

Next, the `triggerManagedFileUploadComplete()` command needs to be created on the JavaScript side. This is done in `[MODULE]/js/managed_file_upload_complete_event_command.js`.

```
(function (Drupal) {

  "use strict";

  /**
   * Add new custom command.
   */
  Drupal.AjaxCommands.prototype.triggerManagedFileUploadComplete = function () {
    // Do stuff here after file upload is complete.
    alert(Drupal.t("File upload complete!"));
  };

}(Drupal));

```

Now the new JavaScript file needs to be registered in MODULE.libraries.yml:

```
command.managed_file_upload_complete_event_command:
  js:
    js/managed_file_upload_complete_event_command.js: {}
  dependencies:
    - core/jquery
    - core/jquery.once

```

With this, the custom command can be attached using the library: `[MODULE]/command.managed_file_upload_complete_event_command`

Now that the custom command and it's related JS callback have been completed, the next thing is to add the new command onto the end of the ajax callback, so it is executed when the upload is complete.

The default ajax callback for `managed_file` elements is \Drupal\file\Element\ManagedFile::uploadAjaxCallback(). This needs to be overridden, adding the command created above to be run after all other ajax commands.

The #ajax property of the `managed_file` element is added in \Drupal\file\Element\ManagedFile::processManagedFile(). As such, if we want to alter the ajax, it has to happen after the above #process handler has been run. So we add another #process callback to be called after the default #process callback. In our process callback, we can change the #ajax callback to a function of our own. The #process callbacks are declared in \Drupal\file\Element\ManagedFile::getInfo(). Adding another #process handler can therefore be done in hook\_element\_info\_alter().

```
/**
 * Implements hook_element_info_alter().
 */
function MODULE_element_info_alter(array &$info) {
  // Add a custom #process hook to the managed_file element:
  $info['managed_file']['#process'][] = 'MODULE_managed_file_process';
  // Add the custom command to managed_file elements, so that it is
  // available when called:
  $info['managed_file']['#attached']['library'][] = '[MODULE]/command.managed_file_upload_complete_event_command';
}

```

Now the command has been created and attached to all `managed_file` elements. The next step is to override the #ajax callback with our own, adding the custom command to it. Let's look at the overridden function (should be put in the .module file):

```
/**
 * Custom ajax callback for managed files.
 *
 * Overrides \Drupal\file\Element\ManagedFile::uploadAjaxCallback()
 *
 * @see \Drupal\file\Element\ManagedFile::uploadAjaxCallback
 */
function MODULE_managed_file_ajax_callback(array &$form, FormStateInterface $form_state) {
  // Retrieve the original response.
  $response = \Drupal\file\Element\ManagedFile::uploadAjaxCallback($form, $form_state, \Drupal::request());

  // Add our own command to the end, so our command is run last:
  $response->addCommand(new \Drupal\[MODULE]\Ajax\ManagedFileUploadCompleteEventCommand());

  return $response;
}

```

The last thing to do is to replace the original ajax command with our own. This is done in the process callback we registered in hook\_widget\_info\_alter():

```
/**
 * Custom process callback added to managed_file elements.
 *
 * Replaces the original #ajax callback with a custom one.
 */
function MODULE_managed_file_process(array &$element, FormStateInterface $form_state) {
  $element['upload_button']['#ajax']['callback'] = 'MODULE_managed_file_ajax_callback';

  return $element;
}

```

This tells Drupal to replace the original ajax callback with `MODULE_managed_file_ajax_callback()`. This callback retrieves the response from the original callback, and adds our custom command to the end of it. The custom command is called when the file has been uploaded, allowing us to run whatever JS we need on the server side after files have completed uploading.

# Answer
> 1 votes
Based on @Jaypan answer and @FLY comment I made a FieldWidget. This indeed removed the need for the `hook_managed_file_process` and `hook_element_info_alter`. This also made it possible to use the widget on a per field basis.

First make your custom FieldWidget in `[MODULE]/src/Plugin/Field/FieldWidget`:

```
namespace Drupal\[MODULE]\Plugin\Field\FieldWidget;

use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Plugin\Field\FieldWidget\FileWidget as CoreFileWidget;

/**
 * @FieldWidget(
 *   id = "[MODULE]_file_widget",
 *   label = @Translation("[MODULE] file upload widget"),
 *   field_types = {
 *     "file"
 *   }
 * )
 */
class FileWidget extends CoreFileWidget {

  /**
   * Override to replace the upload/file HTML control
   * with the [MODULE] form element.
   *
   */
  public static function process($element, FormStateInterface $form_state, $form) {

    $element = parent::process($element, $form_state, $form);

    if (!isset($element['upload'])) {
      return $element;
    }

    $element['upload_button']['#ajax']['callback'] = [get_called_class(), '[MODULE]ManagedFileAjaxCallback'];
    $element['upload_button']['#attached']['library'][] = '[MODULE]/[MODULE].managed_file_upload_complete_event_command';

    return $element;
  }

  /**
   * Custom ajax callback for managed files.
   *
   * Overrides \Drupal\file\Element\ManagedFile\ManagedFile::uploadAjaxCallback()
   *
   * @see \Drupal\file\Element\ManagedFile\ManagedFile::uploadAjaxCallback
   */
  public function [MODULE]ManagedFileAjaxCallback(array &$form, FormStateInterface $form_state) {
    // Retrieve the original response.
    $response = \Drupal\file\Element\ManagedFile::uploadAjaxCallback($form, $form_state, \Drupal::request());

    // Add our own command to the end, so our command is run last:
    $response->addCommand(new \Drupal\[MODULE]\Ajax\ManagedFileUploadCompleteEventCommand($form, $form_state));

    return $response;
  }
}

```

Then as Jaypan already wrote create a file in `[MODULE]/src/Ajax` for your custom Ajax command (Give the file the name of your class with the php extension):

```
namespace Drupal\[MODULE]\Ajax;

use Drupal\Core\Ajax\CommandInterface;

/**
 * Command to trigger an event when managed file upload is complete.
 */
class ManagedFileUploadCompleteEventCommand implements CommandInterface {

  /**
   * Implements Drupal\Core\Ajax\CommandInterface:render().
   */
  public function render() {
    return [
      'command' => 'triggerManagedFileUploadComplete',
    ];
  }

}

```

Create your javascript file that's being triggered by the command in `[MODULE]/js/managed_file_upload_complete_event_command.js`:

```
(function (Drupal) {

  "use strict";

  /**
   * Add new custom command.
   */
  Drupal.AjaxCommands.prototype.triggerManagedFileUploadComplete = function () {
    // Do stuff here after file upload is complete.
    alert(Drupal.t("File upload complete!"));
  };

}(Drupal));

```

Register your javascript file in `[MODULE].libraries.yml`:

```
[MODULE].managed_file_upload_complete_event_command:
  js:
    js/managed_file_upload_complete_event_command.js: {}
  dependencies:
    - core/jquery
    - core/jquery.once

```

You can also use `$form` and `$form_state` in your custom command to use this in your javascript if you need to.

I ended up using different values from the files being uploaded. My `[MODULE]/src/Ajax/ManagedFileUploadCompleteEventCommand.php` looks like this:

```
namespace Drupal\[MODULE]\Ajax;

use Drupal\Core\Ajax\CommandInterface;
use Drupal\file\Entity\File;

/**
 * Command to trigger an event when managed file upload is complete.
 */
class ManagedFileUploadCompleteEventCommand implements CommandInterface {
  // Constructs a ReadMessageCommand object.
  public function __construct($form) {
    $this->form = $form;
  }
  /**
   * Implements Drupal\Core\Ajax\CommandInterface:render().
   */
  public function render() {
    $files = array();
    $form_delta = $this->form['#file_upload_delta'];

    for($i=0;$i<$form_delta;$i++) {
      $file_id = array_keys($this->form[$i]['#files'])[0];
      $file = File::load($file_id);
      $uri = $file->getFileUri();
      $stream_wrapper_manager = \Drupal::service('stream_wrapper_manager')->getViaUri($uri);
      $file_path = $stream_wrapper_manager->getExternalUrl();
      $file_name = $file->getFilename();

      $files[$i] = array(
        'file_id' => $file_id,
        'file_path' => $file_path,
        'file_name' => $file_name,
      );
    }

    return [
      'command' => 'triggerManagedFileUploadComplete',
      'files' => $files,
    ];
  }
}

```

You can use them in the javascript file you made in `[MODULE]/js/managed_file_upload_complete_event_command.js` like this:

```
(function (Drupal) {

  "use strict";

  /**
   * Add new custom command.
   */
  Drupal.AjaxCommands.prototype.triggerManagedFileUploadComplete = function (ajax, response, status) {
    var files = response.files;

    // Do stuff here after file upload is complete.
    console.log(files.file_id);
    console.log(files.file_path);
    console.log(files.file_name);
  };

}(Drupal));

```

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


# Question
Title: Variables are missing on page--node--add.html.twig
I have created two templates

page--node--edit.html.twig

page--node--add.html.twig

I have discovered that the {{ node }} and {{ node\_form }} variables are missing during node creation.

Here is my code to render the node add form there using hook\_preprocess\_page.

```
  $variables['node_form'] = FALSE;
    if ($node = \Drupal::routeMatch()->getParameter('node')) {
      $form = \Drupal::entityTypeManager()
        ->getFormObject('node', 'default')
        ->setEntity($node);
      $variables['node_form'] = \Drupal::formBuilder()->getForm($form);
   }

```

My goal is to print node content type name and form from page--node--add.html.twig template.

PS. No issue on page--node--edit.html.twig (node edit page)

# Answer
> 0 votes
```
if ($node = \Drupal::routeMatch()->getParameter('node')) {

```

There's no node ID in the route at /node/add/foo, so there's no node available, and that condition will always be false.

You need to create the node yourself, e.g.

```
// Get the desired type from the route.
if ($node_type = \Drupal::routeMatch()->getParameter('node_type')) {
  $node = \Drupal::entityTypeManager()
    ->getStorage('node')
    ->create([
      'type' => $node_type->id(),
    ]);

  $form = \Drupal::entityTypeManager()
    ->getFormObject('node', 'default')
    ->setEntity($node);

  $variables['node_form'] = \Drupal::formBuilder()->getForm($form);
}

```

---
Tags: 8, theming
---


# Question
Title: How to print rest of the form using "without" function in twig while printing custom user field present account array?
I am writing custom template to style my "edit user profile" form page.

Below is the code in twig file :

```
  {{ form.first_name }}

  {{ form.last_name }}

  {{ form.account.mail }}

  {{ form.account.current_pass }}

  {{ form.account.pass }}

  {{ form.actions }}

  {{ form|without('first_name', 'last_name', 'account.mail', 'account.current_pass', 'account.pass', 'actions') }}

```

The Problem is that it is print all account field for example account.mail. I guess it is is not understood by "without" function and it prints that field twice so I am unable to print all account custom field elements individually.

Here is the Dump output of twig form:

It is very important to print rest of the form using "without" function but "without" function printing my custom account field twice and not understanding that it is already printed on page.

Also I tried to directly use "account" as argument in without function which is working fine but this may miss some important content render which is present in account array. I want to render all account data except the fields which I want to print individually.

# Answer
> 1 votes
try to print it this way it gives you more control :

```
<div id="candidature_spontanee" class="form-contact candidature_spontanee">

{# 1.use the attribute to set the form action and other attributes #}
<form{{ attributes }}>
 {{ title_prefix }}
 {{ title_suffix }}

     {# 2.print the form elment using : {{ element.elements.key }} #}
     <div class="js-form-item form-item js-form-type-textfield form-item-nom js-form-item-nom form-group custom-input">
       {{ element.elements.nom }}
       <div class="help-block with-errors"></div>
     </div>

     <div class="js-form-item form-item js-form-type-textfield form-item-nom js-form-item-nom form-group custom-input">
       {{ element.elements.telephone }}
       <div class="help-block with-errors"></div>
     </div>

     {# 3.print the captcha if you have a cpatcha #}
     {{ element.captcha }}

     {# 4.you need to output a couple of hidden form elements that is required for the form to be submitted properly and securilly#}
     {{ element.form_token }}
     {{ element.form_build_id }}
     {{ element.form_id }}

     {# 5.output the form action (submit) at the end of the form link  #}
     {{element.actions }}

 </form>

</div>

```

---
Tags: 8, theming, forms
---


title: Email by Taxonomy Term

text:
# Question
Title: Email by Taxonomy Term
For Drupal 8 webform, I see there's a way to specify custom email recipients based on a Select component. But I don't see a Taxonomy term reference as an option in the email handler. Is there a way to set that up in the UI? Using the UI would be ideal to let other form maintainers update the emails as needed. A taxonomy term reference is needed to also use Webform Permissions by Term.

Alternatively, if a select component was made using matching term keys, and the taxonomy term component was set to hidden/private, could the term component be populated with the select component? In that way, I could use the email handler with the select list and still use Webform Permissions by Term.

# Answer
I found I can add an action handler that uses the select list to populate the Webform Permissions by Term element like I was thinking.

With a select list called Institution, using keys that match term keys in a taxonomy, the Update data with YAML section of the action handler can use this:

```
wf_permissions_by_term_element: '[webform_submission:values:institution:raw]'

```

The element gets updated on form completion and update, and individual result access is still limited by the Permissions by Term module.
> 0 votes

---
Tags: webforms, emails
---


title: Use Webform as Module Config Page?

text:
# Question
Title: Use Webform as Module Config Page?
I am building a module that will create webforms for use with the Commerce Webform Order module. These must be somewhat constrained in their structure, so I have developed a form (using FAPI) to configure them.

Well, the form has become rather complex, with several "add another" fields and the like. The Webform module handles these rather elegantly, and I'd love to use its capabilities for my module's config page, but feel that a traditional webform would be subject to error and fiddling.

The config page must look at a given webform (if specified) and use its content to pre-load values, or create fields, to allow for further settings adjustment (e.g. prices of items, additional fields, etc)

So, is it feasible to somehow invoke the webform module to create something that works like a webform but is under the control of my module?

Thanks in advance.

# Answer
> 5 votes
The Webform module just extends Drupal's Form API. Most of the elements available to a webform can be used in custom-built forms. For example, you can use the WebformMultiple element in any FAPI form.

@see https://git.drupalcode.org/project/webform/blob/8.x-5.x/src/Element/WebformMultiple.php

---
Tags: webforms
---


# Question
Title: How can I show the latest added content to a specific link?
I have content type `Videos`, lets say I have 5 videos, they have these url links:

* /videos/video-name-1
* /videos/video-name-2
* /videos/video-name-3
* /videos/video-name-4
* /videos/video-name-5

What I want is when I go to `/videos` I want this page to show the last video added (`/videos/video-name-5`) and I want to make this dynamic e.g. if I add a new video, when I visit `/videos` it will show me the page of that new video I added.

How can I achive this? As much as possible I don't want to use redirect.

# Answer
> 3 votes
You can create a views page that shows the most recent video.

* Structure \> Views \> **Add new view**
    + Title: "**Videos**"
    + Show content of type "**Video**" sorted by "**Newest first**"
    + Check "**Create a page**" option
    + Page title: "**Video**"
    + Path: "**videos**"
    + Display format: "**Unformatted list**" of "**Full posts**"
    + Items to display: "**1**"
    + Save & edit
    + Save again

Now go to the url: http://my-drupal-site.com/videos and it will display the most recent video via the view you created above

---
Tags: 8
---


# Question
Title: Convert machine to human readable node type on page--node--add.html.twig (twig template variables)
I tried to create a variable on hook\_preprocess\_page to achieve it, but I'm only getting the machine readable name so far.

```
$variables['node_type'] = FALSE;
if ($current_path = \Drupal::service('path.current')->getPath()) {
  $path_args = explode('/', $current_path);
  $node_type = $path_args[3];
  $variables['node_type'] = $node_type;
}

```

**UPDATED**

For some reason it works on node add form and node edit forms:

```
if ($current_path = \Drupal::service('path.current')->getPath()) {
  $node_type = \Drupal::entityManager()->getStorage('node_type')->load($node->getType())->get('name');
  $variables['node_type'] = $node_type;
}

```

I just need update the condition because it I'm getting the error on `/node/add/` page (without content type)

# Answer
I don't think there is a `node` object in the `node.add` route, it doesn't exist there yet. But you can still get it from the `node_type` parameter. Untested, but following the code from NodeController.php you should be able to get the label with something like this:

```
//get the machine name from route
$machineName = \Drupal::routeMatch()->getParameter('node_type');
//get the label via definition
$nodeTypeLabel = \Drupal::entityTypeManager()->getDefinition('node_type')->load($machineName)->label();

```
> 1 votes

# Answer
the question is not clear but as I understand you want to pass the node type readable name to the template and this is the easiest way :

```
function THEMENAME_preprocess_page(&$variables){
 //Get the current page rendered node(s).
  $node = \Drupal::routeMatch()->getParameter('node');

  if ($node instanceof \Drupal\node\NodeInterface) {
    // You can get any information about the
    // rendered node through the $node methods
    //just kint($node) then replace the label() method with another one.
    $variables['node_type'] = $node->label();
  }
}

```
> 0 votes

---
Tags: 8, theming
---


# Question
Title: Library item field doesn't show up the remove button
I am using paragraphs and paragraphs library module in my drupal project. The paragraph (Paragraph A) has a text field (unlimited). I don't see a remove button on the field. I only need one item for one page but it shows up more that one fields. Is there a way to remove it?

# Answer
There is no dedicated delete button. Drupals default behavior (including paragraphs) is to automatically delete every empty field at the end of the list. The empty field you see is just a convinience for faster adding of a new item.

Side node: To delete e.g. the first item of the list, remove the content and drag it to the bottom.
> 2 votes

---
Tags: 8, paragraphs
---


# Question
Title: How to use ajax in entity reference custom form to display no entity error in drupal 8?
I created a custom form on entity autocomplete called items like below,

```
$form['items'] = array(
   '#title' => $this->t('Items'),
   '#type' => 'entity_autocomplete',
   '#target_type' => 'node',
   '#selection_handler' => 'default',
   '#selection_settings' => array(
       'target_bundles' => array('items'),
    ),
    '#required' => TRUE,
    '#placeholder' => 'Type items',
);

```

It is working fine. If i type item which is not in the items list the page gets refreshed and displayed the message `There are no entities matching`.

Here i want to display this error message without page loading. I `tried using ajax` like this,

```
'#ajax' => [
    'callback' => '::updateDestinataire',
 ],

```

But it didn't work for me. How can i solve the issue.

# Answer
This error message is provided by `\Drupal\Core\Entity\Element\EntityAutocomplete::matchEntityByTitle()` called by `\Drupal\Core\Entity\Element\EntityAutocomplete::validateEntityAutocomplete()` method and is invoked at element validation (explained later) so it cannot be overriden using AJAX API. To do so, you can implement one of the following:

**Extend the element and create your own and override that particular method**

Assuming your new form element is as follows:

*../my\_module/src/Element/CustomEntityAutocomplete.php*

```
namespace Drupal\my_nodule\Element;

/**
 * My custom autocomplete.
 *
 * @FormElement("custom_entity_autocomplete")
 */
class CustomEntityAutocomplete extends EntityAutocomplete {
  ...
  // Override the ::matchEntityByTitle method with the message you want.
}

```

You change your form render array to:

```
$form['items'] = array(
   '#title' => $this->t('Items'),
   '#type' => 'custom_entity_autocomplete',
   '#target_type' => 'node',
   '#selection_handler' => 'default',
   '#selection_settings' => array(
       'target_bundles' => array('items'),
    ),
    '#required' => TRUE,
    '#placeholder' => 'Type items',
);

```

Clear the cache and everything should work as expected. Mind the namespace and your class path so the discovery work properly.

**or... Provide only the validate method**

I personally prefer the latter but you have this choice too.

The `\Drupal\Core\Entity\Element\EntityAutocomplete::getInfo()` is implemented as follows:

```
/**
 * {@inheritdoc}
 */
public function getInfo() {
  $info = parent::getInfo();
  $class = get_class($this);
  ....
  $info['#element_validate'] = [[$class, 'validateEntityAutocomplete']];
  array_unshift($info['#process'], [$class, 'processEntityAutocomplete']);

  return $info;
}

```

If you look closer you could see that the validate is referenced there so, you could override it on your render array.

```
$form['items'] = array(
   '#title' => $this->t('Items'),
   '#type' => 'entity_autocomplete',
   '#element_validate' => [['\Drupal\my_module\MyAwesomeClass::validateEntityAutocomplete']],
   '#target_type' => 'node',
   '#selection_handler' => 'default',
   '#selection_settings' => array(
       'target_bundles' => array('items'),
    ),
    '#required' => TRUE,
    '#placeholder' => 'Type items',
);

```

This way you could validate your entity autocomplete whatever you please.
> 0 votes

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


# Question
Title: How does drupal 8 handles redirect respose?
Iam using a RedirectResponse in drupal 8 in my custom module when a user is logging in,

```
$user = User::load(\Drupal::currentUser()->id());
$userRoles = $user->getRoles();
  if(in_array('admin',$userRoles)){
   $response = new RedirectResponse('/home');
   $response->send();
  }

```

later i was trying to change the url but even after removing the code the redirection occurs.

# Answer
> 1 votes
Doing a bit of guessing here because your code snippet doesn't show where you've implemented this bit of code. However, just blanket sending a response in the middle of Drupal's runtime is probably always going to have some odd side effects. Symfony's routing system (which Drupal uses) provides a number of different layers at which you can get involved with the events deciding what response to send.

That being said, I don't think you need to worry about any of that. Drupal supports redirecting on user login already through a different mechanism. Something similar to what's outlined here would work well: https://www.drupal.org/forum/support/module-development-and-code-questions/2013-08-18/how-to-redirect-user-after-login-in#comment-11931382

I also found a previous stackexchange for this here: Redirect after user login

---
Tags: users
---


# Question
Title: visually resize images when uploaded inline in ckeditor
is there a way to resize images after uploaded in the inline ckeditor?

if i have a big picture 2000x2000 and upload it (not via IMCE) to the editor, the image is huge and it is displayed in full size.

i have to scroll to left and down and drag the resize button multiple time until i get the result i can work with.

i miss the settings dialogue from D7 where i can define an image size upon upload. i cannot find any extension and i read many discussions that the D8 ckeditor has a lot less functions than in D7. i read about the reason is responsive design but when i resize the image via drag there is still height and width added. so whats the point on this?

# Answer
There's a pretty simple solution, but it does feel a bit hack-y.

1. Add a CSS file to a module/theme with contents like

```
img { max-width: 200px; height: auto; }

```
2. Implement `hook_ckeditor_css_alter()` to get that CSS file loaded in the WYSIWYG iframe:

```
function hook_ckeditor_css_alter(array &$css, Editor $editor) {
  $css[] = drupal_get_path('module', 'mymodule') . '/css/mymodule-ckeditor.css';
}

```

Once that's up and running images in the WYSIWYG should be constrained in width to whatever you set in the CSS file. You might need to resort to `!important`, depending on what other styles are already active; it'll need some tweaking no doubt.
> 1 votes

# Answer
If your html contains a style attribute e.g.it will block the resizing of an image.

```
<img src="image.jpg" style="width:300px;height:200px;" />

```

Remove the style attribute to make sure resizing works. Searched a very long time for this!
> 0 votes

---
Tags: wysiwyg, media
---


# Question
Title: Proper way of Link generation from string
How can I generate a link in a proper way in Drupal 8? I have a field where the user can say an internal or external page/website.

Internal:
/node/6
/articles
/articles#Subheading
etc.

External:
www.google.com
//www.google.com
https://www.google.com

How can I transform these into a link with the following condition:
the site root is: www.mydomain.com/mysite/
internal links should have language versions: i.e. en/articles or pt/articles .

I've tried with `Link::fromTextAndUrl('My link', Url::fromUri('internal:/articles'))`, but this requires a URI which is not my goal and it doesn't follow the selected user language.

# Answer
> 2 votes
You do not need `internal:/` you just need to have some help text that says an internal path should begin with a slash.

After that, when you create the links, you can do:

```
use Drupal\Core\Link;
use Drupal\Core\Url;
use Drupal\Component\Utility\UrlHelper;

....
....
....

function or method.... {
  $path = // get config value
  $label = // get config value

  if (UrlHelper::isExternal($path)) {
    $url = Url::fromUri($path);
  } else {
    $url = Url::fromUserInput($path);
  }

  return Link::fromTextAndUrl($label, $url);
}

```

Of course I am assuming there is always a value... you'd have to add your own checks so you don't get errors calling `Url::` for null or empty input, etc.

The return will be an renderable array to use. I am using a similar method to allow input for third party settings on a config entity. This way the value can be internal or external.

---
Tags: 8
---


# Question
Title: Can't connect to remote DigitalOcean database
I am attempting to connect an existing Drupal 8 site to a DigitalOcean managed Database.

The connection info I've received from DigitalOcean:

```
username = digitaloceanadmin
password = password
host = nameofmydbcluster.db.ondigitalocean.com
port = 25060
sslmode = REQUIRED

```

I've made the adjustments to settings.php:

```
$databases['default']['default'] = array (
  'database' => 'dbname',
  'username' => '...',
  'password' => '...',
  'prefix' => '',
  'host' => 'dbclustername.db.ondigitalocean.com',
  'port' => '25060',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
);

```

However, I'm getting the following error:

```
PDOException: SQLSTATE[HY000] [2054] The server requested authentication method
unknown to the client in ...

```

More errors when I `drush cr`:

```
In Connection.php line 416:

  SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client

In Connection.php line 416:

  PDO::__construct(): The server requested authentication method unknown to the client [caching_sha2_password]

```

I am running Drupal 8.8.1 with php7.2. The DB version on remote is MySQL 8.

Any help would be greatly appreciated.

# Answer
I was able to resolve this from the info found here:

https://skoop.dev/blog/2019/10/04/PHP-and-the-DigitalOcean-MySQL-cluster/

The problem stemmed from the default authentication method for MySQL v8 is caching\_sha2\_password, which the article above suggests is not supported by php yet.

As the article suggests, we can switch back to the old authentication method with the following query:

```
ALTER USER 'myuser'@'%' IDENTIFIED WITH mysql_native_password BY 'thepasswordyouwant';

```

After making this alteration to the dbuser, I was able to connect to the digitalocean database without issue.
> 1 votes

---
Tags: 8, database
---


title: Understanding State of JS in Drupal

text:
# Question
Title: Understanding State of JS in Drupal
I have a simple contributed module that I have written. It has pretty basic javascript. I decided to clean it up and write it in vanilla js, removing jQuery since that seems to be the direction we're going. Here is the resulting code...

```
const viewSourceLinks = document.querySelectorAll(
  '.simple-styleguide--view-sourecode'
);

[].forEach.call(viewSourceLinks, el => {
  el.addEventListener('click', () => {
    el.nextElementSibling.classList.toggle('active');
  });
});

const calculableElements = document.querySelectorAll('.calculate');

[].forEach.call(calculableElements, el => {
  const measuredElement = el.querySelector('.measure');
  const info = el.querySelector('.info');
  const lineHeight = `<label>line-height:</label> ${
    window.getComputedStyle(measuredElement).lineHeight
  }`;
  const fontSize = `<label>font-size:</label> ${
    window.getComputedStyle(measuredElement).fontSize
  }`;
  const margins = `<label>margin:</label> ${
    window.getComputedStyle(measuredElement).marginBottom
  }
        ${window.getComputedStyle(measuredElement).marginRight} ${
    window.getComputedStyle(measuredElement).marginBottom
  } ${window.getComputedStyle(measuredElement).marginLeft}`;

  info.innerHTML = `${fontSize}<br/>${lineHeight}<br/>${margins}`;
});

```

My question is, is this ok? Is this good enough to include as is? In general, it seems the advice is to **always** add your javascript within attached behaviors.

However, once I go down that road, I'm pretty much having to include jQuery in the wrapper. And I would much rather just have vanilla javascript.

The resulting code with behaviors ends up being something like this...

```
(($, Drupal) => {
  Drupal.behaviors.simpleStyleguide = {
    attach(context) {

      const viewSourceLinks = context.querySelectorAll(
        '.simple-styleguide--view-sourecode'
      );

      [].forEach.call(viewSourceLinks, el => {
        el.addEventListener('click', () => {
          el.nextElementSibling.classList.toggle('active');
        });
      });

      const calculableElements = context.querySelectorAll('.calculate');

      [].forEach.call(calculableElements, el => {
        const measuredElement = el.querySelector('.measure');
        const info = el.querySelector('.info');
        const lineHeight = `<label>line-height:</label> ${
          window.getComputedStyle(measuredElement).lineHeight
        }`;
        const fontSize = `<label>font-size:</label> ${
          window.getComputedStyle(measuredElement).fontSize
        }`;
        const margins = `<label>margin:</label> ${
          window.getComputedStyle(measuredElement).marginBottom
        }
              ${window.getComputedStyle(measuredElement).marginRight} ${
          window.getComputedStyle(measuredElement).marginBottom
        } ${window.getComputedStyle(measuredElement).marginLeft}`;

        info.innerHTML = `${fontSize}<br/>${lineHeight}<br/>${margins}`;
      });

    },
  };
})(jQuery, Drupal);

```

I've also read that if you have BigPipe enabled, you have to include jQuery. Not sure if that's true or not.

The vanilla js code above seems to be working. I just want to know that I'm doing this right, and that I'm not violating some Drupal standard by not wrapping it in a behavior.

*Note: I should mention there is no ajax behavior in this module. If there were, perhaps I would have to use behaviors and context.*

# Answer
> 8 votes
The best practice is still to use Drupal's behaviors system even when not relying on jQuery. See Drupal 8 Drupal.behaviors without jquery for reference.

That said, I think you're on the right path. I find jQuery just slows down the page load when vanilla JS will usually do the trick. That's just my opinion and there's a lot of debate out there.

---
Tags: 8, javascript
---


# Question
Title: Using taxonomy exposed filter in a view ends in MySQL can only use 61 tables in a join
**Scenario**

1. One hierarchical vocabulary called Countries with 300 taxonomy terms, one for each country, indenting like:

* America (level 1)
    * + Anguila (level 2)
    * + Antigua y barbuda (level 2)
    * + ... (level 2)
    * Europe (level 1)
    * + Austria (level 2)
    * + Armenia (level 2)
    * + ... (level 2)
2. One content type called Office, then you add a field called Country, and its type is taxonomy reference, related to you recent created vocabulary called Countries.
3. After that, you create a few nodes: the first is called 'My secret office', checking Afghanistan in its country field. The second node is called 'My beautiful office', checking Albania.

Now you think it should be interesting if you could have a page where you can see a list of all your offices. The finest way to achieve this is by creating a view. To do so, you create a view page with this configuration:

* Filter criteria: Content: Content type (= Office)
* Page settings: Path: /offices

Then you visit your new page /offices and you can see 2 offices: My secret office and My beautiful office. Everything works as expected.

Then you add a country filter in you page. Going back to views configuration:

* Filter criteria: Content: Has taxonomy term (exposed, Show as hierarchical) related to Countries.

You return to visit your page, and you can see a filter listing 300 countries and your 2 offices. You are on fire, so you decide to test your brand new filter:

* You check Afghanistan option, and click Search; then you only see My secret office. Great.
* You check Albania option, and click Search; then you only see My beautiful office. Awesome.
* You now check Afghanistan, Albania, Algeria, Andorra, Angola and so on until you have checked all your 300 countries. The correct output should be your 2 offices, since you have no more; so you click search and BAAAM: White Screen of Death. But you are smart, and you have allowed PHP yo show the error log. You see that MySQL had a failure:

**SQLSTATE\[HY000\]: General error: 1116 Too many tables; MySQL can only use 61 tables in a join**

It follows the entire query Drupal is trying to execute. You notice everything is fine EXCEPT for this:

LEFT JOIN {taxonomy\_index} taxonomy\_index\_value\_0 ON node\_field\_data.nid = taxonomy\_index\_value\_0.nid AND taxonomy\_index\_value\_0.tid = :views\_join\_condition\_1

LEFT JOIN {taxonomy\_index} taxonomy\_index\_value\_1 ON node\_field\_data.nid = taxonomy\_index\_value\_0.nid AND taxonomy\_index\_value\_1.tid = :views\_join\_condition\_2

LEFT JOIN {taxonomy\_index} taxonomy\_index\_value\_2 ON node\_field\_data.nid = taxonomy\_index\_value\_0.nid AND taxonomy\_index\_value\_2.tid = :views\_join\_condition\_3

LEFT JOIN {taxonomy\_index} taxonomy\_index\_value\_3 ON node\_field\_data.nid = taxonomy\_index\_value\_0.nid AND taxonomy\_index\_value\_4.tid = :views\_join\_condition\_4

and so on. Drupal is using the left join technique to access the database. The problem is that Drupal is using one left join for each taxonomy termed checked, meaning the first one is related to Afghanistan, the second one to Albania, the third is for Algeria, and so on.

**¿How can I make a search using more than 61 options?**

I think it is not a crazy thing that an user could search for offices in America and Europe, resulting this in more than 100 countries being checked. While looking for a solution, I have wrote a litle Javascript code that prevents the user from marking more than 50 countries so he doesn't face the WSoD.

**Setup:**

* Drupal 8.8.1 (core and all its modules updated)
* I'm not using any contributed module related to taxonomy or views
* PHP 7.1
* MySQL 5.5

# Answer
> 3 votes
**UPDATE**

As discussed here, this issue was caused by some missconfiguration at view level and normally should not occur. Read the full post to get the full picture on how you can step on this error.

**ORIGINAL ANSWER**

I'm adding my findings as answer since comments have limitations both on styles and length, but by all means **THIS IS NOT** an actual answer to the question.

I've tried to reproduce the describe behavior using an exisitng Drupal site that I'm working on:

1. I've a content A with a er field targeting vocabulary B
2. I've generated over 300 terms with hierarchy
3. Added 2 nodes tagged with 2 of the generated terms
4. Created a view as described in the question, but with a slight change: I've one display using "Has term" filter an another display "Has term (with depth)" filter; I explain below why I did this.

The reason using two displays with these two filters is because I saw that "Has taxonomy term" filter (plugin id `taxonomy_index_tid`) is implemented by `\Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid` which extends from `\Drupal\views\Plugin\views\filter\ManyToOne`. Reviewing the code I saw that neither the ManyToOne base filter or the TaxonomyIndexTid implement JOIN queries. On the other hand `\Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTidDepth` extends from TaxonomyIndexTid and has this on it's `::query()` method

```
public function query() {
  ...
  // Now build the subqueries.
  $subquery = Database::getConnection()->select('taxonomy_index', 'tn');
  $subquery->addField('tn', 'nid');
  $where = (new Condition('OR'))->condition('tn.tid', $this->value, $operator);
  $last = "tn";

  if ($this->options['depth'] > 0) {
    $subquery->leftJoin('taxonomy_term__parent', 'th', "th.entity_id = tn.tid");
    $last = "th";
    foreach (range(1, abs($this->options['depth'])) as $count) {
      $subquery->leftJoin('taxonomy_term__parent', "th$count", "$last.parent_target_id = th$count.entity_id");
      $where->condition("th$count.entity_id", $this->value, $operator);
      $last = "th$count";
    }
  }
  elseif ($this->options['depth'] < 0) {
    foreach (range(1, abs($this->options['depth'])) as $count) {
      $field = $count == 1 ? 'tid' : 'entity_id';
      $subquery->leftJoin('taxonomy_term__parent', "th$count", "$last.$field = th$count.parent_target_id");
      $where->condition("th$count.entity_id", $this->value, $operator);
      $last = "th$count";
    }
  }

  $subquery->condition($where);
  $this->query->addWhere($this->options['group'], "$this->tableAlias.$this->realField", $subquery, 'IN');
}

```

As shown it does LEFT JOINS to work with the selected depth and hierachy. All though after selecting all 300 terms in both displays **I was unable to reproduce the described error** (see screenshots below).

*Has taxonmy term*

*Has taxonomy term (with depth)*

Also as commented @mpdonadio the filter is using WHERE IN to filter the terms and delegates to LEFT JOIN when dealing with hierarchy.

Maybe these can shed some light on your error.

---
Tags: views, 8, taxonomy-terms, database
---


# Question
Title: How to add a Custom Serializer to alter the Output of REST EXPORT
To the Response/Output of REST EXPORT of a view, I want to add one extra row.

So I created a Custom Serializer in my module. The path of the file is:

```
My_Module/src/Plugin/views/style/HindiCustomSerializer.php

```

Here I extended the `Serializer` Class from `core/modules/rest/src/Plugin/views/style/Serializer.php`

And I am trying to override the `render()` method in my custom serializer like this. I am copying the `render()` method from original Serializer and adding one extra line from my side.

```
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\rest\Plugin\views\style\Serializer;

/**
 * The style plugin for serialized output formats.
 *
 * Add and extra row to the output.
 *
 * @ingroup views_style_plugins
 *
 * @ViewsStyle(
 *   id = "hindi_custom_serializer",
 *   title = @Translation("Hindi Custom Serializer"),
 *   help = @Translation("Serializes views row data using the Serializer component."),
 *   display_types = {"data"}
 * )
 */
class HindiCustomSerializer extends Serializer implements CacheableDependencyInterface{

  public function render() {
    $rows = [];
    // If the Data Entity row plugin is used, this will be an array of entities
    // which will pass through Serializer to one of the registered Normalizers,
    // which will transform it to arrays/scalars. If the Data field row plugin
    // is used, $rows will not contain objects and will pass directly to the
    // Encoder.
    foreach ($this->view->result as $row_index => $row) {
      $this->view->row_index = $row_index;
      $rows[] = $this->view->rowPlugin->render($row);
    }

    $rows[] = "JUST ADDING AN EXTRA ROW!!";
    unset($this->view->row_index);
    // Get the content type configured in the display or fallback to the
    // default.
    if ((empty($this->view->live_preview))) {
      $content_type = $this->displayHandler->getContentType();
    }
    else {
      $content_type = !empty($this->options['formats']) ? reset($this->options['formats']) : 'json';
    }
    return $this->serializer->serialize($rows, $content_type, ['views_style_plugin' => $this]);
  }

}

```

The option to choose the custom serializer **MyCustomSerializer** should be visible in **Format section of view settings**.

But its not displaying. Is there any step I am missing? Do I need to add some extra information regarding the serializer in `.info` file or any such steps needed ?

PS: If I add this line directly to the original Serializer code, I see the extra row coming in the response.

```
$rows[] = "JUST ADDING AN EXTRA ROW!!";

```

But of course that's not the correct way.

# Answer
> 3 votes
The plugin was missing the proper annotation (added now in the question). Views plugins use Annotation Discovery.

Adding something like the following solved the problem:

```
/**
 * My custom serializer
 *
 * @ViewsStyle(
 *   id = "hindi_custom_serializer",
 *   title = @Translation("Hindi Custom Serializer"),
 *   help = @Translation("Serializes views row data using the Serializer component."),
 *   display_types = {"data"}
 * )
 */
class HindiCustomSerializer extends Serializer {
  ....
}

```

Also worth noting that you don't need to include the `implements CacheableDependencyInterface` since is already declared by the `\Drupal\rest\Plugin\views\style\Serializer` plugin which you are extending from.

---
Tags: views, 8
---


title: How can I clear specific caches?

text:
# Question
Title: How can I clear specific caches?
In Drupal 8, we have `drush cr` which is the new version of `drush cc all` now deprecated.

We also had `drush cc menu` and some more specific commands to clear cache clear. If I try to execute them, I get some weird Symfony error.

What command should I use instead of `drush cc <cache name>` in Drupal 8?

The documentation for `drush cache-clear` doesn't help much.

I tried `drush cr menu`, for example, and it doesn't seem to work.

# Answer
drush is not ready for that right now (as far as I know), so you'll need to write custom drush-scripts or do some other execution. drush cr rebuilds the whole cache, drush cc is not working with drupal8.

the method drupal\_flush\_all\_caches shows how to flush all core caches.

```
$module_handler = \Drupal::moduleHandler();
  // Flush all persistent caches.
  // This is executed based on old/previously known information, which is
  // sufficient, since new extensions cannot have any primed caches yet.
  $module_handler->invokeAll('cache_flush');
  foreach (Cache::getBins() as $service_id => $cache_backend) {
    $cache_backend->deleteAll();
  }

  // Flush asset file caches.
  \Drupal::service('asset.css.collection_optimizer')->deleteAll();
  \Drupal::service('asset.js.collection_optimizer')->deleteAll();
  _drupal_flush_css_js();

  // Reset all static caches.
  drupal_static_reset();

  // Invalidate the container.
  \Drupal::service('kernel')->invalidateContainer();

  // Wipe the Twig PHP Storage cache.
  PhpStorageFactory::get('twig')->deleteAll();

  // Rebuild module and theme data.
  $module_data = system_rebuild_module_data();
  /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
  $theme_handler = \Drupal::service('theme_handler');
  $theme_handler->refreshInfo();
  // In case the active theme gets requested later in the same request we need
  // to reset the theme manager.
  \Drupal::theme()->resetActiveTheme();

  // Rebuild and reboot a new kernel. A simple DrupalKernel reboot is not
  // sufficient, since the list of enabled modules might have been adjusted
  // above due to changed code.
  $files = array();
  foreach ($module_data as $name => $extension) {
    if ($extension->status) {
      $files[$name] = $extension;
    }
  }
  \Drupal::service('kernel')->updateModules($module_handler->getModuleList(), $files);
  // New container, new module handler.
  $module_handler = \Drupal::moduleHandler();

  // Ensure that all modules that are currently supposed to be enabled are
  // actually loaded.
  $module_handler->loadAll();

  // Rebuild all information based on new module data.
  $module_handler->invokeAll('rebuild');

  // Clear all plugin caches.
  \Drupal::service('plugin.cache_clearer')->clearCachedDefinitions();

  // Rebuild the menu router based on all rebuilt data.
  // Important: This rebuild must happen last, so the menu router is guaranteed
  // to be based on up to date information.
  \Drupal::service('router.builder')->rebuild();

  // Re-initialize the maintenance theme, if the current request attempted to
  // use it. Unlike regular usages of this function, the installer and update
  // scripts need to flush all caches during GET requests/page building.
  if (function_exists('_drupal_maintenance_theme')) {
    \Drupal::theme()->resetActiveTheme();
    drupal_maintenance_theme();
  }

```

There's a module too, enable admin\_toolbar's admin\_toolbar\_tools submodule to have it all in the toolbar:
> 10 votes

# Answer
You can use DrupalConsole `cache:rebuild` command and use the interactive mode to select from the list the cache to clear.

```
drupal cache:rebuild

```

You can also use the command alias `cr`

```
drupal cr

```

If you know the cache you are trying to clear try passing as an argument

```
drupal cr menu

```
> 5 votes

# Answer
Drush cc still (or again?) works as it did in v7 you can do e.g.: `drush cc css-js` or `drush cc render` see the link you allready gave: https://drushcommands.com/drush-8x/cache/cache-clear/

if you simply do `drush cc` you will get a list of options. ('menu' is not one of them)

```
$ drush cc
Enter a number to choose which cache to clear.
 [0]  :  Cancel
 [1]  :  drush
 [2]  :  theme-registry
 [3]  :  router
 [4]  :  css-js
 [5]  :  module-list
 [6]  :  theme-list
 [7]  :  render
 [8]  :  token
 [9]  :  views

```
> 4 votes

# Answer
Use **Clear Specific Cache**(https://www.drupal.org/project/ccos) module.

The Clear Specific Cache module will help you to clear the cache of sole/specific entity type (i.e block, node, views block, view page, etc.) from contextual links, local task menu, and operations drop-button.
> 1 votes

---
Tags: 8, drush
---


# Question
Title: How to add /admin/people as a tab to a custom menu?
In a custom module (association), I ceated views that are accessible thru tabs:
The paths are defined in the views;

* Adhérents et personnes -\> /association (this one is also defined as a menu item)
* Adhérents -\> /association/members
* Personnes -\> /association/persons

I'd like to add `/admin/people` as a fourth tab.
How can I do that?

# Answer
> 0 votes
Finally and because of the side effect of the solution proposed by Mike Nolan (see capture2 in my comment), I made it that way:

```
function association_menu_local_tasks_alter(&$data, $route_name) {

  $oCurrentUser = \Drupal::currentUser();
  switch ($route_name) {
    case 'view.association_members_and_persons.page_1':
    case 'view.association_members.page_1':
    case 'view.association_persons.page_1':
      if ($oCurrentUser->hasPermission('administer users')) {
        $data['tabs'][0]['association.people'] = [
          '#theme' => 'menu_local_task',
          '#link' => [
            'title' => t('Users'),
            'url' => Url::fromRoute('entity.user.collection'),
          ],
          '#weight' => 4,
        ];
      }
      break;
    default:
  }

```

# Answer
> 0 votes
In a custom module (mymodule), create a mymodule.links.task.yml file, and add the following:

mymodule.admin\_people: route\_name: entity.user.collection base\_route: route.of.your.custom.menu title: 'Tab text goes here'

Here's what each part does:

**mymodule.admin\_people** Is the identifier of your menu tab item (the file being \*.links.task.yml means its the menutab file)

**route\_name** is the route the tab points to, and **entity.user.collection** is the route that corresponds to /admin/people .

**base route** displays your tab on the specified route. To find the route for your view, download the Devel module, turn it on, and go to "Routes info" to get your route. Usually a view is of the format view.\[view\_machine\_name\].\[view\_display\_id\], i.e. view.myview.page\_1 . Check the "advanced" section of your view's management page for the display ID.

**title** is the text that will go into the tab.

---
Tags: 8, routes, navigation
---


# Question
Title: This import is empty and if applied would delete all of your configurations
Customer bought a theme that has a Commerce plugin installed with sample data. Anxious to get it running and try out the new configuration system, I did what I do prior to Drupal 8.6: I committed everything but sensitive info into git, cloned to my local, and dumped the MySQL database. After getting the index page, every page returned a 500 error like the following ones.

> Attempt to create a field commerce\_remote\_id that does not exist on entity type user

> The entity type does not exist. in `Drupal\Core\Entity\EntityTypeManager::getDefinition()`

Copying all files from modules/commerce to modules/profile should get me past these errors.

`drush updb` returns no updates needed. `drush cr` offers no relief.

OK, I wanted to start using the new configuration system. On the customer site, I ran `drush cex` and committed to git.

On my local, after `git pull`, `drush cim` returns:

> This import is empty and if applied would delete all of your configuration, so has been rejected.

It appears that Drush will not import, but I prefer to use `drush site:install` with an existing configuration.

Can Drush 9.5.2 install a new site onto itself using the existing settings.php file?

I would like to synchronize configuration files to remove that as a factor to resolve my local site being hosed.

I read in another tutorial that the UUID must be copied over because the UUIDs in system.site.yml must match. I can confirm they match by running `drush config.get system.site`.

# Answer
> 1 votes
Do double check the directory where the config files are located. The directory is set in settings.php like:

```
$config_directories['sync'] = 'sites/default/files/[...]/sync';

```

I had the same issue but moving the `config` directory to the correct place solved it.

---
Tags: commerce, drush, installation-profiles
---


# Question
Title: How to enable configuration translation on custom module
I wrote a module where I using a form for editing my module's configs. My current goal to be able to translate some of my config field's values with configuration translation. I already implemented the followings:

* For the menus:

+ mymodule.links.menu.yml
    + mymodule.links.task.yml
* For the translation:

+ mymodule.config\_translation.yml
    + config/schema/mymodule.schema.yml (I indicated also which should be translated and which shouldn't)

I also added language into my config, however, I don't think there's any meaning for it

My current problem is: when I going to my settings page, I go to the translate tab, add a language and that form is totally empty. There's no field listed where I can write anything, just a save button... what am I missing?

**config/install/mymodule.mymodulesettings.yml**

```
service_id: ''
normalized: true
success: 'Successfully subscribed!'
langcode: en

```

**config/schema/mymodule.schema.yml**

```
mymodule.mymodulesettings:
  type: config_object
  label: 'Mymodule settings'
  mapping:
    success:
      type: string
      label: 'Success message'
      translatable: true
    normalized:
      type: boolean
      label: 'E-mail address should be normalized?'
      translatable: false
    service_id:
      type: string
      label: 'Service id'
      translatable: false

```

**mymodule.links.menu.yml**

```
mymodule.mymodule_settings_form:
  title: 'Mymodule Settings'
  route_name: mymodule.mymodule_settings_form
  description: 'Configure Mymodule integration'
  parent: system.admin_config_system
  weight: 99

```

**mymodule.links.task.yml**

```
mymodule.mymodule_settings_form_tab:
  base_route: mymodule.mymodule_settings_form
  title: 'Mymodule Settings'
  route_name: mymodule.mymodule_settings_form

```

**mymodule.routing.yml**

```
mymodule.mymodule_settings_form:
  path: '/admin/config/system/mymodule-settings'
  defaults:
    _form: '\Drupal\mymodule\Form\MymoduleSettingsForm'
    _title: 'Mymodule Settings Form'
  requirements:
    _permission: 'manage mymodule settings'
  options:
    _admin_route: TRUE

```

**mymodule.permission.yml**

```
manage mymodule settings:
  title: 'Manage mymodule settings'
  description: 'Allows users to configure mymodule'

```

**mymodule.config\_translation.yml**

```
mymodule.mymodule_settings_form:
  title: 'Newsroom Mymodule Form'
  base_route_name: mymodule.mymodule_settings_form
  names:
    - mymodule.mymodulesettings

```

# Answer
The problem as commented above is the type of the translatable properties on the schema. Needs to be changed from `string` to `label` also the `translatable: false` can be safely removed since is default behavior, and also no needed for label or text types.

For more information about config translation check the cheatsheet.
> 2 votes

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


# Question
Title: How to access protected property in feed object?
When I try to access protected property in feed object I am getting error `(Error: Cannot access protected property Drupal\feeds\State::$messages)`

**Feed Object:**

Anybody know How to get protected property(messages) from object?

# Answer
There is no public method on the State object that returns the messages. The public methods on the object are:

* `progress()`
* `setCompleted()`
* `setMessage()`
* `displayMessages()`
* `logMessages()`

The method `displayMessages()` is the closest method you can use to access the messages, the messages are then transferred to `\Drupal\Core\Messenger\Messenger`, which has a method called `all()` to return all the messages on that object.

PHP also has an API called 'Reflection', which - among more - allows you to bypass visibility settings on class properties and methods. The main purpose for this API is to retrieve doc comments for functions, classes and methods. I wouldn't recommend to use this unless if it is for debug purposes.

Note that since Feeds 8.x-3.0-alpha6 the messages are also displayed on the feed page while an import is not yet completed.

Why do you need access to the messages? Maybe you can open a feature request ticket in the Feeds issue queue to request adding a public method for retrieving the messages.
> 2 votes

---
Tags: 8, feeds
---


# Question
Title: How do I get the taxonomy term's path alias?
I have come up with a need to show a node term's ***URL alias*** using plain php in drupal 8 but I can't figure out how to do it. In my custom module, I want to get **/fruits/apples** in a variable upon loading ***a node*** which is linked with **Fruits** term.

Here you can see the Edit Term settings page in which I have set the URL alias of the term Fruits to /fruits/apples. I want to get this URL alias whenever a user loads a page linked to this term.

# Answer
You can get it by this way as well (assuming you know $id in advance in code) as of Drupal 8.5.x: **1. For taxonomy term:**

```
Term::load($id); //not important
$aliasManager = \Drupal::service('path.alias_manager');
$alias = $aliasManager->getAliasByPath('/taxonomy/term/'.$id);

```

**2. For node:**

```
$node = \Drupal::entityManager()->getStorage('node')->load($id); //not important
$aliasManager = \Drupal::service('path.alias_manager');
$alias = $aliasManager->getAliasByPath('/node/'.$id);

```

**OUTPUT:** `$alias = /fruits/apples`

**EDIT:** As of Drupal 8.8.x, `path.alias_manager` has been deprecated, use `path_alias.manager` in future versions of Drupal.
> 10 votes

# Answer
More right, easy and universal way:

```
$node = \Drupal::entityTypeManager()->getStorage('node')->load($id);
$node_alias = $node->get('path')->alias;

```

You can also do extra checks if you are not sure if an alias exists:

```
if (!$node->get('path')->isEmpty()) {
    $node_alias = $node->get('path')->alias;
}

```

**UPDATED**

This will work for any entity type. But here is example for taxonomy terms:

```
$term = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->load($tid);
if (!$term->get('path')->isEmpty()) {
    $term_alias = $term->get('path')->alias;
}

```
> 3 votes

---
Tags: 8, nodes, taxonomy-terms
---


# Question
Title: Cache tags for all entities of a certain type
I understand how you can add cache tags to a custom query for a particular entity id (or list of them) but is there a way to add cache tags that will invalidate a query if any entity of type FOO is updated/added/deleted?

# Answer
You could use the module handy\_cache\_tags, then you would have this type of tags:

```
handy_cache_tags:[entity_type]
handy_cache_tags:[entity_type]:[entity_bundle]

```
> 7 votes

# Answer
In your blockcache\_examples.module file:

```
use Drupal\Core\Cache\Cache;
use Drupal\node\Entity\Node;

/**
  * Invalidate the custom tag if entities of type "page" get updated
  */
function blockcache_examples_node_update(Node $entity) {
  if($entity->getType() === 'page') {
    Cache::invalidateTags(['blockcache_examples_page_updates']);
  }
}

/**
  * Invalidate the custom tag if entities of type "page" get inserted
  */
function blockcache_examples_node_insert(Node $entity) {
  if($entity->getType() === 'page') {
    Cache::invalidateTags(['blockcache_examples_page_updates']);
  }
}

/**
  * Invalidate the custom tag if entities of type "page" get deleted
  */
function blockcache_examples_node_delete(Node $entity) {
  if($entity->getType() === 'page') {
    Cache::invalidateTags(['blockcache_examples_page_updates']);
  }
}

```

In your **src/Plugin/Block/MyBlock.php** (or controller, whatever):

```
/**
 * Only when node(s) of type 'page' are updated/insert/deleted. See .module file
 */
public function getCacheTags() {
  return Cache::mergeTags(parent::getCacheTags(), array('blockcache_examples_page_updates'));
}

```

Source: this video explaining block caching
> 1 votes

---
Tags: 8, caching
---


title: How to rename Sticky at top of lists?

text:
# Question
Title: How to rename Sticky at top of lists?
I am using Drupal 8 theme and i am wondering is there any way to change the phrase *Sticky at top of lists* which appears when creating new posts, to something different like *Appear in Search Results* or *Trending?*

# Answer
In a custom Drupal module do something like:

```
function sfusd_scheduler_form_alter(&$form, $form_state, $form_id)
{
    // Let's change sticky at top of lists to client preferred verbiage
    $form['sticky']['widget']['value']['#title'] = 'Pinned to top of announcement list';
}

```
> 0 votes

# Answer
I found a not so clean way if you're still looking for this.

in the following file: \core\modules\node\src\Entity\Node.php on line 414(for me)

```
$fields['sticky'] = BaseFieldDefinition::create('boolean')
  ->setLabel(t('Sticky at top of lists'))
  ->setRevisionable(TRUE)
  ->setTranslatable(TRUE)
  ->setDefaultValue(FALSE)
  ->setDisplayOptions('form', array(
    'type' => 'boolean_checkbox',
    'settings' => array(
      'display_label' => TRUE,
    ),
    'weight' => 16,
  ))
  ->setDisplayConfigurable('form', TRUE);

```

Change the setLabel value and clear your cache, and the text will be changed. if someone has a neater way of doing this please correct my answer.

Since this is in core i would recommend making a text file and adding the line you replaced and give some extra info because with a drupal update you will have to change this again.
> -1 votes

---
Tags: 8
---


# Question
Title: How add sorting by Flag counter in Controller?
I get node list in my Conroller:

```
$query = \Drupal::entityQuery('node')
  ->condition('status', 1)
  ->pager(10)
  ->sort('created' , 'DESC');
$nids = $query->execute();

```

How can add sorting by Flag counter?

# Answer
> 1 votes
The flag count in another table called `flag_counts` so you should do join with `node` table try the following:

```
$database = \Drupal::database();
$query = $database->select('node', 'n');
$query->fields('n', [])
  ->condition('nfd.status', '1', '=');
// Inner join to get the node status.
$query->innerJoin('node_field_data', 'nfd', 'nfd.nid = n.nid');
// This join to get the flag counts by node.
$query->leftJoin('flag_counts', 'fc', 'n.nid = fc.entity_id');
$query->fields('fc', ['entity_id', 'count']);
// Sort by count.
$query->orderBy('fc.count', 'DESC');
$query->range(0, 10);
$result = $query->execute()->fetchAll();

```

---
Tags: 8, flags
---


# Question
Title: How to access webform elements in webform.html.twig
I'm trying to figure out a way to access webform elements from webform.html.twig.

I need to style the form; wrapping some elements and adding bunch of styles all I have in the webform.html.twig is "children" variable which renders the whole form, whereas I need to access every element individually.

I found a link on the web for webform-form.html.twig which might do what I need, however I can't find it in webform template folder

http://cgit.drupalcode.org/webform/tree/templates/webform-form.html.twig?id=1135b65031cd6cd195c2e638300e5ef945a6f652

Any help with this matter is much appreciated.

# Answer
I have figured out a solutions for this situation.

1. create a tempalte file for your form (ex. webform--newsletter.html.twig)
2. there is a variable (element) where you can access each field of the form like this:

> {{ element.elements.YOUR\_FIELD\_NAME }}

3. you need to output the form action (submit) at the end of the form link this:

> {{ element.actions }}

4. the trick with this solution is that you need to output a couple of hidden form elements that is required for the form to be submitted properly:

> {{ element.form\_token }}
>
> {{ element.form\_build\_id }}
>
> {{ element.form\_id }}

My final form template looks like this:

```
<div class="request-form">
  <div class="form-wrap clearfix">
    <div class="col-md-4 form-desc">
      {{ element.elements.form_description }}
    </div>
    <div class="col-md-8">
      <form{{ attributes }}>
        {{ title_prefix }}
        <div class="row">
          <div class="col-md-6">
            {{ element.elements.name }}
            {{ element.elements.email }}
            {{ element.elements.phone }}
          </div>
          <div class="col-md-6">
            {{ element.elements.message }}
            {{ element.form_token }}
            {{ element.form_build_id }}
            {{ element.form_id }}
            {{ element.actions }}
          </div>
        </div>
        {{ title_suffix }}
      </form>
    </div>
  </div>
</div>

```

Hope that helps anyone else

**Update:** I forgot to mention that you also need to print out the following element:

> {{ element.form\_token }}

Credit goes to **maestrojed** Webform twig template causes “the form has become outdated” error
> 6 votes

# Answer
I know this is a late reply, but I haven't seen the following approach mentioned anywhere else. I think the above answers are a bit hacky. What I do is edit the webform submission html twig file with my own markup, right above the `{{form}}` line. So in essence, I would access the name input and label by typing `{{form.elements.name}}` between my html tags, and then between my markup and the `{{form}}` line type this `{% set form =form|without('elements') %}`

This keeps the form token, the form id, the form build id so the form can submit
> 2 votes

# Answer
```
<div class="contact-box">
  <div class="wrap">
    {{ element.elements.form_token }}
    {{ element.elements.form_build_id }}
    {{ element.elements.form_id }}
    <div class="request-form">
      <div class="form-wrap clearfix">
        <div class="col-md-4 form-desc">
          {{ element.elements.form_description }}
        </div>
        <div class="col-md-8">
          <form{{ attributes }}>
            {{ title_prefix }}
            <div class="row">
              <div class="col-md-6">
                {{ element.elements.salutation }}
                {{ element.elements.company }}
                {{ element.elements.first_and_last_name }}
                {{ element.elements.phone_number }}
                {{ element.elements.phone_number }}
                {{ element.elements.e_mail }}
                {{ element.elements.theme }}
                {{ element.elements.meeting }}
              </div>
              <div class="col-md-6">
                {{ element.elements.message }}
                {{ element.form_token }}
                {{ element.form_build_id }}
                {{ element.form_id }}
                {{ element.elements.actions }}
              </div>
            </div>
            {{ title_suffix }}
          </form>
        </div>
      </div>
    </div>
  </div>
</div>

```
> 1 votes

# Answer
Webforms in Drupal 8 are basically just FAPI render arrays with a UI plus some enhancements. To learn how to theme a Webform and its elements, you should search for articles about theming forms in Drupal 8 which will return some useful blog posts like this one.
> 0 votes

---
Tags: theming, webforms
---


# Question
Title: What is the equivalent of a call to drupal_http_request()?
In Drupal 7 I am using the following code.

```
$url = 'testdomain/url';
$response = drupal_http_request($url, array('method' => 'POST', 'headers' => array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8')));
if ($response->code == "200") {
  $result = $response->data;
}

```

What is the equivalent code I should use on Drupal 8?

# Answer
Finally i find a code in https://api.drupal.org/api/drupal/core%21includes%21install.core.inc/8 (1375)

and its working for me :)

```
 try {
    $response = \Drupal::httpClient()->get($uri, array('headers' => array('Accept' => 'text/plain')));
    $data = (string) $response->getBody();
    if (empty($data)) {
      return FALSE;
    }
  }
  catch (RequestException $e) {
    return FALSE;
  }

```

Hope this will help for some one
> 19 votes

# Answer
HTTP client library added to replace drupal\_http\_request()

```
$client = \Drupal::httpClient();
$request = $client->createRequest('GET', $feed->url);
$request->addHeader('If-Modified-Since', gmdate(DATE_RFC1123, $last_fetched));

try {
  $response = $client->get($feed->uri, [
    'headers' => [
      'If-Modified-Since' => gmdate(DATE_RFC1123, $last_fetched),
    ],
  ]);
  // Expected result.
  // getBody() returns an instance of Psr\Http\Message\StreamInterface.
  // @see http://docs.guzzlephp.org/en/latest/psr7.html#body
  $data = $response->getBody();
}
catch (RequestException $e) {
  watchdog_exception('my_module', $e);
}

```
> 2 votes

# Answer
This is working for me, sending a XML file with \Drupal::httpClient() POST

```
$endpoint  = 'http://example.com/something';
$xml = '<>'; // You're XML here.

// Make the request.
$options = [
  'connect_timeout' => 30,
  'debug' => true,
  'headers' => array(
    'Content-Type' => 'text/xml',
  ),
  'body' => $xml,
  'verify'=>true,
];

try {
  $client = \Drupal::httpClient();
  $request = $client->request('POST',$endpoint,$options);

}
catch (RequestException $e){
  // Log the error.
  watchdog_exception('custom_modulename', $e);
}

$responseStatus = $request->getStatusCode();
$responseXml = $request->getBody()->getContents();

```

Hope this helps.

More info about Guzzle here: http://docs.guzzlephp.org/en/latest/index.html
> 1 votes

---
Tags: 8
---


# Question
Title: How to get the raw value of the url in a link field
I'm doing this:

```
$link = $node->field_link->first();
if ($link) {
  $url = $link->getUrl()->toString();
  ...
}

```

If the value in the link field is `/node/123` but there is a URL alias defined as:

```
Alias: /about-us    System path: /node/123

```

I get `/about-us` in `$url`. I want to get `/node/123`.

How do I get the raw url value instead of the aliased value?

# Answer
Instead of rendering the URL object with toString() use the method Url::getInternalPath:

```
$url = $link->getUrl();
if ($url->isRouted()) {
  $path = $url->getInternalPath();
}

```
> 6 votes

# Answer
Another solution I happened upon since I first posted is

```
$uri = $node->get('field_link')->uri;

```

The difference between this and the accepted answer is that this approach gives the actual, raw value in the link field (with 'internal:' appended to the front) whatever it is, without URL alias translation. The accepted answer doesn't translate `/node/123` in the field to `/about-us`, but it does translate `/about-us` in the field to `/node/123`.

Once `$uri` has been modified as needed, it can be put back into the node by

```
$node->set('field_link', ['uri' => $uri]);

```
> 0 votes

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


# Question
Title: How to query solr server from php in Drupal 8
How do you query solr server from php in Drupal 8?

I have installed search\_api, search\_api\_solr and search\_api\_attachments. Also have Solr v.8.4.0 installed.

I installed php SolrClient for Centos 7 following this guidance: https://stackoverflow.com/questions/22959330/fatal-error-class-solrclient-not-found , but I still get "*Class 'SolrClient' not found*" every time I run

```
new SolrClient($options);

```

I have located documentation on querying Solr from php in Drupal 7 (apachesolr\_get\_solr()) but nothing in Drupal 8.

# Answer
I managed to fix the problems with SolrClient install: https://stackoverflow.com/questions/41052999/php-warning-unable-to-load-dynamic-library-usr-lib64-php-modules-solr-so-und%C2%A0

This is how I can now query the solr server from php (right out of php SolrClient manual):

```
$options = array
(
    'hostname' => 'localhost',
    'port'     => '8983',
    'path'     => 'solr/sbn01'
);

$client = new SolrClient($options);

$query = new SolrQuery();

$query->setQuery('*file/10*');

$query->setStart(0);

$query->setRows(50);

$query->addField('id');
$query->addField('its_fid');
$query->addField('ss_uri');

$query_response = $client->query($query);

$response = $query_response->getResponse();

print_r($response);

```
> 0 votes

---
Tags: 8, search
---


title: The page isn’t redirecting properly

text:
# Question
Title: The page isn’t redirecting properly
I have been trying to intercept a page request from `/node/nid` which is of type `the_content_type` and then appending some facet query parameters to it which is something like this

`?f[0]=city%3A160&f[1]=country%3A48`.

The purpose is to preselect the facet options from that page.

Here is the subscriber class I have written so far

```
<?php

namespace Drupal\custom_module\EventSubscriber;

use Drupal\Core\Url;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Drupal\Core\Routing\TrustedRedirectResponse;

class RedirectWithFilterSubscriber implements EventSubscriberInterface {
  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    // This announces which events you want to subscribe to.
    // We only need the request event for this example.  Pass
    // this an array of method names
    return([
      KernelEvents::REQUEST => [
        ['redirectWithFilter'],
      ]
    ]);
  }

  /**
   * Redirect requests for my_content_type node detail pages to node/123.
   *
   * @param GetResponseEvent $event
   * @return void
   */
  public function redirectWithFilter(GetResponseEvent $event) {
    $request = $event->getRequest();

    // This is necessary because this also gets called on
    // node sub-tabs such as "edit", "revisions", etc.  This
    // prevents those pages from redirected.
    if ($request->attributes->get('_route') !== 'entity.node.canonical') {
      return;
    }

    // Only redirect a certain content type.
    if ($request->attributes->get('node')->getType() !== 'the_content_type') {
      return;
    }

    $node = $request->attributes->get('node');
    $node_id = $node->id();
    $node_url = $node->url();
    $country = $node->field_country->getValue();
    $city = $node->field_city->getValue();
    $country_target_id = $country[0]['target_id'];
    $city_target_id = $city[0]['target_id'];

    if (empty($country) && empty($city)) {
      return;
    }

    // This is where you set the destination.
    $option = [
      "query" => [
        "f" => [
          "city:$city_target_id",
          "country:$country_target_id"
        ]
      ],
    ];

    $redirect_url = Url::fromUri("entity:node/$node_id", $option);
    $response = new RedirectResponse($redirect_url->toString(), 301);
    $event->setResponse($response);
  }
}

```

The resulting url looks fine though

`http://project.dev/some-custom-page?f%5B0%5D=city%3A160&f%5B1%5D=country%3A48`

But the problem is, the page always shows

`The page isn’t redirecting properly`

on my browser. I've been figuring this out for almost 3 days now and I can't seem to find a way through it. I've been wanting someone to have a fresh look into it. Maybe I am doing something wrong. Is there somebody can lend me a help please? Or maybe, a different way other than this? Thank you in advance.

# Answer
> 1 votes
Could be a redirect loop. You have to check whether the query string is already present and then stop redirecting again:

```
  public function redirectWithFilter(GetResponseEvent $event) {
    $request = $event->getRequest();
    if ($request->query->has('city')) {
      return;
    }
    ...
  }

```

---
Tags: 8, redirection
---


# Question
Title: NotFoundHttpException after changing webiste hosting, sub-domain
After changing webiste hosting (Drupal 8) I got this very un-intuitive error message:

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

Symfony\Component\HttpKernel\Exception\NotFoundHttpException: in Drupal\Core\PathProcessor\PathProcessorFront->processInbound() (line 43 of core/lib/Drupal/Core/PathProcessor/PathProcessorFront.php).

Drupal\Core\PathProcessor\PathProcessorManager->processInbound('/', Object) (Line: 157)
Drupal\Core\Routing\RouteProvider->getRouteCollectionForRequest(Object) (Line: 141)
Symfony\Cmf\Component\Routing\NestedMatcher\NestedMatcher->matchRequest(Object) (Line: 258)
Symfony\Cmf\Component\Routing\DynamicRouter->matchRequest(Object) (Line: 185)
Symfony\Cmf\Component\Routing\ChainRouter->doMatch('/', Object) (Line: 155)
Symfony\Cmf\Component\Routing\ChainRouter->matchRequest(Object) (Line: 84)
Drupal\Core\Routing\AccessAwareRouter->matchRequest(Object) (Line: 154)
Symfony\Component\HttpKernel\EventListener\RouterListener->onKernelRequest(Object, 'kernel.request', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.request', Object) (Line: 120)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 62)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 628)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

```

The files are all the same, other files on ftp/website (besides Drupal) are accessible and works fine.

I've cleared cache via Admin Panel before moving anything.

I've also tried remove it manually:

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

```

but I guess it's not the point.

The previous website was working on `http://someurl1.com/site/` (sub-domain) and new one is under `http://someurl.com/` (top domain). But even moving everthing on new hosting to `/site/` doesn't change a thing.

When I changed database connection settings in `settings.php` to something wrong intentionally I get:

```
PDOException: SQLSTATE[HY000] [1044] Access denied for user...

```

So I guess it's not the database connection problem either.

Using `http://.../core/rebuild.php` also didn't help.

# Answer
Check database connection through `drush sql-cli` and `show tables`, I got the same error because of an empty database once.

If the data is of no importance, you can run `drush site-install` to re-install Drupal from scratch.
> 0 votes

# Answer
I just had this after transferring an entire database (Drupal 8.8.1) from production back to dev.

Same error on every single route I tried.

Clearing the cache alone didn't fix it, but `composer dump-autoload` (*"Generated autoload files containing 565 classes"*) followed by `drush cr` did.
> 0 votes

---
Tags: 8, installation
---


# Question
Title: How do I configure the recurring node checkout payment?
In the past years, I use commerce node checkout to published a node when the user checkout completed. Now I want to automatically, charge user when their node published expired.

How can I link the node to the recurring product, so the recurring payment happen when the node expire every month?

# Answer
> 0 votes
I got it working. I've read the file "README.txt" and found that any product type can be a recurring product.

Now I configured my existing product type to add the fields, required by recurring payment. So, now when I checkout, it does create a recurring entities for this order. Hope it will help someone.

---
Tags: 7, commerce
---


# Question
Title: common.inc error in newly downloaded Drupal 7.69
I just downloaded drupal 7.69 and tried to configure it. It gives me a page full of the same error:

> Notice: Trying to access array offset on value of type int in element\_children() (line 6656 of /Applications/MAMP/htdocs/KSnew/includes/common.inc).

Here's the relevant part of the code in common.inc, with line numbers:

```
6648 function element_children(&$elements, $sort = FALSE) {
6649   // Do not attempt to sort elements which have already been sorted.
6650   $sort = isset($elements['#sorted']) ? !$elements['#sorted'] : $sort;
6651
6652   // Filter out properties from the element, leaving only children.
6653   $children = array();
6654   $sortable = FALSE;
6655   foreach ($elements as $key => $value) {
6656     if ($key === '' || $key[0] !== '#') {
6657       $children[$key] = $value;
6658       if (is_array($value) && isset($value['#weight'])) {
6659         $sortable = TRUE;
6660       }
6661     }
6662   }

```

Is this a Drupal error??

# Answer
> 2 votes
I think it is PHP related. According to the Drupal 7 php requirements PHP 7.4 is not fully supported. If you are running on 7.4 perhaps try downgrading it to 7.3 and see if it makes a difference.

This is probably the relevant issue that you encountered. Alternatively see if you can use the latest patch in there and post your findings so you can help move the issue forward.

---
Tags: 7
---


# Question
Title: Reinstall a patch with composer - update one module only
Can I update a patch without running `composer update` ? In other words: can I update one module only?

# Answer
> 2 votes
Yes, use the following:

```
composer update --prefer-source drupal/menu_block

```

---
Tags: 8, composer
---


# Question
Title: Group content by taxonomy term, but then also list all terms in each row
I'm looking for help with creating a view.

I have a content type, Thing. Thing has a field on it where you can select multiple terms in a taxonomy, Category. I want my view to look like this:

**Category 1**

* Thing 1

+ Category 1
    + Category 2
* Thing 2

+ Category 1
    + Category 3

**Category 2**

* Thing 1
    + Category 1
    + Category 2

So basically, I want to group by the terms and then list out all terms underneath each Thing. I also don't want groups to end up with headers of "Category 1, Category 2," and I want to make sure each of the terms is listed under each instance of the Thing in the view.

Thanks for any help!

# Answer
> 1 votes
I figured it out!

Instead of just adding Category as a single field in the View and trying to figure out how to configure that to show each Category for a Thing row but only one Category header per group, I have the Category field on there twice - one that does not display multiple in one row (for the headers), and one that does display them all within one row (to list out all Categories for a Thing).

I hope this possibly helps someone else!

---
Tags: 7, views, taxonomy-terms
---