# Question
Title: What is best practice for passing routing parameters?
In submitForm() I want to redirect to a controller and pass the form values. The form values are all arrays, btw.

Here is submitForm.

```
public function submitForm(array &$form, FormStateInterface $form_state) {
    // get values
    $demo_values = $form_state->getValue('demo');
    $data_set_value = $form_state->getValue('data_set');
    $engineering_degrees1 = $form_state->getValue('engineering_degrees1');
    $engineering_degrees2 = $form_state->getValue('engineering_degrees2');
    $engineering_degrees3 = $form_state->getValue('engineering_degrees3');
    $engineering_degrees4 = $form_state->getValue('engineering_degrees4');
    $physical_science_degrees = $form_state->getValue('physical_science_degrees');

    # set form data in url redirect
    $params = ['demos' => $demo_values,
      'data_set' => $data_set_value,
      'engineering_degrees1' => $engineering_degrees1,
      'engineering_degrees2' => $engineering_degrees2,
      'engineering_degrees3' => $engineering_degrees3,
      'engineering_degrees4' => $engineering_degrees4,
      'physical_science_degrees' => $physical_science_degrees];
    $form_state->setRedirect('stats_degrees.render_chart',$params);
  }
}

```

Here is my routing YML file.

```
stats_degrees.render_form:
  path: '/statistics/stats-degrees'
  defaults:
    _title: 'Engineering and Physical Science Degrees Earned by Members of Underrepresented Groups'
    _form: '\Drupal\stats_degrees\Form\StatsDegreesForm'
  requirements:
      _permission: 'access content'
stats_degrees.render_chart:
  path: '/statistics/stats-degrees-chart/{demos}/{data_set}/{engineering_degrees1}/{engineering_degrees2}/{engineering_degrees3}/{engineering_degrees4}/{physical_science_degrees}'
  defaults:
    _controller: '\Drupal\stats_degrees\Controller\StatsDegreesController::stats_degrees_chart'
  requirements:
    _permission: 'access content'

```

Here is my Controller method call.

```
public function stats_degrees_chart($demos,$data_set,$engineering_degrees1,$engineering_degrees2,$engineering_degrees3,$engineering_degrees4,$physical_science_degrees) {

```

Currently, it's throwing a 500 error after I submit the form. Is there a better way to pass the parameters to the controller?

# Answer
> 2 votes
What is best practice to pass the parameters to the controller is opinion based and depends on the use case, so I try to cover all possible approaches.

In general, there are three other ways to pass parameters to controllers, query string, POST data and SESSION. You could serialize the arrays for the query string, but easier would be POST or SESSION.

See How to get $\_POST and $\_GET parameters in a controller.

If you use session values then unset them at the end of the controller because no longer needed session values are bad for caching. See How can I destroy or unset session?.

Specifically for forms there is more. If the purpose of the form is to store the values in the database (permanently in an entity or temporarily in a tempstore), do this first and then reference the database item via a routing parameter.

If you don't want to store the data it could make sense to post the data directly to the controller because you can't attach POST data to a submit redirect.

You don't necessarily need a controller, you can rebuild the form displaying the chart below the form or replacing it. See How do I show the result on same page after submitting the form?

# Answer
> 1 votes
You can use a private tempstore. See for example http://karimboudjema.com/en/drupal/20190315/saving-temporary-values-form-private-tempstore-drupal-8

---
Tags: forms, routes
---


title: Feeds event subscriber stopped working

text:
# Question
Title: Feeds event subscriber stopped working
For some reason my feeds event subscribers have just stopped working.

My code looks like this, the dpm for debugging never gets fired so I think the function isn't being run.

I can't work out what's changed.

```

namespace Drupal\partshub_feeds_modifications\EventSubscriber;

use Drupal\feeds\Event\EntityEvent;
use Drupal\feeds\Event\FeedsEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Reacts to feeds events to modify feed properties.
 */
class FeedsSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events = [];
    $events[FeedsEvents::PROCESS_ENTITY_PRESAVE][] = 'presave';
    $events[FeedsEvents::PROCESS_ENTITY_POSTSAVE][] = 'postsave';

    return $events;
  }

  /**
   * Acts on presaving an entity.
   *
   * @param Drupal\feeds\Event\EntityEvent $event
   *   The feed event.
   */
  public function presave(EntityEvent $event) {
    dpm($event);
    // Get the feed object.
    $feed = $event->getFeed();
    // Get the entity being operated on.
    if ($feed->type->entity->id() === 'parts') {
      $entity = $event->getEntity();
      // Get the unchanged entity.
      $unchanged_entity = \Drupal::entityTypeManager()
        ->getStorage('node')
        ->loadUnchanged($entity->id());
      // Check if the entity is new.
      if (!$entity->isNew()) {
        // Only if part is not new check values.
        if ($feed->type->entity->label() === 'Parts') {
          if ($entity->get('title')->value === 'empty') {
            $entity->get('title')->value = $unchanged_entity->get('title')->value;
          }

          // Part fitment/makes field.
          if ($entity->get('field_make')->isEmpty()) {
            $makes = $unchanged_entity->get('field_make')->referencedEntities();
            foreach ($makes as $index => $term) {
              $tid = $term->id();
              if ($index == 0) {
                $entity->set('field_make', $tid);
              }
              else {
                $entity->get('field_make')->appendItem([
                  'target_id' => $tid,
                ]);
              }
            }
          }

          // Part group code.
          if ($entity->get('field_group_code')->isEmpty()) {
            $codes = $unchanged_entity->get('field_group_code')
              ->referencedEntities();
            foreach ($codes as $index => $code) {
              $code_id = $code->id();
              if ($index == 0) {
                $entity->set('field_group_code', $code_id);
              }
              else {
                $entity->get('field_group_code')->appendItem([
                  'target_id' => $code_id,
                ]);
              }
            }
          }

          // Cross references.
          if ($entity->get('field_cross_references')->isEmpty()) {
            $references = $unchanged_entity->get('field_cross_references')
              ->referencedEntities();
            foreach ($references as $index => $reference) {
              $reference_id = $reference->id();
              if ($index == 0) {
                $entity->set('field_cross_references', $reference_id);
              }
              else {
                $entity->get('field_cross_references')->appendItem([
                  'target_id' => $reference_id,
                ]);
              }
            }
          }
        }
        elseif ($feed->type->entity->label() === 'Physical attributes') {
          if ($entity->get('title')->value === 'empty') {
            $entity->get('title')->value = $unchanged_entity->get('title')->value;
          }
          // Part weight.
          if ($entity->get('field_weight')->isEmpty()) {
            $entity->get('field_weight')->value = $unchanged_entity->get('field_weight')->value;
          }
          // Part Height.
          if ($entity->get('field_height')->isEmpty()) {
            $entity->get('field_height')->value = $unchanged_entity->get('field_height')->value;
          }
          // Part Width.
          if ($entity->get('field_width')->isEmpty()) {
            $entity->get('field_width')->value = $unchanged_entity->get('field_width')->value;
          }
          // Part Depth.
          if ($entity->get('field_depth')->isEmpty()) {
            $entity->get('field_depth')->value = $unchanged_entity->get('field_depth')->value;
          }
        }
      }
    }
  }

  /**
   * Acts on presaving an entity.
   *
   * @param Drupal\feeds\Event\EntityEvent $event
   *   The feed event.
   */
  public function postsave(EntityEvent $event) {
    $feed = $event->getFeed();
    $feeds = ['oe_references', 'sub_components', 'dimensions'];
    $id = $feed->type->entity->id();
    if (in_array($id, $feeds)) {
      $entity = $event->getEntity();
      $parent_field_name = $entity->parent_field_name->value;
      $parent_id = $entity->parent_id->value;
      $vid = \Drupal::entityTypeManager()->getStorage('node')->getLatestRevisionId($parent_id);
      $part = \Drupal::entityTypeManager()->getStorage('node')->loadRevision($vid);
      $paragraph_references = $part->get($parent_field_name)->referencedEntities();
      $paragraph_references_id = [];
      if ($paragraph_references) {
        foreach ($paragraph_references as $paragraph_reference) {
          $paragraph_references_id[] = $paragraph_reference->id();
        }
      }
      if (!in_array($entity->id(), $paragraph_references_id)) {
        $fields = [
          'field_oe_references', 'field_sub_components_', 'field_dimensions'
        ];
        if (in_array($parent_field_name, $fields)) {
          if ($part) {
            $part->{$parent_field_name}[] = $entity;
            $part->save();
          }
        }
      }
    }
  }

}

```

I also have a service definition as follows.

```
services:
  # Name of this service.
  parthsub_feeds_modifications_events_subscriber:
    # Event subscriber class that will listen for the events.
    class: Drupal\partshub_feeds_modifications\EventSubscriber\FeedsSubscriber
    # Tagged as an event_subscriber to register this subscriber with the event_dispatch service.
    tags:
      - { name: event_subscriber }

```

# Answer
> 0 votes
No answer to this, I was getting validation errors before the presave was fired which meant this code never fired.

---
Tags: feeds, event-subscribers
---


title: Off canvas dialog using a button

text:
# Question
Title: Off canvas dialog using a button
I am trying to adapt the relatively new off canvas dialog introduced in Drupal 8.5.

It is suggested to use it with the Drupal Form-API and a link element like this:

```
$form['off_canvas'] = [
  '#title'      => 'Some title',
  '#type'       => 'link',
  '#url'        => \Drupal\Core\Url::fromRoute('some route'),
  '#attributes' => [
    'class'                => ['use-ajax'],
    'data-dialog-type'     => 'dialog',
    'data-dialog-renderer' => 'off_canvas',
    'data-dialog-options'  => \Drupal\Component\Serialization\Json::encode(['width' => '40%']),
  ],
  '#attached'   => [
    'library' => [
      'core/drupal.dialog.ajax',
    ],
  ],
];

```

This works pretty straight forward and out of the box, but for a very special use case I need to attach an AJAX-callback with a button element which is not possible using a link element when looking at the Drupal form API specifications.

This is what I got trying to use a button element and a callback with off canvas dialog functionality:

```
$form['some_button'] = [
  '#type'     => 'button',
  '#value'    => 'some value',
  '#attached' => [
    'library' => [
      'core/drupal.dialog.ajax',
    ],
  ],
  '#ajax'     => [
    'callback' => '::some_callback',
  ],
];

```

Callback function goes here:

```
public function some_callback(&$form, FormStateInterface $form_state) {

  $response = new \Drupal\Core\Ajax\AjaxResponse();

  $title = 'Some title';

  $content = '<div>Some content</div>';
  $options = [];
  $response->addCommand(new \Drupal\Core\Ajax\OpenOffCanvasDialogCommand($title, $content, $options));
  return $response;
}

```

The funny thing is: once the off canvas dialog is initialized using `$form['off_canvas']` it works on both elements for `$form['off_canvas']` and `$form['some_button']`. On pageload it uses the old dialog for `$form['some_button']` and the new off canvas dialog for `$form['off_canvas']`.

So this must be an initialization problem for `$form['some_button]`. But I can not get this to work with the off canvas dialog at pageload and documentation for the new off canvas functionality is quite rare.

I tried to tell `$form['some_button']` to use off canvas as a parameter in a lot of ways, but it does not work. I guess I missed something here.

Can you guys give me a hint how to make this work from the very start using a button with an Ajax callback?

# Answer
When getting back to this issue I did notice the strange behaviour is gone after upgrading to the latest Drupal 8.6.3. All works as expected even using a button.

I am not able to reproduce the behavior/error from above.
> 0 votes

# Answer
How do I adapt this to open off-canvas dialog from javascript/jquery? I've tried the Drupal.dialog script which only opens normal dialogs. I've also seen the Drupal.offCanvas {} script - which is largely undocumented. Any pointers please?
> 0 votes

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


# Question
Title: Programmatically removing value from multi-valued field of a content type
I have a custom content type with a field (id is field\_link\_to\_persona) that is multi-valued text. In my UI I have checkboxes that correspond to values in that field and if I uncheck the box and save I want to remove the value from the field.

I load the node like this:

```
$nodes = \Drupal::entityTypeManager()
            ->getStorage('node')
            ->loadByProperties(['type' => 'document', 'nid' => $docID ]);

            $node = reset($nodes);

```

I can add new values like this:

```
$node->field_link_to_persona[] = $newValue;

```

But how do I remove one? I tried

```
$node->field_link_to_persona->removeItem($id);

```

But I keep getting exceptions about the index not existing.

Any help would be appreciated. I'm somewhat new to drupal so no detail is too trivial :)

# Answer
I recently ran into this same issue. Here is how I was able to make this work. In my case, I was working with a user but it can be easily updated for a node as well.

```
$user = User::load(\Drupal::currentUser()->id());
$id_to_remove = '81' // Make sure to update this to be the actual id you want to remove through something like $term->id().

// Get the field
$my_field = $user->get('field_my_field');
$my_field_values = $my_field->getValue();

// Get the index to remove
$index_to_remove = array_search($id_to_remove,array_column($my_field_values,'target_id'));

// Actually remove the item
$my_field->removeItem($index_to_remove);

// save the user
$user->save();

```
> 5 votes

---
Tags: nodes, entities
---


# Question
Title: How do I Bulk Edit Fields or Taxonomy of Nodes?
I'm working on a site that needs bulk tagging on nodes. The D8 core View Bulk Operations Port is "simple" (https://www.drupal.org/node/1823572) and it doesn't have "modify entity values" which I used for this user-case in D7. There isn't a D8 tagged version of contrib VBO I can find.

My specific use-case is I need to bulk tag groups of blog posts with single terms. I have bulk imported around 2000 nodes from wordpress and need to apply new tags to them. Once the backlog id tagged I don't really need bulk editing any more. (But I'm sure many folks have similar use cases, like bulk editing fields or tags that aren't one-off tasks)

Actions is part of Core so it might be possible to write custom actions for my use case (Tag node with taxonomy term X, Y or Z). This documentation seems the most promising. https://www.drupal.org/node/2020549

Can any confirm this is best way to bulk-edit nodes or is there a different approach that I should consider?

# Answer
Drupal core doesn't provide this functionality, so yes, you need to implement it yourself.

Yes, you can implement your own action plugin to do this. You can also have a form to select which tag you want to apply. Have a look at the node delete action plugin, which uses a confirmation form, but you can implement whatever functionality you want in that form.

Keep in mind that Drupal core is missing another important feature for your use case. The ability to apply a bulk action to more than one page. The best you can do until there is a port of the contrib module to provide this to increase the amount of rows per page, so that you need to repeat it fewer times.
> 7 votes

# Answer
Berdir's answer is accurate, you must write your own action.

I found this article extremely useful to quickly achieve this.

Basically when you create and registering a new action you can specify a 'confirm form', eg 'Are you sure you want to do this?'. You can provide a form for this stage that accepts more information and then uses that information to perform a batch operation on the nodes/entities who's IDs have been passed through.

Note that, as Berdir stated, the action to perform a bulk operation across multiple pages is still (to my knowledge) missing.
> 4 votes

# Answer
views bulk operations (https://www.drupal.org/project/views\_bulk\_operations) gives a special views field that will allow you to bulk change fields

bulk\_update\_fields also promises exactly that. Its a new module for drupal 8 and seems to work with some warnings (in my case)

you can install it stand alone and go to `content/node` and use it as action `bulk update fields to another value` or if you have `view bulk operations` installed overriding `content/node` path you can edit the view and there will be a new action available (which will need to be enabled)
> 1 votes

# Answer
Today, for taxonomy, it's possible via Taxonomy Bulk Actions (TBA) contrib module.
> 0 votes

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


title: Protect user login page with Basic Auth

text:
# Question
Title: Protect user login page with Basic Auth
Is it possible to make Drupal more secure by making LOGIN page private? I would like to make /user/login page private with Basic Auth so an user and password are needed before I get in that page.

Or is there another ways to make the login more safe? Goal is to prevent hackers to get in. Also if there's some module that helps on this it would be nice.

# Answer
> 2 votes
From your question

> Is there another ways to make the login more safe?

Yes,try one of the following modules

Login Security

> Login Security module improves the security options in the login operation of a Drupal site. By default, Drupal introduces only basic access control denying IP access to the full content of the site.

Secure Login

> Secure Login module enables the user login and other forms to be submitted securely via HTTPS, thus preventing passwords and other private user data from being transmitted in clear text. Secure Login module locks down not just the user/login page but also any page containing the user login block (or other forms that you configure to be secured).

# Answer
> 1 votes
You could also:

* Define https protocol for the login page (and the backend) on the Vhost directives. see https://www.drupal.org/https-information. But secure login or password policy module seems great because they also take care of the cookie protection.
* Increase the passwords complexity (lenght, signs, etc). The module Password policy could interest you.
* Setup fail2ban and create a jail for Drupal to ban recurrent attacker (see Vincent article for example)

# Answer
> 0 votes
You may set up a Basic Auth on the /user/ URL.

See this question: https://serverfault.com/questions/532039/apache-basic-auth-for-a-particular-url

A proposed solution modified for this particular situation:

```
#set an environtment variable "auth" if the request starts with "/user"
SetEnvIf Request_URI ^/user auth=1

AuthName "Please login to access"
AuthType Basic
AuthUserFile "/path/to/my/.htpasswd"

# First, allow everybody
Order Allow,Deny
Satisfy any
Allow from all
Require valid-user
# Then, deny only if required
Deny from env=auth

```

# Answer
> 0 votes
In Drupal 8 and 9, you can prevent anonymous access to the /user/login page using the Disable Login module. The module will require users to use an additional querystring and secret value for the querystring to access /user/login.

Admin user can set both the name of the QueryString and the value which will allow access to the login page.

For eg:

http://example.com/user/login

will give access denied.

http://example.com/user/login?key=secret

will allow the user to access the login page if key and secret are the name and value configured in the module.

---
Tags: users
---


title: Debugging "UNCACHEABLE" header

text:
# Question
Title: Debugging "UNCACHEABLE" header
We have a site where the homepage is not being cached and contains the headers:

```
x-cache: MISS, MISS
x-cache-hits: 0, 0
x-content-type-options: nosniff
x-drupal-dynamic-cache: UNCACHEABLE

```

I narrowed this down to the content regions contents, and disabled the "Main page content" for the front page. This then gave me a cache HIT, and no longer responded as UNCACHEABLE. From there, I narrowed it down to a field formatter being used on a paragraph. We have a custom one that extends the normal entity render formatter.

If I swap it back to the original "Render entity" formatter, everything is fine. So then, it must be something we are doing in this custom formatter causing the issue.

I can see when I follow with xdebug that shouldCacheResponse of DynamicPageCacheSubscriber returns FALSE, because something is setting max-age to 0 (not by code). It looks like calls to addCacheableDependency may be triggering this behavior in the formatter:

Essentially, the formatter adds cache data to the render so if any of its referenced items are updated, the cache should be invalidated for that host paragraph so it re-renders:

```
     $view_builder = \Drupal::entityTypeManager()->getViewBuilder($entity->getEntityTypeId());
      $elements[$delta] = $view_builder->view($entity, $view_mode, $entity->language()->getId());

      try {
        $parent = $items->getParent();
        $parent_entity = $parent->getValue();
        $elements[$delta]['#cache']['keys'][] = $parent_entity->id();
        $elements[$delta]['#cache']['keys'][] = $parent_entity->bundle();
        $elements[$delta]['#cache']['keys'][] = $parent_entity->getEntityTypeId();
        $elements[$delta]['#cache']['keys'][] = 'delta_' . $delta;
        $elements[$delta]['#cache']['keys'][] = 'context_aware';

        $this->renderer->addCacheableDependency($elements[$delta], $parent);

        if ($entity->hasField('field_author')) {
          $child = $entity->field_author->entity;

          if (isset($child)) {
            $this->renderer->addCacheableDependency($elements[$delta], $child);
          }
        }

        // similar statements with addCacheableDependency

```

If I comment out this initial line:

```
$this->renderer->addCacheableDependency($elements[$delta], $parent);

```

Then I get a cacheable response. This looks to be because the $parent item (even though it is a node or paragraph or media entity) triggers this:

```
  /**
   * Creates a CacheableMetadata object from a depended object.
   *
   * @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $object
   *   The object whose cacheability metadata to retrieve. If it implements
   *   CacheableDependencyInterface, its cacheability metadata will be used,
   *   otherwise, the passed in object must be assumed to be uncacheable, so
   *   max-age 0 is set.
   *
   * @return static
   */
  public static function createFromObject($object) {
    if ($object instanceof CacheableDependencyInterface) {
      $meta = new static();
      $meta->cacheContexts = $object->getCacheContexts();
      $meta->cacheTags = $object->getCacheTags();
      $meta->cacheMaxAge = $object->getCacheMaxAge();
      return $meta;
    }

    // Objects that don't implement CacheableDependencyInterface must be assumed
    // to be uncacheable, so set max-age 0.
    $meta = new static();
    $meta->cacheMaxAge = 0;
    return $meta;
  }

```

Setting cacheMaxAge to 0 because it is not an instance of CacheableDependencyInterface.

If I am already setting the cache keys, is this line even needed:

```
$this->renderer->addCacheableDependency($elements[$delta], $parent);

```

If I remove that, will there be an adverse effect (like render displays not re-rendering when referenced items are saved)?

# Answer
> 5 votes
This was a good debug deep dive. As mentioned by 4k4 the problem is the first `addCacheableDependency` line.

Instead of passing the host entity itself, I was mistakenly passing the object returned from `getParent` which is a `TypedData` instance that does not implement `CacheableDependencyInterface` \- thus causing the max-age to be set to 0 and the `UNCACHEABLE` header result.

Passing the entity (returned from `getValue()`) resolved the issue:

```
    $parent = $items->getParent();
    $parent_entity = $parent->getValue();
    ...
    $this->renderer->addCacheableDependency($elements[$delta], $parent_entity);

```

---
Tags: 8, caching, performance
---


# Question
Title: How to use drupal_add_library with a module?
I'm new to Drupal and don't really understand how to set up drupal\_add\_library.

I've made a simple module that links out to a .js file. However, this .js file depends on a couple of generic functions. I've put this generic functions in a library and want to call them.

I've set up my code as such:

```
function products_preprocess_page(&$variables) {
  drupal_add_library($module, $name);
  drupal_add_js(drupal_get_path('module', 'products') . '/assets/myScript.js');
}

```

But am not sure what to put in $module and $name (I'm assuming name is the actual name of the .js you want to call from the library), or even if this is the right place to call it.

Can anyone point me in the right direction?

# Answer
You can call it in that hook if you want it on every page (or add some logic to restrict the pages that it loads on), that's fine.

As per the API:

> **$module:** The name of the module that registered the library.
>
> **$name:** The name of the library to add.

If you're creating your own library, Jimmy Ko is correct: you need to declare it in hook\_library.

Note that `$name` should exclude the file extension (e.g. `.js`)
> 0 votes

# Answer
The arguments required by `drupal_add_library()` are the following.

* `$module`: The machine name of the module that registered the library in a `hook_library()` implementation
* $name: The name of the library to add

For example, for the *farbtastic* library, the call to `drupal_add_library()` should be `drupal_add_library('system', 'farbastic')`, since that library is defined in `system_library()`.

Adding libraries and JavaScript in `hook_preprocess_page()` is probably too late, as `template_process_html()` already added them to the page markup.

```
  $variables['head'] = drupal_get_html_head();
  $variables['css'] = drupal_add_css();
  $variables['styles'] = drupal_get_css();
  $variables['scripts'] = drupal_get_js();

```

It's preferable to use `hook_page_build()` to add the library (and the JavaScript code) using the *#attached* property as described in How to add jQuery UI libraries to a page. (Despite the title, what described is valid for every library and JavaScript code.)

Since *#attached* can be used in any render array or form array, it can be used in any hook that returns a render or a form array, or that alters a render or a form array, including `hook_form_alter()`.

```
  // Adds a form field that the javascript utilizes or modifies.
  $form['location'] = array(
    '#type' => 'textfield',
    '#title' => 'Your Location (Country)',
    '#id' => 'country_autocomplete',
    // Both the library and custom JavaScript code are added to the '#attached'
    // property of a renderable array.
    '#attached' => array(
      'library' => array(
        array('system', 'ui.autocomplete'),
      ),
      'js' => array(
        "$path/mymodule-custom-javascript.js",
      ),
    ),
  );
}

```

Drupal can use only the libraries that are added with `hook_library()`, which means that a module that wants to use its own libraries needs to `hook_library()` too.

You can also add a `scripts[]` line in the module/theme .info file if that JavaScript code needs to be added to every page, as described in Writing module .info files (Drupal 7.x). This allows JavaScript to be aggregated in an optimal way.
CSS styles can also be added with `stylesheets[]`.

```
stylesheets[all][] = node.css
scripts[] = somescript.js

```
> 0 votes

---
Tags: 7, javascript
---


title: Get list of applicable shipping methods

text:
# Question
Title: Get list of applicable shipping methods
I would like to get the list of applicable shipping methods for the current cart but dependent on the selected shipping profile. I'm programming a custom controller that should returns the list of available shipping methods and rates but, obviously, given a cart and a customer's shipping profile.
Has commerce shipping module any service or class that could I use to get this information? Perhaps, is there any other way to get it?

I've been reading source code from:
*Commerce\_Shipping\src\Plugin\Commerce\CheckoutPane\ShippingInformation.php*
That is the CheckoutPane plugin that renders shipment options in checkout page. `buildPaneForm` method renders this form, and those lines of code should give me the list of shipping methods:

```
 public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
    ...
    $shipments = $this->order->get('shipments')->referencedEntities();
    ...
    foreach ($shipments as $index => $shipment) {
    ... // all shipments
    }

```

But I have tried it in my custom controller and It always returns empty array. I think there should be a prior process that populate this list, but I can't find it. I have tried appling a state transition but It doesn't work.

# Answer
After some in-depth research on commerce modules, I have found a way to get them. This is an excerpt of the source code with the main instructions (controller class that returns JSON):

```
public function getShippingMethods(Request $request, $id) {

    $commerce_order = Order::load($id);
    // ... some checks to ensure it is a commerce order

    $shipments = $commerce_order->get('shipments')->referencedEntities();

    $options = [];
    foreach ($shipments as $shipment) {
      assert($shipment instanceof ShipmentInterface);
      $rates = $this->shipmentManager->calculateRates($shipment);
      foreach($rates as $rate) {
        $options[] = [ "id" => $rate->getShippingMethodId(),
                       "method" => $rate->getService()->getLabel(),
                       "import" => $rate->getAmount()->getNumber(),
                       "description" => $rate->getDescription()];
      }
    }

    // Return JSON with all shipping methods
    return new JsonResponse( $options );
  }

```

Hope It could help someone.
> 0 votes

---
Tags: 8, commerce
---


# Question
Title: Need to add multiple roles to routing.yml file
I want to assign multiple roles in my routing.yml file :

requirements: \_role: "\['role1', 'role2', 'role3'\]"

This is what I currently have, and it doesn't work.

Can someone tell me how to add this?

Thanks in advance!

# Answer
> 10 votes
I would strongly advise using permissions, not roles. Permissions are super simple to create in D8+, see How do you create a custom permission to administer a custom module?

The Structure of routes documentation says:

> **\_role:** A specific Drupal role, for example 'administrator'. You can specify multiple ones via "," for AND and "+" for OR logic.

> For example, `_role: organizer,participant,controller` means a Drupal user needs to have all three roles to access the page. Note that, since the roles available may differ between sites, it's recommended to use permission-based access restriction when possible.

So if a user needs all three roles, it's:

```
_role: 'role1,role2,role3'

```

or if they just need one of the three roles, it's:

```
_role: 'role1+role2+role3'

```

---
Tags: 8
---


title: how to add javascript to an article?

text:
# Question
Title: how to add javascript to an article?
just installed a stock Drupal 9.2.2 core, trying to create an article with the /node/add/article editor, how do i add javascript to the article?

# Answer
> 2 votes
As @Kevin mentioned in the comments above, you are approaching this from the wrong angle.

By design, Drupal core (since at least Drupal 5) uses text filters and input formats to sanitize HTML added by users in WYSIWIG editors like the default CKEditor.

Earlier versions of Drupal were more permissive in this regard, but years of security patches for various cross-site scripting exploits have made it very difficult indeed to insert inline JS in this way -- and for good reason.

With Drupal, you're not just saying "I trust myself to add JS to this one Article," you're saying "I trust all users whose Roles grant them the permission to use this text filter." It's not easy to create an insecure text filter anymore. If you did, you would want to restrict its use to only trusted users with Admin roles.

For an experienced Drupalist, it's no big deal to attach a JavaScript asset to a render array. CSS and JS assets are managed in Drupal by creating libraries which can be attached to Drupal's render arrays in a variety of ways, using either a custom module or a custom theme, via either PHP code or Twig templates.

(If you're putting up a Drupal site *without* a custom theme, you might want to reconsider. You can quickly make a subtheme of whatever your current theme is, so that you can easily modify things like the JS libraries and Twig templates.)

However, I understand your reluctance to learn custom module or theme development just to add a little JavaScript.

This forum is supposed to be used for answering questions about Drupal core, not recommending contrib modules. Nonetheless, there is a relatively new module that might suit your needs:

Component

From the Component module's Project page:

> Adding JS components to your Drupal site just got a whole lot easier. Just combine your JS components (any type) with a `*.component.yml` and put it in your module or theme. Now, your component will be available in Drupal as a block - automatically!

Admittedly, this is not as easy as pasting something in a WYSIWYG field, but that was never going to work anyway (because security.) You'll still need to start by creating a custom module, theme, or subtheme, so you can add your JS components to the `component.yml` file. But if you are coming from a JS developer mindset, this approach will allow you to just write the JS and stick it in a block on the page.

Obligatory security note:

> This project is not covered by the security advisory policy. Use at your own risk! It may have publicly disclosed vulnerabilities.

But considering that your entire question is about defeating Drupal's built-in security measures against XSS exploits, I can't imagine that this warning will deter you!

**FOLLOW-UP:** Inline JavaScript *is* allowed in the Gutenberg editor from WordPress, and that is why @brown-paul recommends using the Gutenberg editor in Drupal, which might be even easier for you if you're coming from a WordPress background.

---
Tags: javascript
---


# Question
Title: Node url alias pattern based on taxonomy not working properly
I have taxonomy named Category with two terms: News and Articles.

Articles term has custom url alias - `/useful`.

The website was upgaded from D7 to D9. On old D7 version node url pattern was `[node:field_categories]/[node:title]`

On D9 it is the same pattern, BUT instead of `/useful/node-title` it dispalays `/articles/node-title`

Maybe it is not a big deal, but after porting to D9 I would like to maintain current URL structure without changing it radically.

I've tried some other tokens, for example `[node:field_categories:entity:url]`, but it displays absolute path to term with domain and https after slash like `site.com/https://site.com/taxonomy-alias` which is incorrect.

How to fix this?

# Answer
Finally, found an answer!

The correct token for D8/9 is `[node:field_categories:entity:url:path]`

I don't know why, but it is not listed in available tokens.
> 0 votes

---
Tags: taxonomy-terms, path-aliases, 9
---


# Question
Title: Entity Query field condition for Webform submissions
I'm trying to query webform submissions based on a field value. The field is called "ticket\_for". Somethings I tried and do not work:

```
    ->condition('ticket_for',$adnummer)
    ->condition('webform_submission_data:ticket_for',$adnummer,'CONTAINS')
...

```

What kind of condition should I be using in a query like this?

```
$query = \Drupal::entityQuery('webform_submission')
->condition('webform_id', 'ticket')
->condition('entity_id', $eventID)
->condition('webform_submission_data:ticket_for',$adnummer,'CONTAINS');

```

# Answer
As imclean says webform\_submission\_data stores as EAV model. You can also do the following, If you need to have just one condition `ticket_for == $adnummer`.

```
$select = \Drupal::service('database')
->select('webform_submission_data', 'wsd')
->fields('wsd', array('sid'))
->orderBy('wsd.sid', 'DESC')
->condition('wsd.webform_id', 'your_webform_id', '=')
->condition('wsd.name', 'ticket_for', '=')
->condition('wsd.value', $adnummer, '=')
->execute();

$results = $select->fetchAll(\PDO::FETCH_COLUMN);
if ($results != null && count($results) >= 1) {
    $storage = \Drupal::entityTypeManager()->getStorage('webform_submission');
    $submissions = $storage->loadMultiple($results);
}

```

Now just loop the `$submissions`. Done.
> 4 votes

# Answer
Quoting @jrockowitz:

> WebformSubmission data is not stored using Field API (see: #2792583).
>
> You would have to query the `webform_submission_data` table and collect the submission ids (sid) or use the *Webform Views* module.

Source: Entity query webform submission data condition.
> 1 votes

# Answer
The table "webform\_submission\_data" uses the EAV model. To extract useful results you can use a static query.

Example SQL to the get sid meeting all the requirements:

```
SELECT DISTINCT sid
   FROM webform_submission_data wsd
     WHERE wsd.webform_id = 'ticket'
     AND sid IN (SELECT sid FROM webform_submission_data wsd2
                  WHERE wsd2.name = 'ticket_for'
                    AND wsd2.value CONTAINS '$adnummer')
     AND sid IN (SELECT sid FROM webform_submission_data wsd3
                  WHERE wsd3.name = 'entity_id'
                    AND wsd3.value = $eventID);

```

Example static query:

```
$query = $connection->query("SELECT DISTINCT sid
   FROM webform_submission_data wsd
     WHERE wsd.webform_id = 'ticket'
     AND sid IN (SELECT sid FROM webform_submission_data wsd2
                  WHERE wsd2.name = 'ticket_for'
                    AND wsd2.value CONTAINS :adnummer)
     AND sid IN (SELECT sid FROM webform_submission_data wsd3
                  WHERE wsd3.name = 'entity_id'
                    AND wsd3.value = :event_id)", [
  ':adnummer' => $adnummer,
  ':event_id' => $eventID
]);

```

**Update 19 October 2018**

I've created a module to make it easier to query webform submissions by submission field values. See: https://www.drupal.org/project/webform\_query
> 1 votes

# Answer
@imclean's Webform Query is truly a helper. But I wanted to add another alternative here:

1. Use the Webform Views Integration module.
2. Build a view to query the submissions you need.
3. Configure the view to output fields: the webform submission ID field.
4. In the advanced settings of the view under query options disable SQL rewriting to prevent access checks.
5. Programmatically execute the view.
6. And then do whatever you want with the results array.

---

```
use Drupal\views\Views;

$view = Views::getView('MY_WEBFORM_SUBMISSIONS_VIEW_ID');
$view->setDisplay('default'); // Or any other display ID.
$view->execute();
$results = $view->result;

```
> 1 votes

# Answer
You can do something like this

```
$query = \Drupal::entityQuery('webform_submission')
            ->condition('sid', $submission_id, '='); // put the rest of condition here

// this only returns the id of the submission(s)
$result = $query->execute();

// then you can get the rest of the submission data with
$result_data = WebformSubmission::loadMultiple($result);

```
> -1 votes

---
Tags: 8, database, webforms
---


# Question
Title: How can I enforce a default machine name prefix?
We require site administrators to create new webforms with the machine name beginning with `site_`. (This is because config ignore is set to ignore `webform.webform.site_*` for user generated forms while other forms are part of config) How do you validate and set the webform machine name to begin with this prefix value?

# Answer
> 1 votes
By adding this code to a module, administrators can create forms that will can be exported to config while other users with permissions to create webforms will automatically have the machine name set with the `site_` prefix.

```
function mymodule_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // Adds validation to webform in order to check machine name on create.
  if ($form_id == "webform_add_form") {
    $form['#validate'][] = 'webform_create_validation';
  }
}

function webform_create_validation(&$form, FormStateInterface $form_state) {
  $current_user = \Drupal::currentUser();
  // If user creating the webform is not an administrator.
  if (!in_array('administrator', $current_user->getRoles())) {
    // Get machine name of webform being created.
    $ent = $form_state->getFormObject()->getEntity();
    if (isset($ent)) {
      $id = $ent->id();
      // Check to see if webform machine name starts with "site_".
      // If it does not, add it and save.
      if (substr($id, 0, 5) !== "site_") {
        $new_id = 'site_' . $id;
        $form_state->setValue('id', $new_id);
      }
    }
  }
}

```

---
Tags: webforms
---


# Question
Title: Add a hero image and text when a node goes from unpublished to published
I'm trying to add a hero image and text when a node goes from unpublished to published. The things include:

1. Add an image from my media library to a media field on the node
2. Add a page title to the node, drawing upon a field already saved on the node

I'm attempting to build a hook on hook\_node\_update() but it's not working. I'm not sure why.

The code I am using, part of the running\_event\_adding\_header.module file, is the following.

```
namespace Drupal\Core\Field\EntityReferenceFieldItemList;
namespace Drupal\node\Entity;

/**
 * Implements hook_node_update()
 */

function running_event_adding_header_node_update(Drupal\Core\Entity\EntityInterface $entity) {
  // End function if the entity is not an event
  if ($entity->bundle() !== 'event') {
    return;
  }

  // End function if the event is not a running type of event (running events are '30' in my system)
  if ($entity->bundle() === 'event' && $entity->get('field_event_type')->getString() != '30') {
      return;
  }

  // Check if the new state is "published" and the old state was something other than "published".

  if ($entity->get('moderation_state')->getString() === 'published') {

    /**
    * Add hero image and text to running event page, if not already present
    * The hero image field is 'field_hero_image'
    * The hero text field is 'field_tagline'
    */

    if ($entity->get('field_hero_image')->isEmpty()) {
      $media = Media::load(53); // 53 is the media ID for the image I'm wanting to load on all running pages: .../media/53/edit
      $entity->set('field_hero_image', $media);
    }

    //'field_tagline' is the hero title field
    if ($entity->get('field_tagline')->isEmpty()) {
      $entity->set('field_tagline', $entity->label());
    }
    $entity->save();
  }
}//close function

```

## Updated code (29 July).

Per @sonfd's recommendation, this uses hook\_node\_presave(), but is still not changing the node pages:

```
<?php

namespace Drupal\Core\Field\EntityReferenceFieldItemList;
namespace Drupal\node\Entity;

//In the function below, I'm attempting to update
//'event' type nodes, specifically those with an event_type of '30'

//In those nodes, I'm attempting to use a Media library image
//and use the page's title in the hero section

function running_event_add_default_node_presave(Drupal\node\NodeInterface $entity) {
  if ($entity->bundle() === 'event' && $entity->get('field_event_type')->toString()=== '30') {
    if ($entity->get('field_hero_tagline')->isEmpty()) {
      $entity->set('field_hero_tagline', $entity->label());
    }
    if ($entity->get('field_hero_image')->isEmpty()) {
      $media = Media::load(53);
      $entity->set('field_hero_image', $media);
    }
  }

}

```

# Answer
> 2 votes
You can't use hook\_ENTITY\_TYPE\_update() to update the entity's data. This is noted in the hook's docs:

> This hook runs once the entity storage has been updated. **Note that hook implementations may not alter the stored entity data.** Get the original entity object from $entity-\>original.

If you need to update the entity's data, use hook\_ENTITY\_TYPE\_presave() instead. Note that with hook\_ENTITY\_TYPE\_presave() *you must not call* `$entity->save()`, you just set the entity's values and let the entity save on its own.

---
Tags: 8, nodes
---


# Question
Title: Config split settings file generated into split directory
Drupal 8.7 I have a multisite split. The `config_split.config_split.<sitename>.yml` files are supposed to go into the `config/default` directory. For some reason when updating a split on one of my sites, instead of updating the existing file in that location, it creates a new file in the config/sitename directory. It only does it on this one site. When I compare the newly generated file to the one for that site in the default directory, only the new changes are different. The rest is the same.

# Answer
> 0 votes
It turns out that this was caused by the actual config split config item being listed in the graylist of the file... So, in `config/default/config_split.config_split.www.yml` was the entry for `config_split.config_split.www` in the graylist which then made them "different" and a new file would be created (if we had deleted it) or updated in the `config/default/www` directory. Since that entry was removed, it has behaved as it should.

# Answer
> 0 votes
Have you checked the $config\_directories array in the settings.php/settings.local.php files.

It might be a good idea to explicitly set it via config as per https://www.drupal.org/docs/8/configuration-management/changing-the-storage-location-of-the-sync-directory:

```
$config_directories[CONFIG_SYNC_DIRECTORY] = '../config/sync';

```

---
Tags: configuration
---


# Question
Title: "Promoted to Front Page" option only showing for administrator
I am using the "Promoted to Front Page" option for a view that is displayed on a landing page. The option shows in the create/edit form for an administrator, but no other user for the article content type. My "site admin" role allows the user to create/edit own/others for this content type. I am using the group module which is installed for this content type as well as content moderation. This user is assigned to a group with a group role that has permissions for all moderation states. I have looked through all permissions and I don't see a permission to use this. The promoted to front page option is enabled in the manage form display.

Drupal 8.7.7

# Answer
> 1 votes
Core permission settings require a user to have the "Administer content" permission in order to promote a node to the front page. Evidently the problem has been around since at least Drupal 6 (See Andy Carter's Blog post). As suggested in the blog post and in the comment to the question, the Override Node Options module can provide some more refined permissions.

---
Tags: nodes
---


title: Webform update!

text:
# Question
Title: Webform update!
I need to update webform module in my live site, I noticed the warning with doing that with the user Interface so I want to update the files manually, ( because we don't use drush ), Can I get directions for doing this update? again since the site is live and this is our first Drupal site I want to make sure from not breaking the site or having any issues!

also, I have the files in Cpanel so from where exactly should I start to upload the updated files? is it like in the screenshot below

Thanks and appreciate any help!

# Answer
> 0 votes
There is not much more to say than what is explained in the Drupal doc when you click on the links available in the warning (See Updating a Module)

Whatever the method you use for updating your module, I advise you to always test your update on a copy of your website (local environment, development server... with at least similar php version) to ensure everything works fine before updating the live website.

Regarding the update process:

* if you manage your modules with Composer,

+ on the copy of your website, open a console,
    + go to the root of your website (same level as the composer.json file),
    + run `composer update drupal/webform --with-dependencies`,
    + run the database update script (yoursite.com/update.php).
    + If everything is okay, copy the composer.lock file to your prod environment,
    + open a console on your prod environment,
    + go to the root of your website and run `composer install` (it will update your packages and modules to the versions specified in the composer.lock file).
    + finally, run the database update script and check that your website works fine.
* if you don't use Composer, follow the steps from the Drupal doc 11.6. Manually Downloading Module or Theme Files. First for the copy of your website and then for your prod website.

---
Tags: webforms
---


# Question
Title: SOLR displays "submitted by username" only for the Article content type. How do I stop this?
No matter what I do, I can't seem to remove the *Submitted by \[username\]* from popping up in my search results for the Article content type. I'm using the Apache SOLR module. If you visit the article page itself, I never actually display this information, so showing up on the search results page is confusing me.

When I go to manage fields for my search results, I've got the following for content (I removed username but that didn't help).

>

When I look into my General fields and edit *Rendered item*, the view mode for article content type is set to default.

>

>

When I check my default display fields, it is the following.

>

Yet, when I search for a username in search, admin for this example, I get the following results on the page.

>

Why is it still showing *submitted by admin* in the results and how can I actually remove it? I've tried a couple of preprocess functions that I found while searching but nothing seems to work. *(Yes, I've cleared my cache after every change in code.)* Any suggestions or pointing in the right direction would be greatly appreciated.

# Answer
> 2 votes
What you are seeing with the "submitted by" is coming from search result excerpt. This can be configured in a few different ways, but basically, when the node is being indexed, that information is being rendered out behind the scenes and added to the index.

If you want to remove that, you would want to either remove author information from rendering in the first place, which can be accomplished in a few ways; or change the way the data is added to the SOLR index.

The simplest thing would be to edit your node types uncheck the "Display author and date information" box. Make sure to reindex your content.

---
Tags: 8, search
---


# Question
Title: How to solve the "The following module is missing from the file system" error?
I am getting the following error in a Drupal 8 site.

> The following module is missing from the file system

It looks as if a custom module was installed and deleted without uninstalling it.

How can I fix this error?

# Answer
> 25 votes
Drush 9

```
drush cdel core.extension module.MYMODULE

```

# Answer
> 18 votes
Assuming you have deleted an unimportant custom module which doesn't need any uninstall routine to be triggered, you can use the following Drush command.

* Drupal 7

```
drush sql-query "DELETE from system where type = 'module' AND name = 'MYMODULE';"

```
* Drupal 8

```
drush sql-query "DELETE FROM key_value WHERE collection='system.schema' AND name='MYMODULE';"

```

---

See How to fix "The following module is missing from the file system..." warning messages for more info and alternatives.

# Answer
> 14 votes
If you have Drupal Console then a quick way to fix this is to generate a module with the same machine name, then uninstall it.

```
$ drupal generate:module

```

Then type the machine name at the appropriate prompt and accepts defaults for everything else.

```
$ drush pm-uninstall

```

Then you can delete the newly generated module from the file system and continue with your day.

(NB you may find need to keep that generated module, else the error will return. In that case, if you need to install a contrib module with the same name, remove the generated module after adding the contrib module. Then clear the cache.)

# Answer
> 5 votes
The way I fixed it was by using drush and composer. Get the module with require, install and uninstall with drush then remove with composer.

```
composer require drupal/missing_module
drush en missing_module
drush pmu missing_module
composer remove drupal/missing_module

```

**!** The step with `drush en` probably is not nessesary

# Answer
> 4 votes
Now with the Configuration Management module the modules configuration is stored in the core.extension.yml file.

Go to edit the file and try to find the missing module from the filesystem then delete the line and import the config (`drush cim`).

If this not works but you has found the module, then create the module again (just the folder and a valid .info.yml file) and run again the `drush cim` command. This will uninstall the module.

# Answer
> -1 votes
if you know exactely what you're doing and can't use a cleaner method from https://www.drupal.org/docs/updating-drupal/troubleshooting-database-updates

here is a suggestion :

```
drush php:eval '\Drupal::configFactory()->getEditable("core.extension")->clear("module.MY_MODULE_THAT_BREAKS_THINGS")->save(TRUE);'
drush cr

```

---
Tags: 8
---


# Question
Title: Custom 500 Error page: Is there a way to theme a fatal error?
In /core/includes/errors.inc, when there is a fatal error it outputs a response with the message "The website encountered an unexpected error. Please try again later." and a back-trace, if error\_level is set to verbose, and without the back-trace otherwise.

It seems like at this point, there's no way, with an event subscriber to capture the response and alter it.

Is that correct?

Or is there a way to wrap the output from line 268 of errors.inc in Drupal 8.4 with markup?

Note, there's another answer that works if it's not a fatal error, but that doesn't offer a complete solution.

Also, I looked into .htaccess and Apache ErrorDocument directive, but that was misguided. Once Apache passes off to PHP, it can no longer use that directive. That's for *real* server errors.

# Answer
> 4 votes
Symfony's HttpKernel uses the event dispatcher to allow subscribers to handle exceptions and send custom responses. Only if no subscriber does so will it throw the exception further up and let it reach the global error handler. (At which point it's indeed too late to do anything else.)

Drupal already comes with such a subscriber (or rather several of them, which check particular conditions) for HTTP exceptions (These are implementors of `\Symfony\Component\HttpKernel\Exception\HttpExceptionInterface`, such as `NotFoundHttpException`.)

If you absolutely need to intercept *non-HTTP* exceptions wherever they happen, and return custom responses, you can create your own subscriber (see `Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase`), and give it a very low priority (\< -128) to avoid interfering with the core HTTP exception subscribers.

However, architecture-wise I would suggest this is not a good way to go. If you have a controller that triggers a particular exception, then it should catch it and throw the appropriate HTTP exception instead. This also requires much, much less code than messing around with event subscribers. ;)

If need be, you can even throw a ServiceUnavailableHttpException (503) or set a custom status like `new HttpException(500)` if there is no class for it.

Drupal core's exception subscribers don't actually handle 5xx errors, but you can create your own that does, which would probably look something like the following:

```
class Custom5xxHtmlSubscriber extends HttpExceptionSubscriberBase {
  public function on5xx(GetResponseForExceptionEvent $event) {
     // Do stuff
     (new Response())->send();
  }

```

With a corresponding service definition like the following:

```
  custom5xxsubscriber:
    class: ...
    tags:
      - { name: event_subscriber }

```

# Answer
> 0 votes
you can use https://www.drupal.org/project/custom\_500\_error module.

go to the setting and enter your custom message and markups which you want.

after that on all 500 errors, instead of the default message your customized message and markup will be shown.

# Answer
> 0 votes
You can generate custom 500 error responses by implementing a custom error handler and a custom exception handler, depending upon your needs, in your `MODULE.module` script.

## Custom Unhandled Exception Handler

To catch any unhandled exceptions that would typically bubble up to `drupal_register_shutdown_function` and halt processing on the spot (no more "*The website encountered an unexpected error. Please try again later.*" error):

```
// Set a custom exception handler.
set_exception_handler('MODULE_exception_handler');

/**
 * Handles uncaught exceptions.
 *
 * @param mixed $exception
 *   Exception that was uncaught.
 */
function MODULE_exception_handler(\Throwable $exception) {
  $exceptionType = get_class($exception);
  $exceptionMessage = $exception->getMessage();

  $content = "<h1>An error occurred.</h1>
    Error Type: $exceptionType<br>
    Message: $exceptionMessage<br>";

  echo $content;
}

```

## Custom Error Handler

This also catches errors that would normally bubble up, though you must use `exit` to halt processing. If you do not exit, then the messages will stack until Drupal fires the shutdown function.

```
// Set a custom error handler.
set_error_handler('MODULE_error_handler');

/**
 * Provides a top-level error handler.
 *
 * @param int $errno
 *   Level of the error raised.
 * @param string $errstr
 *   Error message.
 * @param string $errfile
 *   Filename that the error was raised in.
 * @param int $errline
 *   Line number where the error was raised.
 *
 * @return bool
 *   True to halt additional PHP processing, false otherwise.
 */
function MODULE_error_handler(int $errno, string $errstr, string $errfile = NULL, int $errline = NULL): bool {
  // $errstr may need to be escaped:
  $errstr = htmlspecialchars($errstr);

  switch ($errno) {
    case \E_USER_ERROR:
      echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
      echo "  Fatal error on line $errline in file $errfile";
      echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
      echo "Aborting...<br />\n";
      // Immediately stop all additional processing.
      exit(1);

    case \E_USER_WARNING:
      echo "<b>My WARNING</b> [$errno] $errstr<br />\n";
      // Uncomment to immediately stop all additional processing.
      // exit(1);
      break;

    case \E_USER_NOTICE:
      echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";
      // Uncomment to immediately stop all additional processing.
      // exit(1);
      break;

    default:
      echo "Unknown error type: [$errno] $errstr<br />\n";
      // Uncomment to immediately stop all additional processing.
      // exit(1);
      break;
  }

  /* Don't execute PHP internal error handler */
  return true;
}

```

**PLEASE NOTE:** In the grand flow of things, the custom error handler is executed *before* the custom exception handler. Keep that in mind when deciding which one to use and when to call `exit` in the error handler.

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


# Question
Title: How can i change dateformat of webform submission
Is there a way where we could change the date format of the form submission? For Example in the Webform I have created there's no date picker in it. But when the web form is submitted by the user by default it comes in this format Sun mm/dd/yyyy but I want it dd/mm/yyyy (It is stored in Structure -\>Websforms --\>Submissions)How can i change the date format once the webform is submitted?

# Answer
I could be wrong but you may need edit the date time in the configuration of your website in /admin/config/regional/date-time
> 1 votes

---
Tags: webforms, datetime
---


# Question
Title: Fatal error: Cannot redeclare Drupal\views\Routing\ViewPageController::getTitle()
I have updated Drupal 9.0.1 to 9.2.2 via Composer. After updating, I am getting a fatal error.

> Fatal error: Cannot redeclare Drupal\views\Routing\ViewPageController::getTitle() in /var/www/html/docroot/core/modules/views/src/Routing/ViewPageController.php on line 98

`drush updb` outputs the following.

```
 -------- ------------------ ------------- ------------------------------------
  Module   Update ID          Type          Description
 -------- ------------------ ------------- ------------------------------------
  file     add_txt_if_allow   post-update   Add txt to allowed extensions for
           s_insecure_exten                 all fields that allow uploads of
           sions                            insecure files.
  system   delete_rss_setti   post-update   Remove obsolete system.rss
           ngs                              configuration.
  system   remove_key_value   post-update   Drop the 'all' index on the
           _expire_all_inde                 'key_value_expire' table.
           x
  system   service_advisory   post-update   Add new security advisory
           _settings                        retrieval settings.
  tour     joyride_selector   post-update   Convert Joyride selectors to
           s_to_selector_pr                 `selector` property.   @see
           operty                           tour_tour_presave()
  views    rename_default_d   post-update   Rename the setting for showing the
           isplay_setting                   default display to
                                            'default_display'.
  views    title_translatio   post-update   Rebuild routes to fix view title
           ns                               translations.
 -------- ------------------ ------------- ------------------------------------

Do you wish to run the specified pending updates? (yes/no) [yes]:
> [notice] Module kint has an entry in the system.schema key/value storage, but is missing from your site.
> [notice] Update started: file_post_update_add_txt_if_allows_insecure_extensions
> [notice] Update completed: file_post_update_add_txt_if_allows_insecure_extensions
> [notice] Update started: system_post_update_delete_rss_settings
> [notice] Update completed: system_post_update_delete_rss_settings
> [notice] Update started: system_post_update_remove_key_value_expire_all_index
> [notice] Update completed: system_post_update_remove_key_value_expire_all_index
> [notice] Update started: system_post_update_service_advisory_settings
> [notice] Update completed: system_post_update_service_advisory_settings
> [notice] Update started: tour_post_update_joyride_selectors_to_selector_property
> [notice] Update completed: tour_post_update_joyride_selectors_to_selector_property
> [notice] Update started: views_post_update_rename_default_display_setting
> [notice] Update completed: views_post_update_rename_default_display_setting
> [notice] Update started: views_post_update_title_translations
> [notice] Update completed: views_post_update_title_translations
> PHP Fatal error:  Cannot redeclare Drupal\views\Routing\ViewPageController::getTitle() in /var/www/html/docroot/core/modules/views/src/Routing/ViewPageController.php on line 98>
> [warning] Drush command terminated abnormally.

In ProcessBase.php line 171:

  Unable to decode output into JSON: Syntax error

  Fatal error: Cannot redeclare Drupal\views\Routing\ViewPageController::getTitle() in /var/www/html/docroot/core/modules/views/src/Routing/ViewPageController.php on line 98

```

Any hint will be appreciated.

# Answer
> 1 votes
Issue got resolved. There was a patch which was already implemeted. and 9.2.\* has incorporated the same in drupal core. So removing the patch has fixed the issue

View titles in breadcrumb and metatag title don't get properly translated

---
Tags: updating, 9
---


# Question
Title: Ways to specify different versions of nodes?
I'm creating a dev portal for a client's software, and they would like to have nodes pertaining to different versions of the software in the documentation.

Rather than have to make an entire new set of nodes for each version of the software, I would like to be able to add/edit a 'version' of the node that pertains to 1.x 2.x etc, within the node edit screen, and control what version the end user sees with a custom module and/or $\_GET variable.

My first thought is to use the translation module since this is essentially the same thing, albeit with languages instead of software versions, but I was wondering if anyone had any ideas of what method I should go about doing this?

# Answer
> 0 votes
In this case, go with taxonomy terms. That way you can organize content around a taxonomy term, one for each version. You can even tag content that is applicable to multiple versions just by selecting taxonomy terms.

Then, you could create a view that says "give me all of the content related to version *X*" and you'd be able to see those. Plus if you ever wanted to do more than "just nodes" e.g. other entities or bundle types, you can just add the field to those bundles and go on your merry way. Plus, since taxonomy terms are entities, you can add fields and content to those terms and build pages that surround those terms.

# Answer
> 0 votes
I am trying to do this same thing for a very similar purpose: to provide documentation (articles, videos, etc) for two different versions of the same software product.

My solution so far is to use **field\_group**, and create horizontal tabs. Each tab contains a content textarea which has the documentation relating to THAT particular version.

So at the top of the node (view and edit) you see these tabs:

```
Installation Guide
    6.x | 5.x | 4.x

```

And switching between the tabs shows you different content.

There are some drawbacks to this solution, but it's the best I can come up with for my situation.

---
Tags: 7, nodes, i18n-l10n
---


# Question
Title: How to translate content but not backend interface?
I'm trying to set up an English administrator back-end and a URL based front-end (anonymous user content) translation. I follow a guide on the subject, but I haven't been able to achieve what I wanted.

I also tried to set up /admin/config/regional/language/detection using various combinations of settings, but either I have the back-end in English along with the rest of the site, or everything is translated.

These are the combinations I tried.

| Interface language | Content language |
| --- | --- |
| User + URL | URL |
| User + URL | User + URL |
| URL | User + URL |
| User + URL | URL |
| User | URL |
| URL | URL |

Is this a bug in the core, or am I miss some important setting?

# Answer
Go to `/admin/config/regional/language/detection` and enable "Account administration pages". On user's edition page, it will unlock a new select list under language settings where the user can set the language for the administration pages.

That way, admins can browse the website using whatever language is selected (either from URL, front-end language selector, browser...) but when accessing administration pages, language of the interface will always fall back to Administration pages language field value.

If English is your default language and you do not want admins to be able to edit this Admin pages language value, you can go to `/admin/config/people/accounts/form-display`and disable "Language settings" field.
> 3 votes

---
Tags: i18n-l10n, 9
---


# Question
Title: How to create a view filter which display nodes if "field1" - "field2" < $amount
I have a content type with 2 fields: `field1` and `field2`

I would like to create a view filter which display node based on a calculation on those two fields.

The filter should display only nodes if `field1 - field2` is lower then a given amount.

Here is my try: At the end of the code, I don't know how to create the query

```
 class Myfilter extends FilterPluginBase implements ContainerFactoryPluginInterface {

  protected ViewsHandlerManager $joinHandler;

  private int $amount;

  public function __construct(array $configuration, $plugin_id, $plugin_definition, RouteMatchInterface $route_match, ViewsHandlerManager $join_handler) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->joinHandler = $join_handler;
    $this->amount = 0;
    if (($node = $route_match->getParameter('node')) && ($node->bundle()=='my_bundle')) {
      $this->amount = $node->get('field_inv_amount')->value;
    }

  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration, $plugin_id, $plugin_definition,
      $container->get('current_route_match'),
      $container->get('plugin.manager.views.join')
    );
  }

  public function query() {
    //parent::query();

    $fields = [
      'field1',
      'field2',
    ];
    foreach ($fields as $field) {
      $table_field_name = 'node__' . $field;
      $configuration = [
        'table' => $table_field_name,
        'field' => 'nid',
        'left_table' => 'node_field_data',
        'left_field' => 'nid',
        'operator' => '=',
      ];
      $join = $this->joinHandler->createInstance('standard', $configuration);
      $this->query->addRelationship($table_field_name, $join, 'node_field_data');
    }
    // I am stuck here... field1-field2 should be < $this->amount
    $this->query->addWhere( ???? );
  }

}

```

Any hint will be appreciated

# Answer
> 1 votes
You have a few errors:

The `'field' => 'nid',` should be `'field' => 'entity_id',`

The `$join =`  line needs to use `Drupal\views\Views::pluginManager('join')`

---

You can using addWhereExpression, working example:

```
  public function query() {

    $fields = [
      'field_num1',
      'field_num2',
    ];

    foreach ($fields as $field) {
      $table_field_name = 'node__' . $field;
      $configuration = [
        'table' => $table_field_name,
        'field' => 'entity_id',
        'left_table' => 'node_field_data',
        'left_field' => 'nid',
        'operator' => '=',
      ];
      $join = $this->joinHandler->createInstance('standard', $configuration);
      $this->query->addRelationship($table_field_name, $join, 'node_field_data');
    }

    // Substracts and filters to less than amount.
    $this->query->addWhereExpression('AND', 'node__field_num1.field_num1_value - node__field_num2.field_num2_value <' . $this->amount);

  }

```

---
Tags: views
---


# Question
Title: Adding Javascript within a hook_entity_type_presave() hook
I'm trying to add Javascript into a hook\_entity\_type\_presave() hook, but it's not firing.

Is it possible to add within this hook?

I've attempted to with no success -- my code is below -- and this example on Drupal.org: https://www.drupal.org/docs/drupal-apis/javascript-api/add-javascript-to-your-theme-or-module ...describes the process of adding javascript within the context of two other custom modules, utilising hook\_element\_info\_alter() and hook\_page\_attachments().

My module:

```
my_module
  my_module.libraries
  my_module.module
  my_module.info.yml
  js
    url-parameter.js

```

my\_module.libraries:

```
url-parameter:
  version: 1.x
  js:
    js/url-parameter.js: {}
  dependencies:
    - core/jquery

```

my\_module.module

```

function my_module_node_presave(Drupal\node\NodeInterface $entity) {

  //other code related to the presave hook, which works fine

  //I attempt to load the JS here, but it's not firing:

  $attachments['#attached']['library'][] = 'js/url-parameter.js';

}

```

js\url-parameter.js:

```
(function (jQuery) {
  jQuery(document).ready(function() {
    alert("hello");
    console.log('Loaded');
  });
})(jQuery);

```

# Answer
> 3 votes
`hook_entity_presave()` and `hook_ENTITY_TYPE_presave()` should not assume the entity has been edited using a form, or a page has been shown to the users. Those hooks are also invoked when an entity is programmatically created, for example with the following code, which could also be used in a `hook_cron()` implementation.

```
$values = [
  'type' => 'article',
  'title' => 'The article title',
  'uid' => 1,
  'status' => TRUE,
];
$node = \Drupal::entityManager()->getStorage('node')->create($values);
$node->save();

```

The hook invoked before an entity is rendered is `hook_entity_view()` (or `hook_ENTITY_TYPE_view()`). Using one of those hooks, a module can add an extra rendering array in `$build`, for example with `$build['#attached']['library'][] = 'js/url-parameter.js';`.

As the example code, `$display->getComponent()` should be used to verify the entity field has been set to be rendered, since administrator users can hide fields from /admin/structure/types/manage/article/display (for the *Article* content type). For example, with the following settings, I would hide a custom entity field and the *Tags* field for the *Article* content type.

>

I would also check the value of `$view_mode` passed to those hooks as that value says why the node is rendered. For example, when the Search module indexes the nodes, `$view_mode` is equal to `'search_index'`; when a node is added to a RSS feed, `$view_mode` is equal to `'rss'`. In those cases, you probably don't want to add a library.

---
Tags: 8, javascript, hooks
---


# Question
Title: FieldItemList::getValue always returns a string, even for a Boolean field
Supposed I added a custom Boolean field, whose cardinality is 1, to a content type. I create a node of that content type, enter a value for that field (for example, `TRUE`), and save the node.

When I get the field value with `$value = node->get('field_custom')->getValue();` `$value` contains the following array.

```
0 => array (1)
  value => string (1) "1"

```

Is there an way to get the field value that reflects the field type, Boolean in this case?

```
0 => array (1)
  value => boolean true

```

I manually cast the value, for example with code similar to the following one.

```
// Boolean
$value = (boolean) $value;

// Integer
$value = intval($value);

```

I also tried `get('x')->value` and using `__get()`.

Drupal knows the field type, which is returned from `$field->getFieldDefinition()->getType()`. I take there is a way to correctly cast the field value.

# Answer
> 3 votes
Normally type casting doesn't matter: https://softwareengineering.stackexchange.com/questions/24378/type-casting-variables-in-php-what-is-the-practical-reason-for-doing-this.

So retrieving an entity field value doesn't need to be type casted:

```
$node->field_bool->value

```

returns a string `'0'`/`'1'` or `NULL` if the field is empty. All three possible values work as expected in PHP. `'1'` results in logical true and the other two values in logical false. This reflects how it is visible in UI where a checkbox can only have two states. Empty is unchecked, checked is saved as `'1'` and when unchecked again it is saved as `'0'`.

However, the Drupal entity system is built on typed data and if you want to write OOP code with type casting, you can:

```
$node->field_bool->first()->get('value')->getCastedValue()

```

returns `FALSE`/`TRUE`.

Caveat: This doesn't work on field level. You need to get a field item to get the boolean typed data and you have to catch an empty field to avoid get() on NULL.

---
Tags: entities, 9
---


# Question
Title: How do I get the comment ID in a template file?
I want to show the comment title linked to the comment permalink. This is the content of the comment.html.twig file.

```
 <div{{ content_attributes.addClass('comment__content') }}>
    {% if title %}
      {{ title_prefix }}
      <h3{{ title_attributes }}><a href="#comment-{{comment.id}}">{{ title | render | striptags}}</a></h3>
      {{ title_suffix }}
    {% endif %}
    {{ content }}
  </div>

```

`{{comment.id}}` didn't work. How do I get the comment ID?

# Answer
template\_preprocess\_comment() sets the following value, which is essentially the string you want to obtain, apart the hash at the beginning.

```
$variables['attributes']['id'] = 'comment-' . $comment->id();

```

The template file can use that value with `{{ attributes.id }}`.

```
<div{{ content_attributes.addClass('comment__content') }}>
  {% if title %}
    {{ title_prefix }}
    <h3{{ title_attributes }}><a href="#{{ attributes.id }}">{{ title|render|striptags }}</a></h3>
    {{ title_suffix }}
  {% endif %}
  {{ content }}
</div>

```

### Reference
> 1 votes

---
Tags: comments
---


# Question
Title: Pass a value via URL to a node edit form and use it to redirect after saving the node
I have a node that includes a series of embedded views. When displaying, I have to pass a value via URL arguments (http://example.org/node/x?id=y), so that the views can get the appropriate information. The user needs to be able to edit this node, but when they save and return to the node it has lost the *id=y* part and the display is incomplete.

I know I can use `hook_form_alter()` to redirect, but I can't figure out how can I redirect after the node is saved using that URL argument?

# Answer
Using `hook_form_alter()`, you can add a submission handler that sets the redirection. The code for the submission handler would be similar to the following one.

```
function mymodule_node_edit_submit(array &$form, FormStateInterface $form_state) {
  $node = $form_state->getFormObject()->getEntity();
  $id = \Drupal::request()->query->get('id');
  $form_state->setRedirect('entity.node.canonical', ['node' => $node->id()], [query => ['id' => $id]]);
}

```

The code for `hook_form_BASE_FORM_ID_alter()` would simply be the following one.

```
function mymodule_form_node_form_alter(&$form, FormStateInterface $form_state) {
  $node = $form_state->getFormObject()->getEntity();

  // Since this hook is invoked for every node, check its content type.
  if ($node->getType() == 'the content type you are interested in') {
    $form['actions']['submit']['#submit'][] = 'mymodule_node_edit_submit';
  }
}

```

The `hook_form_FORM_ID_alter()` implementation should be named `mymodule_form_node_<content_type_machine_name>_alter()`. (Replace *mymodule* with the module machine name, `<content_type_machine_name>` with the content type machine name.) In this case, since the hook is invoked only for a content type, it doesn't need to check the node content type before adding the submission handler.
> 0 votes

---
Tags: forms, redirection, 9
---


title: Add style attribute to view fields

text:
# Question
Title: Add style attribute to view fields
I would like to add a style attribute to each title fields in my view. I have created one field for a color. I tried to rewrite the result like this:

```
<h2 style="color: [field_color];">[title_1]</h2>

```

But the style attribute will be removed. I'm using Drupal 7.

Any help appreciated.

# Answer
> 4 votes
You can set a class to the title field using Style Settings as shown below screen. You can user token replacements in style settings to set class to the title field.

Using small javascript or jquery read the class of title field and set the color same as class name using CSS property.

# Answer
> 1 votes
You can create a tpl for this field (example: views-view-field-MY-VIEW-NAME-page.tpl.php), in this tpl you can add the token writing this:

```
<h2 style="color: <?php print $field->last_tokens['[field_color]'] ?>;"><?php print $field->last_tokens['[title_1]'] ?></h2>

```

# Answer
> 1 votes
I also had to include the value of a field as an inline color for a particular field. After browsing the web for an easy customizable solution, I ended up doing this:

1. Add the value of the color as a CSS Class token, just like the image in the previous post.
2. Rewrite the hook\_preprocess\_views\_view\_field() function like this:

```
 function hook_preprocess_views_view_fields(&$vars) {
  $view = $vars['view'];

  // Loop through the fields for this view.
  $previous_inline = FALSE;
  $vars['fields'] = array(); // ensure it's at least an empty array.
  foreach ($view->field as $id => $field) {

    // render this even if set to exclude so it can be used elsewhere.
    $field_output = $view->style_plugin->get_field($view->row_index, $id);
    $empty = $field->is_value_empty($field_output, $field->options['empty_zero']);
    if (empty($field->options['exclude']) && (!$empty || (empty($field->options['hide_empty']) && empty($vars['options']['hide_empty'])))) {
      $object = new stdClass();
      $object->handler = & $view->field[$id];
      $object->inline = !empty($vars['options']['inline'][$id]);

      $object->element_type = $object->handler->element_type(TRUE, !$vars['options']['default_field_elements'], $object->inline);
      if ($object->element_type) {
        $class = '';
        if ($object->handler->options['element_default_classes']) {
          $class = 'field-content';
        }

        if ($classes = $object->handler->element_classes($view->row_index)) {
          if ($class) {
            $class .= ' ';
          }
          $class .= $classes;
        }

        $class_array = explode(' ', $class);
        foreach ($class_array as $cid => $candidate) {
          // Find the color hex code.
          if (preg_match('/([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?\b/', $candidate)) {
            $style = 'color:#' . $candidate . ';';
            unset($class_array[$cid]);
          }
        }

        $pre = '<' . $object->element_type;
        if ($class) {
          $pre .= ' class="' . implode(' ', $class_array) . '"';
        }
        if ($style) {
          $pre .= ' style="' . $style . '"';
        }
        $field_output = $pre . '>' . $field_output . '</' . $object->element_type . '>';
      }

      // Protect ourself somewhat for backward compatibility. This will prevent
      // old templates from producing invalid HTML when no element type is selected.
      if (empty($object->element_type)) {
        $object->element_type = 'span';
      }

      $object->content = $field_output;
      if (isset($view->field[$id]->field_alias) && isset($vars['row']->{$view->field[$id]->field_alias})) {
        $object->raw = $vars['row']->{$view->field[$id]->field_alias};
      }
      else {
        $object->raw = NULL; // make sure it exists to reduce NOTICE
      }

      if (!empty($vars['options']['separator']) && $previous_inline && $object->inline && $object->content) {
        $object->separator = filter_xss_admin($vars['options']['separator']);
      }

      $object->class = drupal_clean_css_identifier($id);

      $previous_inline = $object->inline;
      $object->inline_html = $object->handler->element_wrapper_type(TRUE, TRUE);
      if ($object->inline_html === '' && $vars['options']['default_field_elements']) {
        $object->inline_html = $object->inline ? 'span' : 'div';
      }

      // Set up the wrapper HTML.
      $object->wrapper_prefix = '';
      $object->wrapper_suffix = '';

      if ($object->inline_html) {
        $class = '';
        if ($object->handler->options['element_default_classes']) {
          $class = "views-field views-field-" . $object->class;
        }

        if ($classes = $object->handler->element_wrapper_classes($view->row_index)) {
          if ($class) {
            $class .= ' ';
          }
          $class .= $classes;
        }

        $object->wrapper_prefix = '<' . $object->inline_html;
        if ($class) {
          $object->wrapper_prefix .= ' class="' . $class . '"';
        }
        $object->wrapper_prefix .= '>';
        $object->wrapper_suffix = '</' . $object->inline_html . '>';
      }

      // Set up the label for the value and the HTML to make it easier
      // on the template.
      $object->label = check_plain($view->field[$id]->label());
      $object->label_html = '';
      if ($object->label) {
        $object->label_html .= $object->label;
        if ($object->handler->options['element_label_colon']) {
          $object->label_html .= ': ';
        }

        $object->element_label_type = $object->handler->element_label_type(TRUE, !$vars['options']['default_field_elements']);
        if ($object->element_label_type) {
          $class = '';
          if ($object->handler->options['element_default_classes']) {
            $class = 'views-label views-label-' . $object->class;
          }

          $element_label_class = $object->handler->element_label_classes($view->row_index);
          if ($element_label_class) {
            if ($class) {
              $class .= ' ';
            }

            $class .= $element_label_class;
          }

          $pre = '<' . $object->element_label_type;
          if ($class) {
            $pre .= ' class="' . $class . '"';
          }
          $pre .= '>';

          $object->label_html = $pre . $object->label_html . '</' . $object->element_label_type . '>';
        }
      }

      $vars['fields'][$id] = $object;
    }
  }

}

```

As you can see, I've added these lines:

```
$style = '';
$class_array = explode(' ', $class);
foreach ($class_array as $cid => $candidate) {
  // Find the color hex code.
  if (preg_match('/([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?\b/', $candidate)) {
    $style = 'color:#' . $candidate . ';';
    unset($class_array[$cid]);
  }
}

```

And change the line under:

```
$pre = '<' . $object->element_type;
if ($class) {
  $pre .= ' class="' . implode(' ', $class_array) . '"';
}
if ($style) {
  $pre .= ' style="' . $style . '"';
}

```

# Answer
> 0 votes
add a name into the field anil suggested then open style.css in your theme folder and type ".my-css-name" followed by desired css results such as:

.my-css-name { color:red; background:green; }

# Answer
> 0 votes
I'm just making something similar and here is what i did:

1- Create a view with color and title fields.

2- Create a custom "views-view-fields.tpl" for that view. (A custom template only for the color field, showed me an error)

3- At `field->content` line add/replace what you need....`<h2 style="color: #<?php print $field->content; ?>">`

/ / / / From now on, i didn't test it, but it should work fine / / / /

4- Exclude the title field and show it on the header/group

5- Create a custom "views-view-unformatted.tpl" for that view.

6- In this view we add `<?php print $title; ?></h2>` after `<?php print $row; ?>`. (we add the title and close the H tag open in the first template)

---

## LAST EDIT:

You can simply use views PHP to print all the thing you need and style won't be filtered.

# Answer
> 0 votes
I had this same problem and solved it by creating a template named

```
views-view-field--field_name_here.tpl.php

```

In my case, the code I used to create the HTML I needed was:

```
<?php

$bg_color = $variables["row"]->field_field_button_background_color[0]["raw"]["rgb"];
$link_title = $variables["row"]->field_field_slideshow_item_cta_link[0]["raw"]["title"];
$link_url = $variables["row"]->field_field_slideshow_item_cta_link[0]["raw"]["url"];

echo '<a style="background-color:'.$bg_color.'" href="'.$link_url.'">'.$link_title.'</a>';

```

Enabling the Devel module and using

```
dpm($row);

```

in the template file was VERY helpful. Couldn't have figured this out without it.

# Answer
> 0 votes
The easiest solution I could find was to insert the value as a data attribute. Then in my JavaScript I take the value from the data field and update the CSS to reflect the change.

# Answer
> 0 votes
Create your custom field in the view as you normally would. instead of printing the style attribute as `style="xyz"` use `data-style="xyz"`. Copy the template for the default view field `views-view-field.html.twig` into your theme and replace its contents with: `{{ output|replace({'data-style=': 'style='})|raw -}}`

When I was previously stuck with: `<a href="/path-to-thing" class="cover-image-style">Title of node</a>`

Now I get the desired: `<a href="/path-to-thing" style="background-image('/path/from/node/media/image.jpg')" class="cover-image-style">Title of node</a>`

---
Tags: views, theming
---


title: Insert PHP snippets in content

text:
# Question
Title: Insert PHP snippets in content
Drupal 9 doesn't have the PHP Filter module in core. I need to insert PHP snippets in the content editor (for example a Twig variable).

Is there any way to insert PHP snippets in Drupal content?

# Answer
> 2 votes
The PHP Filter module has been removed from Drupal core because improperly using it would cause security issues. The security issues were mitigated from the fact that only users with the *use PHP for settings* permission could use the input filter, but that doesn't sanitize the code entered by editors. If then the permission were unconditionally given to every editor, it's like that permission didn't exist.

The Drupal core module is now available as PHP module, but I would not use it.

I would rather do what Hudri suggested, and use the Token Filter module. With that module, and adding its input filter to the input format used for nodes, a user could enter a token which would be replaced with its value. Instead of PHP snippets, I would implement custom tokens that are replaced by the value returned from the PHP code executed in `hook_tokens()`, one of the hooks necessary to modules that want to implement custom tokens.

```
function mymodule_token_info() {
  $type = [
    'name' => t('Custom tokens'),
    'description' => t('Custom tokens to use in the node body field.'),
  ];

  // Custom global tokens.
  $custom['custom01'] = [
    'name' => t("Custom 01"),
  ];
  $custom['custom02'] = [
    'name' => t("Custom 02"),
  ];

  return [
    'types' => [
      'custom' => $type,
    ],
    'tokens' => [
      'custom' => $custom,
    ],
  ];
}

function mymodule_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
  $replacements = [];
  if ($type == 'custom') {
    foreach ($tokens as $name => $original) {
      if ($name == 'custom01') {
        $replacements[$original] = // Set the value of the custom01 token.
      }
      elseif ($name == 'custom02') {
        $replacements[$original] = // Set the value of the custom02 token.
      }
    }
  }
  return $replacements;
}

```

`hook_tokens()` could also return HTML markup used for the node body field. `$bubbleable_metadata` can be used to add cache dependencies.

This method is safer, as it doesn't allow users to enter arbitrary PHP code which, potentially, could also change the password for any user account, delete all the site content, or send users information to external sites.
Even if only trusted users were allowed to use the PHP input filter, there are always chances the entered code causes issues.

---
Tags: 9
---


# Question
Title: How to determine which password hash is used?
We have migrated website from a vanilla coded PHP to Drupal, and I have also migrated all the users.

The old website has been using the `password_hash()` function to encrypt the password.

The website has been running for a month now. I'm looking at the user table, and I want to know determine which users has been encrypted using `password_hash()` or the default Drupal one.

I have this code

```
$query = \Drupal::entityQuery('user');

$uids = $query->execute();

foreach ($uids as $uid) {
    $user = User::load($uid);

    // Checking to do here...
}

```

# Answer
Given the code used by `PhpassHashedPassword::needsRehash()`, a method implemented by the class used for the default password hashing service, a password is stored using the Drupal hashing schema when:

The other hashing schemas Drupal recognizes are the following.

* When the first two hash characters are *U* and *$*, the password hash has been updated by `user_update_7000()` from a MD5 hash used in Drupal 6
* When the first three characters are *$*, *H*, and *$* (or *$*, *P*, and *$*) the hash has been generated by phpass via MD5

As side note, a password hash is regenerated when the user logs in, which is the only moment Drupal has the password. To check for which users the stored password hash isn't using the default Drupal hash schema, it's quicker to check which users haven't logged in after the site was migrated to Drupal.
> 2 votes

---
Tags: 8, users, migrations
---


# Question
Title: Programmatically change page orientation for Entity Print module
In many projects, some entities needs to be printed on LANDSCAPE format, others, on PORTRAIT. I was searching for an example or, maybe, a more precise way to implement a page orientation hook, but didn't really find any. I just need to do something like

`if($entity_type = "foo"){ set page orientation to portrait }`

On this issue, benjy wrote : If you need to do this programatically, see PrintEvents::CONFIGURATION\_ALTER

I looked at the code and saw TestEngineConfigurationAlter class. So I tried to replicate this in a custom module, but it doesn't seem to do anything. I'm obviously missing a piece of the puzzle and I'm humbly asking for help.

Thank you very much :)

---

Related issues on drupal.org

* 2797877: Setting paper orientation for dompdf?
* 2715875: Setting paper size for dompdf in D8

# Answer
Ok so here's a solution.

As mentionned, you only need to add an event in a custom module inside

**my\_module/src/EventSubscriber/EntityPrintSubscriber.php**

I simply use a GET parameter from url to set page orientation.

ie. yoursite.com/print/pdf/entity\_type/entity\_id?orientation=portrait

```
namespace Drupal\my_module\EventSubscriber;

use Drupal\entity_print\Event\PrintEvents;
use Drupal\entity_print\Plugin\PrintEngineBase;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\GenericEvent;

class EntityPrintSubscriber implements EventSubscriberInterface {

  public function alterConfiguration(GenericEvent $event) {
    //ie. /print/pdf/entity_type/entity_id?orientation=portrait
    $request = \Drupal::request()->query->get('orientation');
    if(!empty($request) && ($request == PrintEngineBase::PORTRAIT || $request == PrintEngineBase::LANDSCAPE)){
      $configuration = $event->getArgument('configuration');
      $configuration['orientation'] = $request;
      $event->setArgument('configuration', $configuration);
    }
  }

  public static function getSubscribedEvents() {
    return [
      PrintEvents::CONFIGURATION_ALTER => 'alterConfiguration',
    ];
  }

}

```

Edit:

Don't forget to add a service to your module. So inside my\_module/my\_module.services.yml, add this:

```
my_module.entityprintconfig:
    class: Drupal\my_module\EventSubscriber\EntityPrintSubscriber
    tags:
      - { name: event_subscriber }

```
> 0 votes

# Answer
There's a bug in Entity Print 2.2 so if the above solution by @JFK doesn't work please see https://www.drupal.org/project/entity\_print/issues/3041514
> 0 votes

---
Tags: entities, 8
---


title: Error uploading image

text:
# Question
Title: Error uploading image
Since I changed my drupal to my backup that it's giving me some errors, but overall it stills working, but today I was about to add a new content and when I try to upload new images it shows me this error

> "The file could not be uploaded."

And in log messages I've this message errors:

> Location: http://localhost/node/add/imovel?\_wrapper\_format=drupal\_ajax&ajax\_form=1&element\_parents=field\_image%2Fwidget
>
> Message: The upload directory public://2017-02 for the file field field\_image could not be created or is not accessible. A newly uploaded file could not be saved in this directory as a consequence, and the upload was cancelled.

In the same location this 2 other errors:

> Recoverable fatal error: Argument 1 passed to Drupal\Core\Form\FormState::setError() must be of the type array, null given
>
> Notice: Undefined index: value in Drupal\Core\Field\Plugin\Field\FieldWidget\NumberWidget-\>errorElement()

Now I can't upload images and that don't allow me to add new content. I already try to create a new field but that didn't work.

PS: I think the error has to do something about Image Crop because before this error happen a box to crop my image would appear after I upload and know I upload and no box to crop the image.. And when I press save and publish content the error pops

> The specified file temporary://filekrGdEp could not be moved/copied because the destination directory is not properly configured. This may be caused by a problem with file or directory permissions.

# Answer
This sounds very much like a permission issue. Please check the permissions of

> /home/user/public\_html/sites/default/files/2017-02

The directory must be writeable for Drupal. Set its permissions at least to 710. You might want to set them for testing purposes to 755 or even 777 to see if your error messages disappear.
> 2 votes

# Answer
Try setting private files path in settings.php to:

> "../FOLDER\_WITH\_PRIVATE\_FILES"
> 0 votes

# Answer
I was having this same error.

I didn't have important files in the folder. So I just deleted. Try to upload the file again, and it works, it created the folder and upload the files correctly.

If you already have files in the folder, you may just rename it, try the upload, and if it succeeds and creates the folder anew, you just move the files from the old folder to the new one.

Makes sense?
> -1 votes

# Answer
The fact that i had to change the file permission of settings.php to 755 or above first then after mentioning all the things change it back to 555 then everything worked fine and i would suggest keeping the private directory on the same level as web and vendor directories and mention file path as ../private in settings.php.
> -1 votes

---
Tags: 8, ajax, debugging, media
---