title: How do I disable a module?

text:
# Question
Title: How do I disable a module?
I am trying to disable modules in Drupal 8, and I found some solution like Drupal console, but I am not sure how to use it with XAMPP.

I am unable to understand how I can disable a Drupal 8 module. With Drupal 7, that was possible directly from the user interface, but in Drupal 8 the checkboxes shown before the module name are disabled.

>

How do I disable a module in Drupal 8?

# Answer
In Drupal 8, you cannot anymore disable modules: You can just install or uninstall them. Uninstalling a module has the same effect it had on Drupal 7 and previous versions: It removes the database tables the module installed.

On /admin/modules, Drupal shows you which modules are not installed, and which modules are installed. You can click the checkbox shown for the modules that aren't installed; clicking on *Install* at the bottom of the page will install them.

>

For installed modules, clicking on the checkbox shown before the module name doesn't have any effect. In fact, the checkbox is disabled.

To uninstall a module from the user interface, you just go to /admin/modules/uninstall (or click on the *Uninstall* tab visible on /admin/modules).

>

>

Select the modules you want to uninstall, and click on the *Uninstall* button shown on the bottom of the page.

Keep in mind that Drupal can still not being able to uninstall a module for various reasons, for example because the module implements an entity and you created those entities on the site.

You could also use Drupal Console for uninstalling a module, but you would need to install it (on the server). After you install it, and open a terminal window on the Drupal root directory of the site, with `drupal module:uninstall <module_name>` you would uninstall the `<module_name>` module.

From the user interface it's easier. It's the only possible way, if you are working on a remote site for which the provider doesn't allow you to use an SSH shell.
> 7 votes

# Answer
We can't disable modules in D8 so you can just uninstall them :

I recommend to use drush :

```
drush pm-uninstall [your_module_name]

```
> 2 votes

# Answer
You need to type the command and you need change `sites/defulft/settings.php` `$databases` conect host `localhost` to `127.0.0.1`

**Disable module**

```
./vendor/bin/drupal mou module_name

```

**Enable module**

```
./vendor/bin/drupal moi module_name

```

**List all**

```
./vendor/bin/drupal list

```
> 0 votes

---
Tags: 8, console
---


# Question
Title: drupal_set_message doesn't display message sometimes
I'm uploading a file, to process and display a message at the end. However, the messages that drupal\_set\_message is set to display are displayed sometimes and don't display sometimes, even, if the processing runs successfully in the background. The reload time restriction isn't a problem as it is set to multiple minutes and the processing hardly takes 10-60 seconds on average. Is there a way to force the page to show the messages at any cost? The drupal\_set\_messages that I am concerned about are the last two drupal\_set\_messages in the code. I've even tried using drupal\_set\_message(t('!shell\_c', array('!shell\_c'=\>$shell\_command)), 'status'); but the issue persists where the drupal\_set\_message messages are shown sometimes and not shown sometimes, rather erratically.

```
//Before this part of the code, there is function to create Menu ($items[])
function g_p_proc_form($form, &$form_state, $values) {
    $form['#attributes']['enctype'] = 'multipart/form-data';
    $form['filter'] = array (
        "#type" => "fieldset",
        "#title" => t("File Process <BR> "),
        "#collapsible" => TRUE,
    );
  // without this attribute, upload may fail on submit
    $form['#attributes']['enctype'] = 'multipart/form-data';
    $form['filter']['file'] = array(
        // '#title' => t('File processing'),
        '#type'  => 'file',
        '#name' => 'files[]',
        '#description' => t('Select Submit to start processing the file'),
        '#type'  => 'file'),
        '#upload_location' => 'public://',
        '#attributes' => array('multiple' => 'multiple'),
    );
    // echo '<script type="text/javascript">Drupal.behaviors.DSU_batch_report;</script>'; //christ
    if (isset($_SERVER['CONTENT_LENGTH']) && (int) $_SERVER['CONTENT_LENGTH'] > 'size based on my requirements') {
        drupal_set_message(t(" Warning message on file size"));));
        // unset($_SERVER['CONTENT_LENGTH']);
    }

    $form['filter']['submit_upload'] = array(
        '#type'  =>  'submit',
        '#value' =>  t('Submit'),

    );

    // drupal_set_message(t("in fn"));

    return $form;
}

function g_p_proc_form_submit($form, &$form_state) {
    header(current page)
    try{
        $number_file = count($_FILES['files']['name']);
        $f_name = array();
        for ($i=0; $i<$number_file;$i++)
        {
            $file = file_save_upload($i, array('file_validate_extensions' => array('pdf PDF')), 'public://', FILE_EXISTS_REPLACE);
            $f_name[] = $_FILES['files']['name'][$i]; //[]
        }
            }catch (Exception $error){
        echo 'Exception: ',  $error->getMessage(), "\n";
    }
    $n_f = count($f_name);
    drupal_set_message(t('Number of files to process: !n_f', array('!number_f'=>$n_f)));
    $fn_name = 'g_p';
    $fn_call = $fn_name($f_name);
function g_p($f_name=array()){
    $curr_l = getcwd();
    chdir('My file processing PHP script location ');
    $n_f = count($f_name);
    $shell_command = shell_exec("file_processing_php_script_name.php");
    //header("Location: "Current file processing module menu site"); //Commented out
    drupal_set_message($shell_command); //print_r statements from the file_processing_php_script_name.php
    chdir($curr_l);
}

```

# Answer
> 0 votes
It sounds like you need to maintain a stable message storage solution until the operation is complete.

The D7 core message functions `drupal_set_message()` & `drupal_get_messages()` (the core function used when retrieving messages for rendering) are pushing/popping messages to session var, `$_SESSION['messages']` These messages are designed around a single page request/received operation.

If there many different async requests going on with the same session (or other modules calling `drupal_get_messages()` with its default options), its likely `$_SESSION['messages']` is being cleared out before rendering when you need it.

Try storing your messages somewhere else (e.g. another session variable) then call `drupal_set_message()` with your messages once the full operation is complete. If most messages are background ops, you should use consider `watchdog()` for logging background ops and then use `drupal_set_message()` for a "operation complete" message.

---
Tags: 7, forms, status-messages
---


# Question
Title: turn off wysiwyg for full html filter format?
How do i set it so that the wysiwyg doesn't turn on during full html mode.

I would prefer to hand edit the html during full html filter mode without the wysiwyg editor stripping my html.

I'm using CKEditor.

# Answer
> 1 votes
You can switch to HTML display in D8 by clicking on source tab. So that you can retain Full HTML processing and work without output.

# Answer
> 0 votes
Set your input format to 'Full HTML', edit away, and save. When you come back to the page, it will be in 'Full HTML' format. If, however, you switch it back to Wysiwyg, you will lose your html formatting. Don't switch it back.

# Answer
> 0 votes
You simply can navigate to `admin/config/content/ckeditor` there you can see different profiles, there are to profiles which are added by ckeditor called "Advanced" and "Full". The full profile is the one used when you switch to "Full HTML" you can delete this profile or if you want to keep it, then you can edit it and uncheck "Full HTML" from its list.

in this case when you switch to Full HTML the ckeditor won't show up any more.

---
Tags: 7, wysiwyg
---


# Question
Title: How do I get the current taxonomy term from the plug-in context?
When on a node, the following annotation will obtain the node from the context:

```
/**
 * @Condition(
 *   id = "node_type",
 *   label = @Translation("Node Bundle"),
 *   context = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("Node"))
 *   }
 * )
 */

```

As shown here: https://www.drupal.org/docs/8/api/plugin-api/plugin-contexts

Is there an equivalent way to do this with taxonomy terms when on /taxonomy/term/%?

The code below certainly works but I'm wondering if there is a cleaner method like for nodes. Note that I'm also aware of the `Term::load($tid)` method but that still requires parsing the URL to obtain the tid and isn't portable (the code can be used only when run on a page).

```
  /**
   * Return current term.
   */
  public function getCurrentTerm() {
    $term = null;

    // Below we are using the general method to obtain the objects.
    // \Drupal\taxonomy\Entity\Term::load($tid) is the other

    // Get the unaliased path in the form /taxonomy/term/tid.
    $current_path = \Drupal::service('path.current')->getPath();

    preg_match('/\/taxonomy\/term\/\d+/', $current_path, $matches);

    // Return null if not in proper form.
    if (count($matches)) {
      // Find the parameters for this route.
      $params = \Drupal\Core\Url::fromUri("internal:" . $current_path)
        ->getRouteParameters();

      // Fetch the taxonomy object.
      $entity_type = key($params);
      $term = \Drupal::entityTypeManager()
        ->getStorage($entity_type)
        ->load($params[$entity_type]);
    }

    return $term;
  }
}

```

# Answer
**Update 10.05.2019:**

There is an unresolved issue about that on drupal.org: Term route context.

It uses the same solution as in my answer below.

**Original answer:**

You can create a custom context provider "Taxonomy term from URL".

service definition in `MYMODULE.services.yml`:

```
  MYMODULE.taxonomy_term_context:
    class: Drupal\MYMODULE\ContextProvider\TaxonomyTermContext
    arguments: ['@current_route_match']
    tags:
      - { name: 'context_provider' }

```

The /src/ContextProvider/TaxonomyTermContext.php

```
<?php

namespace Drupal\MYMODULE\ContextProvider;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Plugin\Context\Context;
use Drupal\Core\Plugin\Context\ContextDefinition;
use Drupal\Core\Plugin\Context\ContextProviderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * Sets the current taxonomy term as a context on taxonomy term routes.
 */
class TaxonomyTermContext implements ContextProviderInterface {

  use StringTranslationTrait;

  /**
   * The route match object.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * Constructs a new object.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The route match object.
   */
  public function __construct(RouteMatchInterface $route_match) {
    $this->routeMatch = $route_match;
  }

  /**
   * {@inheritdoc}
   */
  public function getRuntimeContexts(array $unqualified_context_ids) {
    $result = [];
    $context_definition = new ContextDefinition('entity:taxonomy_term', $this->t('Taxonomy term from URL'));
    $value = NULL;
    if (
      ($route_object = $this->routeMatch->getRouteObject())
      && ($route_contexts = $route_object->getOption('parameters'))
      && isset($route_contexts['taxonomy_term'])
    ) {
      if ($term = $this->routeMatch->getParameter('taxonomy_term')) {
        $value = $term;
      }
    }

    $cacheability = new CacheableMetadata();
    $cacheability->setCacheContexts(['route']);

    $context = new Context($context_definition, $value);
    $context->addCacheableDependency($cacheability);
    $result['taxonomy_term'] = $context;

    return $result;
  }

  /**
   * {@inheritdoc}
   */
  public function getAvailableContexts() {
    $context = new Context(new ContextDefinition('entity:taxonomy_term', $this->t('Taxonomy term from URL')));
    return ['taxonomy_term' => $context];
  }

}

```

The ctools module provides already the condition plugin for entity bundles:`ctools/src/Plugin/Condition/EntityBundle.php`. You can use it together with the new service.

See also config block visibility by vocabulary, but it not show block access fail(miss context).
> 1 votes

# Answer
This feature will be available in Drupal 9.1. See this issue

```
/**
 * @Condition(
 *   id = "node_type",
 *   label = @Translation("Node Bundle"),
 *   context = {
 *     "taxonomy_term" = @ContextDefinition("entity:taxonomy_term", label = @Translation("Term"))
 *   }
 * )
 */

```
> 1 votes

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


# Question
Title: How do I pass a value from PHP to JavaScript from a function that returns a render array?
I'm trying to send a variable to my JavaScript. I would like to send a class name to my twig template and the same class-name to my javascript from a function that returns a render array. The function is called from a routing yml to display a page from a link in a page (which is beside the point).

The returned render array is similar to the following one.

```
return [
  '#theme' => 'theme_name',
  '#form' => $form,
  '#data' => [
    'customer' => $obj_customer,
    'customer_subscription' => $obj_customer->getSubscription(),
    'subscriptions_explanation' => $arr_subscription_text,
  ]
];

```

Passing data from PHP to javascript variable available to all pages in Drupal 8 says you can do something with `'#attached' => ['drupalSettings' => ['do' => $something]]` in `hook_page_attachments()`, but that doesn't seem to apply to the method I am using.

How can I do in my case? Adding stylesheets (CSS) and JavaScript (JS) to a Drupal theme doesn't seem to cover this use case.

In my JavaScript I define my JS functions inside:

```
(function ($, Drupal, drupalSettings) {
  Drupal.behaviors.portalCore = {
    someFunction() {
      ...
    }
  };
});

```

Is there perhaps a way to attach a variable to the `portalCore` from my example code?

# Answer
As described in Render API overview (the *Attaching libraries in render arrays* section), #attached can be always used in a render array. If your function/method returns a render array, it could return the following render array.

```
return [
  '#attached' => [
    'drupalSettings' => ['do' => $something],
  ],
  '#theme' => 'theme_name',
  '#form' => $form,
  '#data' => [
    'customer' => $obj_customer,
    'customer_subscription' => $obj_customer->getSubscription(),
    'subscriptions_explanation' => $arr_subscription_text,
  ]
];

```

(It doesn't matter where is the #attached array added. You could also add it to the end of the render array.)

Note that, to avoid conflicts with other modules, it would preferable to prefix the setting name (*do*, in your case) with the module machine name (for example, as in *mymodule\_do*).

As for using `drupalSettings` in a Drupal behavior, see the content of core/misc/machine-name.es6.js, for example.

```
/**
 * @file
 * Machine name functionality.
 */

(function($, Drupal, drupalSettings) {
  /**
   * Attach the machine-readable name form element behavior.
   *
   * @type {Drupal~behavior}
   *
   * @prop {Drupal~behaviorAttach} attach
   *   Attaches machine-name behaviors.
   */
  Drupal.behaviors.machineName = {
    /**
     * Attaches the behavior.
     *
     * @param {Element} context
     *   The context for attaching the behavior.
     * @param {object} settings
     *   Settings object.
     * @param {object} settings.machineName
     *   A list of elements to process, keyed by the HTML ID of the form
     *   element containing the human-readable value. Each element is an object
     *   defining the following properties:
     *   - target: The HTML ID of the machine name form element.
     *   - suffix: The HTML ID of a container to show the machine name preview
     *     in (usually a field suffix after the human-readable name
     *     form element).
     *   - label: The label to show for the machine name preview.
     *   - replace_pattern: A regular expression (without modifiers) matching
     *     disallowed characters in the machine name; e.g., '[^a-z0-9]+'.
     *   - replace: A character to replace disallowed characters with; e.g.,
     *     '_' or '-'.
     *   - standalone: Whether the preview should stay in its own element
     *     rather than the suffix of the source element.
     *   - field_prefix: The #field_prefix of the form element.
     *   - field_suffix: The #field_suffix of the form element.
     */
    attach(context, settings) {
      const self = this;
      const $context = $(context);
      let timeout = null;
      let xhr = null;

      function clickEditHandler(e) {
        const data = e.data;
        data.$wrapper.removeClass('visually-hidden');
        data.$target.trigger('focus');
        data.$suffix.hide();
        data.$source.off('.machineName');
      }

      function machineNameHandler(e) {
        const data = e.data;
        const options = data.options;
        const baseValue = $(e.target).val();

        const rx = new RegExp(options.replace_pattern, 'g');
        const expected = baseValue
          .toLowerCase()
          .replace(rx, options.replace)
          .substr(0, options.maxlength);

        // Abort the last pending request because the label has changed and it
        // is no longer valid.
        if (xhr && xhr.readystate !== 4) {
          xhr.abort();
          xhr = null;
        }

        // Wait 300 milliseconds for Ajax request since the last event to update
        // the machine name i.e., after the user has stopped typing.
        if (timeout) {
          clearTimeout(timeout);
          timeout = null;
        }
        if (baseValue.toLowerCase() !== expected) {
          timeout = setTimeout(() => {
            xhr = self.transliterate(baseValue, options).done(machine => {
              self.showMachineName(machine.substr(0, options.maxlength), data);
            });
          }, 300);
        } else {
          self.showMachineName(expected, data);
        }
      }

      Object.keys(settings.machineName).forEach(sourceId => {
        const options = settings.machineName[sourceId];

        const $source = $context
          .find(sourceId)
          .addClass('machine-name-source')
          .once('machine-name');
        const $target = $context
          .find(options.target)
          .addClass('machine-name-target');
        const $suffix = $context.find(options.suffix);
        const $wrapper = $target.closest('.js-form-item');
        // All elements have to exist.
        if (
          !$source.length ||
          !$target.length ||
          !$suffix.length ||
          !$wrapper.length
        ) {
          return;
        }
        // Skip processing upon a form validation error on the machine name.
        if ($target.hasClass('error')) {
          return;
        }
        // Figure out the maximum length for the machine name.
        options.maxlength = $target.attr('maxlength');
        // Hide the form item container of the machine name form element.
        $wrapper.addClass('visually-hidden');
        // Initial machine name from the target field default value.
        const machine = $target.val();
        // Append the machine name preview to the source field.
        const $preview = $(
          `<span class="machine-name-value">${
            options.field_prefix
          }${Drupal.checkPlain(machine)}${options.field_suffix}</span>`,
        );
        $suffix.empty();
        if (options.label) {
          $suffix.append(
            `<span class="machine-name-label">${options.label}: </span>`,
          );
        }
        $suffix.append($preview);

        // If the machine name cannot be edited, stop further processing.
        if ($target.is(':disabled')) {
          return;
        }

        const eventData = {
          $source,
          $target,
          $suffix,
          $wrapper,
          $preview,
          options,
        };

        // If no initial value, determine machine name based on the
        // human-readable form element value.
        if (machine === '' && $source.val() !== '') {
          self.transliterate($source.val(), options).done(machineName => {
            self.showMachineName(
              machineName.substr(0, options.maxlength),
              eventData,
            );
          });
        }

        // If it is editable, append an edit link.
        const $link = $(
          `<span class="admin-link"><button type="button" class="link">${Drupal.t(
            'Edit',
          )}</button></span>`,
        ).on('click', eventData, clickEditHandler);
        $suffix.append($link);

        // Preview the machine name in realtime when the human-readable name
        // changes, but only if there is no machine name yet; i.e., only upon
        // initial creation, not when editing.
        if ($target.val() === '') {
          $source
            .on('formUpdated.machineName', eventData, machineNameHandler)
            // Initialize machine name preview.
            .trigger('formUpdated.machineName');
        }

        // Add a listener for an invalid event on the machine name input
        // to show its container and focus it.
        $target.on('invalid', eventData, clickEditHandler);
      });
    },

    showMachineName(machine, data) {
      const settings = data.options;
      // Set the machine name to the transliterated value.
      if (machine !== '') {
        if (machine !== settings.replace) {
          data.$target.val(machine);
          data.$preview.html(
            settings.field_prefix +
              Drupal.checkPlain(machine) +
              settings.field_suffix,
          );
        }
        data.$suffix.show();
      } else {
        data.$suffix.hide();
        data.$target.val(machine);
        data.$preview.empty();
      }
    },

    /**
     * Transliterate a human-readable name to a machine name.
     *
     * @param {string} source
     *   A string to transliterate.
     * @param {object} settings
     *   The machine name settings for the corresponding field.
     * @param {string} settings.replace_pattern
     *   A regular expression (without modifiers) matching disallowed characters
     *   in the machine name; e.g., '[^a-z0-9]+'.
     * @param {string} settings.replace_token
     *   A token to validate the regular expression.
     * @param {string} settings.replace
     *   A character to replace disallowed characters with; e.g., '_' or '-'.
     * @param {number} settings.maxlength
     *   The maximum length of the machine name.
     *
     * @return {jQuery}
     *   The transliterated source string.
     */
    transliterate(source, settings) {
      return $.get(Drupal.url('machine_name/transliterate'), {
        text: source,
        langcode: drupalSettings.langcode,
        replace_pattern: settings.replace_pattern,
        replace_token: settings.replace_token,
        replace: settings.replace,
        lowercase: true,
      });
    },
  };
})(jQuery, Drupal, drupalSettings);

```

Note the first line and the last line of the closure.

```
(function($, Drupal, drupalSettings) {
  // ...
})(jQuery, Drupal, drupalSettings);

```

Note also that the behavior's `attach()` method receives `drupalSettings` as second parameter. In fact, the method that attaches the behaviors uses the following code. (`settings = settings || drupalSettings;`)

```
Drupal.attachBehaviors = function(context, settings) {
  context = context || document;
  settings = settings || drupalSettings;
  const behaviors = Drupal.behaviors;
  // Execute all of them.
  Object.keys(behaviors || {}).forEach(i => {
    if (typeof behaviors[i].attach === 'function') {
      // Don't stop the execution of behaviors in case of an error.
      try {
        behaviors[i].attach(context, settings);
      } catch (e) {
        Drupal.throwError(e);
      }
    }
  });
};

```

As side note, if your JavaScript library depends from `drupalSettings`, it must declare its dependency from it, as in the following library definition. (The definition has been taken from user.libraries.yml.)

```
drupal.user.permissions:
  version: VERSION
  js:
    user.permissions.js: {}
  dependencies:
    - core/jquery
    - core/jquery.once
    - core/drupal
    - core/drupalSettings
    - user/drupal.user.admin

```
> 3 votes

# Answer
It does apply to the method you are using. You can add metadata like #cache or #attached to any render element (#theme, #type, #markup, #plain\_text):

```
return [
  '#theme' => 'theme_name',
  '#form' => $form,
  '#data' => [
    'customer' => $obj_customer,
    'customer_subscription' => $obj_customer->getSubscription(),
    'subscriptions_explanation' => $arr_subscription_text,
  ],
  '#attached' => ['drupalSettings' => ['do' => $something]],
];

```
> 5 votes

---
Tags: 8, javascript
---


# Question
Title: Why doesn't my custom OutboundPathProcessorInterface work anymore?
I wrote my own implementation of `OutboundPathProcessorInterface` to rewrite the URL of nodes to use the content of their field\_project\_url field.

```
namespace Drupal\mymodule\PathProcessor;

use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\PathProcessor;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\node\Entity\Node;
use Symfony\Component\HttpFoundation\Request;

class MymoduleFieldRedirectPathProcessor implements OutboundPathProcessorInterface {

  public function processOutbound($path, &$options = array(), Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {

    if (isset($options['entity']) && is_object($options['entity']) && method_exists($options['entity'], 'hasField')) {
      $node = $options['entity'];

      if ($node->hasField('field_project_url') && !$node->field_project_url->isEmpty()) {
        $project_url = $node->field_project_url->getValue();

        if (preg_match("/^\/node\/[0-9]+\/(edit|translate|delete|translations)$/i", $path)) {
          // dont alter operational paths
        }
        else {
          $path = $project_url[0]['uri'];

          dpm($project_url[0]['uri']); // 'http://url.com'

          $options['absolute'] = TRUE;
          $options['external'] = TRUE;
          $options['base_url'] = null;
          $options['prefix'] = null;
        }

        if ($bubbleable_metadata) {
          $bubbleable_metadata->addCacheableDependency($node);
        }
      }
    }
    return $path;
  }

}

```

The teaser of that view has a title, an image linked to the content, and smart trimmed version of the body field, also linking to the content.

The value is appended, giving (for example) http://localhost:8888/myprojecthttp%3A//url.com.

This used to work, but I can't even get this right with older Drupal 8 versions.

What am I doing wrong?

# Answer
> 0 votes
That's the right code of the **processOutbound** method

```
  public function processOutbound($path, &$options = array(), Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {

if (isset($options['entity']) && is_object($options['entity']) && method_exists($options['entity'], 'hasField')) {
  $node = $options['entity'];

  if ($node->hasField('field_project_url') && !$node->field_project_url->isEmpty()) {
    $project_url = $node->field_project_url->getValue();

    if (preg_match("/^\/node\/[0-9]+\/(edit|translate|delete|translations)$/i", $path)) {
      // dont alter operational paths
    }
    else {
      $path = ''; //Don't use $path variable at all

      dpm($project_url[0]['uri']); // 'http://url.com'
      $options['base_url'] = $project_url[0]['uri']; //Add your url as base_url

    }

    if ($bubbleable_metadata) {
      $bubbleable_metadata->addCacheableDependency($node);
    }
  }
}
return $path;

```

}

---
Tags: 8
---


# Question
Title: When passing a variable from a render array to JavaScript how do you reach that variable in your Javascript
I add a variable in the backend to a render array like so (removed superfluous code):

```
$some_var = 'Hello World';
return [
  '#attached' => [
    'drupalSettings' => ['someVar' => $some_var],
  ],
  '#theme' => 'core_portal_customer_subscription_edit',
  '#data' => [
    'namespace_something' => $some_var,
  ]
];

```

I would then like to use that variable in my JavaScript but I can't seem to access the drupalSettings.

I tried doing the following but that console.logs undefined.

```
(function($, Druapl, drupalSettings) {
  Drupal.behaviors.escrowPortalCore = {
    ...
    console.log(druaplSettings.someVar);
  }
}());

```

# Answer
> 0 votes
When you need to use a variable in the JavaScript you have set from the backend and added to the drupalSettings, you can access that variable using the drupalSettings object like tried in the example code from the question but then without adding drupalSettings to the js function, like so:

```
(function($, Drupal, drupalSettings) {
  Drupal.behaviors.portalCore = {
    ...
    console.log(druaplSettings.someVar); // "Hello World"
  }
}(jQuery, Drupal, drupalSettings));

```

---
Tags: 8, javascript
---


title: Webform token formatting

text:
# Question
Title: Webform token formatting
I'm trying to get the answers from one form, pre-filled in another form by adding tokens in the confirmation URL. This works for most answers while using the token: \[webform\_submission:values:?\]

However one of the answers I need to pre-fill is based on a content type (Entity select question), instead of sending just the node number of the content type, it sends 'node 101' (node%3A**101**) in the URL. I need the 'node%3A' part to disappear in order for the pre-fill to work.

This is how my confirmation URL looks like: /thank-you/?destination=\[webform\_submission:values:destination:raw\]&e\_mail=\[webform\_submission:values:e\_mail\]

The e-mail token works, the destination token not. If I leave the raw part out it will send both the destination name and the node in the URL, you will then get something like this: Sri%20Lanka%20%28**101**%29. The node of this content type (Sri Lanka) is 101.

# Answer
You need to add the `:urlencode` suffix and change `[webform_submission:values:e_mail]` to `[webform_submission:values:e_mail:urlencode]`
> 1 votes

---
Tags: webforms, tokens
---


# Question
Title: How do I programmatically add an image while programmatically creating nodes?
I'm writing a script to add nodes programmatically, and I don't know the proper way to add/attach image. Actually I'm not that familiar with Drupal.

Here are the (sample) image objects I found while `print_r`ing the existing `$node` I'm using:

```
field_image: Array ( [und] => Array ( [0] => Array ( [fxid] => 3089 [alt] => [title] => [width] => 95 [height] => 126 [uid] => 249 [filename] => helloworld.jpg [uri] => public://helloworld.jpg [filemime] => image/jpeg [filesize] => 3694 [status] => 1 [timestamp] => 1346748001 [type] => image [media_title] => Array ( ) [media_description] => Array ( ) [field_tags] => Array ( ) [field_license] => Array ( [und] => Array ( [0] => Array ( [value] => nothing ) ) ) [metatags] => Array ( ) [rdf_mapping] => Array ( ) ) ) )

```

The next one I found is the following.

```
field_temp_image: Array ( [und] => Array ( [0] => Array ( [value] => http://www.example.com/sample-path/helloworld.jpg [format] => [safe_value] => http://www.example.com/sample-path/helloworld.jpg ) ) ) `

```

How should I add an image to that node in that way?

# Answer
Let suppose your image fields in `field_body_images` ,

first `load` your node by `node_load` and record your image in `file` tables and add it to your node image field I hope this sample help you to achieve :

```
$n=  node_load($nid);
$file = new stdClass();
$file->filename =$file_name;
$file->filemime =file_get_mimetype($localimagepath.$file_name);
$file->filesize = @filesize(file_create_path($localimagepath.$file_name));
$file->uid = $user->uid;
$file->status = 1;
$file->timestamp = time();
$file->list=1;
$file->data=array('alt'=>'','title'=>$n->title);
drupal_write_record('files', $file);
$record->fid=$file->fid;
$n->field_body_images[]=(array)$file;
node_save($n);

```
> 4 votes

# Answer
### Drupal 8

For Drupal 8 it would go like following. First add the file and get a file ID. Then create the node and attach the given file ID.

```
$data = file_get_contents(__DIR__ . '/images/my_image.jpeg');
$file = file_save_data($data, 'public://my_image.jpeg');

$node = \Drupal\node\Entity\Node::create([
  'type'             => 'page',
  'title'            => 'Foobar',
  'field_my_image' => [
    'target_id' => $file->id(),
    'alt'       => 'Lorem ipsum',
    'title'     => 'Dolor sit amet',
  ],
]);

$node->save();

```
> 3 votes

# Answer
May be not exactly what you need, but why not just add a reference to an image in a field, like your example 2 suggests ? And then in content template file render that field as an image.

In node creation stream:

```
$node->field_image['und'][0]['value'] = "/path_to_image/image.jpg";

```

In content type:

```
<?php
global $base_url;
$image_source_link=$base_url . $node->field_image['und'][0]['value'];
?>
<img src="<?php print($image_source_link); ?>" />

```
> 0 votes

# Answer
In a Drupal 8 form submit callback, with entityTypeManager:

```
public function submitForm(array &$form, FormStateInterface $form_state) {
  // Get values from a managed_file widget.
  $files = $form_state->getValue('uploaded_images');

  $storage_file = $this->entityTypeManager->getStorage('file');
  $storage_node = $this->entityTypeManager->getStorage('node');

  $field_image = [];

  foreach ($files as $fid) {
    /** @var \Drupal\file\Entity\File $file */
    $file = $storage_file->load($fid);
    // Set the file status to permanent.
    $file->setPermanent();
    $file->save();

    $field_image[] = [
      'target_id' => $file->id(),
      'alt'       => '',
    ];
  }

  $values = [
    // Node bundle.
    'type'           => 'gallery',
    // Node title.
    'title'          => 'Gallery',
    // Node status: active.
    'status'         => 1,
    // Author ID.
    'uid'            => \Drupal::currentUser()->id(),
    // Uploaded images.
    'field_image'    => $field_image,
  ];

  /** @var \Drupal\node\Entity\Node $entity */
  $entity = $storage_node->create($values);
  $entity->save();
}

```
> 0 votes

---
Tags: nodes, media
---


# Question
Title: How to install a specifc commit in Composer
The commerce\_webform\_order module (currently in dev status) recently changed one of its dependencies from Webform 5.x (stable) to Webform 6.x (alpha). I want to temporarily freeze commerce\_webform\_module so that Composer keeps it at a particular git commit just before the dependencies changed. I've done this successfully in the past by following a post here but I can't get it to work this time.

I've tried doing
`composer require drupal/commerce_webform_order:1.x-dev#30668342035ae3add3a2e5163e84816fc96edd92`
or adding
`"drupal/commerce_webform_order "1.x-dev#30668342035ae3add3a2e5163e84816fc96edd92",` in my `composer.json` file and I've tried shorter versions of the commit hash (30668342) as shown on the drupalcode.org project here.

I keep getting this message

```
Your requirements could not be resolved to an installable set of packages.
- Can only install one of: drupal/webform[6.x-dev, 5.19.0].
- drupal/commerce_webform_order 1.x-dev requires drupal/webform ^6 -> satisfiable by drupal/webform[6.x-dev].
- Installation request for drupal/commerce_webform_order 1.x-dev#30668342035ae3add3a2e5163e84816fc96edd92 -> satisfiable by drupal/commerce_webform_order[1.x-dev].

```

What might be causing this? What's changed in the last 6 months since it worked for me on the same module last time?

Can you think of any other work-around that allows me to update everything else without pulling in this latest change and the dependency for an alpha version of Webform?

Thanks

# Answer
> 5 votes
```
composer require drupal/commerce_webform_order:dev-1.x#30668342035ae3add3a2e5163e84816fc96edd92

```

dev-1.x points to a git branch so it accepts the commit ref

1.x-dev is dev release at drupal.org and it does not have git commits to reference like that

---
Tags: 8, webforms, composer, version-control
---


# Question
Title: how to access webform submission data from a custom content type
I 'd be grateful if someone could help with this..

I have a webform, let's call it **input form**, which, when submitted, triggers an external application to run on my server. That application uses some of the submission data (reading from webform\_submission\_data table) and after some time produces an output in the form of XML.

Now, through the use of feeds module, I read that XML data and produce a node, of a certain content type, let's call it **results** CT ..

I have a twig template for the *results* content type, and output is nicely presented to the user.

So far, so good.

Now my problem is this. I need to show both input and output in the same *results* page.

I tried to use Webform Content Creator module and indeed I have nodes with submission data - let's call this **input data** CT.

However, at the time of *input form submission*, I don't have the *results* yet. And I want to link the two together, obviously upon the creation of the *results* node.

I tried to reference each content type, using Corresponding Entity References so that when a **results** node is created (automatically through feeds) it would link to the corresponding **input data** CT. I thought that if I can achieve that connection, then I would be able to access the 'input' data through the results page template.

However, I can't make this connection to work - the 'entity reference' field that I use on the results CT, wants an 'entity ID' - and I can't find that. Remember that nodes are created automatically, I don't have a user creating nodes via a select form or autocomplete text field.

I am trying to figure out how to do this through the *sid* (submission id) which seems to be a unique key for every submission, and I have this on both my content types .. So ideally I would like to use the *sid* that I have on my *results* template, and use that to get the submission data I need.

(obviously) I am not very familiar with the drupal API - I am however comfortable with twig .. I don't know if (and how) I could pass that information through a pre-process function to be available in the *results* template.. Is there a simpler way to do it?

Could I link two content types based on a custom field (say a unique number, like *sid* ??).

**Ideally, in a few words, what I want is this:**

*I have a CT (**results**) with various fields, one of which is **sid**. That sid corresponds to a (unique) submission id. How can I access data relevant to that submission id **from within the results twig template**? So I can then present both input (submission data) and output (results) in the same page.*

PS - Perhaps one solution would be to refactor the whole logic, and use one CT for both input/output. Insert some data upon form submission, and then, when results are ready, edit (i.e. fill-in) the rest of the 'output' fields via feeds. Then all data are in one CT. However I would rather avoid this as it's quite a big change .. Shamefully enough, I might just re-enter input data through the XML again - it wouldn't be a problem - but it's a really crap solution ..

I 'd be really grateful if someone could help .. I hope I explained the whole situation adequately enough ..

# Answer
One way to accomplish that would be to use the https://www.drupal.org/project/webform\_entity\_handler module. It is not very widely used module yet but I've used it, it was simple to use and worked well. What that module does it allows you to create arbitrary entity from a webform submission (like the **results** node). So you could store the input, submission id and whatever else you need to this entity at this time.

Then feeds can update this same entity with the results if you know unique identifier like the submission id.
> 0 votes

---
Tags: webforms
---


title: Editable fields in views

text:
# Question
Title: Editable fields in views
I am hiding a field using hook\_form\_alter, because I only want to be able to edit this field in views. then, I used the Editable Views Module to display this field. Now, my problem is that when I press the save button, all of my nodes are saved.

Is there any way to only save nodes where this field has been edited?

# Answer
> 2 votes
Seems you're looking for the jEditable inline content editing module. I tried this module for one of my project and working fine.

Using this module you can do inline edits for individual fields. you can make inline edits at node output and views output too.

Note: Right now There is only dev version available for Drupal 7x so make sure to install and test on local instance first.

# Answer
> 0 votes
In Drupal 8, there's Views Entity Form Field. There's an issue with patches for what you're trying to do.

However, jEditable inline content editing is still available in Drupal 8. So choose the one that works better for your use case.

---
Tags: views, entities
---


# Question
Title: How to enable inline editing on Views in Drupal 8?
It is said to enable the core module "Quick Edit" to be able to easily edit nodes, but there still isn't an easy way to add inline editing in Views. All I want is for text fields to show as inputs which I can change, and then press edit at the bottom. Exactly what is currently achieved with "editablefields" for Drupal 7.

Is there a way to do this in Drupal 8?

Note: Basically my question is the same as this, but for Drupal 8.

# Answer
> 5 votes
*Quick Edit* of nodes in Views works. You can see this on the frontpage, which is a View.

However this works only for Views which show content.

If you have a View which shows content and want to choose the fields and customize the layout, you can create a custom viewmode, configure the fields there and put the layout in the twig files of the view mode.

Of course this does not provide all features of a View which shows fields and the module *Editablefields*. For this you would have to wait until this module is ported to D8.

# Answer
> 5 votes
In Drupal 8, there are now two options:

---
Tags: views, 8
---


# Question
Title: Is it possible to call response()->setStatusCode() within hook_theme_suggestions_page_alter?
We set up a custom error page theme by creating a block with the error text and then used the following code within a `hook_theme_suggestions_page_alter` implementation to determine when to override the template and show that "Page Not Found" block:

```
// error page template suggestions
if (!is_null(Drupal::requestStack()->getCurrentRequest()->attributes->get('exception'))) {
  $status_code = Drupal::requestStack()->getCurrentRequest()->attributes->get('exception')->getStatusCode();
  $suggestions[] = 'page__error';
}

```

Now it turns out that due to some hosting constraints we need to be able to serve up a version of the "Page Not Found" page with an HTTP status code of 200. So, is it possible to use response()-\>setStatusCode() within hook\_theme\_suggestions\_page\_alter? I was hoping to just override the status code for a single arbitrary route, but so far my attempts to call it from there have been unsuccessful.

Admittedly, it would be a hack to call it there even if I can, but I wanted to check before reverting a bunch of theming code.

# Answer
You don't need this code by the way, it is in core since D8.8.x, see https://www.drupal.org/node/2960810.

If you want to change the status code then do this in an event subscriber. If you want Drupal to build a normal 404 page and only change the status code of the already built error page then use a response event subscriber and set the status code:

```
$response->setStatusCode(200);

```

See this answer for the scaffolding https://drupal.stackexchange.com/a/201297/47547
> 2 votes

---
Tags: theming, status-messages
---


# Question
Title: Block plugin's render array values ending up in $variables['content'] instead of $variables
I've got a bizarre issue where my the render array from my block plugin's build() method doesn't seem to be properly interpreted by the template. I've got the following setup.

```
function my_module_theme(){
  return [
    'block__my_module__user_header' => [
      'render element' => 'children', // also tried without this
      'variables' => [
        'tabs' => NULL,
        'user' => NULL,
      ],
    ],
  ]
}

```

and my block plugin class

```
public function build() {

  $render_array = [
    '#theme' => 'block__my_module__user_header',
    '#tabs' => $this->getTabs(), // returns an array of data to handled in twig
    '#cache' => [
      'contexts' => [
        'route',
        'user',
      ],
    ],
  ];

  if ($user = $this->getContextValue('user')) {
    $render_array['#cache']['tags'] = $user->getCacheTags();
    $render_array['#user'] = $user;
  }

  return $render_array;
}

```

But then, when I inspect the variables in theme\_preprocess\_block(), all of that render array information from build() is sitting in $variables\['content'\]. Same in the actual twig template, and same result if I remove `['#cache']` from build(). I'd expect to be able to access `{{ tabs }}` directly, but instead the data is sitting in `{{ content['#tabs'] }}`. Aside from that inconvenience, it also means that any cache tags/contexts I try to set in build() don't end up in the actual render array so they're completely ignored, which is a problem because the "tabs" as rendered in twig are dependent on this context.

I'm completely perplexed, as the same pattern works fine for hook\_theme/block plugins in some of my modules, but this issue crops up in other modules.

# Answer
> 1 votes
This is how block templates work, they render the variable `content`.

```
{{ content }}

```

Your code though is using a block template inside of a block, which doesn't make sense, because the block template is wrapped around the block by Drupal automatically. You probably want to build the inside of the block like a controller output by using a custom template not derived from a block template, which you do when you don't start the template name with `block__`.

See https://www.drupal.org/docs/theming-drupal/twig-in-drupal/create-custom-twig-templates-for-custom-module

---
Tags: 8, theming, blocks
---


# Question
Title: How to add JavaScript to a specific View if I don't know the node?
I've seen the answer here using the NID but I don't know this, I only have the URL. Is there is another way to do this please?

```
function MY_THEME_preprocess_node(&$vars) {
    if($vars['nid'] == 'XX'){
      drupal_add_js('path/to/js/file.js');
    }
}

```

# Answer
Check out hook\_views\_pre\_render https://api.drupal.org/api/views/views.api.php/function/hook\_views\_pre\_render/7.x-3.x

That provides a view object where you could retrieve the machine name of your view and add your drupal\_add\_js when its the relevant view being loaded
> 1 votes

---
Tags: javascript
---


# Question
Title: How to remove stylesheets only for anonymous users?
I am trying to remove all unnecessary/unused stylesheets for anonymous visitors to get better performance and a clean `<head>` section. This works fine by listing them inside `mytheme.info.yml`:

```
stylesheets-remove:
  - path/to/stylesheet.css
  - path/to/another/stylesheet.css
  - core/modules/system/css/components/hidden.module.css

```

However, the third entry in this example breaks the styling of the toolbar - which is only visible to the admin. Is it possible to programatically tell Drupal which stylesheets to remove only for anonymous visitors? I appreciate your help!

# Answer
Having tried to do this myself before, this is probably not a route you want to go down. This approach becomes harder to maintain as you install more modules (different modules can inject CSS on different paths), and often can turn into a maintenance nightmare.

Drupal can aggregate CSS files out of the box; this is often all you need to improve performance dramatically.

To turn on the basic aggregation, you can check **Aggregate CSS files** at `/admin/config/development/performance`.

To do something more complicated, try using the Advagg module. Configuring this module can be complex but it allows you to do more specific aggregation, CSS minification, and so on.
> 1 votes

# Answer
you can use hook bellow (check for the right path)

```
function MYMODULE_page_attachments_alter(array &$attachments) {
  if(\Drupal::currentUser()->isAnonymous()) {
    unset($attachments['#attached']['library']['core/modules/system/css/components/hidden.module.cs']);
  }
}

```
> -2 votes

---
Tags: theming, toolbar
---


# Question
Title: Views: List content NOT authored by the logged-in user
I want to list all the content that was NOT authored by the logged-in user in Drupal 9.

Getting the list of content authored by the logged-in user is pretty easy.

1. Create a View showing content.
2. Add a required relationship to **Author**.
3. Add a contextual filter **User ID** and set **When the filter value is NOT in the URL** to **Provide default value** *User ID from logged in user*.

But I'm stumped about how to negate this; I want the opposite (all content not created by the logged-in user).

# Answer
> 1 votes
In contextual filter, scroll all the way down, click on "▾ MORE" and check mark ☑ Exclude

---
Tags: views
---


title: How to add a field to menus?

text:
# Question
Title: How to add a field to menus?
I am trying to add an extra text field to the menu entity. My field is showing up and saving input but the input saves for all menus not just the one I entered the data for.

This is how it is now:

```
function myModule_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'menu_edit_form') {
    $config = \Drupal::service('config.factory')->getEditable('myModule.settings');
    $my_field = $config->get('my_field');
    $form['my_field'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#default_value' => $my_field,
    '#weight' => '0',
    '#required' => FALSE,
    );

    $form['actions']['submit']['#submit'][] = 'myModule_menu_edit_submit';
  }
}

function myModule_menu_edit_submit($form, $form_state) {
  $config = \Drupal::service('config.factory')->getEditable('myModule.settings');
  $config->set('my_field', $form_state->getValue('my_field'))->save();
}

```

I need to save different data for each form, so I was trying to do change the submit function to:

```
function myModule_menu_edit_submit($form, $form_state) {
  $key = $form_state->getformObject()->getEntity()->id();
  $config = \Drupal::service('config.factory')->getEditable('myModule.settings');
  $config->set($key, $form_state->getValue('my_field'))->save();
}

```

If I do this though, when I enter the data in the field and save, it says updated successfully but the field is blank. Not sure what I'm doing wrong.

# Answer
> 1 votes
I figured out how to add a field to the menus (not menu links, the actual menus). I use the machine name of the menu's title as a key and store the value with the key I use in the `$form` variable.

Here is my code:

```
function myModule_form_menu_edit_form_alter(&$form, $form_state, $form_id) {
  $config = \Drupal::service('config.factory')->getEditable('myModule.settings');
  $my_field = $config->get(str_replace('-', '_', $form_state->getformObject()->getEntity()->id()));

  $form['my_field'] = array(
  '#type' => 'textfield',
  '#title' => t('Title'),
  '#default_value' => $my_field,
  '#weight' => '0',
  '#required' => FALSE,
  );

  $form['actions']['submit']['#submit'][] = 'myModule_custom_submit';
}

function myModule_custom_submit($form, $form_state) {
  $key = str_replace('-', '_', $form_state->getformObject()->getEntity()->id());
  $config = \Drupal::service('config.factory')->getEditable('myModule.settings');
  $config->set($key, $form_state->getValue('my_field'))->save();
}

```

---
Tags: forms, hooks, navigation
---


# Question
Title: Where are Commerce 2 hooks (or Events) in Commerce 2
I am working on replacing our payment system from D7/DC1 to D8/DC2 and the original code makes use of hooks. I have replaced some of them with events but I cannot find any information on the DC2 versions of:

```
mymodule_form_commerce_checkout_form_checkout_alter()
mymodule_form_commerce_checkout_form_review_alter()
mymodule_form_commerce_checkout_complete()
mymodule_form_commerce_cart_add_to_cart_form_alter()

```

Are they still the same or much like the former cart (add, update, remove) hooks, these are also events but I can't locate documentation on them. Anyone know the equivalent events or where to find the docs on these (or their replacements)

/\* Small Update \*/

I found OrderEvents and I think I need ORDER\_PAID to replace mymodule\_form\_commerce\_checkout\_complete()

Does this look correct?

I added OrderEvents::ORDER\_PAID =\> 'orderPaid' to my getSubscribedEvents(){} array and have:

```
public function orderPaid(OrderEvent $event){
    $order = $event->getEntity();
    //Some internal logic here
    $order->save();
  }

```

//Updated Tried a hook form alter and ran through my checkout process and nothing is showing in the logs

```
function srs_hook_form_alter(&$form, $form_state, $form_id){
  \Drupal::logger('hook_form_alter fires')->info('<pre><code>' . print_r($form_id, TRUE) . '</code></pre>');

}

```

# Answer
as you've discovered, you can look in any module's src/Event/\*Events.php file to find a list of their events. Using the order paid event is one way to react once you know that payment has been collected, but note that in scenarios where an order is placed with only a payment authorization (and not a capture), that event would not have been fired yet.

That may be fine in your case - if not, I'd recommend the commerce\_order.place.pre\_transition or commerce\_order.place.post\_transition events that are triggered when the order is placed. That event is coming from the state machine module and correlates to order workflow transitions. You can read more about it in the module's readme.

As for form alters, those exist in D8 as they did in D7.
> 2 votes

---
Tags: 8, commerce, hooks
---


# Question
Title: Drupal 7 Views url translated alias with contextual filter
I want to translate the url of my view. So I've made a translated alias for it. But when I add a contextual filter I get a 404 error.

For example: I've a view with the url `example.com/overview` with alias `example.com/overzicht` this works. This works also `example.com/overview/[category]`, but this doesn't work: `example.com/overzicht/[category]`

How can I fix this?

# Answer
> 1 votes
I've finally found the solution for my problem, after a couple of hours :).

It was solved after installing the Extended Path Aliases module.

# Answer
> 0 votes
The "Sub-pathauto (Sub-path URL Aliases)" module also does the trick (and has an official D8 version as well).

---
Tags: views, i18n-l10n, path-aliases
---


title: How to create new entity within a hook?

text:
# Question
Title: How to create new entity within a hook?
I am trying to create a hook that creates a new entity('Notification') when an entity of another type is created (either of type 'Deadline' or 'Message'), but I can't seem to figure out how to add a new entity from a hook, am I completely missing something?

My hook in ost.module looks like this:

```
function ost_hook_ENTITY_TYPE_create(EntityInterface $entity){
  if ($entity->getEntityType() == ('Deadline' || 'Message')){
    createNotification($entity);
  }
}

```

The function which is called looks like this:

```
function createNotification(EntityInterface $notification){
  $newentity = EntityInterface::create([
    'title' => $notification->label() . "notification",
    'field_content' => $notification->toLink()
  ]);
  $newentity->save();
}

```

# Answer
> 1 votes
The following code solved it for me:

```
function ost_notifications_entity_insert(EntityInterface $entity) {
  if ($entity->bundle() == 'deadline' || $entity->bundle() == 'message') {
    $new_entity = \Drupal::entityTypeManager()->getStorage('node')->create([
      'type' => 'notification',
      'title' => $entity->label(),
      'field_content' => "content"
    ]);
    $new_entity->save();
  }
}

```

# Answer
> 0 votes
That code needs to be changed for the following reasons.

In PHP, `$entity->getEntityType() == ('Deadline' || 'Message')` doesn't check that `$entity->getEntityType()` returns either `'Deadline'` or `'Message'`. Actually, the code you wrote is equivalent to the following one.

```
if ($entity->getEntityType() == TRUE) {
  createNotification($entity);
}

```

`getEntityType()` doesn't return the ID of the type of the entity, but its definition. The method that returns the ID of the type of the entity is `getEntityTypeId()`.

It doesn't make sense to check the value returned from `$entity->getEntityTypeId()` in `hook_ENTITY_TYPE_create()` because `hook_ENTITY_TYPE_create()` is invoked only for the *ENTITY\_TYPE* entities. (You are also supposed to implement `hook_ENTITY_TYPE_create()` by replacing *ENTITY\_TYPE* with the entity type, for example *node* for the Node entity, or *user* for the User entity.)

`EntityInterface` is an interface, not a class; as such, it's never used to call a method, even if it's statically called as in the code you are using.

The correct code is similar to the following one. I assume that *ost\_hook* is the module machine name, *notification* is entity type, and `Notification` is the class implementing the entity you are trying to create.

```
function ost_hook_entity_create(EntityInterface $entity) {
  if ($entity->getEntityTypeId() == 'Deadline' || $entity->getEntityTypeId() == 'Message') {
    $new_entity = Notification::create([
      'title' => $entity->label() . " notification",
      'field_content' => $entity->toLink()
    ]);
    $new_entity->save();
  }
}

```

Alternatively, you could use the following code.

```
function ost_hook_entity_create(EntityInterface $entity) {
  if ($entity->getEntityTypeId() == 'Deadline' || $entity->getEntityTypeId() == 'Message') {
    $new_entity = \Drupal::entityTypeManager()->getStorage('notification')->create([
      'title' => $entity->label() . " notification",
      'field_content' => $entity->toLink()
    ]);
    $new_entity->save();
  }
}

```

If the file containing the hook is *ost.module* (as I suspect), the function implementing the hook is `ost_entity_create()`, not `ost_hook_entity_create()`.

I used `hook_entity_create()` because the code needs to be executed for two different entity types. Using `hook_ENTITY_TYPE_create()`, I should implement two hooks. (I assume that *dealine* and *message* are the entity machine names, in the same way the machine name for the Node entity is *node*.)

```
function ost_deadline_create(EntityInterface $entity) {
  $new_entity = \Drupal::entityTypeManager()->getStorage('notification')->create([
    'title' => $entity->label() . " notification",
    'field_content' => $entity->toLink()
  ]);
  $new_entity->save();
}

function ost_message_create(EntityInterface $entity) {
  $new_entity = \Drupal::entityTypeManager()->getStorage('notification')->create([
    'title' => $entity->label() . " notification",
    'field_content' => $entity->toLink()
  ]);
  $new_entity->save();
}

```

As side note, functions implemented from a module should always be prefixed by the module machine name. A module shouldn't have a `createNotification()` function, which should instead be called `ost_create_notification()` (assuming that *ost* is the module machine name).

---
Tags: entities, hooks
---


# Question
Title: How to programmatically reference entities?
I am trying to reference an entity within my hook, so that every time a new entity is inserted, I create another entity referencing the first entity. I have not yet found a working way to reference an existing entity in my "field\_content" when creating a new entity.
My code looks like the below excerpt:

```
function ost_notifications_entity_insert(EntityInterface $entity) {
  if ($entity->bundle() == 'deadline' || $entity->bundle() == 'message') {
    $new_entity = \Drupal::entityTypeManager()->getStorage('node')->create([
      'type' => 'notification',
      'title' => $entity->label(),
      'field_content' => "referenced entity goes here"
    ]);
    $new_entity->save();
  }
}

```

# Answer
As pointed out by 4k4 in the comments, the most robust way is assign an entity object to the field like so:

```
$new_entity = \Drupal::entityTypeManager()->getStorage('node')->create([
  'type' => 'notification',
  'title' => $entity->label(),
  'field_content' => [
    'entity' => $entity,
  ],
]);

```

For posterity, you can also do it by setting the field column (target\_id) directly, but this is only useful if you have a saved entity. The first example will work for both new and existing entities.

```
$new_entity = \Drupal::entityTypeManager()->getStorage('node')->create([
  'type' => 'notification',
  'title' => $entity->label(),
  'field_content' => [
    'target_id' => $entity->id(),
  ],
]);

```
> 1 votes

---
Tags: entities, hooks
---


# Question
Title: Which version of drupal, php, mysql combination will work on RHEL6? Which version of drupal, php, RHEL will work if we need to use mysql 8.0?
We have a working application which runs on RHEL6 with Drupal 7, php 5.3.3 and mySql 5.1.73. We are planning to migrate it AWS with latest versions which gets support. We need to know the working combination of below modules Drupal version PHP version RHEL version MYSQL version

# Answer
> 3 votes
Drupal doesn't have an opinion on which flavour or version of Linux you use, just that the system requirements are met. So it looks like your actual question around Drupal is the one you've put in the comments:

> Does Drupal 7 work with mysql 8.0

The answer to that is no, MySQL 8 is not currently supported by Drupal 7.

There are ongoing efforts to make that happen, though, you can follow Mysql 8 support on Drupal 7 for the details.

---
Tags: 7
---


# Question
Title: Storage API + Services 3: How to work together?
I am trying to set up a site that will be storing a large amount of images. I am using Storage API module for that and It is working fine through web.

Now I need a REST Service to upload images. I am trying with the default file POST endpoint of the Services module:

```
--> POST http://example.com/api/file http/1.1
Content-Type: application/json
Content-Length: 343901
Cookie: ..............
X-Csrf-Token: .........
{"file":"iVBOR.......Jggg==","filename":"myimage.png","uri":"storage-field-images://myimage.png"}
--> END POST (343901-byte body)

<-- 200 OK http://example.com/api/file (888ms)
Content-Type: application/json
{"fid":"81","uri":"http://example.com/api/file/81"}
<-- END HTTP (74-byte body)

```

But http://example.com/api/file/81 is responding me:

```
{"fid":"81","filename":"myimage.png","uri":"public://myimage.png".........

```

(Not the same uri that I sent in the request)

Am I missing something in the resquest? Or do I have to develop a new endpoint to manage that?

# Answer
> 0 votes
replace `uri` with `filepath`

```
--> POST http://example.com/api/file http/1.1
Content-Type: application/json
Content-Length: 343901
Cookie: ..............
X-Csrf-Token: .........
{"file":"iVBOR.......Jggg==","filename":"myimage.png","filepath":"public://storage-field-images/myimage.png"}
--> END POST (343901-byte body)

```

---
Tags: 7, files, services
---


# Question
Title: How to translate the author line "Submitted by ... on ..."
I've created a custom content type in Drupal 8.9.1. Each content post automatically renders the line

```
Submitted by author_name on 08.07.2020 - 18:21

```

Even though my Drupal system language is set to German, I cannot find a way to show a translated version of this "submitted by" text.

When I check the translations page under `/admin/config/regional/content-language` I also see a correct translation for the segment ("Geschrieben von"). But there's no indicator how this is mapped to the actual English value.

I've also seen posts saying that you have to do that manually in the Node Template. But I have not found such template and guess the approach has changed after Drupal 7.

# Answer
While the page `/admin/config/regional/content-language` holds the actual translated text, it's not the place where the "Submitted by" translation is derived from. To do so you need to

1. Navigate to **Configuration** \> **Regional & language** \> **User interface translation**
2. Search for "**Submitted**" in the `String contains` field. Note the uppercase S (thank you @Hudri).
3. Now enter the translation and save it. Also note the placeholders for author and date information.
> 1 votes

---
Tags: i18n-l10n
---


# Question
Title: Entitybrower access denied for non-admin user
I have created an entity browser for taxonomy terms that is used as an entity reference select form element on a node. This allows users to browse terms grouped by vocabulary, see synonyms etc. The view that it is using has the permission "View published content" and all users including anonymous have this permission. I do not see any permission settings in the entity browser setup itself or in the general permissions for the entity browser module.

The browser works well for the admin user but gives an access denied to editor users. What can I check to investigate this?

# Answer
> 1 votes
There's a separate permission for entity browsers - on the permissions page (*/admin/people/permissions*), they're grouped under *Entity Browser*. You'll need to give any roles that will use the browser the **Access \[My Browser\] pages** permission.

---
Tags: 8, entities
---


# Question
Title: grouped paragraphs by field not filtering to current language
I have a D8.9 multilingual site. I need to group paragraph elements, as well as filter them by page language and Content ID. But my language filter don't seem to work.

I have content type "services." "services" contains a paragraph field, "components" with 3 fields inside. One of the fields in "components" is a taxonomy reference "types" - this is what I need to group the paragraphs by (sometimes)

I've created a View of 'Services', placed as a block on any "services" page. The view has a contextual filter of Content:ID, pulled from URL. It also has a relationship "field\_components: Paragraph" so that I can access the specific paragraph fields.

It also has a filter "**Content: Translation language (= Content language selected for page)**" - because we have 5 translations of the site. (and translation is set within paragraph fields - not on larger paragraph field within "services" content type)

But when I view the service page, it pulls every single translated version paragraph - despite the translation filter.

Let me know if there are further details needed, and I'll edit the question accordingly.

# Answer
Might've just found the answer to my own question.. there are TWO places that the language needed to be edited. At bottom of the center column in Views admin, there's another language option for the view itself. I had to set this "Rendering Language" to "Content language selected for page"

Then the other language paragraphs disappeared.
> 3 votes

---
Tags: 8, views, paragraphs
---


# Question
Title: custom action plugin with ConfigurationForm
I am trying to create a custom action with Configuration Form Field . I am able to create Action and it is being displayed on content page ( `/admin/content` ) , but I am not able to find the path to configure the fields in the Action Plugin.Can anyone please let me know the path to configure the Action Plugin ?

My Code as follows :

**UpdateNodeTitle.php**

```
namespace Drupal\action_plugin_examples\Plugin\Action;

use Drupal\Core\Action\ConfigurableActionBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;

/**
 * Provides a an Update node title action.
 *
 * @Action(
 *   id = "action_plugin_examples_update_node_title",
 *   label = @Translation("Update node title"),
 *   type = "node",
 *   category = @Translation("Custom")
 * )
 *
 */
class UpdateNodeTitle extends ConfigurableActionBase {

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return ['title' => ''];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form['title'] = [
      '#title' => $this->t('New title'),
      '#type' => 'textfield',
      '#required' => TRUE,
      '#default_value' => $this->configuration['title'],
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    $this->configuration['title'] = $form_state->getValue('title');
  }

  /**
   * {@inheritdoc}
   */
  public function access($node, AccountInterface $account = NULL, $return_as_object = FALSE) {
    /** @var \Drupal\node\NodeInterface $node */
    $access = $node->access('update', $account, TRUE)
      ->andIf($node->title->access('edit', $account, TRUE));
    return $return_as_object ? $access : $access->isAllowed();
  }

  /**
   * {@inheritdoc}
   */
  public function execute($node = NULL) {
    /** @var \Drupal\node\NodeInterface $node */
    $node->setTitle($this->configuration['title'])->save();
  }

}

```

**action\_plugin\_examples.schema.yml**

```
action_plugin_examples.configuration.action_plugin_examples_update_node_title:
  type: mapping
  label: 'Configuration for "Update node title" action'
  mapping:
    title:
      type: string
      label: Title

```

**system.action.action\_plugin\_examples\_update\_node\_title.yml**

```
langcode: en
status: true
dependencies:
  enforced:
    module:
      - action_plugin_examples
  module:
    - node
    - pathauto
id: action_plugin_examples_update_node_title
label: 'Update Node Title'
type: node
plugin: action_plugin_examples_update_node_title
configuration: {  }

```

I have seen a similar Action Plugin in core as well but can not find the path to configure the Plugin.AssignOwnerNode Another Contributed module with similar functionality custom pub

# Answer
> 3 votes
You need to install the core module **Actions** first to be able to configure action plugins in UI.

Then you can access the actions overview page:

**/admin/config/system/actions**

On the top of the page your new plugin should be present in the select list for creating advanced actions. When you select the plugin you should see the configuration form of your plugin:

**/admin/config/system/actions/add/action\_plugin\_examples\_update\_node\_title**

Since you have already provided an action configuration in a YAML file you should also see a configured instance of your plugin in the available actions list.

---
Tags: 8, plugins, actions
---


# Question
Title: Add a JS app in Acquia root domain folder
I have a decoupled app, both backend and frontend parts, and I want to add them to Acquia cloud. Right now the js app is placed in a subfolder in drupal's docroot folder.

What I need is to have the JS app in the domain's root folder and have Drupal instance in a subdomain or subfolder. Is this possible? Thanks.

# Answer
is your frontend an Angular / React / Vue app?

Anyway I don't know Acquia cloud but I can confirm that your setup works on an Apache server. I have my Angular app in the root folder along with the vendor and and web folders, and then I have in the web folder the core, libraries, modules eccc.. folders.
> 0 votes

---
Tags: 8, acquia-cloud
---


# Question
Title: Commerce 2 - how to get guest user email from custom submit handler?
I'm altering "review" form in checkout process and adding custom submit handler. From that handler, if user is registered I can get it's email address as:

```
$user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
$email = $user->getEmail();

```

But if I go to checkout as a guess user I can not get email of anonymous user that way - returns null.

How can I get guest user email address? I need a way to get email provided on previous checkout page, no matter if user is registered or not.

# Answer
> 0 votes
Found the way over the cart:

```
$store = \Drupal::service('commerce_store.current_store')->getStore();
$cart = \Drupal::service('commerce_cart.cart_provider')->getCart('default', $store);
$email = $cart->getEmail();

```

---
Tags: 8, users, commerce
---


# Question
Title: How to use a content type form as a block
I need a page to be half content, half node edit form.

How can I do this? I thought I'd put the content type's form display into a block. Sounds easy enough.

I've been trying contrib and custom modules, but I can't seem to grab the form.

Thought I could get away with something like this.

```
class EvaluationBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    $node = \Drupal::routeMatch()->getParameter('node');
    if ($node instanceof \Drupal\node\NodeInterface) {
      $render_array = EntityFormDisplay::collectRenderDisplay($node, 'project_evaluation_form');
      // error_log($render_array);
      return $render_array;
    }
  }
}

```

# Answer
> 1 votes
Thanks to the comments above, the working module code is here:

project\_evaluation\_form\_block.module

```
<?php
/**
 * @file
 */
 function project_evaluation_form_block_entity_type_build(array &$entity_types) {
   $entity_types['node']->setFormClass('project_evaluation_form', 'Drupal\node\NodeForm');
 }

```

src/Plugin/Block/EvaluationBlock.php

```
<?php
/**
 * @file
 * Contains \Drupal\article\Plugin\Block\EvaluationBlock.
 */

namespace Drupal\project_evaluation_form_block\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\Entity\Entity\EntityFormDisplay;

/**
 * Provides an 'evaluation' block.
 *
 * @Block(
 *   id = "evaluation_form_block",
 *   admin_label = @Translation("Evaluation form block"),
 *   category = @Translation("Evaluation form block test")
 * )
 */
class EvaluationBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    $node = \Drupal::routeMatch()->getParameter('node');
    $edit_form = \Drupal::entityTypeManager()->getFormObject('node', 'project_evaluation_form')->setEntity($node);
    return \Drupal::formBuilder()->getForm($edit_form);
  }
}

```

Had to adjust the submission settings for the content type to have the save button appear.

And with this, I am able to add this form as a block to a page.

---
Tags: 8, forms, blocks
---


# Question
Title: Drush cannot connect to the database when updating
I am trying to update Drupal from version 8.7.5 to 8.7.7. I installed Drupal using composer and had a really old version of Drush that I had installed from apt-get. I uninstalled the old version and installed an up to date version. However, I still cannot update the database, I think because it doesn't connect. Drupal itself can connect to the database (obviously because the site has been up and running for months and I have not changed anything other than to try to update things) but for some reason Drush cannot. Weirdly, when I do `drush status`, it shows a Drupal version of 8.7.3, which is not correct. I have tried doing `drush cache:clear` it clears everything but does not change any of the issues. When I do `drush rebuild` I get ' SQLSTATE\[HY000\] \[1044\] Access denied for user 'user'@'%' to database 'database'\`. Any help in getting drush to connect to the database would be much appreciated. Thanks.

**drush status**

```
 Drupal version : 8.7.3
 Site URI       : http://default
 DB driver      : mysql
 DB hostname    : localhost
 DB port        : 3306
 DB username    : joomla
 DB name        : otherrealmdrupal
 PHP binary     : /usr/bin/php7.3
 PHP config     : /etc/php/7.3/cli/php.ini
 PHP OS         : Linux
 Drush script   : /usr/bin/drush
 Drush version  : 9.7.1
 Drush temp     : /tmp
 Drush configs  : /root/.drush/drush.yml
                  /var/www/html/drupal/vendor/drush/drush/drush.yml
 Drupal root    : /var/www/html/drupal
 Site path      : sites/default

```

**drush updatedb**

```
Drush Launcher Version: 0.6.0
ROOT: /var/www/html/drupal
DRUSH VERSION: 9
DRUPAL ROOT: /var/www/html/drupal
COMPOSER ROOT: /var/www/html/drupal
VENDOR ROOT: /var/www/html/drupal/vendor
 [preflight] Config paths: /root/.drush/drush.yml,/var/www/html/drupal/vendor/drush/drush/drush.yml
 [preflight] Alias paths: /root/.drush/sites,/etc/drush/sites,/var/www/html/drupal/drush/sites,/var/www/html/drush/sites
 [preflight] Commandfile search paths: /var/www/html/drupal/vendor/drush/drush/src
 [bootstrap] Starting bootstrap to full [0.22 sec, 8.49 MB]
 [bootstrap] Drush bootstrap phase 5 [0.22 sec, 8.49 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.22 sec, 8.49 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.22 sec, 8.49 MB]
 [bootstrap] Try to bootstrap at phase 5 [0.22 sec, 8.49 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalRoot() [0.22 sec, 8.49 MB]
 [bootstrap] Change working directory to /var/www/html/drupal [0.22 sec, 8.49 MB]
 [bootstrap] Initialized Drupal 8.7.3 root directory at /var/www/html/drupal [0.23 sec, 8.62 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.23 sec, 8.62 MB]
 [bootstrap] Try to bootstrap at phase 5 [0.24 sec, 8.92 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalSite() [0.24 sec, 8.92 MB]
 [bootstrap] Initialized Drupal site default at sites/default [0.24 sec, 9.15 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.24 sec, 9.15 MB]
 [bootstrap] Try to bootstrap at phase 5 [0.24 sec, 9.15 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalConfiguration() [0.24 sec, 9.15 MB]
 [debug] Add service modifier [0.25 sec, 9.38 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.25 sec, 9.38 MB]
 [bootstrap] Unable to connect to database. More information may be available by running `drush status`. This may occur when Drush is trying to bootstrap a site that has not been installed or does not have a configured database. In this case you can select another site with a working database setup by specifying the URI to use with the --uri parameter on the command line. See `drush topic docs-aliases` for details. [0.26 sec, 9.63 MB]
 [bootstrap] Could not bootstrap at phase 5 [0.26 sec, 9.62 MB]

In BootstrapHook.php line 32:

  [Exception]
  Bootstrap failed. Run your command with -vvv for more information.

Exception trace:
  at /var/www/html/drupal/vendor/drush/drush/src/Boot/BootstrapHook.php:32
 Drush\Boot\BootstrapHook->initialize() at /var/www/html/drupal/vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php:34
 Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher->callInitializeHook() at /var/www/html/drupal/vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php:27
 Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher->initialize() at /var/www/html/drupal/vendor/consolidation/annotated-command/src/CommandProcessor.php:145
 Consolidation\AnnotatedCommand\CommandProcessor->initializeHook() at /var/www/html/drupal/vendor/consolidation/annotated-command/src/AnnotatedCommand.php:289
 Consolidation\AnnotatedCommand\AnnotatedCommand->initialize() at /var/www/html/drupal/vendor/symfony/console/Command/Command.php:221
 Symfony\Component\Console\Command\Command->run() at /var/www/html/drupal/vendor/symfony/console/Application.php:981
 Symfony\Component\Console\Application->doRunCommand() at /var/www/html/drupal/vendor/symfony/console/Application.php:254
 Symfony\Component\Console\Application->doRun() at /var/www/html/drupal/vendor/symfony/console/Application.php:147
 Symfony\Component\Console\Application->run() at /var/www/html/drupal/vendor/drush/drush/src/Runtime/Runtime.php:118
 Drush\Runtime\Runtime->doRun() at /var/www/html/drupal/vendor/drush/drush/src/Runtime/Runtime.php:49
 Drush\Runtime\Runtime->run() at /var/www/html/drupal/vendor/drush/drush/drush.php:72
 require() at /var/www/html/drupal/vendor/drush/drush/includes/preflight.inc:18
 drush_main() at phar:///usr/bin/drush/bin/drush.php:141
 require() at /usr/bin/drush:10

updatedb [--cache-clear [CACHE-CLEAR]] [--entity-updates] [--post-updates [POST-UPDATES]] [--no-cache-clear] [--no-post-updates] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-d|--debug] [-y|--yes] [--no] [--remote-host REMOTE-HOST] [--remote-user REMOTE-USER] [-r|--root ROOT] [-l|--uri URI] [--simulate] [--pipe] [-D|--define DEFINE] [--notify [NOTIFY]] [--druplicon] [--xh-link XH-LINK] [--] <command>

```

# Answer
> 3 votes
Finally figured out the problem.

Just change the host line in your settings.local.php:

```
'host' => '127.0.0.1',

```

---
Tags: database, drush, updating, composer
---


# Question
Title: Custom module with config exposed in json api
I have a module with two pieces of config set using an admin form and Drupal the drupal config service.

Like this

```
  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    parent::submitForm($form, $form_state);

    $this->config('mars_spot_collection.defaultcollections')
      ->set('default_collection_title', $form_state->getValue('default_collection_title'))
      ->set('default_collection_description', $form_state->getValue('default_collection_description'))
      ->save();
  }

```

How do I make this conig available in the JSONAPI?

Cheers

# Answer
> 0 votes
You can't do it. Not with the core JSON:API module. Out of the box, the resources JSON:API exposes are all the entity definitions from `EntityTypeManager` which includes content & config entities (defined by extending `ConfigEntityBase`).

However, arbitrarily set config values will not be exposed. JSON:API also doesn't support custom resources, as JSON:API docs state:

> The JSON:API module provides *no PHP API to modify its behavior.* It is designed to have zero configuration.
>
> • Adding new resources/resource types is unsupported: all entities/entity types are exposed automatically. If you want to expose more data via the JSON:API module, the data must be defined as entity. See the "Resources" section.

The JSON:API Resources project attempts to fill this in if you want to design your own endpoint with custom responses.

---
Tags: configuration, 8
---


# Question
Title: Why has this "details" accordion appeared in this view?
I have a view that uses the table format and the "group by" setting.

I've just updated to the Drupal 8.9. Suddenly, each group has this empty *Details* accordion.

>

It wasn't there before.

Why did it appear? How can I get rid of it, other than removing it with CSS?

>

# Answer
> 0 votes
I ran into this issue with a View as well. Fortunately, this issue was reported to Drupal Core, fixed and released in Drupal 8.9.2 and Drupal 9.0.2 all in under a month which is quite commendable.

I just tested this issue by upgrading a test to Drupal 8.9.2 which resolved this issue.

---
Tags: views, 8
---


# Question
Title: Unsupported serialization format on REST/Delete request
I'm getting the following error on my custom resource when sending the following DELETE request even though POST and GET are working fine

*"A fatal error occurred: Serialization for the format is not supported"*

The request looks as follows:

If I'd change the method from DELETE to GET it would return status 200 with the intended - and for testing purposes identical - behaviour. The configuration in the Rest UI module looks as the following and the permissions for the requests (GET, POST and DELETE) are allowed for Guests:

Here is the code of my custom class:

```
/**
 * Provides a Demo Resource
 *
 * @RestResource(
 *   id = "test_resource",
 *   label = @Translation("Demo Resource"),
 *   uri_paths = {
 *      "canonical" = "/test_rest_api/test/{email}",
         "https://www.drupal.org/link-relations/create" = "/test_rest_api/test",
 *   }
 * )
 */
class TestResource extends ResourceBase {
  //Here are construct and create functions

  /**
   * Responds to entity GET requests.
   *
   * Does something
   *
   * @return \Drupal\rest\ResourceResponse
   */
   public function get($email) {
    $message = ["message" => $email];
    return new ResourceResponse($message);
   }

  /**
   * Responds to entity POST requests.
   *
   * Does something
   *
   * @param $data
   * @return \Drupal\rest\ResourceResponse
   */
  public function post(array $data = []) {
    $message = ["message" => $data["email"]];
    return new ResourceResponse($message);
  }

  /**
   * Responds to entity DELETE requests.
   *
   * Does something
   *
   * @return \Drupal\rest\ResourceResponse
   */
  public function delete($email) {
    $message = ["message" => $email];
    return new ResourceResponse($message);
  }
}

```

Has somebody an idea what I'm overlooking? I disabled/enabled the resource multiple and cleared the cache multiple times

# Answer
> 6 votes
In delete method you can not return **ResourceResponse**. Try return **ModifiedResourceResponse**.

```
return new ModifiedResourceResponse(NULL, 204);

```

Notice: First argument of **ModifiedResourceResponse** need are NULL, if your specific data for this parameter throw same error.

# Answer
> 3 votes
Also in DELETE method if you want to return a response you could use return new JsonResponse('Processed'); including the following use statement: use Symfony\Component\HttpFoundation\JsonResponse;

# Answer
> 1 votes
With the help of @OPTASY's answer, I was able to return a response to the client's DELETE request. For example:

```
public function delete($email) {
  $message = ["message" => $email];
  return new JsonResponse(message);
}

```

Be sure to include `JsonResponse` at the top of your file:

```
use Symfony\Component\HttpFoundation\JsonResponse;

```

---
Tags: 8
---


# Question
Title: Allowing anonymous users to contact node authors
I want anonymous users to send messages to node authors. Also I want the sent messages to be visible to node authors in their user account. Here is what I have tried so far:

* Private message - Solves what I am looking for but does not work for anonymous users
* Webforms - New to it but I don't see a way for node authors to access the sent messages within their account

# Answer
> 0 votes
I'm pretty sure this can be done by combining the core Contact module with the Contact Storage module.

Steps to implement

1. Enable the Contact module and give anonymous the permission **Use users' personal contact forms**.
2. Enable the Contact Storage module and create a view showing **Contact message**. Configure a contextual filter with the user ID so that only messages to the logged-in user are displayed.

---
Tags: webforms, message-subscribe, 8
---


# Question
Title: Display summary of paragraph text field in twig
I have a paragraph type called News. In this paragraph type I have a text field (field\_news\_intro ) with a summary. How do I display the summary in a twig template?

`content.field_news_intro.summary` seemed logical, but it doesn't return anything.

My template is called paragraph--news.html.twig

```
<div class="copy larger">
  {{ content.field_news_intro.summary }}
</div>
<div class="copy">
  {{ content.field_news_intro }}
</div>

```

# Answer
> 1 votes
you can get the summary with `summary` attribute in field level.

```
{{ content.YOUR_FIELD_NAME['#items'][0].summary }}

```

in your case answer will be :

```
{{ content.field_description['#items'][0].summary }}

```

---
Tags: theming, paragraphs
---


# Question
Title: How can I attach an image from an existing image field to another multi-value image field?
I have the nodes that have the source image field `field_old_image_field` and the destination image field, `field_new_image_field`. `field_old_image_field`has only one image. `field_new_image_field`can have multiple images and probably does. I need to copy the image from `field_old_image_field` to `field_new_image_field` without disturbing the images that are already in `field_new_image_field`.

Here's my code so far:

```
foreach ($nodes as $node) {
    if ($node->hasField('field_old_image_field') && !empty($node->field_old_image_field->target_id)) {
      $image = $node->get('field_old_image_field');
      $image_uri = $image->entity->getFileUri();
      $image_alt = $image[0]->get('alt')->getString();
      $image_title = $image[0]->get('title')->getString();

      $node->get('field_new_image_field')->appendItem([
        'target_id' => $image,
        'alt' => $image_alt,
        'title' => $image_title,
      ]);
    }

    $node->save();
  }

```

But when I run this code in an update hook, I get

```
In EntityReference.php line 106:

Value is not a valid entity.

```

I was getting it to work earlier, but I wasn't getting the `alt` text or the `title` text copied over. What's wrong with this code and is there an easier way to do this?

# Answer
> 1 votes
The first line doesn't get you an image, it's a field item list:

```
$items = $node->get('field_old_image_field');

```

Then you can get the first item

```
$item = $items[0];

```

and append the item properties to the new field:

```
$node->get('field_new_image_field')->appendItem([
  'target_id' => $item->target_id,
  'alt' => $item->alt,
  'title' => $item->title,
]);

```

---
Tags: 8
---


# Question
Title: Anonymous checkout doesn't properly work
Anonymous users are supposed to have access to Commerce cart/checkout by default. In my current project cart remains empty for anonymous users, even if an order is created. When an anonymous user clicks on *Add to cart*, a new order is correctly created, with the *Owned by anonymous* status. This is fine, but:

* While the current product page is reloaded as expected, the rule displaying the default message (*Foo was added to your cart*) is not fired
* If I manually go to /cart, I get the *Cart is empty* message. /checkout returns a 404 error.
* `$_SESSION` remains empty (I precise this because of `commerce_checkout_access()`).

```
if (empty($_SESSION['commerce_cart_orders']) || !in_array($order->order_id, $_SESSION['commerce_cart_orders'])) {
  return FALSE;
}

```

In fact, it seems that in anonymous context, the order cannot be seen.

How do I debug why the cart remains empty, and the order isn't visible to anonymous users?

My config: clean step by step Commerce install, not Kickstart; some custom line items ; *Access checkout / View own orders of any type / View any product of any type* permissions granted for anonymous.

# Answer
> 8 votes
Happy end, and stupid lost time : the lone problem was the **Anonymous user was accidentally deleted** (don't know how) ! I thank all the gentlemen who tried to help me to debug.

The uid 0 must absolutely be there. If you encounter such case, simply insert an empty row in users table via phpmyadmin or run these 2 queries (for D7) :

```
insert into users (name, pass, mail, theme, signature, language, init, timezone) values ('', '', '', '', '', '', '', '');
update users set uid = 0 where name = '';

```

Meanwhile, I've read many things about *Commerce checkout* to make sure I was doing right. I share some clues below in case it could help somebody else.

**A common issue for empty cart page** (and other Commerce Views issues where user can't see products) is due to *Referenced Product Relationship*: 2 solutions may work depending on your config :

* In the View's advanced settings fieldset, disable SQL rewriting.
* Enable the not-totally-secure `View any product of any type` permission. This is discussed & patched here. If you have *Commons* distribution, you’ll have to disable paranoia (disable with Drush only, it's not visible in the module list).

**Important permissions to grant** (admin/people/permissions) :

* Anonymous :
    + Checkout =\> Access checkout
    + Order =\> Create orders of any type / Create orders
* Authenticated : same ones, plus
    + Order =\> View own orders of any type / View own orders

**Default behavior in Drupal Commerce :**

Anonymous users can add a product to cart, checkout (filling email, name and address), review and complete order. Some documentation to read : Checkout: Anonymous vs. Authenticated and Anonymous Carts and Logged In Users

---

## An a few useful tips and links to enhance default checkout

# Answer
> 0 votes
find file docroot/web/sites/all/modules/contrib/commerce/modules/cart/commerce\_cart.module

find function commerce\_cart\_get\_provider and force it to load CommerceCartProviderSession class

```
/**
 * Returns the instantiated cart provider.
 */
function commerce_cart_get_provider($provider = NULL)
{
  ctools_include('plugins');

  if (empty($provider)) {
     $file = DRUPAL_ROOT . '/' . drupal_get_path('module', 'commerce_cart') . "/plugins/cart_provider/CommerceCartProviderSession.class.php";
     require_once($file);
     $class = 'CommerceCartProviderSession';
     return new $class();
    // the following line was not working
    // $provider = variable_get('commerce_cart_provider', COMMERCE_CART_DEFAULT_PROVIDER);
  }

  // Return NULL if the class could not be found.
  if (!$class = ctools_plugin_load_class('commerce_cart', 'cart_provider', $provider, 'class')) {
    return NULL;
  }

  return new $class();
}

```

---
Tags: commerce, users
---


# Question
Title: how to add an event subscriber when the user reaches the login form
I am new on Drupal 8 , I have implemented a hook 'hook\_form\_alter' in my module to add a new field to the login form , but now I want to handle it with the event , I want to trigger an event when the user reaches the login form and then add this field using event not a hook.

Can anyone please suggest me how to do it ?

This is the hook

```
function my_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_login_form' ) {
    // Add placeholders.
    $form['condition'] = array(
      '#type' => 'checkbox',
      '#options' => t('Enable'),
      '#title' => t('J’accepte les conditions'),
      '#required' => true,
    );
  }
}

```

# Answer
> 1 votes
You can't, not with core alone. D8 doesn't have a form-alter event.

D8 added events as an alternative to some D7 hooks but didn't fully replace all the hooks available. Replacing all hooks was mooted for a D10 goal but didn't make the cut.

As such, the only way to do this modify core functionality like:

* Patch core (see issue comment) to add form-alter events.
* Do something like Hook Event Dispatcher which wraps custom form-alter events around a `hook_form_alter` handler.

Then add an event subscriber for it.

---
Tags: 8, event-subscribers
---


# Question
Title: Inline entity form module fails when creating a new node and the reference method is Views
I have a Drupal 8, core version:8.8.x project, i'm using **inline entity form** module(latest version) for entity reference fields. Also i have tried using entity connect module but it caused various issues. The problem is when creating a new node, using the **inline entity form** and the **reference method** of field is **Views: Filter by an entity reference view** this error is coming up:

```
This entity (node: newNode) cannot be referenced.

```

How to reproduce:

1. Install inline entity form module
2. Create an entity reference field in any content type with **Views: Filter by an entity reference view** as reference method.
3. To your content type manage form display choose **inline entity form - complex** for widget.
4. Add new node for your content type, press add new node to your reference field, fill the modal form, publish it and press create new node(referenced node).
5. Lastly publish and save your node.

I tried some patches published to project issues but most of them are not applying at all. I would appreciate any ideas for solving it or suggestions for using a similar module.

# Answer
> 0 votes
See patch located

Drupal core patch

#42 works with Drupal 8.9.2 give that a try, it should fix your problem.

---
Tags: 8, nodes
---