# Question
Title: Get Field Name Being Deleted From Configuration Updates/Delete Form
Trying to get the `field_name` being deleted when viewing a route like `entity.field_config.user_field_delete_form`.

Example path: `/admin/config/people/accounts/fields/user.user.field_name/delete`

Some Hooks I've tried:

1. `hook_preprocess_html()`
2. `hook_preprocess_page()`
3. `hook_preprocess_page_title()`
4. `hook_preprocess_form_field_config_delete_form_alter()`

But the best I have found is an argument `[%label] => Field Label`.

I have an array of `field_names` and want to check if the `field_name` being deleted matches one of the values.

The goal is to add a custom `\Drupal::messenger()->addWanrning($warning);`.

This would be altering an *existing* delete form/page.

# Answer
Try with `hook_form_alter` something like

```
/**
 * Implements hook_form_alter().
 */
function MyModule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == "field_config_delete_form"){
    $field = $form_state->getFormObject()->getEntity();
    \Drupal::messenger()->addWarning("You are going to delete field : " . $field->getName());
  }
 }

```
> 1 votes

---
Tags: 8, forms, hooks
---


# Question
Title: Optimize image that does not have an image style
We are using the imageapi\_optimize modules with the imageapi\_optimize\_resmushit. We are able to flush the caches for all the image styles and see an improvement. However, there are images that are loaded with `background-image` attribute that do not get optimized and their image styles are set to `Original Image` under `Manage Display` for the `image` field.

**How can I set up the image who use the `Original Image Styles` setting under `Manage Display` to be optimized as well?**

What we tried:

1. Enable `imageapi_optimize`
2. Enabled `imageapi_optimize_resmushit`
3. Setup `image optimize pipeline` and set it to `resmushit`
4. Clear all caches and especially the image style cache using `drush if all`
5. Observe all images where an image style is used other than `Original Image` is optimized after cache.
6. All images where image style is set to `Original Image` is not not optimized.

# Answer
Assuming `background-image` refers to the example: `<img src="" style="background-image: url(path/to/image);" />`.

Background images are different when written as: `style="background-image: url(path/to/image);"`, they do not necessarily use Drupal's render service.

A couple of options to try depending on your use case:

• Try preprocessing your image field URI and then printing out the Image Style image path.

```
use Drupal\image\Entity\ImageStyle;

$imagePath = 'public://images/image.jpg';
$variables['imageStyleURL'] = ImageStyle::load('style_name')->buildUrl($imagePath);

url({{ imageStyleURL }})

```

• Change the output format of the field to "URL to image", then just print out {{ image\_field }} in the `url()`.

```
url({{ image_field }})

```

The problem to your question, is how would Drupal (or contributed module) know that an image URL should be processed by an image style? It would not seem an issue with the modules, more they don't have a chance to do their thing.

Also, Twig Tweak, beyond being a great module for many cases, provides a Twig method for applying an image style in Twig:

```
{{ field_image_path | image_style('image_style') }}

```

\*Note, manual image URL's that contain an image style path will use that image style: `/sites/default/files/styles/image_style/public/pictures/2019-03/file_name.jpg_11`
> 2 votes

---
Tags: 8, hooks, media
---


# Question
Title: error_get_last() doesn't show last warning
Drupal has its own custom error handler, so when I try to get the message from the last warning (e.g. for an invalid regex), there is nothing there:

```
if (@preg_match($regex, NULL) === FALSE) {
  dpm(error_get_last());
}

```

The `@` prevents it from being displayed on the screen, and without that I can see a warning for a $regex of `'/(/'` (about an unmatched paren), but the warning is not shown by `dpm()`, but rather by Drupal.

Is there a way I can get the warning from an invalid regex in this example, so that I could have the message in a variable?

# Answer
Use the same PHP's error functions as Drupal to toggle PHP's error handling behavior.

In particular, you can use `set_error_handler()` / `restore_error_handler()` to toggle the PHP error code handling while you're debugging:

```
// Remove _drupal_error_handler() handling
restore_error_handler();

if (@preg_match($regex, NULL) === FALSE) {
  dpm(error_get_last());
}
// Restore _drupal_error_handler() handling
set_error_handler('_drupal_error_handler');

```

See the PHP doc links for more information on how these error handling functions work.
> 2 votes

---
Tags: 7
---


# Question
Title: Import data with feeds that is not in the source file
I need support to set a field on a feeds mapping that is not in the source.

I already have some code that for some reason is not working.

If I use **hook\_feeds\_after\_parse**, I can set the value but I need to use the method below (new mapping).

```
function  MYMODULE_cronapi($op, $job = NULL) {
    $items['TEST IMPORT'] = array(
        'description' => 'TEST IMPORT',
        'rule' => '1 * 1 * *',
        'callback' => ' MYMODULE_testImport',
    );

    return $items;
}

function MYMODULE_testImport() {
    $test_field_value = 'this is a test';
    $feeds_importer = 'test_feeds';
    $feeds_source = feeds_source($feeds_importer);
    $field_mappings = $feeds_source->importer->processor->getMappings();

    $path_to_xml = 'http://.../sites/default/files/test_content.xml';

    foreach ($field_mappings as &$mapping) {
        if ($mapping['target'] == 'field_test_field') {
            $mapping['test_field'] = $test_field_value;
        }
    }

    $feeds_source->importer->processor->addConfig(array('mappings' => $field_mappings));

    drupal_static_reset('FeedsProcessor::getMappings');

    $feeds_config = $feeds_source->getConfigFor($feeds_source->importer->fetcher);

    $feeds_config['source'] = $path_to_xml;

    $config = array(
        'process_in_background' => TRUE,
    );

    $feeds_source->setConfigFor($feeds_source->importer->fetcher, $feeds_config);
    $feeds_source->importer->addConfig($config);
    $feeds_source->save();
    $feeds_source->startImport();

    while (FEEDS_BATCH_COMPLETE != $feeds_source->import());
}

function MYMODULE_feeds_processor_targets_alter(array &$targets, $entity_type, $bundle) {
  if ($entity_type == 'node' && $bundle == 'test_content') {
    if (isset($targets['field_test_field'])) {
      $targets['field_test_field']['callback'] = 'MYMODULE_set_test_field';
    }
  }
}

function MYMODULE_set_test_field(FeedsSource $source, $entity, $target, array $values, array $mapping) {
    if ($source->importer->id == 'test_feeds') {
        if (!empty($mapping['test_field'])) {
            $entity->{$target}[$entity->language][0]['value'] = $mapping['test_field'];
        }
    }
}

```

# Answer
> 0 votes
1. To get the importer's machine name from the source, instead of doing `$source->id`, this should be `$source->importer->id`.
2. I don't know what you are trying to do with `$mapping['_ad_area']` exactly. `$mapping` contains target configuration (aka mapping settings). I don't see `form_callbacks` on your target code. The default taxonomy reference field also doesn't have an option called '\_ad\_area'. If you added mapping for the 'field\_ad\_area' target, values coming from the source should exist in `$values`.
3. You say you want to provide a value that is not in your original source. If this is a fixed value, you can use the Tamper plugin "Set default value" from the Feeds Tamper module. If you are using the CSV parser, on the mapping form you can just enter a source column name that does not exist in your CSV file. Otherwise, select "Blank source".

If you programmatically want to set a value, you can implement the hook `hook_feeds_after_parse()` in a custom module:

```
/**
 * Implements hook_feeds_after_parse().
 */
function mymodule_feeds_after_parse(FeedsSource $source, FeedsParserResult $result) {
  if ($source->importer->id != 'qc_data_generic_import') {
    return;
  }

  foreach ($result->items as &$item) {
    $item['Blank source 1'] = 'My value';
  }
}

```

---
Tags: feeds
---


# Question
Title: Use custom variable in html.tpl.php for critical css
I have built my current theme in my D7 site upon the Foundation theme, and with that comes a LOT of unused CSS that gives me a low score in Pagespeed Insights. I have tried different things, among others to use the Advagg module and it's submodule "Critical CSS". These modules does no good for my site unfortunately, despite repeated trials and despite safe settings etc. The screen goes blank and/or each page takes minutes to load. When I only use safe settings and critical css, the page speed score does not improve (and yes, all settings are done according to docs and I have spent many hours on trialling without luck).

So, instead I thought I would try to move this row in html.tpl.php:

```
    <?php print $styles; ?>
</body>

```

...to the bottom of the page just before the ending body tag. Then I would need to add the critical css in the head section.

```
    <head>
        <?php print $critical_css; ?>
...

```

But how can I pass a variable like $critical\_css to html.tpl.php, that only contains the just necessary to show the page? Or is this not possible?

# Answer
Instructions for the Critical CSS module:

Navigate to: admin/config/development/performance/advagg/critical-css

Under Add Critical CSS \- Select the theme that is your front page; usually the default is correct. \- User type should be set to 'anonymous' under most circumstances. \- Type of lookup, select URL \- Value to lookup, type in \- Critical CSS, paste in the generated CSS from running your homepage url through https://www.sitelocity.com/critical-path-css-generator which is inside of the 'Critical Path CSS' textarea on the sitelocity page. \- Click Save Configuration.
> 0 votes

---
Tags: 7, theming
---


title: Error when I try to call a form

text:
# Question
Title: Error when I try to call a form
Here is my class:

```
<?php

namespace Drupal\mais\Form;

use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ChangedCommand;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\CssCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Form\FormBase;
use Drupal\mais\Form\annuaireForm;
use Drupal\Core\Datetime\DrupalDateTime;

/**
 * Form controller for adhesion edit forms.
 *
 * @ingroup mais
 */
class adhesionForm extends ContentEntityForm {

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

   /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    /* @var $entity \Drupal\mais\Entity\adhesion */
    $form['#theme'] = 'adhesion_form';
    $form = parent::buildForm($form, $form_state);

    $entity = $this->entity;

    //pour l'ajax
    if (!$form_state->has('entity_form_initialized')) {
    $this->init($form_state);
    }

    $form['add_annuaire'] = array(
       '#weight' => '-9',
      '#type' => 'button',
      '#value' => "Ajouter une fiche a l'annuaire",
      '#ajax' => array(
        'callback' => 'Drupal\mais\Form\adhesionForm::addAnnuaireCallback',
        'event' => 'click',
        'progress' => array(
          'type' => 'throbber',
          'message' => 'Création du formulaire',
        ),

      ),
    );
  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $entity = $this->entity;

    $status = parent::save($form, $form_state);

    switch ($status) {
      case SAVED_NEW:
        drupal_set_message($this->t('Created the %label adhesion.', [
          '%label' => $entity->label(),
        ]));
        break;

      default:
        drupal_set_message($this->t('Saved the %label adhesion.', [
          '%label' => $entity->label(),
        ]));
    }
   //$form_state->setRedirect('entity.adhesion.canonical', ['adhesion' => $entity->id()]);
    $form_state->setRedirect('view.intranet_adhesion.page_1', ['adhesion' => $entity->id()]);
  }
  public static function addAnnuaireCallback(array &$form, FormStateInterface $form_state) {

    $AddAnnuaireForm = \Drupal::formBuilder()->getForm('Drupal\mais\Form\annuaireForm');
    //return $AddAnnuaireForm;

    $ajax_response = new AjaxResponse();
    $ajax_response->addCommand(new HtmlCommand('#div-cible', buildAnnuaire));

   return $ajax_response;

  }

}

```

In the addAnnuaireCallback function, the line

```
$AddAnnuaireForm = \Drupal::formBuilder()->getForm('Drupal\mais\Form\annuaireForm');

```

return an error:

```
Error: Call to a member function getEntityTypeId() on null in Drupal\Core\Entity\EntityForm->getBaseFormId() (line 79 of Drupal/Core/Entity/EntityForm.php).

```

# Answer
Your form is a `ContentEntityForm`, so you need to use the entity form builder service, e.g.:

```
$entity = /** create or load your entity **/
$entity_form = \Drupal::service('entity.form_builder')
  ->getForm($entity, 'default');

```
> 1 votes

---
Tags: forms, ajax
---


# Question
Title: Pass a value from a block preprocess hook to a twig template that inserts that block
I use the D8 `book` module to manage magazines and their articles.

In the `node--magazine.html.twig` template for a magazine, I use the built-in `book_navigation` block to add a table of contents. This is done by `drupal_block("book_navigation", {block_mode: "book pages"})`. Works fine.

For certain "featured" articles in the table of contents, I want to display an image. I use `MYTHEME_preprocess_book_tree(&$variables)` to add the image url to the `items` array in $variables. I've sub-themed `book-tree-html.twig` to get the image url from the `items` array and include the image in the table of contents. Works fine.

BUT, I need to know in `node--magazine.html.twig` whether there are any featured articles in the table of contents to present a proper heading on the page.

QUESTION: What is the best way to pass a variable from `THEME_preprocess_book_tree()` to `node--magazine.html.twig`? It's not a direct connection. Getting preprocess variables in `book-tree.html.twig` is easy, but I need to pass a variable through to `node--magazine.html.twig`, where the book tree is inserted.

What I have tried:

* In the `book-tree.html.twig` template, if there is a featured article, I add a hidden "featured-article" label to the html and then in the magazine template, I test for its presence via `{% if "featured-article" in <rendered block html> %}`. This works, but it feels unsavory.
* In `MYTHEME_preprocess_book_tree()`, I add `$variables['featured'] = $feature_count;` and in the magazine template I `{{ dump(featured) }}`. This doesn't work. I just get NULL. I'm not sure what--if any--connection there is between the $variables array available in the preprocess hook and variables available in the magazine template.
* In `MYTHEME_preprocess_book_tree()`, I could set a global variable and then in the magazine template, call a custom twig extension to check the value of that variable. I haven't tried this yet, but it seems like this should work. Just seems like there should be a more elegant way.

# Answer
After a lot more digging and trying things without success, I ended up solving the problem of passing a value from a block's preprocess hook to a twig template where the block is inserted as per my third option above. Here's what I did:

* Follow the instructions at `http://www.tothenew.com/blog/overview-of-twig-extentions-in-drupal-8` to create a twig extension. This wasn't very difficult, especially since I had already created a custom module. I just had to create a `MYMODULE.services.yml` file and a `TwigExtension.php` file as instructed.
* In the twig extension file, create functions `setTwigValue($name, $value)` and `getTwigValue($name)` using the php $GLOBALS array for storage. Again, the above-mentioned instructions made this pretty easy.
* In the preprocess\_book\_tree hook, count the number of feature articles and then save the count by calling

`Drupal\MYMODULE\TwigExtension::setTwigValue('feature_count', $feature_count);`
* In the node--magazine.html.twig template, get the saved value using

`{% set feature_count = getTwigValue('feature_count') %}`

I'm happy to learn of better/safer ways to accomplish what I've done. But at least it works and it's pretty clean.
> 1 votes

---
Tags: 8, theming
---


# Question
Title: custom module date formatter for publication date
I have a Drupal 8 contrib module AP Style Date that provides a formatter for dates to conform to the AP Style Guide date rules. When using the module Publication Date, this formatter does not come up as an option. The AP Style Date does come up in views and in managing field display for other date types. Is there a modification that needs to be made to the AP Style Date module or something in the publication date that needs to be modified?

# Answer
> 0 votes
The Publication Date module provides a function to define which formatters can be used. I added a patch, which we maintain locally, to add the defined "timestamp\_ap\_style" format to the options. Optionally, I could have added it inside a custom module, but the patch seemed to make more sense.

```
 function publication_date_field_formatter_info_alter(array &$info) {
   $info['timestamp']['field_types'][] = 'published_at';
   $info['timestamp_ago']['field_types'][] = 'published_at';
   $info['timestamp_ap_style']['field_types'][] = 'published_at';
 }

```

Update: Recently I came across a commit in the Smart Date with the same need that I had in the AP Style Date module. So, I tried that and it works.

```
/**
 * Plugin implementation of the 'timestamp' formatter as time ago.
 *
 * @FieldFormatter(
 *   id = "timestamp_ap_style",
 *   label = @Translation("AP Style"),
 *   field_types = {
 *     "datetime",
 *     "timestamp",
 *     "created",
 *     "changed",
 *     "published_at",
 *   }
 * )
 */

```

Simple and elegant.

---
Tags: datetime
---


# Question
Title: add link to edit content in admin top bar
I'm theming a web site that I haven’t created and I‘ve noticed this useful link placed in admin top bar (see screen shot) :

It provides link to edit / delete content.

How can I place this link on other website ?

I use Admin Toolbar + Adminimal Admin Toolbar with Adminimal 8.

Actually, I have the native menu and it is quite disturbing when you work on theming because it is placed inside content.

# Answer
That looks like the "shortcuts" menu tab which comes natively in a D8 installation but if you're looking to add your own custom shortcut menu (& menu items) you might want to look into the hook\_toolbar: https://api.drupal.org/api/drupal/core!modules!toolbar!toolbar.api.php/function/hook\_toolbar/8.2.x

You can build a quick custom module to establish your own links and configurations. Hope I answered your question!
> 1 votes

---
Tags: 8
---


# Question
Title: How do I debug with Xdebug in Visual Studio Code?
When I try to debug Drupal 8 (8.6.11) using Xdebug in VS Code (I'm on Win 10 but I doubt it is relevant in this case) I get the following error:

> Exception has occurred. Dotenv\Exception\InvalidPathException: Unable to read the environment file at /app/.env.

The problem is either with VS Code or with Drupal as someone has reported exact same behaviour on High Sierra and they were using Drupal 8.6.10: https://github.com/lando/lando/issues/1501

I did not find anything in drupal docs about the neccessity of creating a .env file to use Xdebug, so I suspect a bug eihter in Drupal 8 or VS Code.

Has someone encountered similar behaviour? Should I file a bug report on Drupal site?

# Answer
> 2 votes
`InvalidPathException` is an exception related to the `vlucas/phpdotenv` composer package so this issue isn't related to the Lando & VS Code codebases; it's an issue with your Drupal code base.

You can confirm `phpdotenv` is a Drupal dependency by looking at your `composer.json` file and looking at the `require` section.

The issue is the package dependency isn't finding the `/app/.env` file in your Lando environment. Confirm that the `.env` exists in your Lando project root (the same dir as your `.lando.yml` file).

---
Tags: 8, debugging
---


# Question
Title: list of supported value in entity baseFieldDefinitions setDisplayOptions type(field widget)
I'm new in Drupal, I create my first entity and use baseFieldDefinitions to set fields and in fields I use setDisplayOptions to set form like this:

```
$fields['piece'] = BaseFieldDefinition::create('integer')
  ->setLabel(t('piece'))
  ->setDisplayOptions('view', [
    'label' => 'hidden',
    'type' => 'string',
    'weight' => 2,
  ])
  ->setDisplayOptions('form', [
    'label' => 'inline',
    'type' => 'string',/////// what is supported value list of type key
    'weight' => 2,
  ])
  ->setDisplayConfigurable('form', TRUE)
  ->setDisplayConfigurable('view', TRUE);

```

what is supported value list of type key in display option?

I only found `options_buttons` and `string`

# Answer
What you are looking for are the *field widget plugins*, these depend on what modules you have installed.

Use *Drupal Console* to run this command:

```
drupal debug:plugin field.widget

```

This is what I have on a local site with some contrib modules:

```
 -------------------------------------------- ---------------------------------------------------------------------------------------
  Plugin ID                                    Plugin class
 -------------------------------------------- ---------------------------------------------------------------------------------------
  boolean_checkbox                             Drupal\Core\Field\Plugin\Field\FieldWidget\BooleanCheckboxWidget
  datetime_datelist                            Drupal\datetime\Plugin\Field\FieldWidget\DateTimeDatelistWidget
  datetime_default                             Drupal\datetime\Plugin\Field\FieldWidget\DateTimeDefaultWidget
  datetime_timestamp                           Drupal\Core\Datetime\Plugin\Field\FieldWidget\TimestampDatetimeWidget
  email_default                                Drupal\Core\Field\Plugin\Field\FieldWidget\EmailDefaultWidget
  entity_reference_autocomplete                Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget
  entity_reference_autocomplete_tags           Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteTagsWidget
  field_example_3text                          Drupal\field_example\Plugin\Field\FieldWidget\Text3Widget
  field_example_colorpicker                    Drupal\field_example\Plugin\Field\FieldWidget\ColorPickerWidget
  field_example_text                           Drupal\field_example\Plugin\Field\FieldWidget\TextWidget
  field_permission_example_widget              Drupal\field_permission_example\Plugin\Field\FieldWidget\TextWidget
  file_generic                                 Drupal\file\Plugin\Field\FieldWidget\FileWidget
  image_image                                  Drupal\image\Plugin\Field\FieldWidget\ImageWidget
  language_select                              Drupal\Core\Field\Plugin\Field\FieldWidget\LanguageSelectWidget
  link_default                                 Drupal\link\Plugin\Field\FieldWidget\LinkWidget
  menu_item_extras_view_mode_selector_select   Drupal\menu_item_extras\Plugin\Field\FieldWidget\MenuItemExtrasViewModeSelectorSelect
  moderation_state_default                     Drupal\content_moderation\Plugin\Field\FieldWidget\ModerationStateWidget
  number                                       Drupal\Core\Field\Plugin\Field\FieldWidget\NumberWidget
  oembed_textfield                             Drupal\media\Plugin\Field\FieldWidget\OEmbedWidget
  options_buttons                              Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsButtonsWidget
  options_select                               Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget
  path                                         Drupal\path\Plugin\Field\FieldWidget\PathWidget
  string_textarea                              Drupal\Core\Field\Plugin\Field\FieldWidget\StringTextareaWidget
  string_textfield                             Drupal\Core\Field\Plugin\Field\FieldWidget\StringTextfieldWidget
  text_textarea                                Drupal\text\Plugin\Field\FieldWidget\TextareaWidget
  text_textarea_with_summary                   Drupal\text\Plugin\Field\FieldWidget\TextareaWithSummaryWidget
  text_textfield                               Drupal\text\Plugin\Field\FieldWidget\TextfieldWidget
  uri                                          Drupal\Core\Field\Plugin\Field\FieldWidget\UriWidget
 -------------------------------------------- ---------------------------------------------------------------------------------------

```
> 14 votes

# Answer
Would like to add that if you want to get list of baseFieldDefinitions available on your installation run

```
drupal debug:plugin field.field_type

```

and to get huge list of formatters, run this

```
drupal debug:plugin field.formatter

```
> 2 votes

---
Tags: 8, entities
---


title: How do I use React components?

text:
# Question
Title: How do I use React components?
I'm going to use React with D8 and perform so-called Progressive decoupling, i.e. use React Components on existing Drupal pages.

There are several articles on this topic but the information is not complete. It would be great to summarize it and define the best method of implementing React.

I've chosen this guide to start with and created a React App inside my custom module folder. I've also decided to use JSON API instead of RESTful Services, according to the recommendations.

After that author recommends to use Paragraph module to implement separate paragraphs which will be replaced by React components.

It is not clear to me what structure should my custom module have? Do I need a router, controller, .module file or maybe a plugin? Where should I put hook\_preprocess\_paragraph\__HOOK function?

My idea is simple - to use different paragraphs for different React components and insert them into an existing layout.

Any best practices?

# Answer
The 'React block' module aims to add some more structure around React components and Redux state management in Drupal.

React blocks are defined by adding a simple YML file to your exising React component. This allows front end devlopers to create and manage React components as they normally would, and by including this YML file they can make the component available inside Drupal.
> 1 votes

# Answer
You can use https://drupalconsole.com/home which can generate module files for you. What you need for this example is an info and a module file which can be created using the `drupal gm` command from Drupal console. This guide https://www.drupal.org/docs/8/creating-custom-modules is also a good start to understand the structure of modules.
Also, you'll need to define libraries for your module as per this guide https://www.drupal.org/docs/8/creating-custom-modules/adding-stylesheets-css-and-javascript-js-to-a-drupal-8-module
> -1 votes

# Answer
React is just js. You can simply embed react.js and your react app js into your template.

Please look at the section React app embedded in Drupal for basic information on this setup and caveats.
> -1 votes

---
Tags: 8
---


# Question
Title: Rewriting output of existing content block
I've added a content block via the administration panel, and placed and themed it - but now I realise I need to add some extra logic to output different things depending on what user is logged in.

What hook would I use to do this, and does using a hook guarantee it will overwrite whatever content has been put in via the Block admin panel?

# Answer
You can try hook\_block\_list\_alter() hook.

Act on blocks prior to rendering.

This hook allows you to add, remove or modify blocks in the block list. The block list contains the block definitions, not the rendered blocks. The blocks are rendered after the modules have had a chance to manipulate the block list.

You can also set `$block->content` here, which will override the content of the block and prevent hook\_block\_view() from running.
> 0 votes

# Answer
You are trying to overwrite output based on the user type whereas the right thing to do would be build the right output based on the user. So if it is a views block, its visibility should depend on the user role. That way, you build different solutions for different roles and never have to rewrite the output.
> 0 votes

# Answer
Easiest way is `hook_block_view_alter` this hook will give you ability to override output of any block.

you can set condition based on user login like :

`function mymodule_block_view_alter(&$data, $block) {
 if($block->bid == 41){
 if($user->uid == 0){
 $body = "your design without login";
 $data["content"] = $body;
 }else{
 $body = "your design with login";
 $data["content"] = $body;
 }
 }
}
}`
> 0 votes

---
Tags: 7, blocks
---


# Question
Title: How to get the referenced node id in a webform?
I have a webform that is connected to a node in drupal 8. When the webform loads from the node link I need to get the source entity id from url. How can I achieve that in my custom module? the url is as follows: https://example.com/en/form/edu-form?source\_entity\_type=node&source\_entity\_id=134

I tried the following but I get an error:

```
 $node = \Drupal::routeMatch()->getParameter('source_entity_id');
 $nodeId = $node->id();

```

And also this (I tried to get the node id from the webform object)

```
/** @var \Drupal\webform\WebformRequestInterface $request_handler */
$request_handler = \Drupal::service('webform.request');
$source_entity = $request_handler->getCurrentSourceEntity('webform');
$node_id=$source_entity->id;

```

# Answer
> 0 votes
Make sure that the webform's source entity id can be prepopulated via a URL and the below code should work using `$source_entity->id()` instead of `$source_entity->id`

```
/** @var \Drupal\webform\WebformRequestInterface $request_handler */
$request_handler = \Drupal::service('webform.request');
$source_entity = $request_handler->getCurrentSourceEntity('webform');
$node_id = $source_entity->id();

```

---
Tags: nodes, webforms
---


title: How to print link text in twig?

text:
# Question
Title: How to print link text in twig?
I've attached file to a node with Media module. I have custom `templates/file/file-link.html.twig` file, which is rendering the download link with `{{ link }}` tag.

`{{ devel_dump(link) }}` outputs this:

**I need to print `File name` as pure text without any link rendering for some cases**.

I've tried `{{ link.text }}`, `{{ link.text.string }}` and other options, but none of them gave me what I wanted.

# Answer
> 1 votes
I don't know why, but when I tried `{{ link.text }}` one more time - it worked great!

Maybe I forgot to clear cache, when I used it for the first time, I don't know, but I think I should leave this answer for anyone who will search for it.

# Answer
> 1 votes
Maybe this is a render array and you need to use `link['#text']` here (sorry if I'm on the wrong track).

Edit: If `{{ link.text }}` worked on subsequent tries, then my answer is definitely wrong, and the reason for your problem was probably related to caching or something.

---
Tags: 8, theming
---


# Question
Title: How do I set a variable in the configuration file setting.php and use it from code?
How do I set a variable in the configuration file setting.php and use it from code?

# Answer
in settings.php:

```
$conf['yoursite_something'] = 5;

```

Then, in your code:

```
// Second argument is the default.
variable_get('yoursite_something', NULL);

```

Make sure to prefix the variables, either with the module you're using it in or with the site name.
> 27 votes

# Answer
Do note that it is not required to declare persistent variables in settings.php. You can simply call variable\_get() from your code and define a default value in case the variable is not set. For instance, the following code will say hello on every page request as long as the 'mymodule\_say\_hello' variable is not explicitly set to `0`:

```
<?php
function mymodule_init() {
  // Get the mymodule_say_hello variable or use 1 if it's not set.
  if (variable_get('mymodule_say_hello', 1)) {
    drupal_set_message('Hello world');
  }
}
?>

```

If needed, your module could publish a form that allows the admin to turn of this feature (the system\_settings\_form function makes that really easy) or you could change the settings programmatically by calling `variable_set('mymodule_say_hello', 0)`.
> 5 votes

# Answer
# Drupal 8

In your settings.php:

```
$settings['foo'] = 'bar';

```

In your code:

```
use Drupal\Core\Site\Settings;

Settings::get('foo', 'mydefaultvalue');

```
> 4 votes

---
Tags: configuration
---


# Question
Title: How to transfer data from/with PrivateTempStore?
I have an multistepform which handles sessions and stores like this: https://www.sitepoint.com/how-to-build-multi-step-forms-in-drupal-8/

But i want the option that the user can login in between. The previous input is lost if i wouldn't do anything, because the form is creating a new private store. At the moment i save the relevant data in extra cookies and retrieve them after the login succeeded.

Is there a better way to transfer the data between the stores or am I missing something?

Best Regards FirstSanny

# Answer
> 1 votes
See Access session data through the Request object:

**Drupal 7:**

```
function mymodule_session_counter_increment() {
  if (!isset($_SESSION['mymodule_count'])) {
    $_SESSION['mymodule_count'] = 0;
  }

  return $_SESSION['mymodule_count']++;
}

```

**Drupal 8:**

```
class MymoduleSessionCounter {
  function increment(Request $request) {
    $session = $request->getSession();
    $value = $session->get('mymodule_count', 0);
    $session->set('mymodule_count', $value + 1);

    return $value;
  }
}

```

In procedural code you find the request here:

```
$request = \Drupal::request();

```

Session data stored for anonymous traffic is automatically migrated when a user is logging in.

---
Tags: 8, forms
---


# Question
Title: Facet pages bring site down because of bots
We have a search page that uses facets and recently our website has been going up and down. When looking at the logs I noticed that bots (Bing, Ahrefs, etc..) are hitting these facetted pages a lot. Since the facetted pages are not cached I think it is causing this issue.

I did add Search-specific caching but that did not help.

I have seen these related issues with caching and facets:

Has anyone else ran into an issue like this? For now I blocked all bots from accessing the facetted urls (so they will still be able to see the main search page).

# Answer
For example, my facet page path starts with `/library`. I created a Firewall rule in Cloudflare to block anyone visiting a page that contains `/library/` so a facet result page like `/library/xxx/bbb/ccc` and is a known bot will be blocked.
> 0 votes

---
Tags: 7, search
---


title: Autocalculate computed twig field

text:
# Question
Title: Autocalculate computed twig field
I'm building a form which should calculate some values during the form view. I've tried to use the computed twig field. The calculation is working after submission and also, when I move to the previous or next page but I want the field to be calculated immediately after the base values has been entered (jQuery/AJAX).

If theres no way of doing it automatically, how can I accomplish this using a "Calculate" button?

I hope somebody can help with this issue or give an example for a form which is using this kind of calculation.

Cheers

# Answer
if you use the form API to build your form, then you can use the ajax form API.

In the field you want to trigger ajax method, use this :

```
$form['test'] = [
  '#type' => 'textfield',
  '#title' => 'A Textfield',
  '#required' => TRUE,
  '#ajax' => [
    'callback' => '::ajaxTest',
    'event' => 'keyup',
    'wrapper' => 'edit-output',
    'progress' => [
      'type' => 'throbber',
      'message' => t('Verifying entry...'),
    ],
  ],
];

```

Then create a ajaxTest function in your Form :

```
public function ajaxTest(array &$form, FormStateInterface $form_state) : array {
  // you can use the $form_state here to get values of all your fields
  $my_value = $form_state->getValue('my_field');
  // Make your logic code here
  $new_val = 'foo';
}

```

And then just add a AjaxCommand to your ajaxTest function :

```
$response = new AjaxResponse();
$response->addCommand(new InvokeCommand('#my_id_to_change', 'val', $new_val));
return $response;

```

You can find all those in the Form and AJAX API here https://api.drupal.org/api/drupal/core%21core.api.php/group/ajax/8.5.x, regards.
> 1 votes

# Answer
I'm doing something similar to the above request using a computed twig. Make sure "automatically update the computed value using Ajax?" is checked, and then enter this in the computed value / markup section of the computed twig;

`{{ data.weight * data.number_of_packages }}`

this follows the syntax

`{{ data.element_key * data.element_key }}`

This might work or might not. It's super finicky. Right now I have one working computed twig with an if statement and another computed twig with the same code that isn't working! bargh! Feel free to contact me if you're dealing with drupal webforms and would like a computed element. They can be frustrating.

Also, this piece of code, when ran in a computed twig, is great for discovering the element keys of your form!

```
<ol>
  {% for key, value in _context  %}
    <li>{{ key }}</li>
  {% endfor %}
</ol>

```

-Shell
> 1 votes

# Answer
I ended up in writing a module which provides a Composite Element for the webform module. This module defines all fields I need and loads a javascript file in which I included the automatic calculation of the fields I needed.

The total fields are set "readonly", in order to get the values stored into the submission of the form.

The code for the javascript file is:

```
(function ($, Drupal) {

'use strict';

Drupal.webform = Drupal.webform || {};

/**
 * Find all inputs referring to a defined class in a custom composite element and register an input event.
 * If an input is detected and this input is a valid number, do the calculation of the weight and volume
 *
 * One composite element refers to a package to be delivered. A form can consist an unlimited number of packages for now
 *
 * @type {Drupal~behavior}
 */
Drupal.behaviors.vacInputEvent = {
    attach: function (context, settings) {
        var container = $(context).find('#webform_composite_package_table');
        var inputs = $(context).find('[data-drupal-selector="edit-webform-composite-package-items"] input.vac-webform-composite-package-inputs[type="text"]');
        var totals = $(context).find('[data-drupal-selector="edit-webform-composite-package-items"] input.vac-webform-composite-package-totals[type="text"]');
        var grandtotalweight = $('[data-drupal-selector="edit-grand-total-weight"]');
        var grandtotalvolume = $('[data-drupal-selector="edit-grand-total-volume"]');
        inputs.once('vac-input-event').each(function () {
            $(this).on('input', function () {
                if (!isNaN(parseInt($(this).val()))) {
                    calculateInputs(inputs, totals, grandtotalweight, grandtotalvolume);
                }
            })
        });
        //If we are on the right context and all elements are loaded, do an initial calculation.
        //This is also needed, when a composite package is removed from the document
        if (inputs.length && totals.length && grandtotalweight.length && grandtotalvolume.length) {
            calculateInputs(inputs, totals, grandtotalweight, grandtotalvolume);
        }

        /**
         * iterate through the given object, calculate the values and show the values on the regarding totals textfield.
         * @var resultObj
         * - The Object which is generated in the calculateInputs function
         * @var totals
         * - The input elements, showing the calculated totals
         * @grandtotalweight
         * - The input element, showing the grand total of the calculated weight
         * @grandtotalvolume
         * - The input element, showing the grand total of the calculated volume
         **/
        function showTotals(resultObj, totals, grandtotalweight, grandtotalvolume) {
            var row;
            var weight;
            var volume;
            var total_volume ;
            var grand_total_weight = 0;
            var grand_total_volume = 0;

            $.each(resultObj.packageFigures, function (index, value) {
                //Calculation of Weight
                if (!isNaN(value.numberOfPackages) && !isNaN(value.weightOfPackage)) {
                    row = value.rowNo;
                    weight = value.numberOfPackages*(value.weightOfPackage/100);
                    grand_total_weight += weight;
                    (Math.round( weight * 100 )/100 ).toString();
                    weight.toFixed(2).replace(".",",");
                }
                //Calculation of Volume of one collie
                if (!isNaN(value.lengthtOfPackage) && !isNaN(value.widthOfPackage) && !isNaN(value.heightOfPackage)) {
                    row = value.rowNo;
                    volume = ((value.lengthtOfPackage/10000) * (value.widthOfPackage/10000) * (value.heightOfPackage/10000));
                    volume = (Math.round( volume * 100 )/100 ).toFixed(3).replace(".",",");
                } else {
                    volume = "0,00";
                }
                //Calculation of the total volume
                if (!isNaN(value.numberOfPackages) && !isNaN(value.lengthtOfPackage) && !isNaN(value.widthOfPackage) && !isNaN(value.heightOfPackage)) {
                    row = value.rowNo;
                    total_volume = ((value.lengthtOfPackage/10000) * (value.widthOfPackage/10000) * (value.heightOfPackage/10000)) * value.numberOfPackages;
                    grand_total_volume = grand_total_volume + total_volume;
                    total_volume = (Math.round( total_volume * 100 )/100 ).toFixed(3).replace(".",",");
                } else {
                    total_volume = "0,00";
                }

                //Show the calculated values on the regarding textfield
                if (index === parseInt(row)) {
                    totals.each(function () {
                        if ($(this).attr('data-drupal-selector') === 'edit-webform-composite-package-items-'+row+'-item-total-weight-of-package') {
                            $(this).val(weight);
                        }
                        if ($(this).attr('data-drupal-selector') === 'edit-webform-composite-package-items-'+row+'-item-total-volume-of-package') {
                            $(this).val(volume);
                        }
                        if ($(this).attr('data-drupal-selector') === 'edit-webform-composite-package-items-'+row+'-item-total-volume-of-all-packages') {
                            $(this).val(total_volume);
                        }
                    })
                }
            });
            if (!isNaN(grand_total_weight)) {
                grand_total_weight = (Math.round( grand_total_weight * 100 )/100 ).toFixed(2).replace(".",",");
                grandtotalweight.val(grand_total_weight);
            }
            if (!isNaN(grand_total_volume)) {
                grand_total_volume = (Math.round( grand_total_volume * 100 )/100 ).toFixed(2).replace(".",",");
                grandtotalvolume.val(grand_total_volume);
            }

        }

        /**
         * Build an object from the given input fields
         *
         **/
        function calculateInputs(inputs, totals, grandtotalweight, grandtotalvolume) {
            var resultObj = {};
            resultObj.packageFigures = [];
            var currentPackage = {};
            currentPackage.rowNo = "0";
            inputs.each(function () {
                var a = $(this).attr('data-drupal-selector').split('-');
                var row_number = a[5];
                var input = $(this);
                if (currentPackage.rowNo !== row_number) {
                    if (!$.isEmptyObject(currentPackage)) {
                        resultObj.packageFigures.push(currentPackage);
                        currentPackage = {};
                        currentPackage.rowNo = row_number;
                    }
                }
                switch (input.attr('data-drupal-selector')) {
                    case 'edit-webform-composite-package-items-'+row_number+'-item-number-of-packages':
                        currentPackage.numberOfPackages = parseInt(input.val().replace(/\./g,""));
                        break;
                    case 'edit-webform-composite-package-items-'+row_number+'-item-weight-of-package':
                        currentPackage.weightOfPackage = parseFloat(input.val().replace(",","").replace(/\./g,""));
                        break;
                    case 'edit-webform-composite-package-items-'+row_number+'-item-length-of-package':
                        currentPackage.lengthtOfPackage = parseFloat(input.val().replace(",","").replace(/\./g,""));
                        break;
                    case 'edit-webform-composite-package-items-'+row_number+'-item-width-of-package':
                        currentPackage.widthOfPackage = parseFloat(input.val().replace(",","").replace(/\./g,""));
                        break;
                    case 'edit-webform-composite-package-items-'+row_number+'-item-height-of-package':
                        currentPackage.heightOfPackage = parseFloat(input.val().replace(",","").replace(/\./g,""));
                        break;
                }
            });
            //After iteration is finished push the currentPackage to the resultObj and calculate all Totals
            resultObj.packageFigures.push(currentPackage);
            showTotals(resultObj, totals, grandtotalweight, grandtotalvolume);
        }
    }
};
})(jQuery, Drupal);

```
> 0 votes

---
Tags: 8, webforms
---


# Question
Title: how to prevent javascript from running again when an AJAX form is submitted
I have this code in a javascript file to hide some search filters...

```
$('#views-exposed-form-faceted-search-page .form-type-select').once().hide();

```

The user can toggle the visibility of the filters by clicking on my #advanced-search link...

```
$('#views-exposed-form-faceted-search-page #advanced-search a').once('advanced_search').click(function(){
        $('#views-exposed-form-faceted-search-page .form-type-select').toggle();
});

```

It works, but when the AJAX form is submitted, the hide() function runs again and the .form-type-select elements are hidden. How do I prevent them from being hidden a second time? I only want my code to hide the selects when the page first loads.

# Answer
If Ajax reloads this part you are hiding, the marker `once()` has set is overwritten, also the show/hide status. Then you need a different approach, either submit the show/hide status, so that it can be returned by Ajax, or create a show/hide Ajax form element to have full control over it through Ajax.

If this is outside of the Ajax wrapper you can do this in javascript, but apply the jQuery selectors on `context`:

```
$('#views-exposed-form-faceted-search-page .form-type-select', context).once('search-hide').hide();

```

See https://www.drupal.org/docs/8/api/javascript-api/javascript-api-overview
> 2 votes

---
Tags: 8, javascript, ajax
---


# Question
Title: How are global roles synced with group roles?
How are global roles synced with group roles in the Drupal 8 group module?

I expect that the module would either:

* Create a group roles in each group type for each global role

and/or one of the below:

* Create role assignments for users in the group who have a global role that matches a group role name.
* Assign global roles for users who have a group role in any group where the group role name matches a global role name.

In my testing so far it appears to do none of the above.

The group role sub-module is marked as deprecated and has a note that the functionality is in the core group module. A code review shows that the sub-module is basically empty. Therefore I take it the note is correct. I also see that the group module implements hook\_rebuild and it creates a config entity for each global role.

None of the above expected results are happening however.

# Answer
> 0 votes
The answer turns out to be that the word "sync" is a bit misleading in the context of what group roles does. "Sync" implies some kind or periodic or event based update. There is no periodic change or update to the group or global roles of any user based on their roles at the other level.

The group role feature only allows "Advanced Outsider Permissions" which allows those with global roles to have a certain role in every group of a certain group type. Thanks to @sonfd for mentioning it. I had located this feature as well but didn't recognise it as "sync".

This effectively provides for what I had asked for when I said "Create role assignments for users in the group who have a global role that matches a group role name.". Although it does not provide role assignments it does provide permission assignments.

# Answer
> 2 votes
Take a look at the roles & permissions page for a group (and also group's documentation). By default groups treats all authenticated non-members as outsiders no matter what their role is, but there is an advanced option to define permissions based on their global drupal roles.

---
Tags: 8, group
---


# Question
Title: How do I access the configuration variables present in settings.php through my code?
I want to access the variables present in the settings.php in my custom module. For example, if the settings.php file contains the `$config['test']['uid'] = 'ABC';` line, I want to access the content of `$config['test']['uid']` in a controller.

How can I achieve this?

# Answer
You can only override configuration values in settings.php, you cannot introduce new configuration. So the values you have tried to set there cannot be accessed, unless you happen to have configuration named test.uid. But I suspect that probably does not exist.
> 0 votes

---
Tags: 8, configuration
---


# Question
Title: How do I join across two different databases?
I have two databases, the normal drupal db and another db to another system. I want to join two tables from these two different dbs. I have already set up the second database using information from here, but I don't know how I would go about doing a join across two databases.

Imagine both have a users table, but the second database also has a field called "telephone number". I want to join the two users table on uid, so that telephone number (and other fields) are also included in the result.

Any ideas on how to go about this? Is it even possible?

# Answer
Yes, with caveats that your DB infrastructure config will dictate if you can do this.

While MySQL allows you to do cross DB table joins, the DB user needs privileges to access both DB's to do it. Additionally, Drupal can only use one DB connection to execute a cross DB table join query.

So if you had a connection defined in your `settings.php`, called `my_connection`, and it had access to 2 DBs called `DB1` / `DB2` You could do things like:

```
// Assuming 'my_connection' defined in settings.php has access to DB1 & DB2
$db_key = 'my_connection';
$example_join_query = 'SELECT * FROM `DB1`.users AS u1 LEFT JOIN `DB2`.users AS u2 ON u1.uid = u2.uid';
$connection = \Drupal\Core\Database\Database::getConnection('default', $db_key);
$example_results = $connection->query($example_join_query)->fetchAll();

// Same idea, with dynamic queries
$query = \Drupal::database()->select('`DB1`.users', 'u1')->fields('u1');
$query->join('`DB2`.users', 'u2', 'u1.uid = u2.uid');
$query = $query->fields('u1');
$query = $query->fields('u2');
$example_results = $query->execute()->fetchAll();

```

If your DB infra config is something like 2 isolated hosts, you'll need to take a different approach, like querying data for each DB connection then joining the resulting datasets in PHP code (instead of using a SQL `JOIN`).
> 3 votes

---
Tags: 8, database
---


title: Get paths of all open webforms

text:
# Question
Title: Get paths of all open webforms
I have a project to QA all of our open webforms. We have about two screens (using the default pager) of open webforms.

The simple-but-hard way is to copy each link, but I wonder if there is an easier way. Can I programmatically pull up the path for all open webforms? Or is there a module?

I looked at building a view of webforms, but there was only an option to create a view of webform submissions, not of webforms themselves.

# Answer
> 3 votes
You can do it in a custom module using `entity.query` service

```
$query = $this->entityTypeManager()->getStorage('webform')->getQuery();
$webform_ids = $query->condition('status', 'open')->execute();

$webforms = Webform::loadMultiple($webform_ids);
$webform_urls = [];
foreach($webforms as $webform){
  $webform_urls[] = $webform->toUrl()->setAbsolute()->toString();
}

```

Here is a demo module that uses `entity.query` in a controller to output those path as links with title as the title of each webform.

---
Tags: 8, webforms
---


# Question
Title: Revert back to the previous dev version of a module using composer
Current last dev release of the Field Group module for drupal 8 was out on (29 Mar 2019). However, I need to download the **previous** dev version before the dev version release mentioned above.

The last dev release was out on (29 Mar 2019)

but I need the previous dev version which was out on (10 May 2017)

It is important for me to record this specific dev version in composer.json file so the same dev version of the module will be used on all environments.

How can I do that ?

**Note:** i can use any of Composer, Git or Drush commands.

# Answer
> 2 votes
You have to refer to the dev branch and reference the SHA of the version of dev you want in Composer.

Example:

`composer require drupal/field_group:3.x-dev#COMMITSHA`

This will fetch the dev branch of version 8.x-3.x at this specific commit. To get that commit itself, you’ll have to find it on the git page for the project ( which now goes to GitLab).

I can’t find the exact one you are looking for (I’m on mobile) but here is an example.

https://git.drupalcode.org/project/field\_group/commit/a4bd38698187c30184d5c76fd884be86e2091fe7

So you’d do:

`composer require drupal/field_group:3.x-dev#a4bd3869`

---
Tags: 8, drush, composer
---


# Question
Title: Rules add date variable from webform submission
I have a webform where the user also submits date. I would like to populate a date type field with the submitted date. I tried making variable by "Add variable", but I do not know how to access my webform submission.

# Answer
Later I realised that I need to run a custom php code, so I wrote this, which actually works:

```
// use the submitted time value from the webform and convert it to time, also use it for an end date one year later
$time = strtotime($data['components']['submitted time']['value'][0]);
$time2 = strtotime('+1 year', $time);

//convert to date formats to the format used in these fields
$startdate = date('Y-m-d',$time);
$enddate = date('Y-m-d',$time2);

//update the field values and save the updates
$new_user_request -> field_start['und'][0]['value'] = $startdate;
$new_user_request -> field_end['und'][0]['value'] = $enddate;
user_save($new_user_request);

```

Hopefully this helps someone else too.
> 0 votes

---
Tags: 7, rules, webforms, datetime
---


# Question
Title: Problem in dependency injection in drupal custom module service
I face with a problem in defining service in drupal 8.0 my service is :

```
services:
  tracking.middleware:
    class: Drupal\mkt_tracking_v2\Middleware\TrackingMiddleware
    arguments: ['@kernel','@config.factory','@request_stack']
    tags:
      - {name: http_middleware, priority: 1000}

```

the problem is: the object that passes to TrackingMiddleware aren't based on the arguments definition.

as I get this error :

> Thu Apr 04 01:51:23.919189 2019\] \[php7:notice\] \[pid 28435\] \[client 127.0.0.1:51962\] TypeError: Argument 2 passed to Drupal\mkt\_tracking\_v2\Middleware\TrackingMiddleware::\__construct() must implement interface Drupal\Core\Config\ConfigFactoryInterface, instance of Drupal\Core\DrupalKernel given, called in /home/hossein/Project/Drupal/8.7/web/core/lib/Drupal/Component/DependencyInjection/Container.php on line 274 in /home/hossein/Project/Drupal/8.7/web/modules/Marketing/mkt\_tracking\_v2/src/Middleware/TrackingMiddleware.php on line 41 #0 /home/hossein/Project/Drupal/8.7/web/core/lib/Drupal/Component/DependencyInjection/Container.php(274): Drupal\mkt\_tracking\_v2\Middleware\TrackingMiddleware-\>\__construct(Object(Drupal\Core\StackMiddleware\NegotiationMiddleware), Object(Drupal\Core\DrupalKernel), Object(Drupal\Core\Config\ConfigFactory), Object(Symfony\Component\HttpFoundation\RequestStack))\n#1 /home/hossein/Project/Drupal/8.7/web/core/lib/Drupal/Component/DependencyInjection/Container.php(171): Drupal\Component\DependencyInjection\Container-\>createService(Array, 'tracking.middle...')\n#2 /home/hossein/Project/Drupal/8.7/web/core/lib/Drupal/Component/DependencyInjection/Container.php(480): Drupal\Component\DependencyInjection\Container-\>get('tracking.middle...', 1)\n#3 /home/hossein/Project/Drupal/8.7/web/core/lib/Drupal/Component/DependencyInjection/Container.php(230): Drupal\Component\DependencyInjection\Container-\>resolveServicesAndParameters(Array)\n#4 /home/hossein/Project/Drupal/8.7/web/core/lib/Drupal/Component/DependencyInjection/Container.php(171): Drupal\Component\DependencyInjection\Container-\>createService(Array, 'http\_kernel')\n#5 /home/hossein/Project/Drupal/8.7/web/core/lib/Drupal/Core/DrupalKernel.php(1412): Drupal\Component\DependencyInjection\Container-\>get('http\_kernel')\n#6 /home/hossein/Project/Drupal/8.7/web/core/lib/Drupal/Core/DrupalKernel.php(693): Drupal\Core\DrupalKernel-\>getHttpKernel()\n#7 /home/hossein/Project/Drupal/8.7/web/index.php(19): Drupal\Core\DrupalKernel-\>handle(Object(Symfony\Component\HttpFoundation\Request))\n#8 {main}, referer: http://drupal.local/admin/modules/uninstall but as i define the class in this way the constructor parameters is right :

```
 public function __construct(HttpKernelInterface $app,ConfigFactoryInterface $configFactory,RequestStack $requestStack) {
    $this->app = $app;
    $this->configFactory = $configFactory;
    $this->requestStack = $requestStack;
  }

```

did I do any mistake in service definition?

# Answer
From the looks of the core middleware services, the HTTP kernel is automatically provided to the constructor. You don't have to specify it (and even if you did, `@kernel` is Drupal's kernel, so might not be what you meant).

As an example, `ReverseProxyMiddleware`'s constructor signature:

```
public function __construct(HttpKernelInterface $http_kernel, Settings $settings) {

```

And its services entry:

```
http_middleware.reverse_proxy:
  class: Drupal\Core\StackMiddleware\ReverseProxyMiddleware
  arguments: ['@settings']
  tags:
    - { name: http_middleware, priority: 300 }

```

Note no explicit `@kernel`, yet it's the first constructor argument.

So in theory you just need to change you service definition and clear caches:

```
class: Drupal\mkt_tracking_v2\Middleware\TrackingMiddleware
  arguments: ['@config.factory','@request_stack']
  tags:
    - {name: http_middleware, priority: 1000}

```
> 2 votes

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


# Question
Title: SQL error when adding an other database table
**The Code:**

In my module.install i am declaring my main database table. This works without any problems:

```
function my_module_install() {
  create_initial_roles();
  drupal_set_message("Installed module my_module.");
}

function my_module_schema() {
  $schema['my_module_foo'] = [
    'description' => 'Main table for my_module.',
    'fields' => [
      'id' => [
        'description' => 'The ID of the database entry of foo.',
        'type' => 'serial',
      ],
      // Many more fields ...
    ],
     'primary key' => ['id'],
  ];
  // Second table goes here (see code below).
  return $schema;
}

```

But as soon as i'm adding a second table, i am getting a SQL error:

```
// Inserted in shema function (see comment above).
$schema['my_module_bar'] = [
    'description' => 'Secondary table for my_module.',
    'fields' => [
      'id' => [
        'description' => 'The ID of the database entry of bar.',
        'type' => 'serial',
      ],
      // Possibly more fields.
      'primary key' => ['id'],
    ],
  ];

```

**The Error:**

The error occurs when installing the module:

PDOException: SQLSTATE\[42000\]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARACTER SET utf8 COMMENT 'Main table fo' at line 3: CREATE TABLE {my\_module\_bar} ( `id` INT auto\_increment DEFAULT NULL COMMENT 'The ID of the database entry of the bar.', `primary key` DEFAULT NULL ) ENGINE = InnoDB DEFAULT CHARACTER SET utf8 COMMENT 'Main table for my\_module.'; Array ( ) in db\_create\_table() (line 2776 of C:\xampp\htdocs\drupal\includes\database\database.inc).

It looks like it is a problem with the character set (utf8) but it is a bit weird, that this error does not occur with only my main database table.

# Answer
> 1 votes
You're including the primary key as a field, which won't work. It needs to be on the same level as `fields`:

```
'fields' => [
  'id' => [
    'description' => 'The ID of the database entry of bar.',
    'type' => 'serial',
  ],
],
'primary key' => ['id'],

```

---
Tags: database, installation
---


# Question
Title: Image Styles Not Generating Thumbnails/Previews
I have File Browser installed on my website. The module info can be found here: https://www.drupal.org/project/file\_browser

When I go to browse for pictures, there are no images. You can see what I see below:

Below, you can see "WHY" it is not loading.

It seems to think that the system should have generated thumbnails and it is trying to reference those thumbnails. However, the files have not been created.
`/sites/default/files/styles/file_entity_browser_thumbnail/public/md-slider-image/slide-corporate-3.jpg?itok=O25-iC4D`

My next thought was that maybe the GD manipulation tool was not enabled and the system needed that to generate the thumbnails. I checked using command line and that program is installed.

```
GD Support => enabled
GD headers Version => 2.2.4
GD library Version > => 2.2.4

```

After further review, I went ahead and discovered that the "image style" functionality of Drupal is what is supposed to be generating the images. So, I went and just tried to use the "normal" image style functionality by adding an image field to a node and attempting to apply a style in "display settings." When I did this, it did not work. So, it seems the issue lies with "Image styles."

The most obvious solution would seem to be that I do not have the permissions set correctly.

I went to `/sites/default/files/` and the owner is www-data (apache) and the "octal" is 0777. I also made sure to apply these permissions "recursively" so it would copy down to any sub directories. Nothing seemed to change after doing that. I also am not getting any errors that I can find.

Does anyone have any suggestions on how to fix or where an error might be generated that could point me in the right direction?

# Answer
The solution for the image style issue was to alter the HTACCESS in that folder so it would allow apache to use image files.

I can also confirm that it WILL NOT work if you do not have your apache rewrite module turned on.

**Final note** \- this will work without the octal being "777" as I mentioned in original post.
> 1 votes

# Answer
One of the reasons for this might also be mod\_rewrite not being enabled in apache
> 1 votes

---
Tags: files, media, configuration
---


# Question
Title: How do I create a log/statistics of on page events?
I am using drupal 7, I have seen there are already statistic modules but can't find any for my situation

On my website I am trying to track certain on page activities which site admins can see in a table.

Example of activities are if users engage with certain elements on a page, if certain images load before user leaves, and browser information. Alot of information is only available through JS or Jquery not PHP.

On my site I can build a client side log, so when I go to console I can see the statistics I am looking for, but what is the best way to save this log/statistics to by drupal database.

I was thinking of building a content type called 'page log' with different fields relating to page info I need, which would be loaded on every page and filled/submitted via javascript. But think this would be too resource intensive.

To summarise, I have been building a function in javascript which collects on page activities which currently I can view in my browser console. I am looking for a way to save the log for each page to my drupal site in a way which can be recalled easily. Probably through views.

How can I save this log? Thanks for any help

# Answer
> 0 votes
Since, you've built everything in js, next thing to do is send the data from the client. You could do that with an endpoint in a custom module and sending everything you want there with ajax. From there it depends how often you anticipate db writes from these data and you can assess the next step to take. You could:

* Create a content type and programmatically save data to it.
* Create a custom db table with only the fields you want and implement some db logic to save data.
* Use mongoDB and setup a document table to store these data. This is the best option performance wise. You would need to setup the mongoDB module for it.

---
Tags: 7, javascript, nodes
---


# Question
Title: What is the difference between \Drupal::request()->getSession() and \Drupal::service('user.private_tempstore')?
As the title suggests, I'm a bit confused about those two methods of creating and accessing a session on Drupal 8. I'm not quite sure when to use the one over the other, could someone point me to the right direction?

My issue started after a Drupal update, where originally I was using this way to start a session for anonymous users on my module:

```
$request       = \Drupal::request();
$this->session = $request->getSession();

$session       = $this->session->get('mymodule');

```

After the update, the above code won't create a session for anonymous user and the only way to make it work was this piece of code:

```
$tempstore = \Drupal::service('user.private_tempstore')->get('mymodule_name');
$tempstore->set('my_variable_name', ['test var' => 'this is my value']);

echo '<pre>';
print_r($tempstore->get('my_variable_name'));
echo '</pre>';

```

So, even though I've managed to make it work, I'm not quite sure why it did work that way.

# Answer
> 9 votes
The main difference is that session data is stored in the database table `sessions` and PrivateTempStore in `key_value_expire`. Session data is preloaded in memory, private tempstore data only when requested. Session data is for small amount of data not exceeding a few megabytes, private tempstore for bigger chunks of data you don't want to have in memory when not needed.

What you've posted is not starting a session, it gets a value. You would need to set a value first to start a session.

---
Tags: 8, services, sessions
---


# Question
Title: How can I enable search on parts of a word and autocomplete suggestions?
I'm using Search API in Drupal 8.

I tried with Search API pages and even views, but I didn't find `%like%` function query

Can I do %like% in Search API or Views?

# Answer
> 0 votes
Click in "Edit" this Database server, and navigate to the end of that page:

---
Tags: views, 8, search
---


# Question
Title: Different formatter's field by file extension
I have Drupal 7 and a file field and users can upload pdf, office documents and image. For pdf i have pdf.js formatter, office doc's have simple link to download and image show by fancybox plugin. I am need use different formatters if file have different extension. Thanks.

# Answer
> 0 votes
It work for me =)

`$field_link_file = field_get_items('node', $node, 'field_docs_files');
$file_url = file_create_url($field_link_file[0]['uri']);
$parts = pathinfo($file_url);
$extension = $parts['extension'];
 if ($extension == 'jpg' || $extension == 'png' || $extension == 'tif') {
 $options = array(
 'type' => 'colorbox',
 'label' => 'hidden',
 'settings' => array(
 'colorbox_node_style' => 'large',
 'colorbox_node_style_first' => ''
 )
);
 }
 elseif ($extension == 'pdf') {
 $options = array(
 'type' => 'pdf_default',
 'label' => 'hidden',
 'settings' => array(
 'width' => '100%',
 'height' => '800px'
 )
);
}
 else {
 $options = array(
 'type' => 'text',
 'label' => 'hidden',
 'settings' => array(
 'width' => '100%',
 'height' => '800px'
 )
);
 }
 $field_view_files = field_view_field('node', $node, 'field_docs_files', $options);
 print render($field_view_files);`

---
Tags: theming, nodes
---


# Question
Title: Create Text Field Programmatically to Media Type
I want to create a text field to videos with code. I have the following in the .install file in a custom module:

```
function video_update_8101() {
  $field_name = 'field_video_alternative_text';
  // Make sure the field doesn't already exist.
  if (!FieldStorageConfig::loadByName('file', $field_name)) {
    // Create the field.
    $field = FieldStorageConfig::create(array(
      'field_name' => $field_name,
      'type' => 'text',
      'settings' => array('max_length' => 64),
    ));
    $field->save();

    // Create the instance.
    $instance = FieldStorageConfig::create(array(
      'field_name' => $field_name,
      'entity_type' => 'file',
      'bundle' => 'video',
      'label' => 'Alternative tekst',
      'description' => 'En beskrivelse kommer her.',
      'required' => TRUE,
    ));
    $instance->save();
  }
}

```

I get the following when running update.php

```
Attempt to create a field storage field_video_alternative_text with no entity_type.                                                                                [error]
Performing emu_video_update_8101                                                                                [ok]
Failed: Attempt to create a field storage field_video_alternative_text with no entity_type.

```

Furthermore, I want this to happen when I install the module. I suppose it's not at this point?

Edit: I got inspiration from this post: How do programmatically create fields for content types, and ADD them to the the content type form

# Answer
In Drupal 7 fields were shared across all content types; in Drupal 8 they're shared across a single entity type.

As such you've just missed the `entity_type` when creating the storage:

```
$field = FieldStorageConfig::create(array(
  'entity_type' => 'file',
  'field_name' => $field_name,
  'type' => 'text',
  'settings' => array('max_length' => 64),
));

```

As an aside, `hook_update_N` is for updates only, those functions won't be executed upon install. The point of them is to allow older versions of the module to get up to date with the current version that they're upgrading to. The initial state of the latest version of the module should reflect the state the older version of the module would be in after the update.

You can use `hook_install` or config files in config/install/\*.yml to perform initial setup of your module upon install.
> 1 votes

---
Tags: 8
---


# Question
Title: Adding fields to user registration form for admins
I use the Entity Registration module and I created a registration form for specific events in a Drupal 7 site. For the registered users, the fields are name, surname, birth date, upload administrative files etc.

Is there a way for administrators to have specific fields they can fill and that are not available to registered users?

# Answer
You could use `hook_form_alter` to accomplish this

```
yourmodule_regform_alter($form, $form_state) {
    global $user;
    if($user->uid!=<whatever>) {
        unset($form['field_attended'];
    }
}

```

If you want to use permissions, you could create your own with `hook_permission`

```
function administer_attendee_permission() {
    return array('set attendee status' => array(
      'title' => t('Set status for event attendees'),
      'description' => t('Set the status for event attendees'),
     );
}

```

Then your form alter changes to

```
yourmodule_regform_alter($form, $form_state) {
    if(!user_access('set attendee status') {
        unset($form['field_attended'];
    }
}

```
> 0 votes

---
Tags: 7, entities
---


# Question
Title: Disabling Page Cache for Redirect Response
I've implemented a conditional redirect on my site via an event subscriber and returning a redirect response. It's working but, I believe due to the `page_cache` module is getting cached for anonymous users.

This is basically what I'm using to set the redirect response:

```
public function checkRedirectStatus(GetResponseEvent $event) {
    if(shouldIRedirect()) {
        $response = new RedirectResponse('/redirect/path');
        $event->setResponse($response);
     }
}

```

The above gets cached whether or not it returns true unless I add `\Drupal::service('page_cache_kill_switch')->trigger();`.

As this is a fairly high-traffic page I'm concerned about bypassing cache for anonymous users. Are there other options I'm not aware of?

If this is on the `REQUEST` kernel event, how far-reaching is `page_cache_kill_switch`?

Thanks for your help!

# Answer
> 11 votes
This doesn't exactly answer your question, but I feel it's relevant information. I did something similar, but I also didn't like using the kill switch. In another iteration I used a TrustedRedirectResponse which allowed me to handle my cache issue differently. My understanding is this is forcing browsers to always bypass cache when executing the redirect, but the redirect itself is cached by Drupal until $entity's (my cache dependency) cache is invalidated.

```
$response_headers = [
  'Cache-Control' => 'no-cache, no-store, must-revalidate',
];

$response = new TrustedRedirectResponse($url, '302', $response_headers);
// In my case $entity is a content entity where my redirect $url is generated.
// In your case you'd add cache dependencies relevant to determining shouldIRedirect().
$response->addCacheableDependency($entity);
$event->setResponse($response);

```

---
Tags: 8, redirection
---


# Question
Title: Javascript is not loading in Zen custom theme
I'm not able to get my custom theme to run javascript on all pages. My code is as follows. My Custom module is enabled, and Component Libraries module is installed and enabled.

### custom\_theme.Libraries.yml

```
scripts:
  # If this library had JavaScript you could specify it like this:
  js:
    js/script.js: {}
  dependencies:
    - core/jquery

global-scripts:
  version: 1.x
  js:
    js/script.js: {}

```

### custom\_theme.info.yml

```
    libraries:
  - custom_theme/base
  # @TODO Remove these libraries and use attach_library() for all component styles.
  - custom_theme/scripts
  - custom_theme/global-scripts
  - custom_theme/box
  - custom_theme/comment
  - custom_theme/header
  - custom_theme/hidden
  - custom_theme/inline-links
  - custom_theme/inline-sibling
  - custom_theme/print-none
  - custom_theme/responsive-video
  - custom_theme/wireframe
  - custom_theme/autocomplete
  - custom_theme/collapsible-fieldset
  - custom_theme/form-item
  - custom_theme/form-table
  - custom_theme/progress-bar
  - custom_theme/progress-throbber
  - custom_theme/resizable-textarea
  - custom_theme/table-drag
  - custom_theme/nav-menu
  - custom_theme/navbar
  - custom_theme/pager

```

### script.js

```
/**
 * @file
 * A JavaScript file for the theme.
 *
 * In order for this JavaScript to be loaded on pages, see the instructions in
 * the README.txt next to this file.
 */

(function (Drupal) {

  'use strict';

  Drupal.behaviors.my_custom_behavior = {
    attach: function (context, settings) {

      console.log("Hello World");

    }
  };
})(Drupal);

```

# Answer
> 0 votes
The script.js started working after I *cleared all caches*.

If you're having this problem and followed Drupal's official documentation then login to your Drupal site as admin and In Performance section click **clear all caches**

navigate to: Home \>\> Administration \>\> Configuration \>\> Development

---
Tags: theming
---


# Question
Title: What's the best way to add an alert box to a link in D7
I have a link, which is rendered via the l function. It's a link which calls a function that deletes a node. Before the function is called, I want an alert box to pop up and give the user the option to 'Cancel' or 'Confirm'. Adding this as an argument to the l function works:

```
array('attributes' => array('onclick' => 'return confirm("Are you sure?")'))

```

...but is there an existing function, or something, that does a nicer job?

I'd rather not add a contrib module for such a small task.

# Answer
no there is no js related function in drupal 7 that provides a functionality like that. just make sure that custom setup you have there is in your template.php
> 1 votes

# Answer
There are no built-in functions for client-side JS UI confirmation prompts.

If you're want to rely on just Drupal core for node deletion prompts you can use the built-in deletion forms (assuming the user has permissions to access it) and use the `destination` query parameter to redirect the user back to where they need to be:

```
$nid = 123;
$return_path = 'admin';
l(t('Remove Node'), 'node/' . $nid . '/delete', ['query' => ['destination' => $return_path]]);

```
> 0 votes

---
Tags: navigation
---


# Question
Title: Set site URI for drush uli without 'default'
Versions discussed: Drupal 8.6.13, Drush 9.6.1.

This is somewhat similar to How to have an environment specific drush.yml? except that the other thread is now four or five months out-of-date and Drush 9.6.1 doesn't seem to respect the `drush.yml` anymore.

I'm just trying to set my Site URI.

As detailed in that thread, I've tried `web/sites/default/drush.yml` as well as many other locations for the `drush.yml`, done a `drush cc drush`, and yet `drush status` still reveals an incorrect Site URI of `http://default`, showing that it is not respecting the `uri:` line in any of my `drush.yml` files.

To complicate matters, I'm using DDEV, so following up on some suggestions that I've gotten from the Drupal Slack that we should really be using an environment variable (namely `DRUSH_OPTIONS_URI`) have proven tricky, as I'm not exactly sure where that goes inside of the DDEV environment.

Inside the DDEV container, if I do `export DRUSH_OPTIONS_URI=http://my.ddev.local/` then everything works great, but once I quit the container or try to do things from outside it, such as `ddev exec drush uli`, things are back to the incorrect Site URI.

How can I persist this environment variable across restarts of DDEV/Docker?

# Answer
I'm writing this up for posterity, since the Slack is relatively ephemeral. Here's the current method, following Providing custom environment variables to a container:

In e.g. `.ddev/docker-compose.environment.yml` put the following:

```
version: '3.6'

services:
  web:
    environment:
      - DRUSH_OPTIONS_URI=http://my.ddev.local

```

Then `ddev rm` and `ddev start` to prove to see it working. (This works for `drush uli` inside the container, after `ddev ssh`.)
> 6 votes

---
Tags: 8, drush
---


# Question
Title: Print Preprocessed username Field Value in User Template
$account-\>getDisplayName() Bypasses "username" Field Preprocessing in User Template?

I am trying to print the value of the `username` field of the user account in a `user--custom.html.twig` file.

**MYMODULE.module**:

```
function hook_preprocess_user(&$variables) {
  $account = $variables['elements']['#user'];
  $variables['userName'] = $account->getDisplayName();
}

```

**user--custom.html.twig**:

```
{{ user.name.0.value }}

```

Both the above examples access the username, but seem to access the value directly and circumvent any preprocessing of the `username` field (e.g. `hook_preprocess_username()`), so it looks like I need a different approach.

I have a view that shows the "User" entity so does not use fields and relies on the user template. What am I missing when trying to get the processed value of the username field, instead of the user name DB value for the account?

Related: Get username in custom user twig template but different.

In my template, I am rendering `content.user_picture` and trying to render `username`. So maybe I need to load the user instead of both fields? Looking for the processed `username` field value.

# Answer
> 0 votes
You're probably looking for the `username` theme:

```
$variables['userName'] = [
  '#theme' => 'username',
  '#account' => $account,
];

```

---
Tags: 8, theming, users
---


# Question
Title: How can I increase the number of excerpts shown per result?
I have approximately 300 book-sized documents (50k up to 300k words each) that I'm trying to make searchable. **I would like to display as many excerpts from each result as possible up to a maximum number.**

It appears that excerpts are handled by **Solr's highlighters**, but there doesn't appear to be any parameters I can change to force it to show me more. The closest I've found is this:

> **hl.snippets** \- Specifies maximum number of highlighted snippets to generate per field. It is possible for any number of snippets from zero to this value to be generated. The default is 1.

but it seems to have no effect on the results returned. I've increased this to 50, along with increasing **maxAnalyzedChars** and **fragsize** to no avail.

EDIT: If I add hl.snippets=50 in a manually composed query it performs as expected - for some reason search\_api\_solr isn't applying the setting, it always returns 2 snippets. I've also noticed that it's not respecting my search:excerpt view settings.

Will keep updating as I persist.

I've been at this for nearly a week now and am about to start looking at other solutions. Hopefully I'm just being dense - any help is appreciated!

---

*A little more background: I am loading up a database with several hundred manuals, from small to phone-book sized. I need the user to be able to:*

1. *search the entire database using keywords and facets. The results must feature many large snippets which can be skimmed to determine which document is the correct one for their purpose*
2. *Then they need to perform a second search within that document only, which they will refine until they find exactly what the need from it.*

**So I need the ability to display lots of verbose snippets and any extra control I can have over how they are generated would be a huge boon.**

Thank you :)

\[Update\]

I've added

```
<str name="hl">on</str>
<str name="hl.fl">fieldname</str>
<str name="hl.snippets">20</str>

```

to solrconfig.xml and confirmed that it does cause solr to return the specified number of snippets, but I still can't figure out how to get search\_api\_solr do the same. It appears that no matter the settings I apply in the search index or search server, the module still insists on returning 3 or less snippets and generating them via search\_api's highlight.php.

\[Update\] There is a setting in: Configuration -\> Search API -\> Search Server -\> EDIT -\> Advanced: "Retrieve result data from Solr" and "Retrieve highlighted snippets" that sounds like it makes drupal use solr's response instead of creating it via php but it appears to have no effect.

\[Update\] Ok, so now I guess I am going to attempt to create a simple module that uses hooks to modify the query and override the appropriate parameters, then hope that the results get processed properly.

\[Update\] Used devel and determined that Solr is returning the correct number of snippets according to my changed seettings in solrconfig.xml, so it's just a matter of getting drupal to take them and display them. I guess this means either hooking into highlight.php somewhere or just trying to hijack the query and write my own processor/template logic for it. Will share whatever solution I find. Tried to open an issue on drupal.org but it got flagged as spam. Oh bother :)

\[Update\] I am officially giving up. In order for drupal to work with the snippits that solr returns, "Retrieve result data from Solr" and "Retrieve highlighted snippets" must be enabled. When they are enabled however, Drupal asks Solr to send every field used for snippets for each result - in my case these fields are huge so this destroys performance. When those options are not enabled, Solr returns just the result data and highlights, but I cannot work with them because highlight.php generates it's own snippets from scratch. Oh well. My apologies to anyone who makes it here looking for a solution - and good luck!

# Answer
\[Update\] Figured it out.Here's the solution I found. Somebody much more experienced than I will probably come along and offer better ideas but this works for now.

Leave "Retrieve result data from Solr" and "Retrieve highlighted snippets" unchecked, and just edit solrconfig.xml to define your snippets parameters like so:

```
<str name="hl">on</str>
<str name="hl.fl">fieldname</str>
<str name="hl.snippets">20</str>

```

Now solr will return the specified snippets in the results even if Drupal doesn't do anything with them. I cobbled together a simple module that implements hook\_search\_api\_solr\_search\_results\_alter (found in search\_api\_solr.api.php) to grab the results and store them in the $\_SESSION variable:

excerpted from the solr\_snippets.module I Frankensteined together:

```
function solr_snippets_search_api_solr_search_results_alter(\Drupal\search_api\Query\ResultSetInterface $result_set, \Drupal\search_api\Query\QueryInterface $query, \Solarium\QueryType\Select\Result\Result $result) {

    if(!isset($_SESSION['solr_snippets'])) {
        $_SESSION['solr_snippets'] = array();
        }
    $myResults = & $_SESSION['solr_snippets'];
    $myResults = '';
    // Grab the result items
    $result_items = $result_set->getResultItems();
    // Grab the highlighted snippets
    $extra_data = $result_set->getExtraData('search_api_solr_response');
    $highlights = $extra_data['highlighting'];
    [ process the results here and load them back into $myResults ]
    }

```

Then they are picked up by a view field:

```
  public function render(ResultRow $values) {

    return [
        $build['search_results'] = [
           '#theme' => 'solr_snippets',
           '#results' => $_SESSION['solr_snippets'],
          ],
        ];
  }

```

I also had to find a way to get the row count to the field template since it doesn't appear to be passed automatically. I didn't find the right way, but the method that worked for me was to implement hook\_preprocess\_views\_view\_field() and add it to the session variable:

```
function solr_snippets_preprocess_views_view_field(&$variables) {
    $_SESSION['solr_snippets']['rowNum'] = $variables['row']->index;

}

```

That's it, works great and I can use the twig template to customize the SERP results. Credit to https://drupalium.com/articles/creating-custom-view-fields-programmatically for the basic module that I hacked apart to make this. Also Drupalize.me was a Godsend.

Just to reiterate to anyone looking to do the same - what I did here was definitely not "best practice." Be careful and good luck!
> 1 votes

---
Tags: search
---


# Question
Title: View by Taxonomy terms hide empty terms unless they have children
I am trying to get my views block to display terms under this parent term but only show the terms with nodes in them. I managed to get this to work by using the relationship content with term and requiring the relationship. However we have terms with children that are empty but the children are not empty. I want it to display the term(without showing the children)

How do I make my views block display terms under parent term, remove the empty terms but show the empty terms with children?

# Answer
> 1 votes
Your friend is:

> Taxonomy term: Representative node

This is a duplicate, by the way.

# Answer
> 0 votes
Problems with views relationships and results can often be solved by reversing the order in which you construct (or think about) your relationships. Instead of making the parent term the central item of your view, do the following:

1. Create a taxonomy term view.
2. Add a required relationship to your term reference field.
3. Add a contextual filter for the parent term.

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


# Question
Title: If you update a routes file in Drupal 8 how do you clear the cache?
Having worked with Drupal 7 since its launch, I'm learning Drupal 8. At the moment I'm finding that whenever I change anything I have to do `drush cache-rebuild` to get things working again.

On my VPS this takes 15 seconds (and then the next page load also is slow). I have a feeling this may be a sledge hammer to crack a nut situation.

Is there a more efficient way to get Drupal to recompile the (changed) routes from `{module}.routing.yml` files?

# Answer
> 31 votes
You can use

```
drush ev '\Drupal::service("router.builder")->rebuild();'

```

to rebuild the routing information without clearing all the caches.

# Answer
> 9 votes
An alternative to drush is drupal console, which you can then use as:

```
drupal router:rebuild

```

Which is a little less typing than the `drush ev` answer (and a tinsy bit faster, too).

To install drupal console

```
curl -LSs http://drupalconsole.com/installer | php
mv console.phar /path/to/a/suitable/bin/drupal

```

# Answer
> 9 votes
```
drush cc router

```

when using drush 9 do the trick now :-)

---
Tags: caching, 8, routes
---


# Question
Title: Drupal Search Result Sorting in Desc order
I am trying to change my Drupal site's search results. Currently it's showing the default search results by node "Updated or Changed" but i want to change it to node "Created or Published" into Descending ORDER. So all the search results will be ORDER BY CREATED or PUBLISHED. I have looked at many files but couldn't have any success.

Which files do i have to modify and what code?

Any help will be really appreciated.

Thanks!

# Answer
Similar questions here

Use hook\_preprocess\_search\_results and set your criteria there.

Here's the .module file you can use, this sort nodes by their creation time with a descending order. You need to create a .info file to make the module work, also remember to replace \[MODULE\_NAME\] with your own module's name. This is not perfect but at least gives you the data in the order you want.

```
<?php
/**
 * Implement hook_preprocess_search_results()
 */
function [MODULE_NAME]_preprocess_search_results(&$vars) {
        $results = $vars['results'];// via dsm (Devel module), we can see node creation time is available under the 'results' array
        usort($results, function($v1, $v2) {
          return $v2['node']->created - $v1['node']->created; // sort by created time, DESC order
        });
        $value = '';
        $output = '';
        $output_results = array();
        foreach($results as $item) {
          $value .= theme('search_result', array('result' => $item, 'module' => $vars['module']));
          $output_results[] = $value;
          $value = '';
        } // store all results into an array
        #dsm($output_results);
        $output = implode(" ", $output_results)."<br>"; // convert array to string
        $vars['search_results'] = $output;
        #dsm($vars);
}

```

.info file:

```
name = Search Desc
description = sort default search by creation date in DESC order
core = 7.x

```

search.tpl.php file, you need to copy this file from modules/search/search-result.tpl.php and put it under your theme dir, do not modify the original.

```
<?php
$info_split['date'] = date('m/d/Y - H:i', $result['node']->created);// replace update time with created time
?>
<li class="<?php print $classes; ?>"<?php print $attributes; ?>>
  <?php print render($title_prefix); ?>
  <h3 class="title"<?php print $title_attributes; ?>>
    <a href="<?php print $url; ?>"><?php print $title; ?></a>
  </h3>
  <?php print render($title_suffix); ?>
  <div class="search-snippet-info">
    <?php if ($snippet): ?>
      <p class="search-snippet"<?php print $content_attributes; ?>><?php print $snippet; ?></p>
    <?php endif; ?>
    <?php if ($info_split): ?>
      <p class="search-info"><?php print $info_split['user'].' '.$info_split['date']; ?></p>
    <?php endif; ?>
  </div>
</li>

```

**Update:** Given Drupal's default search ranking criteria (by content relevance), an additional hook is needed inside the .module file for OP's question. After adding this, you need to go to /admin/config/search/settings and set the Influence for the 'Node Creation Date' field at the bottom of the page, re-index, and run cron.

```
/**
 * Implement hook_ranking()
 */
function [MODULE_NAME]_ranking() {
  return array(
    'node_created_date' => array(
      'title' => t('Node Creation Date'),
      'score' => 'n.created',
    ),
  );
}

```
> 0 votes

# Answer
As an alternative to the hook\_preprocess\_search\_results solution you could also use the search\_api in combination with the views module as it will allow you to customize your search results much easier.

* Download search\_api search\_api\_db entity views ctools
* Enable Search API, Search views, Database search, Entity API, Views,Views UI,Ctools
* Go to *admin/config/search/search\_api/add\_server* fill in some server name and choose Database service as Service class
* Go to *admin/config/search/search\_api/index/default\_node\_index* and press **Queue all items** for reindexing and then **Index now**
* Enable highlighting at *admin/config/search/search\_api/index/default\_node\_index/workflow*
* Reindex again
* Create a page view of **Default Node Index** \- Create a page - display format: **unformatted list** of **Rendered Entity**
* Add a sort filter of **Indexed Node: Date created (desc)**

**Credits:**
https://www.webwash.net/intro-to-search-api-part-1-how-to-create-search-pages/
> 0 votes

# Answer
I have achieved sorting by creation date by using the **hook\_query\_alter** function in a custom module. Following blog post let me in the correct direction.

```
<?php
**
 * Implements hook_query_alter().
 *
 * @param QueryAlterableInterface $query
 */
function MY_CUSTOM_MODULE_query_alter(QueryAlterableInterface $query) {
 // Alter the core node search query to sort by creation date.
 $is_search = $is_node_search = FALSE;
 $node_alias = FALSE;
 foreach ($query->getTables() as $table) {
   if ($table['table'] == 'search_index') {
     $is_search = TRUE;
   }
   if ($table['table'] == 'node') {
     $node_alias = $table['alias'];
     $is_node_search = TRUE;
   }
 }

 if ($is_search && $is_node_search) {
   $query->orderBy('created', 'DESC');
 }
}

```
> 0 votes

---
Tags: search
---


title: Modify existing custom content form

text:
# Question
Title: Modify existing custom content form
I'm very new to Drupal development and I am completely stuck(.

I have a custom content form, where I need to hide some fields in Inline Entity Form. I am trying to write my own custom module to achieve this, I am doing the following: 1. I create module folder, where I put info.yml file 2. I create Controller file, where I add custom class and this code inside this class:

```
public function MY_MODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {if ($form_id == 'MY_FORM') {...};

```
3. The next thing I am completely stuck at is do I need a routing file to make this work? I can't find any info about this so I'd really appreciate some help! And if I need routing, what should I write there?

# Answer
> 1 votes
Thank you very much! I really didn't need routing!

Well, finally I found the solution to my problem - I created the module with 2 files only - mymodule.info.yml and mymodule.module. In .module file I only added these lines of code and everything worked! (Almost)

```
function mymodule_inline_entity_form_entity_form_alter(&$entity_form, &$form_state) {
if ($entity_form['#entity_type'] == 'node' && $entity_form['#bundle'] == 'my_custom_content_type_machine_name') {
  unset($entity_form['field_I_need_to_hide']);
}}

```

---
Tags: forms, hooks
---


# Question
Title: Add custom ajax command to ajax response after webform is submitted
What I'm trying to do is to invoke some javascript after a webform is successfully submitted by ajax.

To do that I followed this advice and created an EventSubscriber to intercept ajax response and add my custom command there. The problem is that on some reason I can't check if the webform is submitted (data are sent) or not.

```
  public function onResponse(FilterResponseEvent $event) {
    if($event->getResponse() instanceof WebformSubmissionAjaxResponse &&
       $event->getResponse()->getWebformSubmission()->isCompleted()) {
         $event->getResponse()->addCommand(new MyCustomCommand());
    }
  }

```

The problem is in **isCompleted()** method which always returns false on some reason. Actually I checked other methods from WebformSubmissionInterface and in this my event subscriber this WebformSubmission entity always looks empty (getters return nothing) and geState() always returns "STATE\_UNSAVED" not depending if a webform is successfully sent of failed on validation.

What I'm missing? Is anything I'm doing wrong here? Or maybe are there any other method to achive same goal?

# Answer
I had this same issue, what worked for me was under webform settings \> Confirmation \> Confirmation Type. Change the confirmation type to 'Inline (reloads the current page and replaces the webform with the confirmation message)'

This returned true for `$event->getResponse()->getWebformSubmission()->isCompleted()`
> 0 votes

---
Tags: 8, ajax, webforms
---