# Question
Title: Enabling a new content type in the add new content
i have created a new content type but when i go to add content, it does not appear but only appears under content types. I have even tried to clear the caches but all in vein, what could be the cause? i will glad for your help

# Answer
> 0 votes
Go to structure \>\> Menus \>\> Navigation (admin/structure/menu/manage/navigation) and make sure to enable the content type link in that list.

Here I'm showing example for Article Content type.

# Answer
> 0 votes
Just came across this problem, that is a new content type is not showing under `Add content` (or `node/add`) even though it was showing under `Content types` (`admin/structure/types`)

Check your modules and their permissions. I found that `view_unpublished` module has a `View any unpublished content` permission that prevents that content type displaying completely.

---
Tags: nodes
---


# Question
Title: How do I remove a module JavaScript file through a theme?
I need to remove a JavaScript file added from a module through a theme. How can I achieve this?

# Answer
> 6 votes
Implement hook\_library\_info\_alter:

*mytheme.theme:*

```
/**
 * Implements hook_library_info_alter().
 */
function mytheme_library_info_alter(&$libraries, $extension) {
  if ($extension === 'some_module') {
    unset($libraries['some_module.library']['js']['js/foo.js']);
  }
}

```

---
Tags: 8, theming
---


title: Changing homepage

text:
# Question
Title: Changing homepage
I have to change dynamically the homepage according to the server HTTP\_HOST. I've tried to update `$_GET['q']` inside the settings.php. It works but, the internal drupal function `drupal_is_frontpage()` compares with the `drupal_get_variable('site_frontpage')`. A suggestion ? Thanks.

# Answer
> 2 votes
Try either the domain access or subdomain module.

**Update:**

As a poor-man's solution, in settings.php, you could try the following:

```
if ($server['HTTP_HOST'] == 'foo.com'){
  $conf['site_frontpage'] = 'node/XXX';
} elseif ($server['HTTP_HOST'] == 'bar.com') {
  $conf['site_frontpage'] = 'node/YYY';
}

```

Thanks @Chance G for a good idea.

# Answer
> 0 votes
In your settings file or theme preprocess file you could add something like the following using the variable\_set function:

```
if ($server['HTTP_HOST'] == 'foo.com'){
  variable_set('site_frontpage', 'node/XXX');
} elseif ($server['HTTP_HOST'] == 'bar.com') {
  variable_set('site_frontpage', 'node/YYY');
}

```

# Answer
> 0 votes
`variable_set()` is a really really bad idea because it touches the Database everytime. Bad for performance, logically, etc... Simply don't do that ;)

But I extended the solution from @greg\_1\_anderson a bit by also ensuring the front page is not being delievery from cache, see my blog post: https://julian.pustkuchen.com/node/794

I think that's a good solution for Drupal 7. For Drupal 8 I didn't yet find a simple solution, perhaps someone has an idea.

---
Tags: 7
---


# Question
Title: Migrated Servers now 500 Error _db_error_page('Access denied f...')
Moved servers, copied all files and database and set server settings to match old server. Updated settings.php with new database credentials and tripled checked them for the correct information. Console gives me a truncated error message so I don't know the exact problem.

```
[21-Feb-2019 15:02:21 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function ereg() in /public_html/includes/file.inc:1034
Stack trace:
#0 /public_html/includes/file.inc(1032): file_scan_directory('themes/pushbutt...', '\\.info$', Array, 0, true, 'name', 1, 1)
#1 /public_html/includes/common.inc(2888): file_scan_directory('themes', '\\.info$', Array, 0, true, 'name', 1)
#2 /public_html/modules/system/system.module(868): drupal_system_listing('\\.info$', 'themes')
#3 /public_html/includes/theme.inc(493): _system_theme_data()
#4 /public_html/includes/theme.maintenance.inc(51): list_themes()
#5 /public_html/includes/bootstrap.inc(1221): _drupal_maintenance_theme()
#6 /public_html/includes/database.inc(176): drupal_maintenance_theme()
#7 /public_html/includes/database.mysqli.inc(78): _db_error_page('Access denied f...')
#8 /public_html/includes/database.inc(15 in /public_html/includes/file.inc on line 1034

```

# Answer
> 1 votes
> and set server settings to match old server

That process went wrong - `ereg()` was removed in PHP 7.0, and Drupal 6 couldn't have been running on a version of PHP that high on your old server.

I think PHP 5.3 is about as high as you're likely to be able to get with Drupal 6, you should get your server admin to downgrade to that version ASAP.

---
Tags: migrations
---


# Question
Title: Dynamically remove library based on user role, cache context not working
I want to remove all libraries of modules & themes, except those from modules/themes that are defined by me. This should only be done for anonymous users. All libraries should be served to authenticated users.

I'm adding the **user.roles** cache context in the html preprocess hook and remove all library definitions that are not desired:

```
/**
 * Implements hook_preprocess_html().
 */
function mytheme_preprocess_html(array &$variables) {
  $variables['page']['#cache']['contexts'][] = 'user.roles';
}

/**
 * Implements hook_library_info_alter().
 */
function mytheme_library_info_alter(array &$libraries, $module) {
  /* Remove all libraries that are not needed.
  Only remove them for anonymous users, since a lot of libraries are required for the admin interface to work. */
  $allowed_modules_with_libraries = [
    'mytheme',
    'google_tag',
    'my_custom_module',
  ];

  if (!in_array($module, $allowed_modules_with_libraries) && !Drupal::currentUser()->isAuthenticated()) {
    $libraries = [];
  }
}

```

My problem is, that the attached libraries are not completely separated by user role cache context:

**My test workflow:**

* Clear all caches
* Requesting page as authenticated user
* Contrib assets in browser sources panel:

**This is as expected.**

* Requesting same page as anonymous user
* Contrib assets in browser sources panel:

**This is not as expected, nothing should be present here.**

**The other way around:**

* Clear all caches
    + Requesting page as anonymous user
    + No contrib assets are displayed browser sources panel.

**This is as expected.**

* Requesting same page as authenticated user
* Assets in browser sources panel:

**This is not as expected, paragraphs and webform assets are missing.**

The x-drupal-cache-contexts HTTP response header content: `languages:language_content languages:language_interface languages:language_url route session theme timezone url.path url.query_args user`

The `user` cache context is there, shouldn't the response be cached by user (including the role) then?

I tried doing this by using hook\_page\_attachments\_alter, but not all libraries that are attached to the response are listed there. I'm not sure if changing the library definitions with hook\_library\_info\_alter is the right approach. Since I don't want to change the libraries. I just want to detach them from the response.

The `page_cache` and `dynamic_page_cache` modules are enabled.

# Answer
I created a decorator for the LibraryDiscoveryCollector. I think this is not ideal, since it does not remove the attachments, and basically says "these libraries don't exist", if I understand it correctly. But it works. Didn't find a way to remove attached libraries for everything inside preprocessing.

**LibraryDiscoveryCollector decorator:**

```
namespace Drupal\mymodule_assets\Asset;

use Drupal\Core\Asset\LibraryDiscoveryCollector;

/**
 * Decorates the LibraryDiscoveryCollector service.
 *
 * @package Drupal\mymodule_assets\Asset
 */
class MyLibraryDiscoveryCollector extends LibraryDiscoveryCollector {

  /**
   * Adds the user authenticated part to the cache id.
   *
   * @return string
   *   Cache id.
   */
  protected function getCid() {
    if (!isset($this->cid)) {
      $originalCacheId = 'library_info:' . $this->themeManager->getActiveTheme()->getName();

      if (\Drupal::currentUser()->isAuthenticated()) {
        $authenticatedCidString = 'authenticated';
      }
      else {
        $authenticatedCidString = 'anonymous';
      }

      $cacheIdPartsToAdd = [
        $authenticatedCidString,
      ];

      if (!empty($cacheIdPartsToAdd)) {
        $cacheId = $originalCacheId . ':' . implode(':', $cacheIdPartsToAdd);
      }
      else {
        $cacheId = $originalCacheId;
      }

      $this->cid = $cacheId;
    }

    return $this->cid;
  }

}

```

**Services YML:**

```
services:
  mymodule_assets.library.discovery.collector:
    class: Drupal\mymodule_assets\Asset\MyLibraryDiscoveryCollector
    decorates: library.discovery.collector
    decoration_priority: 0 # Execute last
    arguments: ['@cache.discovery', '@lock', '@library.discovery.parser', '@theme.manager']
    tags:
    - { name: needs_destruction }

```

This allows me to cache the library definitions by the user role.

**Removal of libraries:**

```
/**
 * Implements hook_library_info_alter().
 */
function mymodule_library_info_alter(array &$libraries, $module) {
  /* Remove all libraries that are not from this theme.
  Only remove them for anonymous users, since a lot of libraries are required for the admin interface to work. */
  $allowed_modules = [
    'mymodule',
    'google_tag',
  ];

  if (!in_array($module, $allowed_modules) && !Drupal::currentUser()->isAuthenticated()) {
    $libraries = [];
  }
}

```

Help is appreciated if somebody finds a better solution.
> 2 votes

# Answer
`hook_library_info_alter()` is not the right approach. You get the role of the user who installs a module or clears the cache, not of the user who requests the page. Info alter hooks in general are about changing information provided by other extensions and usually are only recalculated if an extension is added or removed and for a better dev experience on a cache clear.

And indeed, `hook_page_attachments_alter()` lists only libraries added by other hook\_page\_attachments(\_alter) hooks. See invokePageAttachmentHooks(), which starts with an empty attachments array:

```
  public function invokePageAttachmentHooks(array &$page) {
    // Modules can add attachments.
    $attachments = [];
    ...

```

So we can rule out both hooks you've mentioned. Attached libraries are collected from many different places (YAML, render arrays, hooks) and they are merged (bubbled up) through the entire page building and rendering process. So it might be a good idea to attach the override in form of a custom library the same way and let Drupal calculate the assets when rendering the page. See https://www.drupal.org/node/2216195#override-extend
> 1 votes

---
Tags: 8, caching, theming
---


# Question
Title: How do I get a field value in a template?
I want to change the default HTML for a custom field called *field\_product\_image* and I created the field--field\_product\_image.html.twig template. Now I need to fill in the following information in the HTML, but for some reason I cannot get the content of the fields.

```
<img src="{{ TWIG }}" alt="{{ TWIG }}" />

```

I tried different suggestions like `{{ content }}`, `{{ field.field_product_image }}`, `{{ field.field_product_image.value }}`, `{{ content.field_product_image }}`, `{{ content.uri.value }}` but they don't output the image link.

# Answer
A simpler way to do this is to use `mytheme_preprocess_image()`.

Here is an example:

```
/**
 * Implements hook_preprocess_image().
 */
function MYTHEME_preprocess_image(&$variables) {
  if ($variables['style_name'] == 'content_embed') {
    $variables['attributes']['class'][] = 'custom_class';
  }

  $variables['attributes']['data-custom-attr'] = 'value';
}

```

Variables can be used to construct new values that get injected before rendered. The above would add `custom_class` to a rendered images class attribute if a specific image style is being used in this instance, and all images would receive the second attribute. Rendering the image will already give you the src and alt attributes for you, so which attributes are you really trying to add?

Reaching into render arrays in the template just leads to a ton of cruft and hard to maintain code because it's really not the place for that.

If you don't want any divs or wrapping HTML in your field, you can just add this to the field twig template:

```
{% for item in items %}
  {{ item.content }}
{% endfor %}

```

This would only render the field item (in this case image), which should leave you with only the image tag on the page and no containers.
> 0 votes

---
Tags: theming
---


# Question
Title: Show 404 on page for node path url instead of redirecting to it's alias
I'm currently using the Redirect module in Drupal 8 along with Pathauto to create aliases on all url's. So for example /node/23 would be /article/some-text-here. When a user types in /node/23 in the url it automatically redirects them to the alias url. I want to show a 404 whenever the user uses the node path url instead of redirecting that way they don't ever have a chance to find something they shouldn't by traversing through my site with that pattern.

# Answer
> 1 votes
The rabbit\_hole module can be used to set 'access' controls for rendered nodes, taxonomies, and other entities. When a user visits the /node/\* or /taxonomy/term/\* page, you can control what happens--403 page, 404 page, redirect, whatever. This can also be overridden on a per-node basis if you require that.

https://www.drupal.org/project/rabbit\_hole

This still allows the entities to be accessible via path alias and shouldn't break any references to those nodes/taxonomies.

# Answer
> 0 votes
Make sure apache `mod_alias` is enabled and create a rule in `.htaccess` like:

```
Redirect 404 /node/.*$

```

# Answer
> 0 votes
I would also try this, although this would apply for Drupal 7

```
$path = current_path();
if($path == 'node/23') {
   drupal_not_found();
}

```

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


title: Builder for Drupal 8

text:
# Question
Title: Builder for Drupal 8
Is there easy way to modify look of the frontpage/categories page etc. within Drupal 8 ?
Something like WP builders that are really easy to use and have ton of options?

I love views and things you can do with it, but always get stuck how to look them nice. Not being developer or designer point and click are my only options.

# Answer
In my experience, not really. For better or for worse the Drupal community tends to lean towards custom themes and custom built components. Drupal is great for building out complex, custom content types. But it doesn't have that "premium plugin and theme" community Wordpress has that can whip you up a decent looking website in 30 minutes.

There is https://www.sooperthemes.com/drupal-modules/glazed-builder but it's not free, and I have never used it so I can't vouch for it.

There are some nice free themes by YG which may give you something like what you are looking for. https://www.drupaldevelopersstudio.com/free-drupal-themes \- I installed one a while ago and was reasonably impressed.

Try searching for themes here: https://www.drupal.org/project/project\_theme and sort by release date rather than "most installed". A lot of the themes you might be looking for are not necessarily going to be the most popular (see my first point).

Of course this is just my personal opinion - it's hard to give a "stackexchange" type answer, which is objectively true and provable. I encourage you to do your own research further to my response.
> 1 votes

---
Tags: views, 8
---


title: How do I edit the links in a filter

text:
# Question
Title: How do I edit the links in a filter
I don't know if this is the right forum, but I'm updating our corporate website, and picking up where the previous person in my job left off. From the main horizontal menu on the front page (newsletters, programs and services, departments, doing business, etc), I am clicking on "Programs and Services" which takes me to the page screencapped below. The individual items shown on this page "Counselling, Youth Program, etc" are linking to pages that I want to get rid of and replace with pages I have built elsewhere on the site. I can't seem to figure out where to go to edit these. Ideally I'd like to get rid of the drop-down filter menu entirely and just have links to the pages I have alreayd built for the topics elsewhere within the site. Any help?

# Answer
This is an educated *guess*:

The page "Programs & Services" on the `programs-services` link is built by Views module.

You can edit the Views by clicking on the small gear icon you see in the top right corner of the content area and choosing "Edit Views". Or find that particular View under Structure \> Views and edit from there.

Under `Filters` on the left you'll probably have several filters listed, with one of them labeled `(exposed)`. You can click on it and Remove - that is how you get rid of the "drop-down" filter currently present above the results.

To change which page titles appear in the results you again have to change something under `Filters`, but it's impossible to tell what because that depends on your site configuration.

Sometimes (besides the Published filter) there is the filter based on Content type, for example, to list only Articles that are on the site, or only Basic pages.

Sometimes there is a filter that filters by Taxonomy (tags) that the content is labeled with (for example list only content tagged with "Medical").

You need to find out what the current filter configuration is (post a screenshot), and how your new pages you want to list there differ from other content (are they of a different Content type, have they been posted after some date, by a different author, tagged with some tag).

Then you'll be able to change the filters accordingly to show the new content instead of the current list.
> 0 votes

---
Tags: views, taxonomy-terms, navigation
---


title: How do I return 500 for fatal errors?

text:
# Question
Title: How do I return 500 for fatal errors?
When I am trying to access Drupal and the database is down, it will return a 500 error. However, when I try to access Drupal when Redis is down, it says:

> Additional uncaught exception thrown while handling exception.
>
> Original
> Predis\Connection\ConnectionException: Connection refused \[tcp://drupal-redis-2:6379\] in Predis\Connection\AbstractConnection-\>onConnectionError() (line 146 of /var/www/corp/sites/all/libraries/predis/src/Connection/AbstractConnection.php).
>
> Additional
> Predis\Connection\ConnectionException: Connection refused \[tcp://drupal-redis-2:6379\] in Predis\Connection\AbstractConnection-\>onConnectionError() (line 146 of /var/www/corp/sites/all/libraries/predis/src/Connection/AbstractConnection.php).

The HTTP code returned, however, is 200. This makes it difficult to detect if a server is down for load balancing purposes.

This question is similar to Site is down due to MySQL error but it returns 200/OK but it remains unanswered and is a little different.

# Answer
This is a known issue, whose fix didn't make it into the Drupal 7 core so far. The culprit can be found within the \_drupal\_exception\_handler(). If another error occurs while handling an exception, it just returns the messages stated in your question without setting HTTP status codes (possibly to avoid further exceptions).

Compare https://www.drupal.org/project/drupal/issues/2666908

The above issue already has a small RTBC patch that solves the problem by adding a 500 status code to the handling of the second exception:

```
function _drupal_exception_handler($exception) {
  require_once DRUPAL_ROOT . '/includes/errors.inc';

  try {
    // Log the message to the watchdog and return an error page to the user.
    _drupal_log_error(_drupal_decode_exception($exception), TRUE);
  }
  catch (Exception $exception2) {
    // Add a 500 status code in case an exception was thrown before the 500
    // status could be set (e.g. while loading a maintenance theme from cache).
    drupal_add_http_header('Status', '500 Internal Server Error');

    // Another uncaught exception was thrown while handling the first one.
    // If we are displaying errors, then do so with no possibility of a further uncaught exception being thrown.
    if (error_displayable()) {
      print '<h1>Additional uncaught exception thrown while handling exception.</h1>';
      print '<h2>Original</h2><p>' . _drupal_render_exception_safe($exception) . '</p>';
      print '<h2>Additional</h2><p>' . _drupal_render_exception_safe($exception2) . '</p><hr />';
    }
  }
}

```

Given the age of that patch, the line numbering differs a little from the current version of `bootstrap.inc`. But it still applies cleanly and works as expected.

After you patched your Drupal, you should be able to receive the 500 error code at your load balancer, if Redis is down or the error page can't be created for another reason.

Please note, if your Drupal already sent headers/output to the browser before the error handler kicks in, above patch may have unintended side-effects. You may have to test yourself, whether your webserver still generates 500 server errors for these edge cases.
> 3 votes

---
Tags: 7, http-request
---


# Question
Title: 'Add another' fieldset on a multi-step webform
I have a multi-step webform using ajax (I'm using webform steps and webform ajax modules). The webform contains several pages (i.e education, career and experience). In education page i have the following fields: degree and major which are placed inside a fieldset.

I tried using the webform add more module but it wasn't working (not displaying) although i followed up several recommendations and i know how it works. You need to specify the number of fieldsets, it doesn't create them dynamically.

Is there any other way for me to use the 'add another degree and major' feature?

I am using Drupal 7 and the Webform module 7.x-4.19.

# Answer
> 0 votes
Try using Field Collection in the form. It got the feature of adding multiple fieldset on the fly.

---
Tags: webforms
---


# Question
Title: Drupal duplicate filename throws AJAX error
I am using the managed\_file in a form to upload a file to Drupal. As you know Drupal saves the name of this file into its database and stores it in the path you give.

Unfortunately, when a user uploads a file which has the filename of a previously existing file, he receives an AJAX error that arises from SQL. Even though Drupal manages to store this file with a different name in the folder, I can't prevent the AJAX error.

Is there a solution for this?

Thanks.

# Answer
> 0 votes
As per Drupal structure you need to add option "FILE\_EXISTS\_RENAME" during save file for example : $file\_temp = file\_save\_data($attachment-\>data, 'public:///' , FILE\_EXISTS\_RENAME);

---
Tags: files, 7
---


# Question
Title: Would replacing hooks with events be a good practice?
Do you think it would be a good practice to replace hooks with events? I mean dispatching an event inside a hook to subscribe afterwards.

For example if you have 20 hooks in your module, is it recommended to dispatch an event for each hook, or just keep using the hooks as usual?

```
/**
 * Implements hook_ENTITY_TYPE_insert().
 */
function my_module_node_insert(EntityInterface $entity) {
  // Dispatch the node insert event so that subscribers can act accordingly.
  \Drupal::service('event_dispatcher')->dispatch(NodeInsertEvent::NODE_INSERT, new NodeInsertEvent($entity));
}

```

# Answer
> 2 votes
Perhaps. I know other developers are using Hook Event Dispatcher because they want to guard against if the hook system goes away in D9. Thus, saving time in the future if indeed they go away.

Whether they go away its pure speculation at this point.

---
Tags: hooks, event-subscribers
---


# Question
Title: drush language importing untranslated strings
I am having 2 environments. A staging and a production one. I want all string to sync the strings, so that whenever a new string comes to staging it is available for translation in production. For this reason I've used drush\_language module.

Export via

`drush language-export-translations --statuses='not-translated'`

This provides a .po file where part of it you can see:

```
msgctxt "tripping_context"
msgid "Giannis test translations"
msgstr ""

```

When i run an import on prod via

```
drush language-import-translations  --langcode="sv"

```

No new strings are picked up.

Anything wrong I am doing here?

# Answer
> 0 votes
The statuses flag is saying to export untranslated strings, so you are importing an empty file. Or are there any steps you missed to describe?

---
Tags: drush, i18n-l10n
---


# Question
Title: How do I set access permissions per field?
**What I need to do**

I have some user account fields that should be administrator-only (read/write/edit). For example, the IP address used to register.

So, I want to restrict access to administrators.

**Current state of field permissions in Drupal 8 (as of Feb 19, 2016)**

# Answer
This is an old thread, but as I stumbled upon same problem, not wanting to use a heavy module for few fields, I ran into this article (after this one, so I thought I could share) : https://atendesigngroup.com/blog/form-and-view-modes-vs-field-access-drupal-8

From other exemples around, this one takes care of cache context .

Just be careful to comments below article and some other little mistakes in code example. Correct and working code looks like this :

```
function YOUR_MODULE_NAME_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
  $result = AccessResult::neutral();
  if ($field_definition->getName() == 'field_we_care_about') {
    if ($operation == 'edit' && !in_array('administrator', $account->getRoles())) {
      $result = AccessResult::forbidden();
    }
  }
  return $result->addCacheContexts(['user.roles:administrator']);
}

```
> 13 votes

# Answer
If you want to write the code yourself, the Examples module includes a `field_permissions` example module.

After missing the Drupal 8 cycle, Field Permissions finally got a release for Drupal 9, so you can install the module now.
> 11 votes

# Answer
Field Permissions has a full release for D8 now. It allows you to set permissions per field.
> 7 votes

---
Tags: 8, entities
---


# Question
Title: 405 Method Not Allowed Error when making a JSON API request from a simple create-react-app
The following request is giving me a 405 Method not allowed when running from a simple create-react-app generated project from localhost:3000. I really need this app to run outside of the domain (decoupled). This feels very much like a cross origin issue but I'm sending the `X-CSRF-TOKEN` header token and have apache configured to accept the headers as well.

No idea what I'm doing wrong...

```
Host: contenta.loc
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: GET
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
Access-Control-Request-Headers: authorization,x-csrf-token
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

```

However, running the same code from within a custom module on the same domain executes as expected.

```
import React, { Component } from 'react';
import axios from 'axios';
import Querystring from 'query-string';
import SubRequests from 'd8-subrequests';

const URL = 'http://contenta.loc';

class App extends Component {

  state = {
      csrfToken: '',
      oauthToken: {}
  };

  constructor(props){
    super(props);

    this.initializeCsrfToken();
    this.initializeOauthToken();
  }

  initializeCsrfToken(){
    axios.get(URL + '/session/token')
    .then(response => {
      this.setState({csrfToken: response.data});
    })
    .catch((error) => {
      console.log('error ' + error);
    });
  }

  initializeOauthToken(){
    const data = {
      grant_type: 'password',
      client_id: '77e40506-4b2a-4317-b6c0-5ed5b27ce886',
      client_secret: 'test1123',
      username: 'test',
      password: 'test'
    };

    axios.post(URL + '/oauth/token', Querystring.stringify(data))
      .then(response => {
        this.setState({oauthToken: response.data.access_token});
      })
      .catch((error) => {
        console.log('error ' + error);
      });
  }

  fetchSubrequests() {
    const subrequests = new SubRequests(URL + '/subrequests?_format=json');
    const AuthStr = 'Bearer '.concat(this.state.oauthToken);

    subrequests.add({
      uri: '/api/categories'
    });

    subrequests.add({
      uri: '/api/tags'
    });
    subrequests.add({
      uri: '/api/menus'
    });

    axios.get(subrequests.getUrl(), {
      headers: {
        Authorization: AuthStr,
        'X-CSRF-Token': this.state.csrfToken,
      }
    }).then(dataresponse => {
      console.log(dataresponse);
    })

  }

  render = () => {
    return (
      <button >
        <div onClick ={
          () => {this.fetchSubrequests()}
        } > Fetch Subrequests</div>
      </button>
    )
  }

}

export default App;

```

---

---

UPDATE:

Here's what my `services.yml` cors.config looked like: (THIS IS WRONG???)

```
   # Configure Cross-Site HTTP requests (CORS).
   # Read https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
   # for more information about the topic in general.
   # Note: By default the configuration is disabled.
  cors.config:
    enabled: true
    # Specify allowed headers, like 'x-allowed-header'.
    allowedHeaders: ['x-csrf-token,authorization,content-type,accept,origin,x-requested-with']
    # Specify allowed request methods, specify ['*'] to allow all possible ones.
    allowedMethods: ['POST, GET, OPTIONS, DELETE, PUT']
    # Configure requests allowed from specific origins.
    allowedOrigins: ['*']
    # Sets the Access-Control-Expose-Headers header.
    exposedHeaders: true
    # Sets the Access-Control-Max-Age header.
    maxAge: false
    # Sets the Access-Control-Allow-Credentials header.
    supportsCredentials: false

```

This is what my cors.config needs to be for it to work!!

```
cors.config:
    enabled: true
    # Specify allowed headers, like 'x-allowed-header'.
    # ['x-csrf-token,authorization,content-type,accept,origin,x-requested-with']
    allowedHeaders: ['*']
      # - '*'
    # Specify allowed request methods, specify ['*'] to allow all possible ones.
    # ['POST, GET, OPTIONS, DELETE, PUT']
    allowedMethods: ['*']
    #  - '*'
    # Configure requests allowed from specific origins.
    allowedOrigins: ['*']
    # Sets the Access-Control-Expose-Headers header.
    exposedHeaders: true
    # Sets the Access-Control-Max-Age header.
    maxAge: false
    # Sets the Access-Control-Allow-Credentials header.
    supportsCredentials: false

```

Here's what my `apache.conf` looks like:

```
<VirtualHost *:80>
  ServerName loc
  DocumentRoot /Users/justinwinter/Sites
  VirtualDocumentRoot /Users/justinwinter/Sites/%-2/docroot
  UseCanonicalName Off
  Header set Access-Control-Allow-Origin "http://localhost:3000"
  Header set Access-Control-Allow-Credentials true
  Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, PATCH, DELETE"
  Header always set Access-Control-Allow-Headers: "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization"

  <Directory "/Users/justinwinter/Sites/*/docroot">
    AllowOverride All
    Order allow,deny
    Allow from all
    Require all granted
  </Directory>

  AddType application/x-httpd-php .php
</VirtualHost>

```

---

**NOT WORKING FROM A SEPARATE JS REACT APP**

The following screenshot shows the result of running the same JS from within the contenta.loc domain (same server as the endpoint)

**WORKING FROM WITHIN A CUSTOM MODULE**

The following screenshot shows the error when running the JS from within the create-react-app nodejs localhost server.

# Answer
You can enable CORS support modifying the sites/default/services.yml file

```
cors.config:
enabled: true
allowedHeaders:
  - '*'
allowedMethods:
  - '*'
allowedOrigins:
   # Note: you need to specify the host + port where your app will run.
  - localhost:8000
exposedHeaders: false
maxAge: false
supportsCredentials: false

```
> 2 votes

# Answer
Maybe try `['x-csrf-token', 'authorization', 'content-type', 'accept', 'origin', 'x-requested-with']` instead.
> 2 votes

# Answer
Here is the working example of `local.services.yml` file which can be placed in the `sites/` folder:

```
# Local development services.
#
# To activate this feature, follow the instructions at the top of the
# 'example.settings.local.php' file, which sits next to this file.
parameters:
  http.response.debug_cacheability_headers: true
  cors.config:
      enabled: true
      # Specify allowed headers, like 'x-allowed-header'.
      allowedHeaders: ['*']
      # Specify allowed request methods, specify ['*'] to allow all possible ones.
      allowedMethods: ['*']
      # Configure requests allowed from specific origins.
      allowedOrigins: ['*']
      # Sets the Access-Control-Expose-Headers header.
      exposedHeaders: false
      # Sets the Access-Control-Max-Age header.
      maxAge: false
      # Sets the Access-Control-Allow-Credentials header.
      supportsCredentials: false
services:
  cache.backend.null:
    class: Drupal\Core\Cache\NullBackendFactory

```

Check `sites/default/default.services.yml` for example. Check also: Opt-in CORS support.

The file should be loaded from your settings file, e.g.

```
/**
 * Enable local development services.
 */
$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/local.services.yml';

```

If you're using Apache, check also: CORS on Apache.
> 1 votes

---
Tags: 8
---


# Question
Title: Entity Print Module: Create PDF from HTML
I´m trying to use the entity\_print module for generating a PDF in Drupal 8. I want to print out HTML. My module has no entities it gets data from a solr server and generates HTML output.

My first thing is to make a route and a sort of flag to fire the pdf generation:

```
mymodule.page_detail:
path: '/detail/{Title}/{ObjIdentifier}'
defaults:
_controller: '\Drupal\mymodule\Controller\myController::detailpage'
Title: ''
ObjIdentifier: ''
ViewPdf: '0'
...

mymodule.page_detail_pdf:
path: '/detail/pdf/{Title}/{ObjIdentifier}'
defaults:
_controller: '\Drupal\mymodule\Controller\myController::detailpage'
Title: ''
ObjIdentifier: ''
ViewPdf: '1'

```

...

Then in my Controller I check for

```
if (isset($myModuleViewPdf) && $myModuleViewPdf == "1") {
  ...

```

Now the entity Print magic should come into play. I use the services and make a print engine and a print builder:

```
$print_engine = \Drupal::service('plugin.manager.entity_print.print_engine')->createSelectedInstance('pdf');
$print_builder = \Drupal::service('entity_print.print_builder');

```

Now I´m struggeling somehow. When I look over the functions docroot/modules/entity\_print/src/PrintBuilder.php

I see that they are using entities for the output but I want to use HTML. How can I do this?

Greetings Lars

# Answer
> 5 votes
If you want to send the PDF directly to the user then you can do something like this:

```
// Get your HTML from Solr.
$html = $this->getHtmlFromSolr();

$print_engine = \Drupal::service('plugin.manager.entity_print.print_engine')->createSelectedInstance('pdf');

$print_engine->addPage($html);
$print_engine->send('mydocument.pdf');

```

# Answer
> 0 votes
The previos code works the first time you load the page but will throw errors in your watchdog, and you will give a WSOD when you reload the page.

You need a new Strem Response for the PDF, you cannot reuse the controller stream.

```
$html = $this->getHtmlFromSolr();

$print_engine = \Drupal::service('plugin.manager.entity_print.print_engine')->createSelectedInstance('pdf');
$print_engine->addPage($html);

return (new StreamedResponse(function () use ($print_engine) {
  $print_engine->send('youdocument.pdf');
}))->send();

```

---
Tags: 8, files
---


# Question
Title: What is the correct way to send a node list to the REST API?
In Drupal, we can create nodes with the core module "RESTful Web Services". There is a lot of documentation about creating **one node** with one request, the Drupal documentation provides the following example:

```
curl --include \
  --request POST \
  --user klausi:secret \
  --header 'Content-type: application/hal+json' \
  --header 'X-CSRF-Token: <obtained from http://example.com/rest/session/token>' \
  http://example.com/entity/node?_format=hal_json \
  --data-binary '{"_links":{"type":{"href":"http://example.com/rest/type/node/article"}},"title":[{"value":"Example node title"}],"type":[{"target_id":"article"}]}'

```

We want to import 25.000 nodes on a regular basis and worry that this could take really long if we use a separate request for each node.

It should be possible to send a list of nodes. Drupal's REST web service uses the Serializer Component from the Symphony framework. The Symphony docs say that it includes the serialization of lists of nodes. Passing a list to the REST web service should simply look like this.

```
curl --include \
  --request POST \
  --user klausi:secret \
  --header 'Content-type: application/hal+json' \
  --header 'X-CSRF-Token: <obtained from http://example.com/rest/session/token>' \
  http://example.com/entity/node?_format=hal_json \
  --data-binary '[{"title":[{"value":"Title 1"}],"type":[{"target_id":"article"}]},{"title":[{"value":"Title 2"}],"type":[{"target_id":"article"}]}]'

```

When I send this data, I get this response.

> Could not determine entity type bundle: type field is missing.

t seems that the serializer does not recognize that I send a list.

What is the correct way to send a node list to the REST API?

# Answer
# Solution 1: Custom Endpoint

Unfortunately, entities are expected to be created one by one when using RESTful web services. You can create your own web service endpoint by writing a custom module and there, you can create support for creating multiple nodes with a single request. However, you'll still have to use batches of say, 50 nodes per request for things to work smoothly. This is more of a `push` import.

You might also want to try the `jsonapi` module to see if supports importing multiple operations in a single request.

# Solution 2: Migrate API

Have you considered Drupal's migrate API instead? With migrate, you can import nodes from a remote XML / JSON document with a simple `drush` command which you can setup as a part of cron on your server. You can update existing items and create non-existing items. Migrate will also create nodes one by one, but it will be much faster than REST requests because it will not involve 1 HTTP request per node. This is more of a `pull` import.
> 5 votes

---
Tags: 8, nodes
---


title: Print element title in email

text:
# Question
Title: Print element title in email
Given the following element in my webform, how do I print *Name: Fred* in my email?

```
Title   Key   Value
Name    name  Fred

```

I understand how to print the raw value. How do I print the title?

```
[?]: [webform_submission:values:name:raw]

```

An admin may change the element's title, so I can't have *Name: \[webform\_submission:values:name:raw\]*.

# Answer
> 0 votes
Accessing a webform's element properties including #title, #description via tokens is not currently supported. I am not sure the core Webform module should provide these tokens, but a third-party module can easily make these tokens available.

# Answer
> 0 votes
You can now use a Twig template. I have an if statement so that the label and colon are omitted if the element is left empty.

```
{% if data.name %}
  {{ elements.name['#title'] }}: {{ data.name }}
{% endif %}

```

---
Tags: 8, webforms
---


# Question
Title: Programmatically pass parameters to Apache Solr integrated with Search API
I'm currently trying to enable spellcheck results with the search api. If I visit my apache solr server directly with http://myserver:8983/solr/d8/select?q=goood+worksd&spellcheck=true and provide the keywords and set spellcheck to true in the url parameters

I receive expected results

> { "response":{"numFound":0,"start":0,"docs":\[\] }, "spellcheck":{ "suggestions":\[ "goood",{ "numFound":1, "startOffset":0, "endOffset":5, "suggestion":\["good"\]}, "worksd",{ "numFound":1, "startOffset":6, "endOffset":12, "suggestion":\["worked"\]}\]}}

In the response I can see the spellcheck information I need in the spellcheck section.

However when I set the options programmatically before doing the query with the search api I don't receive any of this information.

```
    $index_id = 'default_solr_index';
    $index = \Drupal\search_api\Entity\Index::load($index_id);
    $query = $index->query();
    $parse_mode = \Drupal::service('plugin.manager.search_api.parse_mode')
        ->createInstance('terms');
    $parse_mode->setConjunction('AND');
    $query->setParseMode($parse_mode);
    $query->keys($search_terms);
    $query->setFulltextFields(['title', 'body_field_parse', 'type','field_description','name','body','field_title','field_summary']);
    $query->addCondition('status', 1);
    $query->sort('search_api_relevance', 'DESC');
    $query->setOption('spellcheck','true');
    $executed_query = $query->execute();
    var_dump($executed_query->getAllExtraData());

```

When I var\_dump($executed\_query-\>getAllExtraData()) all I get is

> { \["search\_api\_solr\_response"\]=\> array(1) { \["response"\]=\> array(4) { \["numFound"\]=\> int(0) \["start"\]=\> int(0) \["maxScore"\]=\> float(0) \["docs"\]=\> array(0) { } } } }

I've done all kinds of variations giving true instead of 'true' and adding other options like

```
$query->setOption('spellcheck','true');
$query->setOption('spellcheck.build','true');
$query->setOption('search_api_spellcheck','true');
$query->setOption('spellcheck.extendedResults','true');

```

But nothing seems to work. I saw a spellcheck search api module someone posted but I couldn't get it to work and it seemed to do things very similar to how I'm doing it now. Is there a way to pass these parameters to my query to my apache solr? Or is my method correct and getAllExtraData not the proper way to get this information back?

# Answer
> 1 votes
After digging deep into the search\_api\_solr module I found a spot where it's applying options to the solr parameters inside the search method of the SearchApiSolrBackend class here

```
  foreach ($options as $option => $value) {
    if (strpos($option, 'solr_param_') === 0) {
      $solarium_query->addParam(substr($option, 11), $value);
    }
  }

```

I noticed that it only applies the parameter if it's preceded by 'solr\_param\_' and if it is it strips out the 'solr\_param\_' before applying it to the actual parameter. All I had to do was add 'solr\_param\_' to the beginning of my option like so.

```
$query->setOption('solr_param_spellcheck','true');

```

Once I did that, getAllExtraData() returned what I needed.

> array(1) { \["search\_api\_solr\_response"\]=\> array(2) { \["response"\]=\> array(4) { \["numFound"\]=\> int(0) \["start"\]=\> int(0) \["maxScore"\]=\> float(0) \["docs"\]=\> array(0) { } } \["spellcheck"\]=\> array(1) { \["suggestions"\]=\> array(16) { \[0\]=\> string(5) "goood" \[1\]=\> array(4) { \["numFound"\]=\> int(1) \["startOffset"\]=\> int(11) \["endOffset"\]=\> int(16) \["suggestion"\]=\> array(1) { \[0\]=\> string(4) "good" } } \[2\]=\> string(5) "goood" \[3\]=\> array(4) { \["numFound"\]=\> int(1) \["startOffset"\]=\> int(42) \["endOffset"\]=\> int(47) \["suggestion"\]=\> array(1) { \[0\]=\> string(4) "good" } } \[4\]=\> string(5) "goood" \[5\]=\> array(4) { \["numFound"\]=\> int(1) \["startOffset"\]=\> int(60) \["endOffset"\]=\> int(65) \["suggestion"\]=\> array(1) { \[0\]=\> string(4) "good" } } \[6\]=\> string(5) "goood" \[7\]=\> array(4) { \["numFound"\]=\> int(1) \["startOffset"\]=\> int(93) \["endOffset"\]=\> int(98) \["suggestion"\]=\> array(1) { \[0\]=\> string(4) "good" } } \[8\]=\> string(5) "goood" \[9\]=\> array(4) { \["numFound"\]=\> int(1) \["startOffset"\]=\> int(111) \["endOffset"\]=\> int(116) \["suggestion"\]=\> array(1) { \[0\]=\> string(4) "good" } } \[10\]=\> string(5) "goood" \[11\]=\> array(4) { \["numFound"\]=\> int(1) \["startOffset"\]=\> int(129) \["endOffset"\]=\> int(134) \["suggestion"\]=\> array(1) { \[0\]=\> string(4) "good" } } \[12\]=\> string(5) "goood" \[13\]=\> array(4) { \["numFound"\]=\> int(1) \["startOffset"\]=\> int(154) \["endOffset"\]=\> int(159) \["suggestion"\]=\> array(1) { \[0\]=\> string(4) "good" } } \[14\]=\> string(5) "goood" \[15\]=\> array(4) { \["numFound"\]=\> int(1) \["startOffset"\]=\> int(182) \["endOffset"\]=\> int(187) \["suggestion"\]=\> array(1) { \[0\]=\> string(4) "good" } } } } } }

Not entirely sure why I have so many duplicate results here so if anyone has input on that that would be helpful. Otherwise I do have the data I need.

---
Tags: 8, search
---


# Question
Title: How do I change the site name in the .theme file?
I'm looking for a solution to change the site name in a .theme file in Drupal 8. I'm using the Group module and want to display a different site name when the current user navigate inside each group. How can I achieve this ?

# Answer
In a \*.theme file this would be difficult to find all places where the site name may end up. This is much easier to do it in settings.php right at the start:

**settings.php:**

```
if ($_SERVER['REQUEST_URI'] == '/abc/def') {
  $config['system.site']['name'] = 'abc-def';
}

```
> 1 votes

# Answer
You can override the site title based on the group name by implementing a Config Factory Override class inside a custom module, and passing a '@current\_route\_match' argument and a few other arguments noted below to help get the information you need out of the entity represented at the current route.

In my case, I needed to limit the site name change to a specific group bundle type called `division` that has a specific field value. The code below is currently working for me inside a custom module called: `mysite_group`. There are two helper methods that contain the logic for finding the group entity and deciding whether or not to change the site name. The logic should work both on the group page itself, as well as on any other entity or node that is related to the group.

Note: the site we built is leveraging entity\_reference fields to maintain the mapping between nodes-\>groups, if this is not the case for your site, you can take the example below and modify the logic contained in the `getSiteNameFromEntityReference()` method and customize it to your needs.

```
# in mysite_group.services.yml
services:
  mysite_group.group_site_name_config_override:
    class: \Drupal\mysite_group\GroupSiteNameConfigOverride
    arguments: ['@current_route_match', '@entity_type.manager', '@entity_field.manager']
    tags:
      - {name: config.factory.override, priority: 5}

```

```
<?php
// in mysite_group/src/GroupSiteNameConfigOverride.php

namespace Drupal\mysite_group;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\field\Entity\FieldConfig;

/**
 * Override the site name config variable on groups and nodes that relate to
 * groups.
 */
class GroupSiteNameConfigOverride implements ConfigFactoryOverrideInterface {

  /**
   * {@inheritdoc}
   */
  public function __construct(RouteMatchInterface $route_match, EntityTypeManagerInterface $entity_type_manager,EntityFieldManagerInterface $entity_field_manager) {
    $this->routeMatch = $route_match;
    $this->entityTypeManager = $entity_type_manager;
    $this->entityFieldManager = $entity_field_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function loadOverrides($names) {
    $overrides = [];
    if (!in_array('system.site', $names)) {
      return $overrides;
    }

    $site_name = NULL;
    if ($entity = $this->getViewedEntity()) {
      if ($entity->getEntityTypeId() == 'group') {
        $site_name = $this->getSiteNameFromGroup($entity);
      }
      else {
        $site_name = $this->getSiteNameFromEntityReference($entity);
      }
    }

    if ($site_name) {
      $overrides['system.site'] = ['name' => $site_name];
    }

    return $overrides;
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheSuffix() {
    return 'GroupSiteNameConfigOverride';
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheableMetadata($name) {
    return new CacheableMetadata();
  }

  /**
   * {@inheritdoc}
   */
  public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
    return NULL;
  }

  /**
   * Helper method loads the viewed entity from the current route.
   *
   * Adapted from https://www.drupal.org/node/2309797#comment-12752478
   *
   * @return an entity object, when it exists; otherwise null.
   */
  protected function getViewedEntity() {
    foreach ($this->routeMatch->getParameters() as $param) {
      if ($param instanceof EntityInterface) {
        $page_entity = $param;
        break;
      }
    }
    if (!isset($page_entity)) {
      // Some routes don't properly define entity parameters.
      // Thus, try to load them by its raw Id, if given.
      $types = $this->entityTypeManager->getDefinitions();
      foreach ($this->routeMatch->getParameters()->keys() as $param_key) {
        if (!isset($types[$param_key])) {
          continue;
        }
        if ($param = $this->routeMatch->getParameter($param_key)) {
          if (is_string($param) || is_numeric($param)) {
            try {
              $page_entity = $this->entityTypeManager->getStorage($param_key)->load($param);
            }
            catch (\Exception $e) {
            }
          }
          break;
        }
      }
    }
    if (!isset($page_entity) || !$page_entity->access('view')) {
      $page_entity = FALSE;
      return NULL;
    }
    return $page_entity;
  }

  /**
   * Helper method determines the site name based on the specified group
   * entity.
   *
   * @return (string) site name value based on the specified group; null if the group
   */
  protected function getSiteNameFromGroup(EntityInterface $group) {
    $site_name = NULL;

    // In our application only groups in the 'division' bundle that have a
    // 'library' specified in their field_division_type should provide an
    // alternate site name.
    if ($group->bundle() == 'division' && $group->field_division_type->getString() == 'library') {
      $site_name = $group->label();
    }
    return $site_name;
  }

  /**
   * Helper method loads the site name from an entity reference field.
   *
   * @return (string) site name value based on the first group found in the
   *   entity reference field on the specified entity.
   */
  protected function getSiteNameFromEntityReference(EntityInterface $entity) {
    $site_name = NULL;
    $bundle = $entity->bundle();
    $type = $entity->getEntityTypeId();
    $valid_group_type = 'division';

    // Gather a list of all entity reference fields.
    $map = $this->entityFieldManager->getFieldMapByFieldType('entity_reference');

    // We only care about entity reference fields on the current entity.
    $reference_field_ids = [];
    if (!empty($map[$type])) {
      foreach ($map[$type] as $name => $data) {
        if (!empty($data['bundles'][$bundle])) {
          // TODO: Improve logic to determine which reference fields may be
          // used to determine the site name, for improved performance. The
          // order in which we process reference fields is currently
          // arbitrary, based on the order returned by
          // EntityFieldManager::getFieldMapByFieldType()
          $reference_field_ids[] = "$type.$bundle.$name";
        }
      }
    }

    // Determine if any of the reference fields on the current entity point
    // to a group.
    foreach (FieldConfig::loadMultiple($reference_field_ids) as $field_config) {
      $field_name = $field_config->getName();
      $target_type = $field_config->getSetting('target_type');
      if (!empty($target_type)) {
        $handler_settings = $field_config->getSetting('handler_settings');
        if (isset($handler_settings['target_bundles'][$valid_group_type])) {
          if ($referenced_entities = $entity->{$field_name}->referencedEntities()) {
            // If multiple entities are referenced, the first one with a
            // custom site name takes precedence.
            foreach($referenced_entities as $referenced_entity) {
              if ($site_name = $this->getSiteNameFromGroup($referenced_entity)) {
                break 2;
              }
            }
          }
        }
      }
    }

    return $site_name;
  }

}

```
> 0 votes

---
Tags: theming, 8, group
---


# Question
Title: Missing bundle property on entity of type taxonomy_term
I am using the Feeds Import module as described in Drupal as an interface for users to Add/Edit/Search a database.

When we import, we get the following error:

> Missing bundle property on entity of type taxonomy\_term

Why does that error message appear?

# Answer
This error is caused when there is no ***Vocabulary*** selected in the ***Term reference*** fields of the content type into which feed import is performed.

Go to the Manage fields of your content type into which you are importing. Check all the ***Term reference*** fields and reconfirm that in the ***Field Settings***, correct ***Vocabulary*** is selected.
> 2 votes

# Answer
In my case, my entity (term) did not have the property `vocabulary_machine_name`.

It was `["vocabulary_machine_name"] => NULL` when it should have the right **vocabulary\_machine\_name**, in this case 'forum'.

So a made sure the term has it:

```
                        $term->name = ...;
                        $term->vid = ...;
                        $term->vocabulary_machine_name = 'forum'; //here
                        $term->format = ...;

```
> 0 votes

---
Tags: 7, taxonomy-terms, feeds, importing-exporting
---


# Question
Title: form #type => checkboxes with zero / empty option value
I am building something which uses a form element with `'#type' => 'checkboxes'`.

I want this to be reusable, so it should accept anything as option values that works as a PHP array key (integers and non-integer strings).

```
$form['checkboxes'] = [
  '#type' => 'checkboxes',
  '#options' => [
    0 => 'zero',
    '' => 'empty string',
    ' ' => 'space',
    'other' => 'Other',
  ],
];

```

However there seems to be a problem with values `0` (zero) and `''` (empty string).

Even when the checkboxes for '' or 0 are checked, the values are gone in the `$element['#value']` array, e.g. when checking with a custom '#element\_validate' callback.

```
$element['#value'] === [
  # '' and 0 are gone, even if they were checked.
  ' ' => ' ',
  'other' => 'other',
];

```

Interestingly, the `$_POST` still contains the values, with an interesting twist, where space and empty string behave like array insertion via `[]`. I suppose this is due to the way POST data is sent.

```
$_POST['checkboxes'] === [
  0 => '0',
  1 => '',
  2 => ' ',
  'other' => 'other',
];

```

I can imagine why all of this happens, but is there a workaround or solution?

EDIT: The previous version of the code snippet was misleading, sorry. I had mixed up $\_POST and the original '#options' array.

# Answer
I managed to prevent this problem by adding an '#element\_validate' handler on the checkboxes element.

The code below is a simplified version of what I did, up to you to fine-tune.

```
$element['#element_validate'][] = '_MYMODULE_checkboxes_validate';

function _MYMODULE_checkboxes_validate(array &$element, array &$form_state) {

  // The form value already has the format $[$id] = $id, mostly.
  // However, if trim($id) === '', the array key will be an integer increment.
  $value = $element['#value'];

  // Make sure it has the expected format.
  if (!is_array($value) || [] === $value) {
    $ids = [];
  }
  else {
    // Get rid of integer keys for empty-ish string ids.
    $ids = array_combine($value, $value);
  }

  // Remove dangling * => 0 entries.
  form_set_value($element, $ids, $form_state);
}

```

Note: If you have the value\_is module installed, empty-ish values will always be unset, thanks to `_value_is_disabled_options_value_callback()`.
> 0 votes

---
Tags: 7, forms
---


# Question
Title: How do I troubleshoot a node not appearing in workbench?
I have a bug report where a user is not able to see 'Draft' status nodes that they have just created in their workbench interface (at `/admin/workbench`). They are able to see other nodes in various approval phases.

I've backported the site to a local development environment and logged in as that user and I'm able to re-create the issue. Also, with my administrator user, I have the same issue -- the new node doesn't show up in my workbench queue either. However, it does show up in the content overview. The problem is that for most users, we only give them workbench queues to access content, and not the content overview.

I've looked at the various configurations for workbench, and at the fields on the new nodes, and I don't even have a starting point as to what to look at to troubleshoot this issue. My users are able create and publish content on a daily basis, so there's not a major misconfiguration in the site.

What makes a node appear in a workbench queue in Drupal 8? We have both the `workbench` and `workbench_access` modules enabled. I'm not sure how these interact with the core workbench features.

**Edit** I noticed in the module page that "Workbench core is a series of Views", so I looked in the views on our site. We seem to be using the built-in-views, so I edited the "Workbench: Recent content (Content)" view, and removed the Filter Criteria "Content: Published status or admin user". I thought this would prevent my user from seeing the new node. However, after I removed that filter criteria, the draft node still did not appear in the preview of that view. So that doesn't seem to be causing the problem.

# Answer
> 0 votes
Absent the "right way to do it", what I've done is go ahead and given "Bypass Access Restriction" permissions to certain roles. That allows them to get their work done, but I would like to know what the correct thing here is.

---
Tags: 8, workbench
---


title: How to get view pager url in node page?

text:
# Question
Title: How to get view pager url in node page?
How to get pager url in node page ,actually what i want i am creating a view block with listing of nodes with ajax in view exposed filter,because exposed filter doesnt work without ajax,the problem i am facing when i am clicking pagination of view url is not creating like /system-manager/central-ordering/?page=1 .

Also used quick tabs where i am showing view as block in tab.

What i want when user click on the node in view page to see the node content ,i am placing there back button but on clicking back button everytime its going to pager 1(/system-manager/central-ordering) ,not on the same pager from where its clicked(/system-manager/central-ordering?page=3) .

Is it possible to add pagination in view url argument with ajax?

# Answer
If your intent is showing node content by clicking on node title or similar, you can use the Views Reference Filter filter instead of the Exposed filter. It basically filters one View display with another display. You create one display with a list of node titles, another view display showing node content and add the special filter to the second display. This makes for a very nice user interface for instant filtering.

You can use this answer to a similar case to compare and follow steps: Filter a view by clicking on a link on another view
> 0 votes

---
Tags: 7, views
---


# Question
Title: Exposed Filter of Child Terms on Parent Page
I'm looking for a dummy's guide on how to configure the default taxonomy term views so that I can display an exposed filter of child terms on the parent page.

Assuming I have the taxonomy structure below.

1. Sports
    * Football
    * Basketball
    * Boxing
2. Entertainment
3. Politics

I want when I'm on Sports page, there is an exposed filter where I can select either of football, basketball or boxing.

I have followed all tips I could find online but the option to add contextual filter of "Taxonomy Term: Parent term" was not available.

# Answer
You can create a separate Views of type Taxonomy term (not content!) display Block that is showing taxonomy term names, add the Relationship to the parent term and require it, and a Contextual filter to taxonomy term ID using that relationship.

Test it by entering parent term ID into Preview, you should see the parent's children.

Edit the Format to set the fields to display inline, or use CSS (later) to make them appear horizontally.

Then in your Content (original) Taxonomy Term views add `View area` into Header and choose the above Block with `Inherit contextual filters` option ticked.
> 1 votes

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


# Question
Title: How can I design a relationship between two types of users?
I have two types of users in drupal-7: children users and parents users. How can I design a relationship between these types of users?

Also How can I maintain this relationship in the code? i.e. getting the parent of the child or vice versa.

# Answer
You can use the User Relationships module for that.

> Administrators are able create relationship types (friend, coworker, etc). Relationship types can be setup to be one-way or mutual. If a relationship type is one-way (subscriber) only the requester is shown as relating to the requestee. Relationship types can also be set as needing or not needing approval.

I've used this module for one of my project. It works great!
> 3 votes

# Answer
Consider using the relation module. You can:

* Create binary and n-ary relations among various entities.
* Store meta information about the relationship in fields, as relations are fieldable entities.
* Export/Import the relationship via features.
* Specify the directional nature of the relationship.

Relations also ships with views integration, so you get that for free without any coding, plus, its got a neat API.
> 0 votes

# Answer
From official Dynamic Entity Reference module page on Drupal.org:

> Dynamic Entity Reference provides a field type/widget/formatter combination for Drupal 8 that allows an entity-reference field to reference more than one entity type

DER has active development for Druapl 8 also
> 0 votes

---
Tags: 7, users
---


title: No Available release found

text:
# Question
Title: No Available release found
On the module update area, my install of 7.56, can seem to find matches to core and a few modules.

How do I begin to fix this?

## What I've tried so far:

Based on translating an answer in Cannot update drupal8: “No available releases found” to v7, I attempted

```
drush vdel update_last_check -y
drush rf
drush cc all
drush cron

```

This failed to do anything meaningful.

# Answer
> 1 votes
Nothing helped in our case, but running the following command:

```
drush sql-query "truncate cache_update"

```

---
Tags: 7, updating
---


# Question
Title: What is the equivalent of hook_translated_menu_link_alter() to alter a menu link?
I want to alter the menu link in Drupal 8. In Drupal 7 we can achieve this using `hook_translated_menu_link_alter()`.

```
function module_translated_menu_link_alter(&$item, $map) {
  global $user;

  if (!empty($item['access'])) {
    // Administrator will access all menu's.
    if (strpos(current_path(), 'admin/structure/menu/manage/' . $item['menu_name']) === 0 && user_access('administer menu')) {
      return;
    }
    // If userid is equal to menu user id.
    if ($user->uid == 1) {
      $access = 'UNBLOCK';
      break;
    }
   // Block menu.
    else {
      $access = 'BLOCK';
    }
    // Access FALSE if Menu not for USER.
    if ($access == 'BLOCK') {
      $item['access'] = FALSE;
    }
  }
}

```

In Drupal 7 I am hiding/disabling menu based on some conditions like the user ID.

Similarly, I want to alter the menu link in Drupal 8. How can I achieve it?

# Answer
> 4 votes
HOOK\_link\_alter would be one D8 equivalent to hook\_translated\_menu\_link\_alter:

```
/**
 * Implements hook_link_alter().
 *
 * @inheritdoc
 */
function HOOK_link_alter(&$variables) {
  $url = $variables['url'];
  // Check url is routed in Drupal.
  if ($url->isRouted()) {
    // Load the current user by user ID.
    $currentUser = User::load(\Drupal::currentUser()->id());
    // Check access.
    $urlAccess = $url->access();
    // Get url options.
    $urlOptions = $url->getOptions();
    // Your code here.
  }
}

```

See Drupal 8 class URL for more API info.

However, you could use Hook\_preprocess\_HOOK() as such:

```
/**
 * Implements hook_preprocess_hook().
 *
 * @inheritdoc
 */
function HOOK_preprocess_menu(&$variables) {
  if (isset($variables['menu_name']) && $variables['menu_name'] === 'menu_name') {
    foreach($variables['items'] as $key => $item) {
      $url = $item['url']->toString();
      if ($url == '/user') {
        // Remove menu item.
        unset($variables['items'][$key]);
      }
    }
  }
}

```

Just checking `path` above, but it shows you can hide a single menu item based on certain criteria.

---

For the access restrictions, depending on your needs, you might look at routing and permissions based on the `entity` instead of the menu item and let Drupal handle the menu item display.

For menu access by role look at this module: https://www.drupal.org/project/menu\_item\_role\_access

# Answer
> 0 votes
From drupal.org on /node/2122241:

> Altering menu links and adding menu links dynamically
>
> Statically defined menu items may be altered using hook\_menu\_links\_discovered\_alter() (but note there is no hook\_menu\_link\_discovered(), the menu links are built from the .yml files as explained above). This hook may also be used to add new dynamic menu items.
>
> More often, you may want to use a deriver class to add new menu link plugins. For example Views provided menu links are added in views.links.menu.yml, which specifies the deriver class \Drupal\views\Plugin\Derivative\ViewsMenuLink.
>
> Finally, you can use the plugin manager directly to add, update, and remove definitions.

You could probably use hook\_menu\_links\_discovered\_alter for your scenario.

---

Edit: You want to edit the permission to access that link, so it automatically does not show up in the menu.

Read on drupal.org: /node/2311427

> Drupal 8
>
> In Drupal 8, you can support dynamic permissions by referencing a function that will dynamically define those permissions. This callback defines the permissions for core's filter module.
>
> ```
> // in filter.permissions.yml
>
>
> permission_callbacks:
>   - Drupal\filter\FilterPermissions::permissions
>
> // in FilterPermissions.php
>
> class FilterPermissions {
>   public function permissions() {
>     $permissions = [];
>     // Generate permissions for each text format. Warn the administrator that any
>     // of them are potentially unsafe.
>     /** @var \Drupal\filter\FilterFormatInterface[] $formats */
>     $formats = $this->entityManager->getStorage('filter_format')->loadByProperties(['status' => TRUE]);
>     uasort($formats, 'Drupal\Core\Config\Entity\ConfigEntityBase::sort');
>     foreach ($formats as $format) {
>       if ($permission = $format->getPermissionName()) {
>         $permissions[$permission] = [
>           'title' => $this->t('Use the @label text format', ['@url' => $format->url(), '@label' => $format->label()]),
>           'description' => String::placeholder($this->t('Warning: This permission may have security implications depending on how the text format is configured.')),
>         ];
>       }
>     }
>     return $permissions;
>   }
> }
>
> ```

You should also read this article https://www.lullabot.com/articles/what-happened-to-hook\_menu-in-drupal-8 (scroll down to "Access Control" and "Hook\_Menu\_Alter").

I hope this helps.

---
Tags: 8, navigation
---


# Question
Title: Howdo I display all the images from a field in a view?
I'm trying to display multiple images from an image field in one view as an Owl Carousel, but I only see a maximum of 5 images to be displayed there. Googleing it, I found that there's an option **ALL,** that should display all of the images, but it just doesn't appear to me, so do you know what do I need to configure to enable ALL the images in that field?

**General setup:** I'm using Drupal 7x, with a sub-theme from Bootstrap and Views 7.x-3.20.

**Views setup:** it was created as an Unformatted list and it's showing just Fields one of them is the image field you can see below.

In the red box I've seen the ALL option, but it just doesn't appear in my setup.

Thanks, Daniel.

# Answer
> 1 votes
You see the limited number of values (as a drop-down) in Views instead of a text field where you can type in `all` or some number because you have limited the number of values this field can take in its settings.

Check your Content type field settings for "Imagenes" and see if it's limited:

Since this is in your field settings it's enough to set your Views field multi-settings to `5` because there are never more than five values in this particular case.

---
Tags: 7, views, media
---


# Question
Title: How do I use a preprocess function to add custom classes to a view fields?
I have a View that outputs several fields per row. I'd like to use a preprocess function to add a class to one of the fields, depending on the value of another field. How do I do that in Drupal 8?

Note, I do not want to add a class to the entire row -- just a specific field in that row. The output would be something like:

```
<div class="views-row">
  <div class="views-field field-name-a"> ... </div>
  <div class="views-field field-name-b has-custom-class"> ... </div>
</div>

```

# Answer
As mentioned in the comment you can add classes to fields through the interface, and you can use field tokens as CSS classes.

## Add field-value-based CSS class to a field

1. Position the field with the value you want to use as the CSS class (**the value-class field**) above the field where you want the class to appear (**the styled field**).
2. Set **the value-class field** to `Exclude from display` if you don't want it to appear there.

If you need it visible in some other place then add that same field again where you need it, while keeping the first one for the token (because you can only use tokens of fields preceding in the Fields list).
3. Edit the field where you want to apply the CSS class (**the styled field**) \>

* Uncollapse `Style settings` \>
    * **Customize field and label wrapper HTML** (or `Customize field HTML` if you don't need the wrapper) \>
    * **Create a CSS class** and
    * enter the first part of your class (`myclass`)

    (class names can't start with numbers and some special characters so it's good to control at least the first character to make it independent of the other field's value to prevent trouble down the line).
4. Uncollapse `Rewrite results` (don't enable it, you just need to temporarily reveal and uncollapse to copy the token),

* uncollapse `Replacement patterns`,
    * copy the value-class field token and
    * paste it in the above `CSS class` field

    (you end up with something like `myclass-[field_name_a]`).
5. Save the View and check your HTML output (in any theme), you will see a class based on your value-class field on the field where you added the class, something like `class="views-field views-field-name-b myclass-namebvalue"`.
> 1 votes

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


# Question
Title: How do I move files and directories after installation?
I moved directory within a server so the Drupal 8 installed URL should change from *ip-address/old-folder/d8* to *my-site.com/d8/*.

When I checked the new URL, the front page worked, but other pages gave a 404 error that said *old-folder/d8/admin/structure/*.

I read Moving drupal to a subdirectory, but the answer there didn't resolve my problem.

Which file/config I should change in Drupal 8.6?

# Answer
> 0 votes
I would expect you just need to clear (or 'rebuild' as it is often called nowadays) the cache, as 4k4 is suggesting in a comment.

There are several ways you can do that:

1. The "built-in" option is to go to /admin/config/development/performance and hit the clear cache button there.
2. Another popular option is with drush, where you could issue `drush cr` to rebuild the cache from the command line. Your site or server would need to have drush installed, though. It can be a lifesaver if for whatever reason you can't get to the UI page, though.
3. In a similar vain, drupal console (a tool quite similar to drush) can do the same thing, with `drupal cache:rebuild`, `drupal cr` or `drupal cc`.
4. If you are running with the default database cache mechanism, you can truncate the tables that start with `cache_` as their table name. Treat this as a last resort, though, and do make a backup in case you make a mistake. In particular, do *not* truncate the cachetags table.

---
Tags: 8
---


# Question
Title: Displaying the contents of a document file (doc, docx, etc.)
I'm looking for a way to display the contents of an uploaded document file such as a .docx file.

In Drupal 6 I used the iPaper module which did the trick as all I needed was api code to connect with the service, and the documents were able to be kept private.

But for Drupal 7, I'm pretty sure the File entity (fieldable files) module should do the trick, but I'm not able to get it working for any files other than .txt.

There are some Google viewer modules which I'm not sure what added functionality they have over the above module, but those don't appear to work correctly. One of them requires that files are public domain which doesn't work for this project due to privacy requirements.

Some other modules like group docs viewer and ajax docs viewer charge a hefty monthly fee for displaying rendered files, but all I need is a simple open source docx viewer.

What is the best way to proceed? Which modules are stable for production use?

Best case would allow for user upload, file contents displayed under the actual file attachment, and the rendered document editable for the user.

Note: i've gotten the google docs module to work but that doesn't allow for private files. google needs to access the file publicly in order to render. scribd field also works to some extent but has too many errors and bugs still. looking for a better, simpler solution.

# Answer
Maybe this module can be usefull : Flipping Book

> This module provides an integration point between Drupal7 and FlippingBook (http://flippingbook.com/). Flippingbook is a very used software to make digital publication from any document you have (.doc, .pdf...).
> 0 votes

# Answer
Try the PDF Reader module.

From this article:

> My solution was to use the PDF Reader with the Embed display option. This option would allow me to attach a PDF to a Drupal node, and reliably display it on a Drupal web page.
> 0 votes

---
Tags: 7, entities, files
---


title: Running a site on a non-standard port

text:
# Question
Title: Running a site on a non-standard port
I have a server which I want to run drupal site on it.

The default http port 80 was block and it does not have a static IP address. I have to run Drupal on non 80 port, let's say 8765.

Since I do not have a static IP, I apply a sub-domain name from noip which is **drupal8.myftp.org**. So finally my domain name should be **drupal8.myftp.org:8765**

First, I read the tutorial here

From line 46

> * Note that if you are installing on a non-standard port number, prefix the
> * hostname with that number. For example,
> * www.drupal.org:8080/mysite/test/ could be loaded from
> * sites/8080.www.drupal.org.mysite.test/.\**

So In my scenario, I should create a directory like sites/8765.drupal8.myftp.org/ and put the settings.php here. Then I also need to create a 8765.drupal8.myftp.org.php file under “sites” directory to tell Drupal to looking for the settings.php within sites/8765.drupal8.myftp.org directory.

I did create the directory and the file.

But Drupal still looking for the settings.php under default directory, why?

**Questoin1:** what content should be in the 8765.drupal8.myftp.org.php file? Since I can not find any tutorial about this, I just leave it blank, I assume it's just a symbol to let Drupal know it should look for the settings.php in the 8765.drupal8.myftp.org category.

**Question2:** Why Drupal doesn't look for the settings.php under 8765.drupal8.myftp.org directory? Do I did sth wrong?

Since I need to add

**$base\_url=”http://drupal8.myftp.org:8765**

in the settings.php and the file under sites/8765.drupal8.myftp.org directory doesn't work. So I have to add it to the settings file under default directory. But still, If I open the site drupal8.myftp.org:8765 and view the source code

```
<link rel="shortcut icon" href="http://drupal8.myftp.org/core/misc/favicon.ico" type="image/vnd.microsoft.icon" />
<link rel="alternate" hreflang="en" href="http://drupal8.myftp.org/node/3" />
<link rel="alternate" hreflang="zh-hans" href="http://drupal8.myftp.org/zh-hans/node/3" />

```

We can see all the link are still point to drupal8.myftp.org, therefore, all image and css info are gone.

So could anybody give me some instructions, I have be stuck in this for three days, any help is highly appreciated.

Thanks in advance.

@Pathak,

Thank you for your kind reply.

Yes, I create a folder called 8765.drupal8.myftp.org and place settings.php within it. So the path is

```
sites/8765.drupal8.myftp.org/settings.php

```

I also create a file call 8765.drupal8.myftp.org.php reference to example.sites.php.

The path is

```
sites/8765.drupal8.myftp.org.php

```

According to example.sites.php

> The array is written in the format: '..' =\> 'directory'. As an example, to map www.drupal.org:8080/mysite/test to the configuration directory sites/example.com, the array should be defined as:
>
> $sites = array( '8080.www.drupal.org.mysite.test' =\> 'example.com', );

Then in the 8765.drupal8.myftp.org.php, I write the $sites array as follow;

```
$sites = array(
    '8765.drupal8.myftp.org' => '8765.drupal8.myftp.org',
  );

```

But still, if open the site drupal8.myftp.org:8765, the settings.php under the default directory was read. All links are point to drupal8.myftp.org without the port number. Could you please point out on which step I was wrong?

# Answer
> 2 votes
All of those instructions only apply if you actually want to have a multi-site installation and e.g. different installations on different ports. Something that most people recommend to not do as it results in maintenance issues sooner or later.

If you just want to have one installation, use sites/default/settings.php and you're good to go.

# Answer
> 0 votes
If you are creating a new folder and placing settings.php there as well, Drupal will treat your site as a multisite installation. So all you need to do is look into `'sites/example.sites.php'`. Copy it to `'sites.php'` and create an array `$sites` mapping default and your custom site folder as well.

# Answer
> 0 votes
I believe you are having two problems, although it might be only one.

First of all, are you planning to use this Drupal installation as a multisite installation, i.e. are you planning on serving multiple sites from the one code base?

If not, than you do not need to do any of that. Drupal will use the sites/default directory by *default* when it gets to serve a request. Running it off a non-standard port is handled completely by the web server and is a non-issue, as far as Drupal is concerned. So, you might just be making things hard on your self, by not following the multisite instructions correctly (see further).

So, if you're *not* planning on using multisite (and I would like to add, think carefully if you think you do - as Berdir is saying, it can be very limiting and can really only be recommended in very specific circumstances), stop here. Rename your site directory to default (and/or merge it with the standard one); if your requests are not ending up at Drupal, your problems are more likely with your web server.

If you really *do* want multisite, note that the instructions do not tell you to create a 8765.drupal8.myftp.org.php file. You need a 8765.drupal8.myftp.org *directory* (actually, the directory doesn't even need to be called that, you can map it in the sites.php file). Within the directory, you need a settings.php file, which you can base off of settings.default.php in the default directory. To point Drupal to that directory, you need the sites.php file (in the sites/ directory, so not in your site subdirectory). If you named the directory as you did, that's all you need; Drupal should be able to find the site directory based on the naming, provided you are accessing the site with that domain name and that port. If you chose to give the directory a different name (e.g. just `myftp`), you can map the site to the directory:

```
$sites = array(
  '8765.drupal8.myftp.org' => 'myftp',
);

```

Note that to use the Drupal multisite feature (which includes having Drupal use a directory other that sites/default for a particular site), you *do* need the sites.php file, but if you named your directory appropriately, you *don't* need to add the mapping in the $sites array within it; the instructions are actually not very clear, in that regard,

But again, if you do not need multiple sites to be served from the same Drupal directory (and basically I would recommend against that), you don't need to do all that, Drupal will be fine running with the sites/default directory, regardless of the port that's being used by the web server.

---
Tags: 8
---


# Question
Title: How do I set the private file system path's permissions?
There is an option in *Configuration \> File system* which let you define a path for private files. After setting a path in this field, the access for all users is restricted (including admin). I need to give the permission of accessing this directory and its files to some users. How?

# Answer
> 1 votes
Your module has to implement `hook_file_download()`. By default all private files will give access denied.

If your access rules are not complex, you can also use one of contrib modules, ex. Private files download permission

# Answer
> 1 votes
The difference between the Drupal public and private file systems is whether the web server or Drupal handles accessing the files.

* With the public file system, Drupal doesn't do anything for accessing the files. The assumption is that the web server can access these files and they are within the web root of the site. Drupal just generates URLs that allow the web server to serve those files.
* With the private files system, things are different. They are served by Drupal, and Drupal gets to decide if the user has access to those files. In core, this happens when the file is attached to content the user has access to, if I'm not mistaken, but there are other ways to tell Drupal a user should get access to a file. Since Drupal should have full control over file access (through URL paths it serves), this means that the private file system should be in a directory *outside* the web root, as those files are not intended for direct access by the web server (theoretically you could also have the files within the web root and use some other means to restrict access through the web server, like .htaccess, but that's a more fragile solution).

Both directories should be readable and writable by Drupal (whatever user Drupal runs as, which would typically be something like `apache`, `httpd` or `php`, depending on your setup). The public file system should be within the web root, the private file system should really be outside it, if you ask me, but at the very least have some other way configured to not be accessible through the web server from the outside.

---
Tags: users, security, files
---


# Question
Title: Can I change an upload URL to match the original upload?
I uploaded a PDF in Dupal and used the URL created. Somehow, that document wasn’t saved or was deleted, so now that URL (which is being promoted widely) leads to a page not found. I uploaded a new document, but Drupal renames the URL just slightly.

Can I somehow change this URL to match the original upload or redirect somehow? I am not sure which version I use (or where to find this).

# Answer
> 0 votes
There are many ways you can approach this to solve it, but maybe the simplest is to just upload the file with the correct (old) name into the location where Drupal expects it. I don't mean upload through Drupal but through your hosting account into the correct folder.

Another way is to add a Redirect from the old URI to the new one, through Drupal Redirect module or on the server configuration (.htaccess usually).

---
Tags: uri
---


# Question
Title: How do I mock the "file_system" service?
How do I mock the *file\_system* service in PHPUnit?

The issue is being reproduced when `\Drupal::service('file_system')` is executing in the test suite environment. If `\Drupal::service('file_system')` is removed the class loads the assertions in the test class run perfectly. My belief is that this service needs to be mocked. (This could be completely false. I am really unsure).

The terminal error displayed when running the test is the following.

> Drupal\Core\DependencyInjection\ContainerNotInitializedException: \Drupal::$container is not initialized yet. \Drupal::setContainer()

This is the class method that executes the Drupal 8 service.

```
 /**
   * @inheritdoc
   */
  public function setBasePath($path = Null) {

    if ($path !== Null) {
      $this->directories['base'] = $path;
    } else{
     $this->directories['base'] = \Drupal::service('file_system')->realpath(file_default_scheme() . "://");
    }
  }

```

This is the test class that is going to test the above class in the future. Right now it compares a string only.

```
/**
 *
 * @group react_forms
 */
class DirectoryStructureTest extends \Drupal\Tests\UnitTestCase {

  /**
   * @var object
   */
  private $objToTest;

  /**
   *
   */
  public function setUp() {
    $this->objToTest = new DirectoryStructure();
  }

  public function testGetDirectories() {

    $this->assertEquals('this', 'this');
  }

  /**
   * Once test method has finished running, whether it succeeded or failed,
   * tearDown() will be invoked. Unset the unit created object.
   */
  public function tearDown() {
    unset($this->objToTest);
  }
}

```

# Answer
You shouldn't call `file_system` with `\Drupal::service('file_system')` use dependency injection instead:

So try something like the following in your service:

1. Add arguments to your `*.services.yml` file.

```

services:
  yourModule.yourService:
    class: Drupal\yourModule\yourServiceClass
    arguments: ['@file_system']

```
2. Inject the `file_system` service in your Class:

```

  use Drupal\Core\File\FileSystemInterface;

  /**
   * The file system service.
   * @var \Drupal\Core\File\FileSystemInterface
   */
  protected $fileSystem;
  /**
  * Class constructor.
  * @param \Drupal\Core\File\FileSystemInterface $file_system
  */
  public function __construct(FileSystemInterface $file_system) {;
    $this->fileSystem = $file_system;
  }

```
9. Change `setBasePath` method to be like.

```

  /**
   * @inheritdoc
   */
  public function setBasePath($path = Null) {

    if ($path !== Null) {
      $this->directories['base'] = $path;
    } else{
     $this->directories['base'] = $this->fileSystem->realpath(file_default_scheme() . "://");
    }
  }

```
> 2 votes

---
Tags: testing
---


# Question
Title: How do I hide an empty field if my custom field formatter removes all items?
I have a custom field formatter (in Drupal 8) that displays a list of taxonomy terms on a node. Some terms are not meant to be displayed, so the field formatter removes them from the items list.

Occasionally, all items are removed -- yet the HTML elements that wrap the field are still rendered. How do I hide the field completely when all items are removed?

EDIT FOR CLARITY:

I have a field with machine name field\_tags that is an entity reference to multiple taxonomy terms.

To render this field, I wrote a custom formatter as a field formatter plugin in a custom module. The code is stored in the standard location in mymodule/src/Plugin/Field/FieldFormatter/TermListFormatter.php

My class extends EntityReferenceFormatterBase.

In my class, my viewElements() method strips out some items as needed and sometimes returns an empty array if no items should be rendered.

```
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];

    // Loop through each of the terms in this field.
    foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
      $label = $entity->label();

      // ONLY show taxonomy terms that begin with "Test".
      if (mb_substr($label, 0, 5) === 'Test') {
        $options = [
          'query' => [
            'tags' => [$entity->id()],
          ],
        ];

        // Output terms as links to /test?tags[]={tid}
        $elements[$delta] = [
          '#type' => 'link',
          '#title' => $label,
          '#url' => Url::fromRoute('view.test.page_1'),
          '#options' => $options,
        ];

        if (!empty($items[$delta]->_attributes)) {
          $elements[$delta]['#options'] += ['attributes' => []];
          $elements[$delta]['#options']['attributes'] += $items[$delta]->_attributes;
          // Unset field item attributes since they have been included in the
          // formatter output and shouldn't be rendered in the field template.
          unset($items[$delta]->_attributes);
        }

        $elements[$delta]['#cache']['tags'] = $entity->getCacheTags();
      }
    }

    // This will be an empty array if there were no terms beginning with "Test"
    return $elements;
  }

```

When all the terms are stripped out, the field wrapper elements are still output as follows:

```
<span class="views-field views-field-field-tags">
  <span class="field-content"></span>
</span>

```

How do I stop these elements from appearing when there are no terms to show?

# Answer
> 4 votes
Drupal adds the field wrapper only if the result returned by viewElements() contains at least one renderable child.

*FormatterBase::view():*

```
  public function view(FieldItemListInterface $items, $langcode = NULL) {
    ...
    $elements = $this->viewElements($items, $langcode);

    // If there are actual renderable children, use #theme => field, otherwise,
    // let access cacheability metadata pass through for correct bubbling.
    if (Element::children($elements)) {
      $entity = $items->getEntity();
      $entity_type = $entity->getEntityTypeId();
      $field_name = $this->fieldDefinition->getName();
      $info = [
        '#theme' => 'field',
        '#title' => $this->fieldDefinition->getLabel(),
        '#label_display' => $this->label,
        '#view_mode' => $this->viewMode,
        '#language' => $items->getLangcode(),
        '#field_name' => $field_name,
        '#field_type' => $this->fieldDefinition->getType(),
        '#field_translatable' => $this->fieldDefinition->isTranslatable(),
        '#entity_type' => $entity_type,
        '#bundle' => $entity->bundle(),
        '#object' => $entity,
        '#items' => $items,
        '#formatter' => $this->getPluginId(),
        '#is_multiple' => $this->fieldDefinition->getFieldStorageDefinition()->isMultiple(),
      ];

      $elements = array_merge($info, $elements);
    }

    return $elements;
  }

```

This means for the question if the field formatter removes all items the field is hidden.

However, field formatter and field preprocessing handle empty fields differently. If you only remove the first field item it is possible that the condition for an empty field has different results. See How to print all values of a multi-value field, except the first?

---
Tags: 8
---


# Question
Title: How to access a parent paragraph twig file from a child node twig file?
In my bootstrap theme, I am trying to make the id of the paragraph the same as an attribute for each of the child nodes, so an accordion will work properly. I have tried looking at doing it through hooks, but I can't seem to access the paragraph data from my node hook.

# Answer
You can use `hook_preprocess_paragraph` hook to set the same id to all child nodes, in the below code snippet example all child nodes will have `paragraph-PARAGRAPH-ID` as id.

```
use Drupal\Component\Utility\Html;
/**
 * Implements hook_preprocess_HOOK().
 */
function myModule_preprocess_paragraph(&$variables) {
  $paragraph = $variables['paragraph'];
  $identifier = Html::cleanCssIdentifier('paragraph-' . $paragraph->id());
  $variables['attributes']['id'] = $identifier;
}

```
> 0 votes

---
Tags: 8, theming
---


title: Automate views and xml sitemap

text:
# Question
Title: Automate views and xml sitemap
I have a D6 site that uses both a geography taxonomy and a category taxonomy to organize 10s of thousands of nodes. XML sitemap does a great job with automatically listing the individual taxonomy pages (all of geography A or all of category B) and the nodes themselves. But I have views set up that show pages for "Category B in Geography A" such as http://example.com/myview/brooklyn/web\_designers

I know that you can use xmlsitemap\_custom to add these views results one at a time. Is there any way to automate adding the entire cross section of the two taxonomies? I want to add the view for every combination of the two taxonomies to the site map.

# Answer
> 1 votes
## Drupal 6

### Option 1:

1. Enable the 6.x-2.x XML sitemap custom sub-module.
2. Manually add the links to your views at admin/settings/xmlsitemap/custom

### Option 2:

1. Enable the 6.x-2.x XML sitemap menu sub-module.
2. Create a new menu at admin/build/menu/add with the menu name xmlsitemap and title XML sitemap. Make sure that the 'Include this menu in the sitemap.' checkbox is selected.
3. Edit your view's page view, and add the view to the 'XML sitemap' menu under the 'Page settings'.

---

## Drupal 7

1. Modules/XML Sitemap: Check "XML sitemap node" (Adds content links to the sitemap.)
2. Configuration/Search and Metadata/XML sitemap/Settings: Click on the "Content" tab. Go to your View created content, click on it.
3. In the XML sitemap tab, set Inclusion to Included. Save.
4. Back to Configuration/Search and Metadata/XML sitemap/ - click on Rebuild Links. You'll now have all of the Views created pages listed in sitemap.xml

# Answer
> 0 votes
You can implement `hook_xmlsitemap_link_info()`, and insert your links programmatically.

See api for datails.

# Answer
> 0 votes
This is something I have struggled to find an answer for for years - how to get dynamic views to be included in a sitemap and submitted to search engines. I finally found a solution so sharing it here to help others. This is for Drupal 7.

1. forget xml sitemap. It's great for everything else, but it doesn't do this job well. It's ok to have two sitemaps.
2. install views datasource and enable at least views xml
3. create a view that uses xml data document for its format. for settings i have raw xml, root element urlset, top-level child name as url, plaintext output, `<?xml-stylesheet type="text/xsl" href="/sitemap.xsl"?>` as xml document header, content type default and importantly do NOT check views api mode (or it will output within your theme)
4. I have some hidden fields for nid and title to build the url and filters for the content type I want to list. I build the links with this php code:

```
$newurl = 'http://' . $_SERVER['SERVER_NAME'] . '/res/' . $row->nid . '/' . $row->nid . '/' . str_replace(' ', '-', $row->title);
if (isset($newurl)) {
  print $newurl;
}

```

There are other ways to do this but this was the most efficient way for my case. parse\_url may work better for you but for me it was overkill.
5. updated date can be gotten from the content and the other sitemap fields you can just use custom text fields for.
6. in .htaccess, right below where RewriteBase is (whether it's commented out or not), add in a permanent redirect from the content type to the view. Will look something like this: RewriteCond %{REQUEST\_URI} CONTENT\_TYPE\_PATH/(\[0-9\]+)/(.*) RewriteRule ^CONTENT\_TYPE\_PATH/(\[0-9\]+)/(.*)$ http://%{HTTP\_HOST}/VIEW\_PATH/$1/$2? \[L,R=301\] NOTE: with MAMP local install and some shared hosting this doesn't work. You can google for some suggested workarounds - none worked for me for MAMP but I decided I didn't need to worry about this for my local install and it works on my host.
7. make sure xml sitemap module excludes content type, rebuild if needed
8. add templates for sitemap view, use theme suggestions for specific name. I needed to add html, page and views overrides to make sure it only outputs the xml data
9. add http://www.google.com/ping?sitemap=http://MYSITE/MYSITEMAPVIEW etc to custom submission urls in xml sitemap config. Optionally also add to robots.txt and/or submit manually - i did all 3 :) I think that's about it, but if I missed a step let me know and i'll fill in the missing parts.

---
Tags: views, xml-sitemap
---