# Question
Title: What happens to URL alias when a node is unpublished?
We have many pages where we set "Generate automatic URL alias" to true and false. Then we will eventually unpublish some of the pages. Looking at Webmaster tools, we have found the URLs are still indexed and cached so when any unpublished page is crawled again it is generating a 404.

Given that in the Path settings we have set the Update action set to "Create new alias. Delete old alias", we need assistance in figuring out what happens to url aliases once the page is unpublished in the scenario where "Generate automatic URL alias" is set to true or false.

# Answer
> 3 votes
Nothing happens and nothing should.

An alias only exists on the URL level. It simply aliases "/blog/2018-01-23/my-awesome-article" to "/node/27", does a lookup for what when a request is coming in and that's it. After that, the routing and entity (access) systems are taking over to figure out what to display and who is allowed to see it.

If you unpublished node 27, then it still exists and admins can still access it, using that alias. In theory, it wouldn't even care if node 27 is deleted, it would still de-alias it to "/node/27" and then the routing system would return a 404 page as there is no node 27 anymore. This actually doesn't happen with nodes because there is code that listens on nodes being deleted and deletes aliases pointing to them as well.

It also doesn't matter if you use a manual alias or generated one using pathauto, that only differs while saving the node and telling pathauto if it should generate one dynamically or not.

But that's actually not your question, because what you're really asking is how google updates its index when you unpublish content. And what you describe is exactly what should happen, eventually google will re-index your content, see that it no longer exists and removes it from its index. There isn't really anything else you can do directly. You could use a sitemap.xml to tell Google index your content more or less frequently but that's about it.

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


title: How to create modal windows (pop-ups)?

text:
# Question
Title: How to create modal windows (pop-ups)?
I am trying to use Drupal 8's core function to open a page in a modal window. Unfortunately it is very hard to find some official documentation about it, and most of the blogs covering this topic seem to be outdated. But as far as I know, it should be possible to create a modal dialog by adding the following attributes to an a-element:

```
class="use-ajax” data-dialog-type="modal"

```

So that a full example would look like:

```
<a href="/impressum/lizenzen/43" class="use-ajax" data-dialog-type="modal">
   <span class="glyphicon glyphicon-copyright-mark" aria-hidden="true"></span>
</a>

```

Where in my case `/impressum/lizenzen/43` is a path to a views page.

This seems to work, but only when I am logged in as admin. As this does not seem to be an permission problem, I assume it is related to the admin theme (Seven), that might include some core libraries that Bootstrap (the which I use for my site) might not. But oddly enough, in the title bar of the modal appeared, instead of the page title, the string ´Array´, what makes me assume, that an unexpected array to string conversation took place:

Could somebody

* lead me to the official documentation of cores modal API,
* explain to me, what could be the reason that it works as admin only.
* And finally tell me, why on earth an array to string conversation takes place calling a modal?

# Answer
> 7 votes
This the official documentation for the API change you've mentioned:

Modal/dialog/ajax is using query parameters instead of accept headers

The most important detail is to attach this library:

```
$build['#attached']['library'][] = 'core/drupal.dialog.ajax';

```

You ask about why this works on admin pages without this. The reason is, admin pages already have dependencies on most Drupal jQuery libraries, while non admin pages are loaded without any jQuery out of the box (which is a great performance improvement in D8).

**Bootstrap Theme**

If enabled in the theme settings of the Bootstrap theme, "jQuery Modal" is replaced by "Bootstrap Modal", see this code snippet:

*LibraryInfo::alter()*

```
elseif ($extension === 'core') {
  // Replace core dialog/jQuery UI implementations with Bootstrap Modals.
  if ($this->theme->getSetting('modal_enabled')) {
    $libraries['drupal.dialog']['override'] = 'bootstrap/drupal.dialog';
    $libraries['drupal.dialog.ajax']['override'] = 'bootstrap/drupal.dialog.ajax';
  }

```

For this to work you attach the same core library as above, so that the Bootstrap theme can find these core libraries to override them.

# Answer
> 7 votes
I struggled with the Documentation as well. However, I was able to get my Modal working using the Dialog API D8 Core provides.

```
confirmationDialog = Drupal.dialog(CONTENT_OF_MODAL, {
  dialogClass: 'ADD_ANY_CLASSES',
  resizable: false,
  closeOnEscape: false,
  create: function () {
    $(this).parent().find('.ui-dialog-titlebar-close').remove();
  },
  beforeClose: false,
  close: function (event) {
    $(event.target).remove();
  }
});

```

Displaying a Modal

```
confirmationDialog.showModal();

```

Closing a Modal

```
confirmationDialog.close();

```

# Answer
> 5 votes
For anyone trying to add this to a theme, you can simply add drupal.dialog.ajax to your libraries.yml file under JS dependancies :

```
- core/drupal.dialog.ajax

```

More about theme dependencies here.

# Answer
> 1 votes
Your theme needs to declare a dependency on core/drupal.ajax because ajax is not loaded automatically for anonymous users.

```
dependencies:
    - core/jquery
    - core/drupal.ajax
    - core/drupal
    - core/drupalSettings
    - core/jquery.once

```

---
Tags: 8, javascript
---


# Question
Title: How to use Dompdf with Entity Print without composer?
I'm trying to make Entity Print work but I'm having issues with configuring the module.

The project I'm working on is two years old and for some reasons, I can't use composer and the `module` folder is at the project's root. The modules that have been created manually are in `modules/custom`, those downloaded are in `modules/contrib`

I downloaded and unzipped dompdf 0.8.1 in my vendor directory, and did the same in `modules/contrib` for Entity Print.

However, after the installation, when I try to make the module work, I get the message

> "Dompdf is not available because it is not configured. Please install with: composer require "dompdf/dompdf 0.8.0".

I have the choice between `TCPDF (v1)` that gets a PHP error when activated, that makes me need to reinstall the module if I want to get back to the configuration page, and `Php Wkhtmltopdf` that can't reach the server X even though I installed every related libraries I could find.

One coworker told me that he managed to make Entity Print work with DomPDF, but he couldn't remember how, even though it had something to do with the autoload.

I can't manage to make the couple solutions I found, and I don't really know what I'm looking for.

Please tell me if you need to see a file's content, I don't really know what I can show you for now.

Thank you in advance

# Answer
> 1 votes
I have been using the same module and was able to get it setup with Dompdf. Here are the steps in detail I used.

Summarized steps:

1. composer require drupal/entity\_print (this automatically downloads the dompdf dependency for me)
2. On the content type, I enabled the custom display setting of PDF
3. Followed steps in "From your theme" to create the print.css and twig templates
4. composer require dompdf/dompdf (in case #1 doesn't download it)

Alternative: Ludwig module

---
Tags: 8
---


# Question
Title: limit custom html.tpl.php to exact page, not subpages, drupal 7
I have a custom tpl page intended for a specific page like so:

html--something--anotherthing.tpl.php

This allows some custom handling on the page /something/anotherthing as desired. Unfortunately it is also being applied to sub pages like /something/anotherthing/details where the custom handling is not desired. Is there a syntax for naming tpl files so that it only applies to the desired page?

edit: I've enabled theme\_debug and it suggests exactly what I already have for the filename so not helpful.

# Answer
> 2 votes
If it's just one page you can just use something like `node--nid.tpl.php` or `page--node--nid.tpl.php` right? (Assume that `/something/anotherthing` and `/something/anotherthing/details` are two difference nodes)

# Answer
> 1 votes
If /something/anotherthing is a node, the answer by cchen has you covered. In case it's not...

The base suggestions are built up in `theme_get_suggestions`, (called by `template_preprocess_html`), and mirror the path and its parents. So for a path of /foo/bar/baz, you'll automatically have:

* html
* html\__foo
* html\__foo\__bar
* html\__foo\__bar\__baz

You can approach changing that in a couple of different ways:

1. Don't use the built-in suggestions, create your own:

```
function MYMODULE_preprocess_html(&$vars) {
  // Example only, if you have a better way to determine the path, use it!
  if (request_uri() == '/something/anotherthing') {
    $vars['theme_hook_suggestions'] = 'something__anotherthing';
  }
}

```

A template file named `something--anotherthing.tpl.php` would be picked up for that path only.
2. Remove the built-in suggestion for the parent when visiting the child:

```
function MYMODULE_preprocess_html(&$vars) {
  if (request_uri() == '/something/anotherthing/details') {
    $index = array_search('html__something__anotherthing', $vars['theme_hook_suggestions']);

    if ($index !== FALSE) {
      unset($vars['theme_hook_suggestions'][$index]);
    }
  }
}

```

This method is probably best as an example only, as you'll have to remember to add more exceptions to the code as you add new pages under /something/anotherthing.

Both examples can also be implemented in a theme if that's preferable.

---
Tags: 7, theming
---


title: drush @sites command doesn't work

text:
# Question
Title: drush @sites command doesn't work
The command `drush @sites status` doesn't do anything.

The full command obtained for the process is:

> `/usr/bin/php /home/myuser/.config/composer/vendor/drush/drush/drush.php --php=/usr/bin/php --php-options= @sites status`

This is my enviroment:

* Drupal: 8.2.4
* Drush: 8.1.7

The "**drush site-alias**" command says me:

* @site1
* @none
* @site2
* @self
* default
* site1
* site2

I have a setup for Drupal multi-sites with subdirectories, the aliases file is:

**~/.drush/aliases.drushrc.php**

```
<?php
/**
 * @file
 * Site alias for all sites
 */
$root = '/var/www/html';

$aliases['site1'] = array(
    'uri' => 'multisite.local/site1',
    'root' => $root,
    'path-aliases' => array(
        '%dump-dir' => '/tmp'
    ),
);
$aliases['site2'] = array(
    'uri' => 'multisite.local/site2',
    'root' => $root,
    'path-aliases' => array(
        '%dump-dir' => '/tmp'
    ),
);

```

The full output of the **drush status** command is:

```
 Drupal version                  :  8.2.4
 Site URI                        :  http://default
 Database driver                 :  mysql
 Database hostname               :  localhost
 Database port                   :  3306
 Database username               :  db_user
 Database name                   :  db_name
 Database                        :  Connected
 Drupal bootstrap                :  Successful
 Drupal user                     :
 Default theme                   :  bootstrap
 Administration theme            :  seven
 PHP executable                  :  /usr/bin/php
 PHP configuration               :  /etc/php.ini
 PHP OS                          :  Linux
 Drush script                    :  /home/myuser/.config/composer/vendor/drush/drush/drush.php
 Drush version                   :  8.1.7
 Drush temp directory            :  /tmp
 Drush configuration             :
 Drush alias files               :  /home/myuser/.drush/aliases.drushrc.php
 Install profile                 :  standard
 Drupal root                     :  /var/www/html
 Drupal Settings File            :  sites/default/settings.php
 Site path                       :  sites/default
 File directory path             :  sites/default/files
 Private file directory path     :  private/default
 Temporary file directory path   :  /tmp
 Sync config path                :  sites/default/files/config_BrLQsjBr6VkcTEyCkzkY-es-hzISWg4d3oV2EEEoqh-UZMLBJWDiDaq78TIWm-lBbVi-aPHISw/sync

```

# Answer
> -1 votes
"@sites" is no longer available with Drush 9. I presume this what is being used with Drupal 8 here.

More information here: https://github.com/drush-ops/drush/issues/3019#issuecomment-334503217

> Drush 9 no longer supports executing a single command on multiple sites with alias lists (@A,@b,@c) or @sites. Neither of those syntaxes are available in any context. You may still use drush sa @group to see all aliases in a group; that is the only context in which Drush recognizes alias lists.

---
Tags: 8, drush, multi-sites
---


title: Date format help

text:
# Question
Title: Date format help
I am trying to add Japanese date Y年 n月 j日 in fields but the date is being displayed 2016年 2月 6日 年月日 . I want to remove 年月日 at the end of the date it indicates year month and day. 2016年 2月 6日 is exact format of date and 年月日 this is not needed.

# Answer
You can specify new date formats here via: /admin/config/regional/date-time/formats

If you wanted to add or remove 年月日 to these dates, you can just enter it in there. If it doesn't show up an alternative way is to do a hook date format, check out: https://www.phase2technology.com/blog/programatically-creating-date-formats/
> 2 votes

# Answer
If you haven't found the answer yet, here it is!

Simply add a '\\' before each character.

So 'Y年n月j日' should become 'Y\年n\月j\日'

Source: https://www.drupal.org/forum/support/post-installation/2011-04-30/custom-date-formats-write-dates-the-japanese-way#comment-6443784
> 0 votes

---
Tags: 7, datetime
---


# Question
Title: When I add a context filter, my view is wrapped in a div
I created a view block to display a button (join / leave) above my groups. When I add a context filter to my view, it is wrapped in a div without "class" and "id".

1) I added to my view the following context filter:

(Group content User) User: User ID

2) When the filter value is NOT available: Provide a default value: User ID of the logged in user

Here is the result :

```
<div><section class="views-element-container block block-views block-views-blockgroup-button-rejoindre-ou-quitter-block-1 clearfix" id="block-views-block-group-button-rejoindre-ou-quitter-block-1">

      <div class="form-group"><div class="view view-group-button-rejoindre-ou-quitter view-id-group_button_rejoindre_ou_quitter view-display-id-block_1 js-view-dom-id-7e52cd584bd1944bf2360a966e72384fc9e36069f506a9b448a39dde191c802e">

      <div class="view-empty">
      <a class="btn btn-success" href="/group/2/join"><i class="fa fa-sign-in"></i> Rejoindre le groupe</a>
    </div>

          </div>
</div>

  </section>

</div>

```

If I delete the context filter, the div envelope would disappear, but that's not the view I want:

```
<section class="views-element-container block block-views block-views-blockgroup-button-rejoindre-ou-quitter-block-1 clearfix" id="block-views-block-group-button-rejoindre-ou-quitter-block-1">

      <div class="form-group"><div class="view view-group-button-rejoindre-ou-quitter view-id-group_button_rejoindre_ou_quitter view-display-id-block_1 js-view-dom-id-66463110f7422801aaa138cc3887e2da44cb7833e8200c59f0e952de0bc55d5e">

      <div class="view-content">
          <div class="views-row">
    <div class="views-field views-field-id"><span class="field-content btn btn-danger"><a href="/group/2/leave"><i class="fa fa-sign-out"></i> Quitter le groupe</a></span></div>
  </div>
    <div class="views-row">
    <div class="views-field views-field-id"><span class="field-content btn btn-danger"><a href="/group/2/leave"><i class="fa fa-sign-out"></i> Quitter le groupe</a></span></div>
  </div>

    </div>

          </div>
</div>

  </section>

```

I encounter this problem with other block view, it's really weird. An idea ?

# Answer
> 0 votes
Check the twig template (by turning on twig debugging) that is generating the div for your contextual filter. Then alter it with an ID or Class tag.

Let me know if you need help turning on twig debugging.

Find the twig template that is generating that div, copy it and rename it with one of the FILE NAME SUGGESTIONS. The add the following code to the div.

```
<div{{ attributes.addClass('my-class') }}></div>

```

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


# Question
Title: Downloading from private directory corrupting some file types
We have set up a private file system on a website based on drupal's guidelines. We are using Drupal 8.

We have setup the private file directory outsite of `/var/www` at `/var/privatefiles`. When downloading certain types of files - specifically docx - files are being corrupted. pdfs and other common types seem to be working fine.

File upload is working correctly as I am able to scp the files directly from the server and they are intact.

Additionally, on a test server made from a copy of the server we set up the private files inside the siteroot and that works without problem. This solution is not ideal however as we do not want the files to be accessible directly from the web.

I cannot find anything that discusses this issue, surely I am not the first person to set up a private directory this way and have docx files break?

UPDATE:

Further testing indicates that what is occurring is that drupal or php are adding 3 newline `0a` characters to the start of every file served from the private file system. It has np effect on some formats but all MS files - docx,xlsx etc - are broken.

How do I fix this?

# Answer
We have finally solved the issue and in case it is of use will put the answer here.

Based on this php issue we realised the issue could be a closing php tag somewhere else on the site.

In the end we found three small modules - one animated a set of banner images on the site; one made some api calls for a search feature; and another created some custom blocks from an external api call.

Each of these had `?>` at the end of their `.module` files. Removing them fixed the problem.

Why this problem went on to affect all files served I do not know.
> 1 votes

---
Tags: files
---


title: How do I use the states API in a hook?

text:
# Question
Title: How do I use the states API in a hook?
I'm trying to use the states API in Drupal 8 but I'm having trouble, and I'm also having difficult debugging.

Use case:

On user accounts, I have a taxonomy term reference field called **Gender**. The three terms in the taxonomy vocabulary are female, male, and other.

I also have a text field on user accounts called **Other**. I want to show this **Other** field if and only if **Gender** is set to *other* (term ID: 27).

Here is the code I'm using:

```
function mymodule_form_user_register_form_alter(&$form, &$form_state, $form_id) {
  $form['field_gender_other']['#states'] = array('visible' =>
    array('input[name="field-gender"]' => array('value' => '27'),
    ),
  );
}

```

I based this off of code I used for Drupal 7. Unfortunately, it's not doing anything.

I looked at `StateDemo.php` in the fapi submodule of the Examples module for Drupal 8, but that's for building a new form, and I'm trying to modify an existing form.

# Answer
> 5 votes
You should use code similar to the following one.

```
$form['field_popin_text']['#states'] = [
  'visible' => [
    'select[name="NAME_OF_SELECT_LIST"]' => ['value' => '27'],
  ]
];

```

# Answer
> 2 votes
I use this to display or hide fields with dependency in a dropdown select list.

```
/**
 * Implements hook_form_alter().
 */
function MYMODULE_form_alter(&$form, \Drupal\Core\Form\FormStateInterface &$form_state, $form_id) {
  if ($form_id == 'node_CONTENT_TYPE_form' || $form_id == 'node_CONTENT_TYPE_edit_form') {
    conditional_field_select(
      $form,
      'field_target',
      'field_controller',
      ['value_a', 'value_b', 'value_c'],
      'visible'
    );
  }
}

function conditional_field_select(array &$form, $targetField, $controlledBy, array $values, $state = 'invisible', $cond = 'or') {
  if (isset($form[$targetField]) && isset($form[$controlledBy])) {
    $form[$targetField]['#states'][$state] = [];
    foreach ($values as $value) {
      array_push($form[$targetField]['#states'][$state], ['select[name=' . $controlledBy . ']' => ['value' => $value]]);
      if (end($values) !== $value) {
        array_push($form[$targetField]['#states'][$state], $cond);
      }
    }
  }
}

```

It can easily be changed to input.

```
array_push($form[$targetField]['#states'][$state], [':input[name=' . $controlledBy . ']' => ['value' => $value]]);

```

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


# Question
Title: Getting translations programmatically from non-default language
Scenario: I have the original string: "Perro", which has its translations: EN =\> "Dog", FR =\> "Chien". Mission: In my custom module, I have the string "Chien" and I need to get its English translation, "Dog".

# Answer
This will work for a node that has a field\_animal with translation (in Drupal 8). First we found the french translation then we compare with the string, second we fetch the english translation.

```
$myString = 'Chien';
$translation = \Drupal::service('entity.repository')->getTranslationFromContext($node, 'fr');
$animalFr = $translation->get('field_animal')->value;
if ($myString == $animalFr){
  $translation = \Drupal::service('entity.repository')->getTranslationFromContext($node, 'en');
  $animalEn = $translation->get('field_animal')->value;
}

```
> 1 votes

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


# Question
Title: Running 'composer update' replaces module folders
I'm going through the nightmare of trying to update a site to 8.4.4 from 8.3.2. It seems like the best way forward is to delete `vendors` and `composer.lock` and let composer replace everything. However, when I do this, it also goes through and replaces all of my module folders as well. A number of them are patched, so replacing them straight out of the gate simply doesn't work.

Is this normal behavior for composer? Is there some way to specify that I only want to replace what's going into the vendor directory?

# Answer
> 1 votes
> Is this normal behavior for composer?

Yes

> Is there some way to specify that I only want to replace what's going into the vendor directory?

Sure, remove the reference to the module(s) from composer.json. Obviously at that point you’ll need to manage any updates for them yourself.

A better resolution would be to install Composer patches, and patch the modules automatically as they’re being installed/updated.

# Answer
> 0 votes
Inside the "extra" section of your composer.json, you can specify paths to patches (locally or remote). After running 'composer update' your modules will be patched automatically:

```
"enable-patching": true,
"patches": {
  "drupal/core": {
    "Content translation bug":
    "https://www.drupal.org/files/issues/2137815-33.patch"
  },
  "drupal/paragraphs": {
    "Inline editing fix": "patches/paragraphs_fix.patch"
  }
}

```

---
Tags: updating, composer
---


title: Views breadcrumb

text:
# Question
Title: Views breadcrumb
I need to have breadcrumb builder that will make all "News" nodes appear as breadcrumb children of a View we've created at /news

I did follow this post : Add a breadcrumb to a view page?

But it doesen't work, the module is installed with no error but no change on my breadcrumb, i did a simple **die;** in modules/custom\_modal/src/Controller/CustomModalController.php

```
public function applies(RouteMatchInterface $route_match) {
 print_r("OK");
 die;

```

But no success .. and no error, i can't explain that, so any help is welcome

# Answer
> 1 votes
I recommend using "Easy Breadcrumb": https://www.drupal.org/project/easy\_breadcrumb. Make sure your news articles geth the path of /news/my-news-article, and the easy breadcrumb module will automatically add correct breadcrumb of *\> news \> my news article*.

> Easy Breadcrumb takes advantage of the work you've already done for \>generating your paths' alias, while it naturally encourages the creation \>of semantic and consistent paths. This modules is currently available for \>Drupal 7 and 8.

---
Tags: views, 8, breadcrumbs
---


# Question
Title: Any solution to use two different $base_url's for drupal 7
Any solution to use two different $base\_url's for drupal 7. What i need to do is when i log to my site using IP/VPN, $base\_url should be xxxx.xxxx.xxxx.xxxx and without any vpn connections $base\_url should be aaaa.aaaa.aaaa.aaa. Any solutions? I'm Using Drupal 7.54

# Answer
Rather than trying to change the base\_url manually you might be better using something like https://www.drupal.org/project/domain or Drupal's language translation system and having 2 domains setup and the content shared for both domains.

So they effectively will look and act the same but the base url for drupal will be whatever the user is currently on. Then you could use these modules inbuilt hooks if you wanted to force a user ontop a specific domain based on their IP or whatever
> 0 votes

---
Tags: theming
---


# Question
Title: How can I print out large variables in hook_entity_presave for debugging?
I'm trying to print out the `$entity` variable im `hook_entity_presave` because I want to see all of the properties and their values at the time of saving.

The problem is that every way I have tried to print out the information, I get out of memory limit PHP errors. My PHP settings are set to 1024M max memory.

I have tried `print_r()`, `var_dump()` and `debug()`, all with the same result. I also tried `dpm()`, which allows the page to continue without running out of memory, but nothing gets output.

```
function my_module_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
  debug($entity, NULL, TRUE);
}

```

# Answer
You don't want to see all properties. That's internal data that doesn't help you much anyway. What you want to see is the field values. And the easiest way to do that is this:

```
debug($entity->toArray());

```

That gives you a simple structure of all fields and their values. You can access them in a similar way as that array looks like, e.g. $entity-\>field\[$delta\]-\>property, \[$delta\] is optional and defaults to 0. See http://wizzlern.nl/drupal/drupal-8-entity-cheat-sheet for more details.

The other way is to use an IDE with a debugger, then you can set break points, inspect anything at runtime and even execute code.
> 4 votes

# Answer
I had the same issue with not being able to print variables of a large Drupal array. I came across this solution on the Drupal site. Credit goes to the user `malaynayak` for the solution.

```
$result = json_decode(json_encode($array));
var_dump($result);

```

or

```
$result = unserialize(serialize($array));
var_dump($result);

```
> 2 votes

# Answer
Have you tried:

`$export_str = var_export($entity, TRUE);
 dpm($entity_str);`
> 0 votes

---
Tags: 8, debugging, entities
---


# Question
Title: How to add GitHub repositories in Profile Installation
How to add Git repositories to install module while installing Drupal 8 Profile. Is any way to add repositories path in .yml or .profile to module installation? Is this possible?

# Answer
> 1 votes
The easiest way is to add the dependencies to your profile's composer.json file, and use Composer to install the profile into your project. The dependencies will be automatically downloaded with it.

Failing that, it'll be a custom script job which will take whatever shape makes sense for your workflow/config.

---
Tags: 8, installation-profiles
---


# Question
Title: How to disable shipping for ONLY virtual products and not if combined with physical
In Drupal Commerce, I'm trying to come up with a rule the bypasses shipping if virtual product types are put into the cart, but ONLY if all products are virtual; if physical products are put in, then the rule wouldn't fire because these products need to be shipped.

Below, for reference, is a solution for virtual products; it's close but it won't suffice if combined with both physical and virtual products.

**Install Commerce Rules Extra**

* Create a rule for Event: Process checkout pane
* Add Action: Change pane properties
* Value: Shipping information
* Page to move to: `<do not change>`
* Enabled: uncheck
* Add Condition: e.g. by Order contains products of particular product types, or based on Commerce order contains shippable products supplied by Commerce Physical Product. You may have to clear caches before this takes effect.

# Answer
Commerce Shipping has a couple of ways you can approach this. The simplest is to set the weight of your virtual products to zero, they won't be assessed shipping charges, and they won't affect any weight based calculations.

EDIT: Alternatively, you can use Commerce Rules Extra to add conditions that exclude your virtual products in the conditions for your Flat Rate.
> 1 votes

# Answer
To bypass the shipping pane if the cart only contains virtual products, add an "and" condition that checks to see if the cart contains product types that are virtual or not shippable and if the cart does not contain product types that are shippable.
> 0 votes

# Answer
Here's a sketch of the way I've dealt with similar situations in a rule.

* Create a variable to record outcome, eg. needs\_shipping, defaulted to false
* Loop through the items in the cart
* If the current item is physical, set needs\_shipping to true.

It's also possible to encapsulate this loop in code and call it from a rule, which will make the rules easier to maintain.
> 0 votes

---
Tags: rules, commerce
---


title: Generating URL with CSRF token

text:
# Question
Title: Generating URL with CSRF token
I have a route that requires a CSRF token:

```
mp.ajax.authorized:
  path: /mp/ajax/authorized
  defaults:
    _controller: 'Drupal\mp\Controller\AjaxController::authorizedCallback'
  requirements:
    _csrf_token: 'TRUE'

```

I need to generate a URL for this route. As the route has \_csrf\_token set to TRUE, the route needs to contain a CSRF token.

I've generated a URL from the route using Url:

```
Url::fromRoute('mp.ajax.authorized', [], ['absolute' => TRUE])->toString()

```

It generates a route with a token:

```
http://example.com/mp/ajax/authorized?token=91018d3f93299fe116c5596ea32d9addca063a92

```

I also tried the url\_generator service to generate the URL:

```
$url_generator = \Drupal::service('url_generator');
$url = $url_generator->generateFromRoute('mp.ajax.authorized', [], ['absolute' => TRUE]);

```

And it generates the same URL.

However, the token on the URL is incorrect, as the actual CSRF token that is retrieved from CsrfTokenGenerator is:

```
1qG-Tw4AyQgNmVWtlkp_to7mielSz8ZfQZAkhWqAlsQ

```

I've done some reading, and it appears that the token given from Url is a placeholder, but I need the actual token, not the placeholder. Does anyone know how to get this?

Update: I've discovered I can retrieve the URL with a token in it by passing token as a parameter to the Url builder:

```
Url::fromRoute('mp.ajax.authorized', [], ['absolute' => TRUE, 'query' => ['token' => \Drupal::csrfToken()->get()]])->toString()

```

However, this token fails validation in Drupal\Core\Access\CsrfAccessCheck, so it appears this is not the correct solution.

# Answer
Well, I found a solution, however, I'd be amazed if there isn't a better way to do it, and in fact I'm pretty sure it's bypassing the placeholder API, so it's likely the wrong way to do it. But until someone gives me a better solution, it's a working one.

The solution is to generate the token manually, then set it as a GET query on the URL when generating the URL.

When generating the token however, you need the internal path for the route, which is used as a basis for generating the token.

```
$url = Url::fromRoute('mp.ajax.authorized');
$token = \Drupal::csrfToken()->get($url->getInternalPath());
$url->setOptions(['absolute' => TRUE, 'query' => ['token' => $token]]);
$absolute_url = $url->toString()

```

Note that I've already found this method doesn't work on routes with optional parameters, so if someone comes across this, you'll have to find another method in such a case.
> 4 votes

# Answer
Based on the code of Jaypan but with additional parameter (node id):

**routing.yml:**

```
entity.node.publish:
  path: '/node/{node}/toggleStatus'
  defaults:
    _controller: 'Drupal\publishcontent\Controller\PublishContentPublishEntity::toggleEntityStatus'
  requirements:
    _csrf_token: 'TRUE'
    _publish_access_check: 'TRUE'

```

**custom function:**

```
$nid = 100;
$url = Url::fromRoute('entity.node.publish', ['node' => $nid]);
$token = \Drupal::csrfToken()->get($url->getInternalPath());
$url->setOptions(['absolute' => TRUE, 'query' => ['token' => $token]]);
$absolute_url = $url->toString();

```

Will return something like this:

```
https://www.exapmle.com/node/100/toggleStatus?token=PF06yJ7PLR052_HxeTWvsuye88d7NAZgwanN3yiswU

```
> 2 votes

---
Tags: 8, csrf
---


# Question
Title: How to bulk update existing path alias after changing the URL alias pattern?
How to bulk update existing URL alias?

I have Path auto module add path alias to URLs. I have changed the URL alias pattern. Now I want to update the pattern of old URLs also.

How can I achieve this?

# Answer
> 6 votes
> it works only to URL which does not have path alias – Vamsi

Then first go to `/admin/config/search/path/delete_bulk` and delete the aliases in question.

Then update `/admin/config/search/path/update_bulk`

# Answer
> 3 votes
go to configuration \> Search and metadata \> Url aliases \> bulk generate.

If you already have already aliases and want to change them to the new ones you could delete all the content aliases first, is another option in url aliases.

# Answer
> 2 votes
With Pathauto you can delete all the content aliases and then bulk generate new ones - but this **does not** address the problem if you have many pages with custom aliases mixed with automatic aliases as these will also be deleted. Bulk generate will only generate aliases for nodes that are checked for automatic alias AND has *no alias* \- deleted unchecked auto alias nodes will revert back to default pattern of node/#

To get around this issue you can use Administrative views (or your own view with bulk operations)

1. go to Pathauto and change your URL pattern to the new desired pattern.
2. go to admin/content (using Admin Views with VBO)
3. select all nodes with aliases you want to update
4. choose operation - unpublish
5. choose operation - publish
6. go see your new updated aliases :)

The idea here is just to change something so that the nodes are saved again, the aliases are updated with the current pattern upon save. and using VBO allows you to do as many as you want, and you could add extra exposed filters to your View to better select your list of nodes to update.

---
Tags: 7, path-aliases
---


# Question
Title: Add fields to a coded block and use them in a templated block
I want to programmatically create a block to which I can add a body field, a link and an image and then create a block twig template file where I can use these fields. For the uploaded image ideally I would want to be able to use a responsive image style. Am hoping someone someone can tell me how I would do this?

# Answer
> 0 votes
Probably the easiest way to do this is a block with a settings form.

When you place a block of this class via the block layout, you can add your information in the settings. To have another block with different settings, just place another block.

Some sample code:

```
 public function blockForm($form, FormStateInterface $form_state) {
    $form = parent::blockForm($form, $form_state);

    $config = $this->getConfiguration();

    $form['my_block_text'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Foo'),
      '#description' => $this->t('my desc'),
      '#default_value' => isset($config['my_block_text']) ? $config['my_block_text'] : '',
    );
    return $form;
  }
  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    parent::blockSubmit($form, $form_state);
    $values = $form_state->getValues();
    $this->configuration['my_block_text'] = $values['my_block_text'];
  }
  public function build() {
    $config = $this->getConfiguration();
    $text = $config['my_block_text'];
    ...
  $block = [
   '#theme' => 'my_module_my_theme',
    '#my_text' => $text,
    ...
  ];
  return $block;
}

```

For images / files, you can just use the standard file form type. The config will get the fid of the image. In the build, you will need to load the file entity and generate the URL to the file. (Lots of existing examples of this).

To get it all to twig, you will need to use a hook\_template() implementation that defines the twig template and variables. Then pass it to the theme using the render array created in the block build code.

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


# Question
Title: Loading views blocks that aren't actively set
Is there a way to programmatically load a views block that isn't active in the config(not placed under admin-\>structure-\>block layout).

My usual method to load a block programmatically is something like the following in `hook_preprocess_node`:

```
$block = Block::load('views_block__courses_block_3');
$block_render = \Drupal::entityTypeManager()->getViewBuilder('block')->view($block);

```

However, that seems to just return `null` if I haven't placed the block into a region after creating it under views.

Also noticed that the block isn't listed in the config table until placed into a region.

# Answer
See this answer for details.

Basically, the way to do this is to add a "Hidden Blocks" region to your theme, then place the blocks you want to render there. The region does not get rendered so it's not a big resource drain. We do this to use have "block" paragraphs using paragraphs all the time.
> 3 votes

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


# Question
Title: Form display: How to move fields into the advanced group?
How can I move a field in a node edit form from the main region into the advanced/secondary group region in the right-hand column?

This question asks how to move elements out of the secondary group into the main group, but this is the inverse.

I tried setting a group for my field in a similar way to the above answer:

```
$form['field_article_language_filter']['#group'] = 'advanced';

```

This did move it, but I'd like it to be in a group with a summary arrow button to toggle it closed or open.

# Answer
In a custom module or your theme, create a group and place your field in there:

```
/*
* Implements hook_form_alter()
* @param     Array $form, Object $form_state, Array $form_id
* @return    Array $form
*/
function MY_MODULE_form_node_form_alter(&$form, FormStateInterface $form_state,  $form_id) {

  // Create a languages group in the right-hand column
  $form['languages'] = [
    '#type' => 'details',
    '#title' => t('Languages'),
    '#group' => 'advanced',
    '#attributes' => [
      'class' => ['node-form-options']
    ],
    '#attached' => [
      'library' => ['node/drupal.node'],
    ],
    '#weight' => 100,
    '#optional' => TRUE,
    '#open' => TRUE,
  ];

  // Move the languages settings to the right-hand column
  $form['field_article_language_filter']['#group'] = 'languages';

  return $form;
}

```

This is based on this gist, thanks to Dan Braghis.
> 11 votes

---
Tags: 8, forms
---


title: Order nodes by comment_count

text:
# Question
Title: Order nodes by comment_count
I try to order nodes title by `->comment_count`.. the code below: using `db_select` :

```
function odrer_node_by_comment_count($type) {
  $query = db_select('node', 'n');
  $query->join('comment', 'c' , 'c.nid=n.nid');
  $query->join('node_comment_statistics', 'ncs', 'ncs.nid=n.nid');
  $query->fields('n', array('title'))
   ->condition('n.type', $type, '=')
   ->condition('c.status', 1 , '=')
   ->orderBy('ncs.comment_count', 'DESC');

   $result = $query->execute()->fetchAll();

   if (isset($result)) {
     foreach ($result as $node) {
       return $node->title;
     }
   }
}

```

The issue here is node title return more than one..
Then I use `db_query`:

```
function odrer_node_by_comment_count($type) {
 $result = db_query('SELECT c.nid AS nid
    FROM {comment} c
    JOIN {node_comment_statistics} ncs ON ncs.nid = c.nid
    WHERE c.status = 1
    ORDER BY ncs.comment_count DESC')->fetchAllKeyed();

   if (isset($result)) {
     foreach ($result as $node) {
       return $node->title;
     }
   }
}

```

It works fine,, But i don't know how to pass the $type into query..

# Answer
> 0 votes
No code needed, i have not try this but i think it works, create a view of comments (not nodes), order them by number of comments, and a relationship to the parent node of comment, then modify each field in display settings to use the relationship to the parnet node, this will display the node instead of the comment. that's it.

---
Tags: nodes, database
---


# Question
Title: How can I consistently see the "renderable" version of a views field?
I created a custom views style plugin. I currently use:

```
$value = $view->field[$label_column]->getValue($row);

```

to get the value of the field. However, I was recently informed that this does not work for list fields(like 0=\>'yes'=, 1=\>'no'). This original line displays 0 and 1 instead of 'yes' and 'no'. This user suggested I use:

```
$items = $view->field[$label_column]->getItems($row);
$value = $view->field[$label_column]->render_item(1, $items[0]);

```

It seems like this solution does not work on standard fields. I also recently found that the original line does not respect field rewrites. Is there a universal way to see the field value after rewrites, while also respecting lists?

# Answer
> 1 votes
Use advancedRender(), this is a method in the base class of views fields, which renders an entity field respecting field rewrites and other settings:

```
$value = $field->advancedRender($row);

```

---
Tags: views, 8, entities
---


title: How to remove modules via ftp?

text:
# Question
Title: How to remove modules via ftp?
I need to know how to remove modules via ftp, i activated some modules, and now im getting constantly errors like

> Fatal error: Call to undefined function views\_include() in /home/a7898297/public\_html/sites/all/modules/eva/eva.module on line 113

so how can i remove custom modules?

# Answer
> 4 votes
You need to disable the module on http://example.com/admin/modules first. That should take care of your error messages.

If your administration interface is not accessible - caused by the error message - you could access the database directly and disable the module in the system table - as suggested by Mołot and outlined in https://drupal.org/node/157632.

Additionally to disabling the module, you should also uninstall it - which will remove any configuration and data associated with this module from the database: http://example.com/admin/modules/uninstall (at least it should, if it is properly written).

Now, you can safely remove the module from the modules directory, if you want to. Since the module is disabled and uninstalled, it will not interfere with your Drupal installation, however, it is advisable to clean up the modules directory, and move the module to a location outside the webroot - to avoid issues if the module has security holes and the web-server is (mis)configured to allow direct execution of modules.

Before you do all this, I would save a backup of the database and the custom module, in case the functionality and data might be needed after all.

You can of course do all of this also on the command line using drush - since you asked about ftp, I assume you do not have ssh access.

# Answer
> 0 votes
In addition to the other answer (disabling the plugin manually via database), you can also do it via FTP if you worry about damaging the database.

Find the module's *.module* file and plainly delete its contents (but leave the empty file there). This will usually make any fatal errors disappear since the module now does almost nothing. Now you can access your admin interface again and uninstall the offending plugin.

For me this is the most straightforward way.

# Answer
> -4 votes
You must install the FireFtp addon in Mozilla Firefox, connect the host, and delete the modules. That is not working for you. You must disable modules from admin/modules and uninstall them from admin/modules/uninstall; that would delete any database table that the modules created.

I would recommended to edit modules/eva/eva.module on line 113, and delete the `views_include()` function; after that, disable and uninstall the modules.

---
Tags: 7
---


# Question
Title: How to create a view that list all child nodes of current page?
I have a content type "A" that has an entity reference field to content type "B".

I need to create a view that will be embed on "A" node page for listing all "B" nodes referenced to it.

I know I have to use contextual filters for getting the current node id and a relationship, but not sure exactly the recipe.

# Answer
1. Create a view of content type B. (View Type Block)
2. Create a relationship in that view to the content that contains the reference field by clicking on add a relationship, and search for the name of your reference field)
3. Create a contextual filter to filter by ID using that reference field. Choose "Provide default value" then "Content ID from URL".
4. Display your block on the appropriate pages.
> 2 votes

---
Tags: views, 8
---


# Question
Title: How to publish in an organization with hierarchy?
My Drupal experience is limited to a single site with custom content types and standard roles. Please take a look at the use case below, involving content being routed through multiple organizational levels, so there is consolidation at each level and some content being "highlighted" for the next higher level.

My company has weekly activity reports. Each member submits an activity report and then the team lead chooses a few to be submitted to our section manager. Then our section manager chooses a few (from multiple teams) to be submitted to our division manager. Then our division chooses a few (from multiple sections) to be submitted to our top level manager.

What stuff should I look into to accomplish content going through different levels like this?

# Answer
Have a look at the Group module (commonly perceived as an alternative for Organic Groups).

Group allows for creating arbitrary collections of your content and users on your site, and grant access control permissions on those collections. It is available as of D7, and has a D8 version also. The Group module creates groups as entities, making them fully fieldable, extensible and exportable. Which also makes it integrate very well (out of the box) with commonly used modules such as Rules, Views, etc.

Some more questions you may want to look at for more details:

# Sample configuration

Below is an example of a possible configuration, which may help to get you started with possible configurations (using the Group module):

```
Group type ID ! Group type ! Group role ID ! Role
--------------+------------+---------------+------------
 1            ! Class      ! 3             ! Instructor
 1            ! Class      ! 4             ! Student
 2            ! Customers  ! 5             ! Lead
 2            ! Customers  ! 6             ! Prospect
 2            ! Customers  ! 7             ! Licensed Customer
 2            ! Customers  ! 8             ! Sales
 2            ! Customers  ! 9             ! Support
 2            ! Customers  ! 10            ! Accounting
 2            ! Customers  ! 11            ! R&D
 3            ! Project    ! 12            ! Project Manager
 3            ! Project    ! 13            ! Developer
 3            ! Project    ! 14            ! Customer

```

### Group Types

The above example consists of 3 ***group types***:

* Class.
* Customers.
* Project.

### Group Roles

For each of the 3 group types, there are specific ***Roles*** defined, some more details about some of them:

* for the *Class* group, these are the 2 roles that are configured:
    + Instructor.
    + Student.
* for the *Project* group, these are the 3 roles that are configured:
    + Project Manager.
    + Developer.
    + Customer.

These are the *Group Specific Roles*: these roles can be configured per group type and will only be available on groups of that group type. As an example, for group type "*Class*", the defined roles are **Instructor** and **Student** (which are not available for the other group types.

On top of the group specific roles, there are also *Special Global Roles*: These are the special (hardcoded) roles named **Outsider** (= a signed in user that did not join a group) and **Member** (= a signed in user that did join a group). These cannot be defined by the Drupal administrator, and they are always available for any group. These roles can have different permissions sets for each group type. Special case: the role **Anonymous** is related to a user that is not signed.

### Groups

Each of the configured group types can have any number of ***Groups***.

Examples of groups:

* for the *Class* group type, there could be these **Groups**:
    + Getting started with Drupal.
    + Drupal for site builders.
    + Become an expert in using the Rules module.
* for the *Customers* group type, there could be these **Groups**:
    + Service Requests.
    + Order Processing.
    + Sales Orders.
    + Relationship Management.

### Permissions

For each of the configured group types, you can then also configure for each ***Content Type*** which ***Role*** has what kind of access (= none, view, create, edit, delete). Be aware: even though this looks similar to Drupal's permission configuration, these permissions are not the same permissions (they are specific to the Group module).

# Your usecase

In your case, your challenge seems to be about this:

> ... content going through different levels like this?

Translated to an implementation using the Group module, it seems to me that all that's needed is to assign, and later on re-assign, each node (content) to an appropriate group. Whereas you use appropriate group permissions/roles to accutally perform these assignments.

And for the required group types to be configured, I'd start with these specific group types:

* Teams (with groups Team T1, Team T2, ..., Team Tn).
* Sections (with groups Section Sa, Section Sb, ..., Section Sx).
* Devisions (with groups DevX, DevY, DevZ).

# Resources
> 0 votes

---
Tags: nodes, workflows
---


# Question
Title: Display Suite Custom Wrappers and Custom Classes Tabs Not Appearing in Manage Display
I am using Display Suite layouts for some of my pages. I want to add in some custom classes for the regions. However, the custom classes and custom wrappers tabs are not appearing on the Manage Display screen for my view modes. I am able to add custom classes on the Display Suite Custom Classes screen, but cannot apply them to the display, as the tabs are not there.

Am I missing something? I have seen videos where they appear for other users so don't know why they are not appearing for me.

Below is a screenshot showing the missing tabs.

I want to basically target the view mode as a class on the page. At the moment, it is only inserting the layout I have selected as a class, so if I am using the same layout for different view modes I can't differentiate between them if they are for the same content type.

# Answer
Two possibilities come to mind.

1) Have you saved since you selected "One Column" as the layout? The configuration options change once you select something other than -None-

or

2) Have you checked that you have the correct Display Suite permissions? Namely, 'Administer classes' and 'Administer fields'
> 1 votes

---
Tags: 8, theming, display-suite
---


# Question
Title: How to get Display Mode of a product variation in hook_commerce_form_add_to_cart_form_alter?
I want to alter a product display using hook\_form\_alter as below:

```
/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function HOOK_form_commerce_order_item_add_to_cart_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

  $product = $form_state->getFormObject()->getEntity()->getPurchasedEntity();

// THIS WHERE I want something like
  if($product->viewMode() == 'compact') {
     // do something...
  }
}

```

Any help would be appriciated.

# Answer
Never mind figured out myself,

I found the answer to get the view\_mode you need to access storage of form stage using following code.

```
$form_state->getStorage()['view_mode'];

```

This will return string based on which view mode the form is attached to.

i.e, "defualt" or "compact" etc...
> 0 votes

---
Tags: commerce, hooks
---


title: Sort result by taxonomy term weight

text:
# Question
Title: Sort result by taxonomy term weight
```
 $query = db_select('node', 'n');
   $query->join('field_data_taxonomy_catalog', 'tc', 'n.nid = tc.entity_id');
   $query->leftjoin('field_data_field_chip', 'fdc', 'n.nid = fdc.entity_id');

   $query->fields('tc',array('taxonomy_catalog_tid'));
   $query->fields('fdc',array('field_chip_tid'));

   $query->fields('n',array('nid'));

   $query->condition('tc.taxonomy_catalog_tid',$get_tid,'=');

   $query->orderby("fdc.field_chip_tid","ASC"); //I Want to sort the resultset on the basis of weight instead of the term Id.

   $result = $query->execute()->fetchAll()

```

I need to sort the result on field\_data\_field\_chip weight instead of the term Id. I am new to Drupal and don't know how to fetch the weight of the taxonomy terms.

# Answer
> 2 votes
The `weight` column in the `taxonomy_term_data` table contains the information you need.

You can join it in to your current query via `taxonomy_term_data.tid`.

# Answer
> 0 votes
Approaching this from a sitebuilding perspective using Views:

1. You can use the module Views Term Hierarchy Weight Field, which not only sorts by weight but respects nesting of terms.
2. Alternatively, if your taxonomy does not have a hierarchy/nesting of terms \[aka is flat\], you can build a view with a relationship for the "Taxonomy Terms on Node". Refer to this Drupal issues post that walks you through how to set it up.

# Answer
> -3 votes
https://www.drupal.org/docs/7/api/database-api/dynamic-queries/ordering

See drupal standard documentations, it may help you

---
Tags: 7
---


# Question
Title: CKEditor and IMCE: how to access to public files directory
I have a problem that I can't access public files directory from IMCE as file browser (and CKEDITOR as editor). When an user write a blog post, he can't upload images to public directory because this path doesn't appear in the IMCE directory tree.
Prior to post this question I have searched in Drupal Answers, in Drupal forum and in Google if there is an answer to my question but without success. I've read some other answer to similar questions but without success. I put here my configuration.

*Config media file system:*

* Public path: sites/default/files
* Private path: sites/default/files/private
* Temp path: tmp
* Checked: Private files served by Drupal

CKEditor file explorer: IMCE (for all)

Users, that can write blog post, has permission to "Bypass file access control", "Administer files", "add and upload new files", etc.

When they write a blog post and open IMCE to upload an image in the body, the paths shown in the directory tree are all relative to private directory and they can't select public path.
It's for Drupal 7.

How should I do to allow user to upload files to public path with IMCE?

**UPDATE**
After some days searching about this question, I have found where is the problem. There are two, very old, open issues in IMCE that are just my problem. https://www.drupal.org/project/imce/issues/2018863 https://www.drupal.org/project/imce/issues/1700438
CKEditor launch IMCE according to the method you have selected to download files in Admin \> Configuration \> Media \> File system, under the "Default download method". If you select private download then CKEditor always open IMCE in private folder and then you can't switch to public folder, despite of the new node will be public (blog post).
I think it's a very big problem. I should have the option to select if I want public or private directory in IMCE when It was launched by CKEditor.

# Answer
> 1 votes
Chances are you haven't set filebrowser permissions within the IMCE config page.

1. Go to Configuration \> Media \> IMCE
2. Setup/confirm the IMCE Profile for filebrowsing. NOTE: IMCE has its own "profiles" which can be used as roles specific to the filebrowser functionality. The default User-1 role has the ability to see all files/folders. If you need more granular access to subfolders/specific folders within the files directory, setup a new profile.
3. Check that your blogger/blog contributor role has a profile assigned in Public Files column (and if necessary, private files column).

---

In addition to checking the IMCE filebrowser permissions, you'll want to check the individual field settings. It can only be set to save/upload to either Drupal's public files directory or private files directory. It doesn't allow content managers to choose which directory to upload/save to at time of upload/per piece of content.

# Answer
> 0 votes
It would be helpful to provide information on which Drupal Version you are working with and what editor related modules are activated. In Drupal 8 the ckeditor module is activated as part of core. IMCE can be added (and used to browse files) as a contributed module. The comments provided by Drupal for the settings php file indicate that you need to set the private path outside Drupal site path (i.e., not in sites/default/files).

From settings ...

> * A local file system path where private files will be stored. This directory must be absolute, outside of the Drupal installation directory \> and not accessible over the web.

In Drupal 8 there is a separate configuration step for IMCE (admin/config/media/imce that lets you set folder paths for an admin profile and a member profile. Maybe you have something set in your member profile that's directing them the so-called private path?

I'd would recommend checking out the folder path settings in IMCE and maybe eliminating the private path settings in settings.php entirely. Also, see if an admin can create a blog post and put the image in the public directory. And clarify what Drupal version you are using.

---
Tags: 7, wysiwyg, files
---


# Question
Title: Core Updates after install with composer create-project drupal/drupal
So I installed Drupal with `composer create-project drupal/drupal <...>`

It works fine, but now I'm trying to update core from 8.4.1 to 8.4.4 What's the right way to do that? `composer update` only updates the modules, not core. How do I update core? I don't know that much about composer, but if I edit the composer.json and remove

```
"replace": {
    "drupal/core": "^8.4"
},

```

and add

```
"require": {
    "drupal/core": "^8.4",
    ...
 }

```

it seems to work. Is this the right way to do this? If so, why is this not in the default composer.json, that comes with the project?

# Answer
You do in fact want to remove the drupal/core declaration (as it exists) in the *replace* section of composer.json, and then add the entry as you noted to the *require* section. Then run `composer update drupal/core --with-dependencies`.

You can find Drupal's official process for a Core upgrade with composer here: https://www.drupal.org/docs/8/update/update-core-via-composer-option-4
> 1 votes

---
Tags: 8, updating
---


# Question
Title: Updating modules fails with XAMPP on Windows 10
I'm pretty sure I installed Drush 8 correctly on Windows 10. I ran the command window as administrator. I changed to my Drupal directory, but I get "Command pm-update needs a higher bootstrap level to run - you will need to invoke drush from a more functional Drupal environment to run this command. The drush command 'pm-update' could not be executed. Drush was not able to start (bootstrap) the Drupal database. Following are all the messages & commands I entered.

```
ColorConsole [Version 2.4.2000 ] Microsoft Windows [Version 10.0.14393] (c)        2016 Microsoft Corporation. All rights reserved.
C:\Users\samst\Downloads>cd C:\xampp\htdocs\D8
C:\xampp\htdocs\D8>drush status Drupal version : 8.2.4
Site URI : http://default
Database driver : mysql
Database hostname : localhost
Database port :
Database username : root
Database name : d8
PHP configuration : C:\xampp\php\php.ini
PHP OS : WINNT
Drush script : C:/Users/samst/AppData/Roaming/Composer/vendor/drush/drush/drush.php
Drush version : 8.1.5
Drush temp directory : C:\Users\samst\AppData\Local\Temp
Drush configuration :
Drush alias files :
Drupal root : C:\xampp\htdocs\D8
Drupal Settings File : sites/default/settings.php
Site path : sites/default
Sync config path : sites/default/files/config_zKz1ApBZ7jZluMMX-WwnTZyMM0eVUEH6DkWwb6HxM_V0Y0izLCsKyaGVKs7EDZiAE FFWlaSJ4g/sync
C:\xampp\htdocs\D8>drush drush pm-update The drush command 'drush pm-update' could not be found. Run drush cache-clear drush to clear the [error] commandfile cache if you have installed new extensions. Drush was not able to start (bootstrap) the Drupal database. [error] Hint: This may occur when Drush is trying to: * bootstrap a site that has not been installed or does not have a configured database. In this case you can select another site with a working database setup by specifying the URI to use with the --uri parameter on the command line. See drush topic docs-aliases for details. * connect the database through a socket. The socket file may be wrong or the php-cli may have no access to it in a jailed shell. See http://drupal.org/node/1428638 for details.
Drush was attempting to connect to: Drupal version : 8.2.4
Site URI : http://default
Database driver : mysql
Database hostname : localhost
Database port :
Database username : root
Database name : d8
PHP configuration : C:\xampp\php\php.ini
PHP OS : WINNT
Drush script : C:/Users/samst/AppData/Roaming/Composer/vendor/drush/drush/drush.php
Drush version : 8.1.5
Drush temp directory : C:\Users\samst\AppData\Local\Temp
Drush configuration :
Drush alias files :
Drupal root : C:\xampp\htdocs\D8
Drupal Settings File : sites/default/settings.php
Site path : sites/default
Sync config path : sites/default/files/config_zKz1ApBZ7jZluMMX-WwnTZyMM0eVUEH6DkWwb6HxM_V0Y0izLCsKy aGVKs7EDZiAEFFWlaSJ4g/sync
C:\xampp\htdocs\D8>drush cache-clear drush 'drush' cache was cleared. [success]
C:\xampp\htdocs\D8>drush pm-update Command pm-update needs a higher bootstrap level to run - you will need to invoke drush from a more [error] functional Drupal environment to run this command. The drush command 'pm-update' could not be executed. [error] Drush was not able to start (bootstrap) the Drupal database. [error] Hint: This may occur when Drush is trying to: * bootstrap a site that has not been installed or does not have a configured database. In this case you can select another site with a working database setup by specifying the URI to use with the --uri parameter on the command line. See drush topic docs-aliases for details. * connect the database through a socket. The socket file may be wrong or the php-cli may have no access to it in a jailed shell. See http://drupal.org/node/1428638 for details.
Drush was attempting to connect to: Drupal version : 8.2.4
Site URI : http://default
Database driver : mysql
Database hostname : localhost
Database port :
Database username : root
Database name : d8
PHP configuration : C:\xampp\php\php.ini
PHP OS : WINNT
Drush script : C:/Users/samst/AppData/Roaming/Composer/vendor/drush/drush/drush.php
Drush version : 8.1.5
Drush temp directory : C:\Users\samst\AppData\Local\Temp
Drush configuration :
Drush alias files :
Drupal root : C:\xampp\htdocs\D8
Drupal Settings File : sites/default/settings.php
Site path : sites/default
Sync config path : sites/default/files/config_zKz1ApBZ7jZluMMX-WwnTZyMM0eVUEH6DkWwb6HxM_V0Y0izLCsKy aGVKs7EDZiAEFFWlaSJ4g/sync
C:\xampp\htdocs\D8>

```

I am running D8 with XAMPP on Windows 10. I've spent a significant amount of time searching the web for a solution. I tried changing the 'host' line in settings.php. That did not help.

# Answer
> 0 votes
Check if `mysql` binary is on your path.

Just run `mysql` from the same terminal window. If it works, then it will be a problem with your db config in drupal.

If it doesn't work, add the location of mysql binary `C:\xampp\mysql\bin` for me, to the `PATH` variable. It will fix it.

---
Tags: drush
---


title: How do I fetch translated strings?

text:
# Question
Title: How do I fetch translated strings?
I have a progressively decoupled Reactjs application running on top of Drupal. Its a multilingual application.

I need to fetch the translated strings from the Drupal itself and handle the translations editor and everything in Drupal itself, rather than maintaining a separate translation system for react.

How is it possible? A simple `Drupal.t()` doesn't work. I checked.

Any examples I can refer?

# Answer
> 0 votes
`Drupal.t()` works in this case. Have to to compile the javascript and clear the Drupal cache in order for strings to appear.

For props way:

On `get_sample_props()`:

```
function getsampleprops() {
  return ['sampleval' => t('Hello World!!!')];
}

```

On the controller,

```
$build = [
  '#theme' => 'sample_react',
  '#props' => json_encode($this->get_sample_props()),
];

```

On the template, I did:

```
<div data-component="Sample" data-prop-labels='{{props|raw}}'></div>

```

On the React side, I used

```
$val = this.props.labels.sampleval;

```

Volia, its done. Its bit inconvenient, but work gets done.

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


title: How to create a "history" of activity?

text:
# Question
Title: How to create a "history" of activity?
I've a site with users that can create and edit contents, vote, flag, comment, etc. I would like to have a page with a history of every action, something like:

* on day X user has create the content "Title".
* on day X user2 has commented "Title 1".
* and so on.

Is there something like this? I've found Activity, but for D7 there is only a "dev" version, released con july 2012.

Another way could be to create, with Rules or a custom module, custom entries in Watchdog and than create a view with Views Watchdog.

Any ideas?

# Answer
There is Heartbeat pretty cool module with nice API. Also you can integrate with many other modules as well.

> Heartbeat displays user activity on a website. This module is an API to log activity. The logged data contains message structures, attributes and variables. Once the activity messages exist in the database, they will be parsed and build into activity streams.

**Other modules that work great with heartbeat activity**

1. Facebook-style Statuses
2. Flag
3. friend
4. Friendlist
5. User relationships
6. Display suite
> 1 votes

# Answer
The Message module aims to provide specifically this functionality. It requires some configuration, as it is, like many good modules, created to work as a platform to build on, rather than as a direct solution.
> 1 votes

# Answer
IMO the Message module would be a perfect fit to answer this question. Using this module, you can create your own custom "*Events logging*" (to register things that happened in a site).

Specific to this question here, I'd create one or more so called "Message types" that contain data about:

* the usernames (of the latest editors of content).
* the relevant date(s).
* any data about the actual entity (node, user, etc) or event you want to track, such as the node's id, its title, author, relevant field values, etc.

You could even track how those data looked like before and after they got updated.

About *Message types*: think of them as equivalent to Content types, whereas you create messages (instead of nodes) of a specific Message type (instead of Content type).

### Rules integration

A really interesting facility of the Message module is its perfect integration with the Rules module. Have a look at the answer to "How to implement a follow author (or user) function?" for way more details on that.

In your case, you'd simply create some (rather basic) custom rules which use:

* a Rules Event like "Before saving a new node", of "After updating an existing node" (or variations of these events). Or other events about any other entities you want to track.
* a Rules Action to "Create a message" (of a selected Message type).

That's really it ... and things like "*... delete a piece of content, or change another user's roles, block them, etc ...*" are all minor variations of this (and a piece of cake to create an appropriate/similar rule).

### Example included in Commerce Kickstart

A great sample of this can be found in Commerce Kickstart, which uses the Commerce Message module, to create such "*Events logging*". In that case in the format of an Order History, as shown in this screenprint (from this module's project page).

### Replicate/replace the Activity module

Should you want to do so, it seems perfectly possible to build a view (report) that contains the data similar to what you can do with the Activity module as shown in this screenprint (from this module's project page).

### More info about the Message module

The Message module is an amazing module, it is fully entity based, which implies that it perfectly (out of the box) integrates with modules such as Views and Rules.

Though there is ***not a lot of documentation about it*** (which is what makes it a hidden D7 gem ...). A possible way to get started with it, and to get an idea of the kind of things it can be used for, is to have a look at the answers to:

**Tutorials:**
> 0 votes

---
Tags: 7, users, log-messages
---


# Question
Title: Migrate multiple migrations into same node
I need to do a migration from multiple endpoints into the same node. All endpoints provide the full list of rows/nodes, but their data need to be mapped into different fields of the same node and into different translations (so not similar to this question, where one endpoint is the complete list and the second is the single row data).

Here is what I've got so far:

First migration, create the nodes in default language

```
id: kognitiv_rooms_base
label: Rooms Step 1 (room data in german and available rates)
migration_group: kognitiv
migration_tags:
  - rooms
  - masterdata
status: true

source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: json
  urls: https://www.example.com/rooms_endpoint_one.json?lang=de
  item_selector: /result/rooms
  track_changes: true
  fields:
    -
      name: code
      label: 'Kognitiv room code'
      selector: code
    -
      name: title
      label: 'Room name'
      selector: title
    -
      name: description
      label: 'Room description'
      selector: description
    -
      name: min_occupancy
      label: 'Minimum room occupancy'
      selector: min_occupancy
    -
      name: std_occupancy
      label: 'Standard room occupancy'
      selector: std_occupancy
    -
      name: max_occupancy
      label: 'Maximum room occupancy'
      selector: max_occupancy
  ids:
    code:
      type: string

destination:
  plugin: entity:node

process:
  type:
    plugin: default_value
    default_value: room
  title: title
  langcode:
     plugin: default_value
     default_value: de
  uid:
    plugin: default_value
    default_value: 1
  sticky:
    plugin: default_value
    default_value: 0
  promote:
    plugin: default_value
    default_value: 0
  short_description: description
  long_description: description
  room_min_occupancy: min_occupancy
  room_std_occupancy: std_occupancy
  room_max_occupancy: max_occupancy
  remote_datasource:
    plugin: default_value
    default_value: kognitiv
  remote_id: code

dependencies:
  enforced:
    module:
      - kognitiv_importer

```

Second migration, fill additional fields in existing nodes

```
id: kognitiv_rooms_ammenities
label: Rooms Step 2 (ammenities and room size)
migration_group: kognitiv
migration_tags:
  - rooms
  - masterdata
status: true

source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: json
  urls: https://www.example.com/rooms_endpoint_two.json
  item_selector: /facility/rooms
  track_changes: true
  fields:
    -
      name: code
      label: 'Kognitiv room code'
      selector: code
    -
      name: size
      label: 'Room size'
      selector: /types/0/size
  ids:
    code:
      type: string

destination:
  plugin: entity:node

process:
  type:
    plugin: default_value
    default_value: room
  nid:
    plugin: migration_lookup
    migration: kognitiv_rooms_base
    source: code
  uid:
    plugin: default_value
    default_value: 1
  roomsize: size

migration_dependencies:
  required:
    - kognitiv_rooms_base

dependencies:
  enforced:
    module:
      - kognitiv_importer

```

Third migration, translate the nodes

```
id: kognitiv_rooms_en
label: Rooms Step 3 (english translation)
migration_group: kognitiv
migration_tags:
  - rooms
  - masterdata
  - english
status: true

source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: json
  urls: https://www.example.com/rooms_endpoint_one.json?lang=en
  item_selector: /result/rooms
  track_changes: true
  fields:
    -
      name: code
      label: 'Kognitiv room code'
      selector: code
    -
      name: title
      label: 'Room name'
      selector: title
    -
      name: description
      label: 'Room description'
      selector: description
  ids:
    code:
      type: string

destination:
  plugin: entity:node
  translations: true

process:
  type:
    plugin: default_value
    default_value: room
  langcode:
     plugin: default_value
     default_value: en
  content_translation_source:
    plugin: default_value
    default_value: de
  nid:
    plugin: migration_lookup
    source: code
    migration: kognitiv_rooms_base
  title: title
  uid:
    plugin: default_value
    default_value: 1
  short_description: description
  long_description: description

migration_dependencies:
  required:
    - kognitiv_rooms_base
    - kognitiv_rooms_ammenities

dependencies:
  enforced:
    module:
      - kognitiv_importer

```

I've got the idea with setting `nid` with `migrate_lookup` from those examples, using it for translations.

My problem is that only the first migration works. Both the 2nd and 3rd migration fail because of a `"Integrity constraint violation: 1062 Duplicate entry '100000130' for key 'PRIMARY': INSERT INTO {node} (nid, vid, type, uuid, langcode)..."`. The `nid` value is correct, but I guess it should be an `update` instead of an `insert`.

How can I force Migrate to update an existing node? The 2nd query should update the node in the same language, the 3rd query should add/update the english translation of the node.

I'm on Drupal 8.4, using Migrate Plus 4.0

# Answer
The code above works, including updating existing nodes in the same language and adding/updating translations. After installing the module on a fresh site, everything worked. Obviously during the numerous iterations of developing, uninstalling and reinstalling, some invisible old data/cache/whatever was left in a rollback run and caused the error.
> 2 votes

---
Tags: 8, migrations
---


title: Remove translation from the title field

text:
# Question
Title: Remove translation from the title field
Is there a way to **disable** translations from Title field in each content type.

In the /admin/config/regional/content-language, when I remove translations from Title fields it gives `Fatal error: Maximum execution time of 120 seconds exceeded`. No matter what time I give in the ini file this always happens. Is there a way to correct this? Or is there a way to remove Title fields translation without going to content-language

# Answer
> 6 votes
Yes, there is another way to do this in configuration. You can change

```
  translatable: true

```

in `core.base_field_override.node.[content-type].title.yml`.

If you don't find this configuration file, then there are no changes made so far for the title field. You can do this for example by modifying "Title field label" in the content type, which is also stored in this configuration and if it doesn't exist it will be created, so that you'll find the yaml in the exported config.

After you've changed the field label, export the configuration, open for each content type the mentioned yaml file, change translatable to false and reimport the configuration again.

See https://www.drupal.org/docs/8/configuration-management/workflow-using-the-drupal-ui or if you have installed drush use these two commands:

```
drush config-export
drush config-import

```

see https://www.drupal.org/docs/8/configuration-management/workflow-using-drush.

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


# Question
Title: Add a custom submission handler to a form
How can I add a custom form submission handler?

I tried adding `$form['#submit'][] = 'mymodule_form_submit';` or `$form['actions']['submit']['#submit'][] = 'mymodule_form_submit';` to `hook_form_alter()`.

```
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\Request;

function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_trends_form' || $form_id == 'node_trends_edit_form') {
    foreach (array_keys($form['actions']) as $action) {
      if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
        $form['actions']['submit']['#submit'][] = 'mymodule_form_submit';
      }
    }
  }
}

```

```
function mymodule_form_submit(array $form, FormStateInterface $form_state){
    //die("why won't this execute? :(");
    drupal_set_message("Why won't this message show?");
}

```

It seems `drupal_set_message()` is not called. I also tried rebuilding the cache, but the function is still not called.

I am using Drupal 8.2.3.

# Answer
If you use `hook_form_node_form_alter()` maybe use example code:

```
function MYMODULE_form_node_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  foreach (array_keys($form['actions']) as $action) {
    if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
      $form['actions'][$action]['#submit'][] = 'mymodule_form_submit';
    }
  }
}

```

and for the submit function use:

```
function MYMODULE_form_submit(array $form, \Drupal\Core\Form\FormStateInterface $form_state){
  //die("I'm not getting run, why :(");
  \Drupal::service('messenger')->addMessage("Why won't this message show?");
}

```
> 37 votes

# Answer
**Creating a custom webform handler plugin for drupal 8.**

*This document assumes you've already installed and enabled webform and webform-ui*

1) Create your webform. \- Go to structure -\> webforms and press the "+ Add webform" button. \- You can either use the ui or use yaml, that's up to you. example yaml for a one field form that takes an email address:

```
email:
  '#type': email
  '#title': email
  '#title_display': invisible
  '#placeholder': 'ENTER YOUR EMAIL'
  '#attributes':
    class:
      - my-ip

```

The indentation is important for yaml so make sure you get it right. indents are spaces.

Now save your form.

2) Creating a webform handler plugin

Next we can create a new plugin which will show up in the "Emails/Handlers" section when editing the webform. I will call it myhandler, you can call it what you want, provided you replace all mentions of myhandler with the name you pick.

a) Create a new folder for your plugin, do this in your drupal root (referred to here as /var/www/html/) in the following subfolder: /var/www/html/modules/Custom/myhandler

b) Create a new file in the above directory called myhandler.info.yml in this file goes the following:

```
name: My Form Handler
description: handles form submits, does something with them.
package: Custom
type: module
version: 1.0
core: 8.x

```

3) Create a src directory in your module directory, eg: /var/www/html/modules/Custom/myhandler/src in src create Plugin in Plugin create WebformHandler

(this can be achived in one go using

```
mkdir -p /var/www/html/modules/Custom/myhandler/src/Plugin/WebformHandler/

```

which will make the entire structure in one go using the -p flag to mkdir.)

4) Create a new file `/var/www/html/modules/Custom/myhandler/src/Plugin/WebformHandler/MyFormHandler.php`

in that file goes the following php code, i've left the config form setup in so you can see how to configure your plugin if needed.

```
<?php
namespace Drupal\myhandler\Plugin\WebformHandler;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\webformSubmissionInterface;

/**
 * Form submission handler.
 *
 * @WebformHandler(
 *   id = "myhandler_form_handler",
 *   label = @Translation("MyHandler form handler"),
 *   category = @Translation("Form Handler"),
 *   description = @Translation("Do something extra with form submissions"),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_SINGLE,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 * )
 */
class MyFormHandler extends WebformHandlerBase {

     /**
       * {@inheritdoc}
       */

     public function defaultConfiguration() {
        return [
            'submission_url' => 'https://api.example.org/SOME/ENDPOINT',
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
        $form['submission_url'] = [
            '#type' => 'textfield',
            '#title' => $this->t('Submission URL to api.example.org'),
            '#description' => $this->t('The URL to post the submission data to.'),
            '#default_value' => $this->configuration['submission_url'],
            '#required' => TRUE,
        ];
        return $form;
    }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    // Your code here.
        // Get an array of the values from the submission.

        $values = $webform_submission->getData();

        // Get the URL to post the data to.
        $post_url = $this->configuration['submission_url'];

        $message = "MyHandler got form data:".print_r($values,1);
        \Drupal::logger('myformhandler')->error($message);

        return true;
 }
}
?>

```

5) Enable your MyHandler module (using drush or extend menu) and then rebuild your drupal cache ( "drush cr" from anywhere under your drupal root (/var/www/html here) would do that if you use drush )

6) edit your webform, go to "Email / Handlers" and click on "+ Add Handler" button You should see your plugin listed, click Add Handler, you should now see a box asking for the submission url. click Save button. If something doesn't look right, or it isn't working, check the apache error log, you might find something helpful there.

7) Test your form - make a submission to the form, and then check the watchdog log (drush ws), you should see the values sent to it. They might be truncated in the output you see, don't panic, it's all there. What you do with this now is up to you.

Hope this helps someone. I cobbled it together from stuff I found around the place and wrote it into a single document. Thanks to the others who got me here.
> 24 votes

# Answer
if using hook\_form\_BASE\_FORM\_ID\_alter in Drupal 8 core 8.4.3, I found the ways of adding the custom submit handler didn't work. This worked for adding the submit handler function name:

```
$form['#submit'][] = 'mymodule_submit_handler';

```

In another situation, using hook\_form\_FORM\_ID\_alter in Drupal 8.4.5, I found the above did not work for adding the custom submit handler. Instead, this worked:

```
$form['actions']['submit']['#submit'][]  = 'mymodule_submit_handler';

```
> 15 votes

---
Tags: forms, 8
---


# Question
Title: How to use Ubercart product SKU as a condition in Rules?
I need to display a message on the cart page if one or more specific SKUs are added to the cart.

For example, if a product with SKU # ABC123 is added to the cart, the Rule should be triggered and thus display a message... if a product with SKU # XYZ789 is added to the cart, the Rule would not be triggered and no message would be displayed.

It seems like this should be a fairly simple function, but for the life of me I cannot find a way to accomplish this. Can anyone please point me in the right direction?

Thanks!

# Answer
This answer does not use Rules, but rather hard-coding inside of the cart template.

As the message should be displayed each time the user is on the /cart page, something like this might work. If page--cart.tpl.php doesn't exist, create it and add ...

```
$items = uc_cart_get_contents();
foreach($items as $item) {
    if($item->model == 'ABC123') {
        drupal_set_message('Item ABC123 is in the cart');
    }
}

```
> 0 votes

---
Tags: 7, rules, ubercart
---


title: The path alias doesn't work on https

text:
# Question
Title: The path alias doesn't work on https
When I visit http://www.example.com/node/439432 on my site, it correctly redirects me to https://www.example.com/myalias.html.
However, When I try to visit https://www.example.com/node/439432, I am not redirected to https://www.example.com/myalias.html.

When I check the network, I get a 200 status for the node page.

>

# Answer
Use the Global Redirect module to achieve this: https://www.drupal.org/project/globalredirect
> 0 votes

---
Tags: 7, redirection, path-aliases
---


# Question
Title: How to add version parameter to JS & CSS files to avoid browser cache?
What is the best way to append the file version number in order to give to the users the right JS/CSS files?

Actually i am working on a website which has a browser cache expiration date set to 5 days.

# Answer
The easiest way to achieve this is to add the 'css\_js\_query\_string' variable to the end of your css/js path. This will have to be hard-coded or via a preprocess function in template.php.

Example:

```
<script src="/path/to/js/file/file.js?ver=<?php print variable_get('css_js_query_string', ''); ?>"></script>

```
> 2 votes

---
Tags: 7, javascript, caching
---


# Question
Title: Where do I specify the URL of the incoming XML?
In D8 I installed the feeds module.

I added a feed type named Coindesk

Before I can do the mapping I should add a url to this feedtype. I cannot find where I should do this. I looked in all the settings...

Where should I add the url van de XMl feed?

# Answer
> 1 votes
You make the linkage to the XML input in feeds instance definition.

The D8 Feeds module follows the entity module with definitions and instances.

There are the feed type definition which defines the processors and mappings. These are created in the configurations feeds admin screen.

And there are the feeds instances. These are where you define the input and it's basic settings for a feed type. They are created under content / feeds.

This is an improvement over the prior versions as it lets you use the same feeds mappings over different inputs.

---
Tags: 8, feeds
---


# Question
Title: How to add a prefix - suffix to a view title
I am using Drupal 8. I want to add Prefix and suffix to view title. I tired with following code but in result html is not rendering.

```
function Hook_preprocess_page_title(&$variables) {
$variables['title_prefix'] ='<div class="row heading-section"><div class="col-md-9 el-col-md-middle">
        <div class="row">';
$variables['title_suffix'] ='</div></div></div>';

}

```

Result

```
<div class="row heading-section"><div class="col-md-9 el-col-md-middle"> <div class="row">My Title</div></div></div>

```

# Answer
The variables `title_prefix` and `title_suffix` will be rendered using Twig, and therefore filtered from markup and potentially harmful code.

If you like to use HTML within Twig variables, you need to use an instance of the Markup class:

```
use Drupal\Core\Render\Markup;

/**
 * Implements hook_preprocess_HOOK() for page_title.
 */
function mytheme_preprocess_page_title(array &$variables) {
  $variables['title_prefix']['#markup'] = Markup::create('<div class="row heading-section"><div class="col-md-9 el-col-md-middle"><div class="row">');
  $variables['title_suffix']['#markup'] = Markup::create('</div></div></div>');
}

```

PS.: The above hook would add the markup to all titles. If this really is your intention, consider altering the `page-title.html.twig` template instead.
> 4 votes

---
Tags: theming
---


# Question
Title: Alternative to the need for dozens of roles to access special materials
My organization wants to create access to specific resources and materials based on a role, but the issue is that there is the potential for dozens of such roles, each granting access to specific materials.

Is there a better way to manage this without having to have dozens of roles and permissions in the system, such as to use taxonomy or something else that is set up to accommodate such a volume?

**Scenario:**

A user can access our site and pay for and subscribe for special access to sections A, B, and C, each separately. Then we would need a way to track who has paid for access to which sections. I believe the section would include text, downloads, and possibly a forum and training videos.

**Note**: CiviCRM takes and tracks payments and memberships.

# Answer
Have a look at the Group module (commonly perceived as an alternative for Organic Groups).

Group allows for creating arbitrary collections of your content and users on your site, and grant access control permissions on those collections. It is available as of D7, and has a D8 version also. The Group module creates groups as entities, making them fully fieldable, extensible and exportable. Which also makes it integrate very well (out of the box) with commonly used modules such as Rules, Views, etc.

Some more questions you may want to look at for more details:

# Sample configuration

Below is an example of a possible configuration, which may help to get you started with possible configurations (using the Group module):

```
Group type ID ! Group type ! Group role ID ! Role
--------------+------------+---------------+------------
 1            ! Class      ! 3             ! Instructor
 1            ! Class      ! 4             ! Student
 2            ! Customers  ! 5             ! Lead
 2            ! Customers  ! 6             ! Prospect
 2            ! Customers  ! 7             ! Licensed Customer
 2            ! Customers  ! 8             ! Sales
 2            ! Customers  ! 9             ! Support
 2            ! Customers  ! 10            ! Accounting
 2            ! Customers  ! 11            ! R&D
 3            ! Project    ! 12            ! Project Manager
 3            ! Project    ! 13            ! Developer
 3            ! Project    ! 14            ! Customer

```

### Group Types

The above example consists of 3 ***group types***:

* Class.
* Customers.
* Project.

### Group Roles

For each of the 3 group types, there are specific ***Roles*** defined, some more details about some of them:

* for the *Class* group, these are the 2 roles that are configured:
    + Instructor.
    + Student.
* for the *Project* group, these are the 3 roles that are configured:
    + Project Manager.
    + Developer.
    + Customer.

These are the *Group Specific Roles*: these roles can be configured per group type and will only be available on groups of that group type. As an example, for group type "*Class*", the defined roles are **Instructor** and **Student** (which are not available for the other group types.

On top of the group specific roles, there are also *Special Global Roles*: These are the special (hardcoded) roles named **Outsider** (= a signed in user that did not join a group) and **Member** (= a signed in user that did join a group). These cannot be defined by the Drupal administrator, and they are always available for any group. These roles can have different permissions sets for each group type. Special case: the role **Anonymous** is related to a user that is not signed.

### Groups

Each of the configured group types can have any number of ***Groups***.

Examples of groups:

* for the *Class* group type, there could be these **Groups**:
    + Getting started with Drupal.
    + Drupal for site builders.
    + Become an expert in using the Rules module.
* for the *Customers* group type, there could be these **Groups**:
    + Service Requests.
    + Order Processing.
    + Sales Orders.
    + Relationship Management.

### Permissions

For each of the configured group types, you can then also configure for each ***Content Type*** which ***Role*** has what kind of access (= none, view, create, edit, delete). Be aware: even though this looks similar to Drupal's permission configuration, these permissions are not the same permissions (they are specific to the Group module).

# Rules integration

Since you seem to be using CiviCRM also, you should definitely also consider using the CiviCRM Entity module, especially because of its integration with the Rules module ... combined with automagically creating (or deleting) so called "Group memberships" (which you can do via Rules). For an example of how to use Rules to create or remove such group memberships, refer to my answer to "How to add and delete a user to another group using the Group module?".

# Resources

# Note

About your concern (as in your additional comment), which includes:

> ... having a list of permissions associated with each role multiplied so many times, editing and saving them taking extra processing power and stability issues. As well as the amount of work to the system each time the organization wants to add content. It just seems messy.

You're right, using standard Drupal permissions (with a zillion of roles) it would indeed become *messy*. But after you realize/discover how the Group module's roles/permissions work, your concern should be addressed ...
> 1 votes

# Answer
The Monster Menus Module was developed especially for educational organizations, but can be used outside of that context as well. It allows you to have many different groups with different permissions that are controlled by the module instead of Drupal itself.
> 0 votes

---
Tags: 7, users
---


title: Can't get a Redirect Hook to Fire

text:
# Question
Title: Can't get a Redirect Hook to Fire
I'm attempting to use `hook_redirect_alter()` as described in `redirect.api.php`.

I created `my_module.module` and entered the hook as: `function my_module_redirect_alter($redirect)` To test I just entered a `drupal_set_message` and attempted to write a notice to the log but I can't seem to get it to actually fire.

```
function my_module_redirect_alter($redirect) {
  $message = "redirect_alter worked!";
    \Drupal::logger('my_module')->notice($message);
}

```

What am I doing wrong here? Am I misunderstanding this hook?

# Answer
> 1 votes
Good afternoon.

1) install the devel module.

2) Install the modules, devel, kint.

3) change your code for the following:

```
function my_module_redirect_alter($redirect) {
   dpm($message = "redirect_alter worked!");
   kint($redirect);
}

```

4) try to perform a process such as updating a node and when redirecting, you must show the messages.

**Note: dpm() and kint() are functions of the devel module to inspect a variable**

---
Tags: 8, redirection
---


title: Where to put reusable code?

text:
# Question
Title: Where to put reusable code?
I have used Drupal 7 for a while, but am only starting to learn to use the tpl and template.php files. As you would expect, I have become good friends with the documentation, but am still having trouble putting all the pieces together at times.

One thing that I have not figured out how to do, but seems pretty basic, is to create a function in template.php or a custom tpl file (not sure what I need as well as how to do it) that outputs HTML. Let me explain what I mean...

I have created a custom node--content-type.tpl.php. In there, I have put the following code in to replace the normal submitted by information:

```
<?php if ($display_submitted): ?>
  <div class="submitted">
    <div class="created">
      <span>Created by <?php print $node->name; ?> on <?php print format_date($node->created, $type = 'medium'); ?>.</span>
    </div>
    <div class="revised">
      <span>Last revised by <?php print (user_load($node->revision_uid)->name); ?> on <?php print format_date($node->changed, $type = 'medium'); ?>.</span>
    </div>
  </div>
<?php endif; ?>

```

I am trying to figure out how to reuse this code in some of my other custom node tpl files without simply cutting and pasting it in. I am obviously missing something basic. How can I go about doing this?

# Answer
> 4 votes
Re-usable template code should ideally be in its own template, backed by its own theme function:

```
function THEME_theme() {
  return [
    'foo_partial' => [
      'variables' => ['node' => NULL],
    ],
  ];
}

```

foo-partial.tpl.php:

```
<div class="submitted">
    <div class="created">
      <span>Created by <?php print $node->name; ?> on <?php print format_date($node->created, $type = 'medium'); ?>.</span>
    </div>
    <div class="revised">
      <span>Last revised by <?php print (user_load($node->revision_uid)->name); ?> on <?php print format_date($node->changed, $type = 'medium'); ?>.</span>
    </div>
  </div>

```

There are a number of different permutations you could use to actually get that HTML into the node template, here's one of them:

```
function THEME_preprocess_node(&$vars) {
  if ($vars['node']->type == 'page' && $vars['display_submitted']) {
    $vars['submitted_html'] = [
      '#theme' => 'foo_partial',
      '#node' => $vars['node'],
    ];
  }
}

```

node.tpl.php

```
...
<?php
if ($display_submitted && $submitted_html):
  echo render($submitted_html);
endif;
?>
...

```

# Answer
> 0 votes
If you want it to be standard across all your nodes, you can create a simple node.tpl.php file that will apply to all node pages.

EDIT: For it to apply to some subset of nodes, check out Can I use one node template file for multiple content types? on d.o.

---
Tags: theming
---