# Question
Title: How do I create a Twig override for server 500 error?
How do I override the template used for a 500 error?
Is there any way to achieve this from a module?

# Answer
This cannot be done in Drupal as a 500 error is a server error. Drupal will never be reached.

However, if you can configure the server, you can accomplish this yourself. This may also work from the .htaccess level in Drupal. I suggest trying it at the server level first if you can.

If you are running Apache, you can use custom ErrorDocument directives.

If you are running Nginx, see How To Configure Nginx to Use Custom Error Pages on Ubuntu 14.04.
> 4 votes

---
Tags: theming, 8
---


title: Is having a routing.yml file necessary?

text:
# Question
Title: Is having a routing.yml file necessary?
I'm new to Drupal 8, and was curious why some modules have a \*-routing.yml file, while others don't.

Why is this the case? Does this mean that modules lacking in a \*-routing.yml file don't have any routing URLs?

# Answer
`*.routing.yml` is used to define custom endpoints and their receiving controllers. It's the config version for `hook_menu` in D8. If the module does not introduce custom paths, then it will not need one.
> 4 votes

---
Tags: 8, routes
---


# Question
Title: How to apply a style to a specific page?
I want to apply different stype on the pages of my site.

The following code applies a hard background to all product pages :

```
body.path-product {
    background-image: url("/themes/contrib/bootstrap_subtheme_front_office/images/background-page.svg");
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center center;
    background-attachment: fixed;
}

```

I want a different style to be applied for the product/add/produit path.

How to do this ?

Screenshot :

enter image description here

In my theme I created a file "html--product--add.html.twig" and I pasted in the contents of "html.html.twig".

```
{#
/**
 * @file
 * Default theme implementation to display the basic html structure of a single
 * Drupal page.
 *
 * Variables:
 * - $css: An array of CSS files for the current page.
 * - $language: (object) The language the site is being displayed in.
 *   $language->language contains its textual representation.
 *   $language->dir contains the language direction. It will either be 'ltr' or
 *   'rtl'.
 * - $rdf_namespaces: All the RDF namespace prefixes used in the HTML document.
 * - $grddl_profile: A GRDDL profile allowing agents to extract the RDF data.
 * - $head_title: A modified version of the page title, for use in the TITLE
 *   tag.
 * - $head_title_array: (array) An associative array containing the string parts
 *   that were used to generate the $head_title variable, already prepared to be
 *   output as TITLE tag. The key/value pairs may contain one or more of the
 *   following, depending on conditions:
 *   - title: The title of the current page, if any.
 *   - name: The name of the site.
 *   - slogan: The slogan of the site, if any, and if there is no title.
 * - $head: Markup for the HEAD section (including meta tags, keyword tags, and
 *   so on).
 * - $styles: Style tags necessary to import all CSS files for the page.
 * - $scripts: Script tags necessary to load the JavaScript files and settings
 *   for the page.
 * - $page_top: Initial markup from any modules that have altered the
 *   page. This variable should always be output first, before all other dynamic
 *   content.
 * - $page: The rendered page content.
 * - $page_bottom: Final closing markup from any modules that have altered the
 *   page. This variable should always be output last, after all other dynamic
 *   content.
 * - $classes String of classes that can be used to style contextually through
 *   CSS.
 *
 * @ingroup templates
 *
 * @see bootstrap_preprocess_html()
 * @see template_preprocess()
 * @see template_preprocess_html()
 * @see template_process()
 */
#}
{%
  set body_classes = [
    logged_in ? 'user-logged-in',
    not root_path ? 'path-frontpage' : 'path-' ~ root_path|clean_class,
    node_type ? 'page-node-type-' ~ node_type|clean_class,
    db_offline ? 'db-offline',
    theme.settings.navbar_position ? 'navbar-is-' ~ theme.settings.navbar_position,
    theme.has_glyphicons ? 'has-glyphicons',
  ]
%}
<!DOCTYPE html>
<html {{ html_attributes }}>
  <head>
    <head-placeholder token="{{ placeholder_token|raw }}">
    <title>{{ head_title|safe_join(' | ') }}</title>
    <css-placeholder token="{{ placeholder_token|raw }}">
    <js-placeholder token="{{ placeholder_token|raw }}">
  </head>
  <body{{ attributes.addClass(body_classes) }}>
    <a href="#main-content" class="visually-hidden focusable skip-link">
      {{ 'Skip to main content'|t }}
    </a>
    {{ page_top }}
    {{ page }}
    {{ page_bottom }}
    <js-bottom-placeholder token="{{ placeholder_token|raw }}">
  </body>
</html>

```

How to put the class "body.path-product-add" in this file ?

# Answer
> 1 votes
I guess you want to apply that class to the body tag. If that's true then you just need to append body\_classes array and put your class in the end.

```
set body_classes = [
  logged_in ? 'user-logged-in',
  not root_path ? 'path-frontpage' : 'path-' ~ root_path|clean_class,
  node_type ? 'page-node-type-' ~ node_type|clean_class,
  db_offline ? 'db-offline',
  theme.settings.navbar_position ? 'navbar-is-' ~ theme.settings.navbar_position,
  theme.has_glyphicons ? 'has-glyphicons',
  'path-product-add',
]

```

And then clear cache of your website.

---
Tags: theming, 8
---


# Question
Title: How to know user submitted first content of a specific type?
I used Rules module to know when a user has logged in and notify the user about his/her login event.

Now I just want to check when the user has submitted a content of one specific type for the first time, so I just can understand when the user has submitted his/her first content of a speccific content type!

How can I modify my rule in Rules to implement this?

# Answer
While given answer works great, there are usually a variety of different methods to achieve your goals, one solution could be usage of a combination of Views and Views Bulk Operations (VBO) modules to achieve that

* Create a view containing nodes of your desired type
* Add a contextual filter and limits results to nodes written by logged in user
* add a VBO view mode
* in rules you can load a VBO items (check how)
* Now if array is empty, created node is the first node of that type which the user has submitted

You also might do all the job with Rules, if you don't want this feature for many content types you can add a Boolean field to the user's account with default value of '**False**' indicating if user has written his/her first content of desired type, then on node submit event you can check this field to recognize if this post is his/her first post of that type or not. Remember to set this field to **True** after submission of first content of desired type.

> The above approach saves some processing cause needs no query as it calculated once and used many times

You also can write a custom rules event (API), containing a query on nodes table with condition `node.uid == user->uid` and `node.type == "TYPE_MACHINE_NAME"`, then if query is not empty, that means user has already submitted a content of that type. so return **False**.
> 4 votes

# Answer
Another solution, which does not require ANY additional modules, is to create a dedicated role, let's call that role "**Contributor**" (use whatever role fits).

Then create a rather basic rule like so:

* Rules Event: After saving new content.
* Rules Conditions (both must be satisfied):
    + The submitted content has a type that matches your specific type.
    + The current user does NOT yet have role "**Contributor**".
* Rules Action = Assign the "**Contributor**" role to the author of the node.

With the above in place, improve your existing rule to check if ... you guessed it ... the user has role "**Contributor**".
> 4 votes

# Answer
Use the Flag module to flag a user when they first submitted content that fits your requirements. To flag such user create a rather basic rule like so:

* Rules Event: After saving new content.
* Rules Condition: Whatever fits (if any).
* Rules Action = Flag the user.

With the above in place, improve your existing rule to check if the user is flagged.
> 3 votes

---
Tags: 7, nodes, users, rules
---


# Question
Title: Is there a way to edit/write templates from the user interface?
One of the UI/UX issues with Drupal is that theme templates are not editable from within the interface. Even for devs who know what they are doing this is awkward time consuming distraction needing FTP and other software outside of Drupal to create/remaster themes or put in a little logic . While knowing that the ability to edit tpl.php templates from the UI can potentially create security issues, still it seems to me that showing the template code and ability to re-write templates within the interface is lacking in Drupal 7.

Css can be writen to files (from themes and modules ie administratiom theme and css editor) so why not templates?

Can it be done?

# Answer
> 1 votes
As far as I know, the best you could do in Drupal from the admin side is alter the layout using Display Suite, Panels, and to some extent, Field Groups (Bootstrap Field Group can come in handy). Advanced functionality will still require code access (i.e. adding custom layouts and layout CSS). That's usually what you end up doing with templates most of the time, just moving things around.

It's rare that you edit the widgets and field outputs (you write formatters for those, which then can be changed via admin once installed). Also, editing widgets using templates instead of formatters is a maintenance nightmare and full of surprises.

> Even for devs who know what they are doing

Devs who know what they're doing store changes in version control, and therefore code. ;)

---
Tags: 7
---


title: Adding a new dependency to a module

text:
# Question
Title: Adding a new dependency to a module
As a module maintainer, I want to add a dependency to one of my existing modules, so that my entity can use a field type plugin declared by the dependency.

What steps do I need to take to make sure that:

1. `entup` doesn't WSOD because my new field depends on a non-existent module.
2. Drupal end-users get prompted to download and install the new dependency.

I did find another similar issue -- What is the protocol for adding a new module dependency to a module that has only had a dev release? -- which deals with Drupal 7. This will help address question #2, but doesn't speak to the added complexity of `entup`.

I also found an issue dealing with deployments via drush -- Enable new modules dependencies on deploy -- but this doesn't address my questions either.

Any other tips or advice?

# Answer
> 2 votes
> @Ivan Jaros is correct.

a) use dependency in your module info file, b) implement hook\_requirements, c) activate the field only if the other module exists(ie. soft dependency).

> @Kevin, *after* you've enabled the module

Use a) and c) above.

> 2. Drupal end-users get prompted to download and install the new dependency.

In c) you need to set a message to the user explaining why the field is unavailable and where to get the dependency. Use function drupal\_set\_message.

Links:

D8: module exits, https://www.drupal.org/node/1894902 , see \Drupal::moduleHandler()-\>moduleExists($module)

D8: set message, https://api.drupal.org/api/drupal/core%21includes%21bootstrap.inc/function/drupal\_set\_message/8.4.x

---
Tags: 8, entities, updating
---


# Question
Title: Drupal 8 - Variables - Template Twig - Cache
In the HOOK of my project XXX\_preprocess I am defining a variable based on a cookie.

My Hook function

```
function XXXXXX_preprocess(array &$variables) {
if (isset($_COOKIE[personsSearchCookie]) && !empty($_COOKIE[personsSearchCookie])) {
    $personsFilter = explode("-", $_COOKIE[personsSearchCookie]);
    $variables["personsFilter"] = array (
        "filterType" => $personsFilter[0],
        "filterId" => $personsFilter[1]
    );
}

```

But in the Twig template, it always gives me the initial value of that variable, it never changes. My Twig code:

```
Filtering results by [{{ personsFilter.filterType }}]<br />

{% if personsFilter is defined and personsFilter.filterType is defined and personsFilter.filterType is not empty %}
    {% if personsFilter.filterType == "area" %}
        Filtering by Area <br />
    {% endif %}

    {% if personsFilter.filterType == "office" %}
        Filtering by Office <br />
    {% endif %}
{% else %}
    No filtering
{% endif %}

```

This should be a cache theme, right?

How can I make so that when my cookie changes, the variable is modified and since twig can access the new value?

In the prepreocess function in all re-loads, the variable change correctly, but, in twig, the variable have bad value.

Thank you!

# Answer
> 3 votes
In your question, it wasn't clear how you are defining the render array (a block, a form, etc.) Assuming you are rendering this twig file through a render array, you could add the following to the render array for this particular element to turn off caching of this element:

```
 '#cache' => [
    'max-age' => 0,
  ],

```

You could get more specific by implementing conditional logic to clear the cache on a certain condition. From the `examples` module, in the cache\_example, we have the CacheExampleForm function createExpiringItem():

```
/**
* Submit handler to create a new cache item with specified expiration.
*/
public function createExpiringItem($form, &$form_state) {

$tags = array(
  'cache_example:1',
);

$interval = $form_state->getValue('expiration');
if ($interval == 'never_remove') {
  $expiration = CacheBackendInterface::CACHE_PERMANENT;
  $expiration_friendly = $this->t('Never expires');
}
else {
  $expiration = time() + $interval;
  $expiration_friendly = format_date($expiration);
}
// Set the expiration to the actual Unix timestamp of the end of the
// required interval. Also add a tag to it to be able to clear caches more
// precise.
$this->cacheBackend->set('cache_example_expiring_item', $expiration_friendly, $expiration, $tags);
drupal_set_message($this->t('cache_example_expiring_item was set to expire at %time', array('%time' => $expiration_friendly)));
}

```

And, also shown in the examples is invalidating:

```
$tags = array(
  'cache_example:1',
);
Cache::invalidateTags($tags);

```

So in your preprocess, you could use this type of logic to invalidate the cache. Hope this helps.

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


# Question
Title: How to nest Rules, call a rule from another rule and how to choose between 2 Rules Actions?
Is there a way to nest Rules, or make them behave more like an `if / then / else` functionality.

Currently I can only figure out how to trigger a Rules Action based on a Rules Condition, but not how to choose between 2 Rules Actions.

In addition, is there a way to call one rule from another?

# Answer
Your question consists of multiple questions, so my answer also consists of multiple parts ...

### Part 1

To implement conditional logic in Rules, your very first attempt should be to only use Rules Conditions, and try to use the `AND` and `OR` operators to combine multiple Rules Conditions. If no such operator is specified, then the default is that ALL Rules Conditions must be true for the Rules Actions to be executed (this is equivalent to using the `AND` operator).

For way more details about this, refer to my answer to "What's the difference between combining Rules conditions with AND and just have them follow one after the other?".

Attention, even though using these `AND` and `OR` operators may seem obvious, it is NOT! For an example of how confusing it can be, refer to the video tutorial about "Combining conditions".

### Part 2

> Currently I can only figure out how to trigger a Rules Action based on a Rules Condition, but not how to choose between 2 Rules Actions.

You're right, to "*choose between Rules Actions*" is like performing Rules Conditions within Rules Actions, which you cannot do with only the Rules module. However, the Conditional Rules module allows you to exactly do that (execute Rules Conditions as part of Rules Actions).

My favorite example to illustrate this can be found in my answer to "How to check whether one's current User Points are negative with the Rules module?", which includes a rule that looks like so:

```
{ "rules_display_userpoints_after_updating_content" : {
    "LABEL" : "Display userpoints after updating content",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "userpoints_rules", "rules", "rules_conditional" ],
    "ON" : { "node_update" : [] },
    "DO" : [
      { "userpoints_rules_get_current_points" : {
          "USING" : { "user" : [ "site:current-user" ], "tid" : "all" },
          "PROVIDE" : { "loaded_points" : { "total_points" : "Number of points in all categories together" } }
        }
      },
      { "drupal_message" : { "message" : "You now have [total-points:value] points" } },
      { "CONDITIONAL" : [
          {
            "IF" : { "NOT data_is" : { "data" : [ "total-points" ], "op" : "\u003C", "value" : "20" } },
            "DO" : [
              { "drupal_message" : { "message" : "You have sufficient points (you still have [total-points:value] ...)." } }
            ]
          },
          { "ELSE" : [
              { "drupal_message" : { "message" : "You DO NOT have sufficient points (you only have [total-points:value] ...)." } }
            ]
          }
        ]
      }
    ]
  }
}

```

This rule retrieves, as the very first Rules Action (not Rules Condition!), the current amount of user points of a user. And after the Rules Action to display some message, you can see the Conditional Rules module at work (starting from `CONDITIONAL`): it will show a message that depends on the total amount of points.

For another example using the Rules Conditional module (for which there is not a lot of docu available), refer to my answer to the question "How to prevent a node being saved when using the Rules module?".

Bonus: Instead of using ***`if/else`*** (conditional) logic within the Rules Action, you can also use ***`Switch`*** logic. For another example using such *Switch* logic, refer to rule included in my answer to "How to set the values of some fields depending on the value of a list box?".

Be aware: the Conditional Rules module only has a beta release for D7, though it's used in over 8K sites (which makes it seem like a pretty robust module though).

As an alternative to using the Conditional Rules module, you can also create corresponding Rules Components, with similar Rules Actions to be performed, but also with additional Rules Conditions equivalent to any Rules Conditions you'd want to include by using the Conditional Rules module. And then perform that Rules Component inside your Rules Actions of your original rule. For more details on that, refer to the answer to "What's the alternative to using the Conditional Rules module?"

### Part 3

> In addition, is there a way to call one rule from another?

That's what **Rules Components** is all about, which you can do for:

* only Rules Conditions, using a Rules Component of plugin type "Condition set".
* only Rules Actions, using a Rules Component of plugin type "Action set".
* both Rules Conditions and Rules Actions, using a Rules Component of plugin type "Rule".

Rules Components may use *variables*, whereas there are 2 variations of them:

* **Parameters** which are used as ***input*** that the Rules Component needs in order to execute.
* **Provided** which are ***output*** (instead of input), and which can be used (after the execution of the Rules Component completed) in the rule that calls the Rules Component.

For more details about this, refer to:

PS: I'm assuming this question is about D7.
> 3 votes

---
Tags: rules
---


title: How to securise custom modules

text:
# Question
Title: How to securise custom modules
I'm trying to understand how to securise my custom modules to avoid php insert into custom inputs and SQL injections in my db\_query.

For inputs I'm using :

```
$form['custom'] = array(
      '#type' => 'textfield',
      '#title' => t('Custom),
      '#description' => t('Custom'),
      '#default_value' => '',
)

```

I tried to insert some PHP in the input and it actually run it whereas in the documentation it saiys that using form API should escape PHP by using check\_plain and the safe example given is :

```
$form['also_safe'] = array(
  '#type' => 'select',
  '#default_value' => 0, // FAPI will pass through check_plain(),
  '#options' => node_get_types('names'),  // FAPI will sanitize the '#options' attribute with check_plain() for select boxes.
);

```

So what am I doing wrong ?

Concerning my SQL query I can't succeed to use as documented :

```
$result = db_query('SELECT $ FROM {custom} WHERE uid= :uid", array(':uid' => $value['in_array'])).

```

When calling a non object value I just get an error, so doing something like that works well but doesn't escape SQL injection :

```
$to_user_balance = db_query("SELECT * FROM {ubercart_funds_user_funds} WHERE uid=" . $value['in_array']));

```

I have to precise that I'm actually learning PHP and still didn't get what objects are. Because my aim is result and not capability, if somebody can explain me quickly how to securise my queries and inputs or drive me to a clear documentation.

I already know those documentation page and didn't help :

# Answer
> 2 votes
It's a better idea to use `db_select` or other DB API functions, rather than trying to use `db_query` directly. You'd want to try something like:

```
 $to_user_balance = db_select('ubercart_funds_user_funds', 'ucfuf')
   ->fields('ucfuf')
   ->condition("uid", $value['in_array'], '=')
   ->execute()
   ->fetchAssoc();

```

For more, see https://api.drupal.org/api/drupal/includes%21database%21database.inc/function/db\_select/7.x

And for overall DB API docs, see: Drupal.org DB API docs

---
Tags: 7, forms, database, security, input-formats
---


title: Entities, bundles and fields

text:
# Question
Title: Entities, bundles and fields
I've created entities and bundles through Entity Construction Kit UI, and now I'm trying to re-create everything with code, in a module. I managed to generate entity with Drupal console, added fields, and everything works well.

The problem is when I try to create bundles for an entity, with different fields. In ECK, I can create an entity, then bundles, and add different fields to each bundle. However, I can't understand how to do it in the code, and after reading tons of documentation, it feels like bundles are only configuration entities and can't have fields.

So my questions are :

* Is there something I don't understand ?
* How can I mimic ECK "bundles with fields" in code ? My goal is to create profiles, like the profile module can do for users, but referenced from an other entity, and with specific behavior, so I'd prefer create my own entities.

# Answer
Yes, the bundle entities themself are not fieldable.

But bundle config entities in the end only exist to manage bundles for the content entity type, and as far as content entities are concerned, bundles are basically just a string (and a bit of metadata like a title). It's even possible to have bundles based on plugins or other things.

Per-bundle fields (usually configurable fields defined only in config, but it would be possible to define them in code as well, currently not trivial) are then attached to a content entity type + specific bundle. Fields actually consist of two definitions: field storage, which is tied to the entity type and defines name and storage-level settings, and the field, which is for a bundle and has bundle-level settings, label and so on. Base field definitions defined in the baseFieldDefinitions() method are exposed as both the field storage and field definition.

Haven't yet read it in detail, but http://www.daggerhart.com/drupal-8-custom-entities-bundles/ is a recent (as in, ~1h old) extensive resource on how to build entity types with bundles.
> 4 votes

---
Tags: 8, entities
---


# Question
Title: "Future Post" is appearing next to blog posts
How to disable the words "Future post" appearing in Italics next to blog titles? Blog posts scheduled for future time are showing up "Future post" text....I am having a hard time figuring how to get rid of this text. Any help or suggestions are highly appreciated.

# Answer
I can't see the source code of course, but based on the text differences I'm assuming you could CSS to change the display or visibility of that particular text, or if that's not an option as it hides needed text in blog posts elsewhere, you could make a custom template file for that content type and adjust it accordingly from there.
> 0 votes

---
Tags: nodes
---


# Question
Title: How can I upgrade ONLY Drupal core with composer?
I knew that Drush make files were being phased out, but I kept using them, because in my opinion Composer isn't the best package manager in the known universe. It updates too much or too little, has uninformative error messages, and takes a lot more ram than necessary. Don't get me wrong, I still used composer, but not for Drupal core updates, because those are more important and sometimes security releases.

But, in 8.4, Drush 9 is required, and in Drush 9 make files don't work at all.

My concern is this: I have some wildcards in my composer.json similar to the ones mentioned in this issue: https://www.drupal.org/node/2609568 which tell composer where to find my modules' composer.json files. Yet, when I run

```
composer update drupal/core --with-dependencies

```

Whether or not I run it --with-dependencies, it will always go into the merge-plugin include paths and update all of those packages as well. Now, if my site is out in production, I would like an easy way to update core and core's vendor files WITHOUT updating a bunch of contrib modules' libraries which I do not care about. What if core releases a security update? I want to be able to conveniently update core and *only* core quickly. With Drush make, this was simple.

Has anyone figured out a way to do this with composer?

# Answer
> 4 votes
I do two things.

1. I use `webflo/drupal-core-strict` in my `composer.json` to make sure the same tested core dependencies are the ones used in my project.
2. I pin both `drupal/core` and `webflo/drupal-core-strict` to an exact Drupal version so I can regression test and know exactly what I am deploying.

So, my projects looks like

```
"require": {
    "drupal/core": "8.3.6",
    "webflo/drupal-core-strict": "8.3.6",
    "composer/installers": "^1.2",
    "drupal-composer/drupal-scaffold": "^2.2",
    "cweagans/composer-patches": "~1.0",
    "drush/drush": "~8.0",
    "drupal/console": "~1.0",
},

```

And where there is a new core version, I `composer update drupal/core webflo/drupal-core-strict` and then double check the lockfile.

---
Tags: 8, updating, composer
---


# Question
Title: Can I create a url alias for private files?
Should we be able to add a url\_alias (in D8 from /admin/config/search/path) for a private file?
Right now it allows me to add an alias (and I can see that it is being rendered in the front end) but it generates a 404.

In my particular case the path for the uploaded file is ... /system/files/2017-08/1.pdf

A related, but different question, includes ...

# Answer
> 2 votes
Interesting question.

In theory, every routed path should be able to have an alias because it runs through \Drupal\Core\PathProcessor\PathProcessorAlias::processInbound() before routing, which converts it back to the system path.

However, private files, and image styles are special and quite weird. Because the routing system does not really support having an argument with / and doesn't know how to properly map that to a single argument (Not sure if that is still true or if there would be a better way now with more recent symfony versions), we have a workaround.

That workaround for private files is \Drupal\system\PathProcessor\PathProcessorFiles::processInbound(), which converts the full private path to just "/system/files" with file as a query argument.

The problem is now that those two run on the same event, and PathProcessorFiles runs first, at that point, the path is still the alias and does not match system/files/$something.

I'd say this is a bug and the priority of the service definitions should be adjusted for this. That is path\_processor.files (currently 200) and path\_processor\_alias ( currently 100). Setting the first to 99 and clearing caches makes it work for me.

I'd suggest you open a core issue for this, I suspect nobody tried this yet.

---
Tags: 8, path-aliases, files
---


# Question
Title: Custom install profile fails at creating folders
I have a relatively simple custom installation profile for Drupal 8.
All it does is:

* Ask for the sites domain name and the name of the theme it should scaffold.
    + Use the domain name to create the proper multi-site folder in `/sites/<domain-name>`
    + Use the theme name to create a theme folder under the multisite folder: `/sites/<domain-name>/themes/custom/<theme-name>`
    + Copy the relevant example files to the domain and theme folder, from the default site.

The problem I'm having is that it fails at creating the folders, due to it not being permitted to create the folders. The `/sites` is set to permission 0755, and the problem is only fixed if I set sites to have permission 0777.

The folders are created using PHP's `mkdir()` function, as is set to create the folders recursively.

**Questions:**

1. Is there a better way to make folders during installation, than using php's `mkdir()`, that would fix my permission issue?
2. My assumption would be that the script (drupals installation UI) is being run as a different user than the one who owns the folder/filers of the site (installed via cli git and composer). How to I check which user the script is being run under? (using apache2 on centos7, in case it is relevant)

# Answer
> 0 votes
You've setup the Drupal code from the command line and now run the install from UI? Then this is normal if you have different users for the command line and the webserver, which is recommended. Only cheap hosters use one user for both. Drupal is supposed to have write access only for the `sites/*/files` folder and temporarily for `settings.php` during installation.

So you need to run this from the command line. Build the folders in a script or install the profile with a console command, which probably works without that you need to change anything in code.

Btw. this is why installing Drupal from the command line is so efficient, you get the permissions right from the start.

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


title: Link to send message is not displayed

text:
# Question
Title: Link to send message is not displayed
I am trying to get Privatemsg and DrupalGap working together.

I have installed both modules, configured the privileges and everything is working fine in the drupal site.

But with phonegap I am getting trouble displaying the 'Send this user a private message' link in the view of each user. I have set 'visible' the 'private msg' field in the drupalgap display in: admin/config/people/accounts/display/drupalgap but it's not working.

I have noticed It's always displaying only the history field even if I set to 'hidden' all the fields in the view configuration page: admin/config/people/accounts/display/drupalgap

I have cleared all caches.

What am I missing? How can I have the 'Send this user a private message' link displayed?

# Answer
DrupalGap's implementation of Private Message has not evolved enough to take into consideration any Private Message configuration set on a **DrupalGap** `Manage Display` page for User Entities.

That being said, I would recommend creating your own page to custom render a User Entity. With these docs, essentially replace the usage of `node` with `user` and that'll give you a custom page in which you can render your users.

Then in your `page_callback` function to render the users, you can add a widget to the `content` render array, which could display a button that when clicked will navigate the user to a custom DrupalGap form+page where you can build the input elements (recipient, subject, message, etc).

Then in your form's submit handler, you'll actually send the message to the user.
> 1 votes

---
Tags: 7, privatemsg, javascript
---


# Question
Title: How to prevent SubFormState storage leaking into parent?
I have ajaxified form where I add or remove plugins. If plugin is present it provides its configuration form.

I am using the SubFormState, as one should, but I have noticed that if plugin sets data into the form state's storage(ie. it also uses ajax), they will leak into the parent form state.

Beside key collision(high probabilty with multiple plugins) the main issue I am facing is that once I remove a plugin but add it again, the data from previous configuration is still present in the form state storage so I end up with already configured plugin form, which is highly undesired.

This is happening because the plugin has no way of knowing it has been removed from the parent form so there is no way to unset the data from storage and the parent form has no way of knowing the plugin(s) put something into the storage as well, so there is no garbage collecting possible.

I am wondering if I should Implement a plugin interface that would have "flushState" method that I would have to invoke when I would remove the plugin from the form or there's a better way to do this?

# Answer
> 1 votes
So far, I have solved it by using #array\_parents for getting/setting values into form state storage in plugin forms since there cannot be a key collision in parent form this way.

Small issue with this is that I have to provide the whole parents in there. So if the plugin form is not flat, I have to add all those additional parents in there since they will appear in the ...

... additionally to this in ajax plugin form submit handlers and ajax callbacks I have to get the the "root" element(ie. the form element for the plugin) by detecting #array\_parents on the trigger and extracting the proper form element by #array\_parents and extracting the #array\_parents from it to get to the data in the storage.

Overall it is a massiv DX fail. I have a \***load of plugins and to bulletproof them this way will take a lot of unnecessary time now.

I was thinking about extending the SubformState as KeyedSubformState where the state would "hide" the plugin's storage under provided key so the parent form would control this and be responsible for avoiding key collision and the plugin form doesn't have to be altered in any way(since values are already taken care of) but I have decided not to do it this way since it feels like adding additional layer is not a good idea in the long run...also it won' work for ajax submit handlers since they receive the full form and state and not the subform element and state.

If anyone has a better solution, I'm all ears. But for now it seems plugins are treated like homeles people :D

---

Also, for the love of god, do not use #parents in plugin form. Or you'll be leaking values into the parent form. Overall, just make the plugin form as dumb as possible. Flat and no ajax, just to be safe.

---

This is, currently working, plugin with ajax.

```
/**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $ajax = [
      'wrapper' => Html::getId($this->getPluginId() . '-countries-ajax-wrapper'),
      'callback' => [get_called_class(), 'ajaxRebuildCountries'],
      'progress' => [
        'type' => 'throbber'
      ]
    ];

    $form['allowed_countries'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Allowed countries'),
      '#prefix' => '<div id="' . $ajax['wrapper'] . '">',
      '#suffix' => '</div>'
    ];

    $country_list = $this->countryManager->getList();

    // @see https://drupal.stackexchange.com/questions/243812
    // @see https://www.drupal.org/node/2902121
    $state = $form['#array_parents'];
    $state[] = 'allowed_countries';
    $state[] = 'countries';

    if ($form_state->has($state) === FALSE) {
      $form_state->set($state, $this->getSetting('countries'));
    }
    $countries = $form_state->get($state);

    $form['allowed_countries']['countries'] = [
      '#type' => 'table',
      '#default_value' => [],
      '#empty' => $this->t('No countries have been added yet.')
    ];

    foreach ($countries AS $iso => $level_1) {
      $row = [];

      $row['iso'] = [
        '#markup' => $iso
      ];

      $row['label'] = [
        '#markup' => $country_list[$iso]
      ];

      $row['level_1'] = [
        '#type' => 'value',
        '#value' => []
      ];

      if ($level_1_list = Address::hasLevel1($iso)) {
        $row['level_1'] = [
          '#type' => 'select',
          '#title' => Address::getLevel1Label($iso),
          '#options' => $level_1_list,
          '#default_value' => $level_1,
          '#multiple' => TRUE
        ];
      }

      $row['delete'] = [
        '#type' => 'submit',
        '#value' => $this->t('Delete'),
        '#submit' => [[get_called_class(), 'deleteCountrySubmit']],
        '#name' => 'delete_country_' . $iso,
        '#ajax' => $ajax
      ];

      $form['allowed_countries']['countries'][$iso] = $row;
    }

    $form['allowed_countries']['add_country'] = [
      'country' => [
        '#type' => 'select',
        '#title' => $this->t('Add country'),
        '#options' => array_diff_key($country_list, $countries),
        '#ajax' => $ajax + ['trigger_as' => ['name' => 'add_country_submit']],
        '#empty_value' => '',
        '#empty_option' => t('- Select -')
      ],
      'submit' => [
        '#type' => 'submit',
        '#value' => $this->t('Add country'),
        '#submit' => [[get_called_class(), 'addCountrySubmit']],
        '#name' => 'add_country_submit',
        '#ajax' => $ajax,
        '#attributes' => [
          'class' => ['js-hide']
        ]
      ]
    ];

    return $form;
  }

  /**
   * Form submit handler for attaching a new allowed country.
   *
   * @param array $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   */
  public static function addCountrySubmit(array $form, FormStateInterface $form_state) {
    $element = static::getFormElement($form, $form_state);

    // @see https://drupal.stackexchange.com/questions/243812
    // @see https://www.drupal.org/node/2902121
    $get_country = array_merge($element['#parents'], ['add_country', 'country']);
    $get_countries = array_merge($element['#parents'], ['countries']);
    $set_state = array_merge($element['#array_parents'], ['countries']);

    $country = $form_state->getValue($get_country);
    $countries = $form_state->getValue($get_countries);
    $countries[$country] = [];

    ksort($countries);

    $form_state->set($set_state, $countries);

    $form_state->setRebuild();
  }

  /**
   * Form submit handler for removing allowed country.
   *
   * @param array $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   */
  public static function deleteCountrySubmit(array $form, FormStateInterface $form_state) {
    $element = static::getFormElement($form, $form_state);

    $country = substr($form_state->getTriggeringElement()['#name'], strlen('delete_country_'));

    // @see https://drupal.stackexchange.com/questions/243812
    // @see https://www.drupal.org/node/2902121
    $get_countries = array_merge($element['#parents'], ['countries']);
    $set_state = array_merge($element['#array_parents'], ['countries']);

    $countries = $form_state->getValue($get_countries);
    unset($countries[$country]);

    ksort($countries);

    $form_state->set($set_state, $countries);

    $form_state->setRebuild();
  }

  /**
   * Ajax callback for rebuilding the allowed countries form elements.
   *
   * @param array $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *
   * @return mixed
   */
  public static function ajaxRebuildCountries(array $form, FormStateInterface $form_state) {
    return static::getFormElement($form, $form_state);
  }

  /**
   * Helper method to retrieve the form element containing the plugin
   * configuration "form" from the parent form for ajax calls since
   * there is no SubformState involved and we are getting the whole
   * parent form.
   *
   * @param array $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *
   * @return mixed
   */
  public static function getFormElement(array $form, FormStateInterface $form_state) {
    $trigger_parents = $form_state->getTriggeringElement()['#array_parents'];
    $key = array_search('allowed_countries', $trigger_parents);
    return NestedArray::getValue($form, array_slice($trigger_parents, 0, $key + 1));
  }

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

    // Fix Level 1 administrative area.
    $values = array_map(function($value) {
      if (is_array($value) && isset($value['level_1'])) {
        return $value['level_1'];
      }
      return $value;
    }, $values);

    $form_state->setValues(['countries' => $values]);
    parent::submitConfigurationForm($form, $form_state);
  }

```

---
Tags: 8, forms
---


# Question
Title: how to redirect user login from other server?
The user login is from the other drupal site using cas(Central Authentication Service). Then it will lead to my main site and an authenticated user can view the contents. The main site is used Drupalgap to redesign the interface for mobile.

Now, when using the web browser, it works fine to login and start to view the contents. However, I don't know how to do it for Drupalgap. I saw some apps can login with the account from other sites, once the login is successful, it will redirect and come back to the app.

Does anybody know how to do it?

My attempt is trying to use the login url from the other site.

`bl('Login', 'www.example.com/cas', { InAppBrowser:true });`

This will open a new web browser, not inside my app page. When successfully login, there's a link to go back to my main site. These are operating through the new web browser, not inside my original app.

# Answer
> 1 votes
On the Drupal side, create a custom module to implement `hook_form_alter()` and use it to attach a custom `#submit` handler to the `user_login_form`. In the custom submit handler, you can redirect the user to the headless DrupalGap web app:

```
/**
 * Implements hook_form_alter().
 */
function example_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'user_login_form' && arg(0) == 'drupalgap') {
    $form['#submit'][] = 'example_user_login_form_submit';
  }
}

function example_user_login_form_submit($form, &$form_state) {
  $uid = 123; // This id will be somewhere in the $form or $form_state object.
  drupal_goto('https://example.com/#user_' . $uid);
}

```

Replace `drupalgap` with your service endpoint path, but by default it is `drupalgap`.

---
Tags: javascript
---


# Question
Title: Drupal 8: SQL Insert with 10.000 datasets exceeds 300 MB PHP memory via batch_set()
I have tried to use Drupal's batch\_set() function to execute a SQL insert with 10.000 items. It exceeds 300 MB of PHP memory. 512 MB of PHP memory are getting the job done. This is the case, if I use the batch\_set() function and if I do not. There is currently no benefit in my use-case, either I use batch\_set() or I am not using it. I expect from batch\_set() to keep the PHP memory consumption low.

Here is what I am doing. After an user updates the user account, I am updating all nodes for internal purpose. This service method's code is being triggered:

```

$batch = array(
  'title' => 'Rebuilding user permissions',
  'init_message' => 'Start rebuilding user permissions.',
  'progress_message' => 'Completed @current step of @total.',
  'error_message' => 'Rebuilding user permissions has encountered an error.',
  'operations' => array(
    array(
      [get_class($this), 'updateGrants'],
      [$grantsByNid]
    ),
  ),
);
batch_set($batch);

```

The **$grantsByNid** contains around 10.000 items. The method which is triggered via the batch, is this:

`/**
 * @param array $grantsByNid
 */
 public static function updateGrants($grantsByNid) {
 $query = \Drupal::service('database')->insert('node_access');
 $query->fields(
 ['nid', 'langcode', 'fallback', 'gid', 'realm', 'grant_view', 'grant_update', 'grant_delete']
 );
 foreach ($grantsByNid as $nid => $grants) {
 foreach ($grants as $grant) {
 $query->values([$nid, $grant->langcode, 1, $grant->gid, $grant->realm, $grant->grant_view, $grant->grant_update, $grant->grant_delete]);
 }
 }
 $query->execute();
 }`

How can I prevent $query-\>execute(); from causing this error:

> ( ! ) Fatal error: Allowed memory size of 201326592 bytes exhausted (tried to allocate 20480 bytes) in /home/jepster/PhpstormProjects/permissions-by-term-behat/drupal/core/lib/Drupal/Core/Cache/DatabaseCacheTagsChecksum.php on line 108

I have googled a lot and I cannot find out, why Drupal 8's database functionality is using all the memory and why the batch functionality is not preventing this.

# Answer
Ivan Jaros is correct, right now you just do the work twice.

You're expecting something that is not possible.

Batch saves the operations data in the database, it has to. So you save one huge array only to load it again and store it in a separate table.

A batch makes only sense if you can actually split up the processing into smaller bits and *not* have all the data in one large array.

Specifically for node access processing, the API for this already exists, no need to re-invent the wheel. See node\_access\_rebuild(), which can do this either in the current request (not recommended for a large amount of data) or with a batch. And you can see that there is only one batch operation without data, but if you look at it, you can see it is doing a pager query to process the whole list of nodes (there are Drupal sites with millions of nodes).
> 3 votes

# Answer
Providing code example for Berdir's answer here to give you more information.

Read this article https://www.drupal.org/docs/7/api/batch-api/overview

and check the example module here to checkout the proper way of using the batch processing Drupal 8: https://github.com/GiantRobot/csvimport

you will then know how to alter your code to work.

cheers!
> 0 votes

---
Tags: 8, database
---


# Question
Title: Show comment link function based on node comment settings and not user privilege
I'm creating a custom theme and module for one of my content types. I want to show the comments link in a specific content type only if comments are turned on for the node or even globally for the content type specifically. I had originally used the following, simplified for example, in my tpl.php, which shows the link if the user has the privilege to comment. However, in my case, while I allow comments all over the site, I don't allow them on this particular content type. I want to leave the option open in case we do allow comments in the future.

```
<?php
 if (user_access('post comments')) {
  print '<a href="#">Comment</a>';
 }
?>

```

I was hoping that the system would recognize that a user that has privilege to comment every else still doesn't have privileges to comment on this node, and the link would not show, but it seems to show to anyone that has comment privileges, regardless of node.

What should replace `user_access()`?

# Answer
If you look at https://api.drupal.org/api/drupal/modules%21node%21node.tpl.php/7.x

and click `View source`

and scroll down a bit, you will see that there is a variable that you can use:

> **$comment**: State of comment settings for the node.

So my guess would be that the value is either 1 (TRUE) or 0 (FALSE).

Using Devel module you can use Devel's dpm() function, so put:

```
dpm($comment);

```

to dump and see it's value.

If my guess is correct, then you would need to do something like this:

```
 if ($comment == 1) {
    print '<a href="#">Comment</a>';
 }

```
> 1 votes

---
Tags: 7, theming
---


# Question
Title: Rules, User registration, loop through other users with condition, set field value to 0
My configuration is the following :

Using D7

I have a node type called Items.

User with a node id entity reference field to this node can be affiliated to one of these nodes, four of them..

(So there is (x) Users who are affiliated to Node A, (x) Users to Node B.. C and so on..)

When registering new user has a "field\_current\_owner" (on/off), set by defaut And choose his affiliation to one of these four nodes.

I want to make a rule that cycle through other users affiliated to the same "node id reference" to have their "field\_current\_owner" switch off.

I am a bit confused with rules components.. someone could shade some light on my problem ?

Should i made a component which turn any user with id different (negate) than registered user with condition regisetred has same node id reference trigger event get field i/o to "off" ?

I am a bit confused, then when i make a rule with my component fields previously inputed, how can I make it cycle through my user list ?

I am a bit in the mist with this module, can someone please give me hand ? Even a hint ?

Thanks by advance

# Answer
> 0 votes
Assuming your Rules event is User Updated and you don't have hundreds / thousands of users referencing each of the nodes,

Use the Action: `Fetch Entity by Property [User>Entity Reference Field]` and give it the Entity Reference of the Updated User. This will give you a list called `Entity Fetched`.

1. Create a Loop using `Entity Fetched`
2. Add an action to the Loop (on the right) and `Set a Data Value: [List Item>Field>Not Current Owner]`
3. Under the loop, `Set a Data Value: [Updated User>Field>Current Owner]`

That will save each user that references the node.

If you don't want that because of performance etc.,

1. You would create a Rules component and send each `List Item` in Step 2 above.
2. Then in that rule component, have a condition that checks the user's `Current Owner field` is set to True, and have an action to set it to false.
3. Do step 3 as above in the main Rule to set the current user as owner.

---
Tags: 7, rules
---


# Question
Title: Add image by pasting URL with media module
In the screenshot, you can see I have the option to upload a video by URL. This is provided with the media module and the video embed field module.

Is there a similar module for adding images by pasting a URL. Or will this need to be a custom solution?

# Answer
> 0 votes
I found a module for your need.

https://www.drupal.org/project/imagecache\_external

---
Tags: 8, media
---


title: why some fields hidden from node?

text:
# Question
Title: why some fields hidden from node?
well I have a content type in which I needed about 6 taxonomy fields..

it was working at first but suddenly it stopped showing taxonomy fields in node display page.

I used Field Permissions and Field Group modules and I show the fields in content type's display management. but nothing changed!

although I can use views to get and show the data but it may be an error in my drupal core or something.

Update: I disabled field group and field permissions.. every thing works fine now! but cause I need these modules I should continue trying!

# Answer
I it been a **long time that** you created that content type ?

It is on a **production** website already ?

Are you working on a **fresh** Drupal 7 installation ?

You could **delete** and **recreate** that content type if there is no serious impact on your site or your data.

If you do that, then your can check if the situation happens again. Sometimes there are particular manipulations while working that are responsible for those situations (and you can find out if you did something in a certain way the first time).

**But remember** : to me this operation depends on the 3 questions that I've asked on top of this text.

Does it help a bit ?
> 0 votes

---
Tags: 7, entities
---


title: File browser error - IMCE

text:
# Question
Title: File browser error - IMCE
IMCE - http://ufku.com/drupal/imce/7

I am trying to load file browser window via IMCE module on CHOOSE FILE button-(form upload field) click.

My following code loads such window fine from which I can select a file. But once I select the file, it opens a new window and display image file in new window instead of adding that file name in CHOOSE FILE button for me to further save and upload that file to my location (same as normal form file upload does).

Please note that I am not using IMCE in WYSIWYG editor rather a form upload field.

Here is my code;

$form\['image\_file'\] = array( '#type' =\> 'file', '#title' =\> t('File \*'), '#size' =\> 20, '#description' =\> t('Please use JPG file only.'), '#upload\_validators' =\> array( 'file\_validate\_extensions' =\> array('pdf'), ), '#upload\_location' =\> 'public://my\_image\_files/', '#attributes' =\> array('onclick' =\> "window.open('/imce', '', 'width=760,height=560,resizable=1')"), );

By following the documentation in http://ufku.com/drupal/imce/7, I have tried using

'/imce?app=myApp|sendto@myFileHandler'

and have created this function to call but no luck.

(function myFileHandler(file, win) { alert('FILE UPLOAD myOnloadFunc'); $('#urlFieldId').val(file.url);//insert file url into the url field win.close();//close IMCE })(window.jQuery, window.Drupal, window.Drupal.bootstrap);

Any idea what I am doing wrong here or perhaps I am missing configuration settings somewhere?

Thanks

# Answer
I have achieved this with the following;

1)

```
<script>
function imageFileSelector() {  window.open('/imce?urlField=edit-image-file-path-1', '', 'width=760,height=560,resizable=1');   }
</script>

```

'edit-image-file-path-1' is id value for form field 'image\_file\_path\_1'.

2)

```
$form['image_file_selector'] = array(
  '#markup' => t("<br /><b>Image File *</b><br><a onclick=imageFileSelector();>Click to choose Image File</a><br>"),
);
$form['image_file_path_1'] = array(
  '#type' => 'textfield',
  '#attributes' => array('readonly' => 'readonly'),
  '#default_value' => $result->image_file_path_1,
);

```
> 0 votes

---
Tags: files
---


# Question
Title: File upload form element that will allow the user to select files from server
I want to achieve (Create a form that will allow the user to select files from server) in Drupal 8.3 and have followed steps 1 to 4 but for some reason it's not working at my end.

Can someone shed light how code can be updated in Drupal 8.3 to achieve above?

Thanks

# Answer
> 0 votes
I have achieved this in version 8.3 by enabling IMCE module and with the following logic i.e

1)

```
<script>
  function imageFileSelector() {
    window.open('/imce?urlField=edit-image-file-path-1', '', 'width=760,height=560,resizable=1');
  }
</script>

```

'edit-image-file-path-1' is id value for form field 'image\_file\_path\_1'.

2)

```
$form['image_file_selector'] = array(
  '#markup' => t("<br /><b>Image File *</b><br><a onclick=imageFileSelector();>Click to choose Image File</a><br>"),
);
$form['image_file_path_1'] = array(
  '#type' => 'textfield',
  '#attributes' => array('readonly' => 'readonly'),
  '#default_value' => $result->image_file_path_1,
);

```

---
Tags: 8, forms, files
---


# Question
Title: Rules Scheduler Component parameter is empty
I created a rule for scheduling a action component after 48h. The rule gets triggered correctly and the task shows up at the "Workflow" tab in rules.

The problem is that the scheduled component gets an empty parameter and so can execute the actions. Drupal log shows an *"The variable or parameter node is empty."* warning.

Here is the rule:

```
{ "rules_set_submission_status_to_archived" : {
    "LABEL" : "SUBMISSION: Set submission status to archived",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "TAGS" : [ "archived", "submission" ],
    "REQUIRES" : [ "rules", "rules_scheduler" ],
    "ON" : { "node_insert--submission" : { "bundle" : "submission" } },
    "IF" : [ { "entity_is_of_type" : { "entity" : [ "node" ], "type" : "node" } } ],
    "DO" : [
      { "schedule" : {
          "component" : "rules_times_up_for_submission",
          "date" : "+2 days",
          "identifier" : "Archive submission [node:nid] \u0022[node:title]\u0022 after 48h.",
          "param_node" : [ "node" ]
        }
      }
    ]
  }
}

```

Here is the scheduled component:

```
{ "rules_times_up_for_submission" : {
    "LABEL" : "Times up for submission, archive and pay back credits",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "TAGS" : [ "archived", "submission" ],
    "REQUIRES" : [ "rules", "commerce_credits", "php" ],
    "USES VARIABLES" : { "node_to_archive" : { "label" : "Node", "type" : "node" } },
    "IF" : [
      { "node_is_of_type" : {
          "node" : [ "node-to-archive" ],
          "type" : { "value" : { "submission" : "submission" } }
        }
      },
      { "entity_has_field" : { "entity" : [ "node-to-archive" ], "field" : "field_status" } },
      { "data_is" : { "data" : [ "node-to-archive:field-status" ], "value" : "submitted" } },
      { "entity_has_field" : { "entity" : [ "node-to-archive" ], "field" : "field_use_free_credits" } },
      { "data_is" : { "data" : [ "node-to-archive:field-use-free-credits" ], "value" : "0" } }
    ],
    "DO" : [
      { "commerce_credits_add" : {
          "entity" : [ "node-to-archive:author" ],
          "credit_type" : "credit",
          "number" : [ "node-to-archive:field-submission-price" ]
        }
      },
      { "data_set" : { "data" : [ "node-to-archive:field-status" ], "value" : "archived" } },
      { "entity_save" : { "data" : [ "node-to-archive" ], "immediate" : "1" } },
      { "php_eval" : { "code" : "watchdog(\u0027schedule\u0027, $node_to_archive);" } }
    ]
  }
}

```

So basically, the node is not passed to the scheduler component. Is there something broken in my system or do I miss something?

# Answer
> 1 votes
Some tips to help you find out what's happening / going wrong (based on revision 2 of your question):

* Try to execute your Rules Component "manually" (just to test), to unit-test if it works as desired. To do so, use the "execute" link to the right of the Rules Component (in the Rules UI).
* It could be a permission issue, i.e. think about which "user" (authority) the scheduled component executes with.

Some more tips to help you find out what's happening / going wrong (based on revision 3 of your question), and your extra comment which includes "*... shows this error: "Recoverable fatal error: Object of class stdClass could not be converted to string in DatabaseStatementBase-\>execute() (line 2227 of database.inc)." The log has a "page not found" warning from /admin/config/workflow/rules/components/manage/autocomplete/node\_to\_archive/form-xxx.../ ...*":

* Try to temporary remove that very last rules action (to execute that PHP code), and see what happens.
* If the error still doesn't go away, it seems the time is right to start Rules debugging, as explained in my answer to "Where is the Rules Evaluation Log?".

***Last but not least*** ...

About this part of your question:

> The problem is that the scheduled component gets an empty parameter and so can execute the actions. Drupal log shows an "The variable or parameter node is empty." warning.

Please have a look at what's described in my answer to "Why can my view not access the data of a new node when using Rules event After saving new content?". It explains that "after saving something" actually happens ... "before saving something" (which is not a bug, simply how the Rules module works ...). I wouldn't be surprised that this is also what explains your problem. Here is why I think so:

* Your (main) rule uses the event "after saving something".
* Assume that the rules action (to schedule your component) actually happens (also) "before saving something"; In that scenario the part of your message that says *"The variable or parameter node is empty."* makes sense ... (get it?).

So it would be interesting to see what would happen if (even only to test), you'd replace the (single) Rules Action (to schedule your Rules Component) by the execution of an additional Rules Component (let's call it "Test\_tip\_from\_Pierre") which is scheduled to execute after X secs or mins, and with a single Rules Action (equal to your Rules Action you now have in your main rule). Using that approach, for sure the node will have been saved before you actually schedule your original Rules Component. And that is what might resolve (eliminate / prevent) your warning like "*The variable or parameter node is empty.*"

---
Tags: 7, rules
---


title: Add a taxonomy ID class to the body tag

text:
# Question
Title: Add a taxonomy ID class to the body tag
I have a taxonomy vocabulary whose various parents and children need to have different styles. I would need the tid of the every taxonomy page to appear as a class in the body tag in order to make CSS selectors.

I tried using How can I dynamically add URL or taxonomy to body class to work out a solution, but it seems to work only for nodes. I get a class called path-taxonomy for every taxonomy term and that's it.

I would prefer not to install any module.

# Answer
> 3 votes
The linked example gets the path. Here better use routing. Check the name of the matched route and then get a parameter which is defined in the route. Normally you use `getParameter()` to get the loaded entity, in this case it's `getRawParameter()` for the id:

*mytheme.theme:*

```
function mytheme_preprocess_html(&$variables) {
  if (\Drupal::routeMatch()->getRouteName() == 'entity.taxonomy_term.canonical') {
    $variables['term_id'] = \Drupal::routeMatch()->getRawParameter('taxonomy_term');
  }
}

```

*html.html.twig:*

```
{%
  set body_classes = [
    term_id ? 'term-id-' ~ term_id,
  ]
%}
<body{{ attributes.addClass(body_classes) }}>

```

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


# Question
Title: create link for URL-based text field in content type
Drupal 7 question: In my Events content type, I have a text field called RSVP URL. On the event page, it currently displays as

**RSVP URL:** http://example.com

However, I would like it to be a link, displaying like so:

**RSVP URL:** http://example.com

I'm not seeing a way to do this, except perhaps via adding the Link module?, but I'm a newbie who's never even installed a module before, and I'm wondering if there's another built-in way. Thanks.

# Answer
> 2 votes
Click on edit in front of your link field in your content type's manage field tab.

You need to change Text processing option to filtered Text.

Then while adding this content type just type the URL with HTML tag.

I hope this solves your problem without installing a module.

# Answer
> 2 votes
I feel like the simpliest way to do that will be to install the linke field module directly from the web.

To do so :

* Go to **admin/modules** ;
* Clic on Install new module ;
* **Open a new tab**. Paste link module link and go. A page displays with the **description** of the module ;
* At the bottom of that page, **Copy the link to the file** (zip or tar.gz one) which is this one (this one is the zip one) ;
* **Go to the drupal** (Install new module) **page**. Paste that link on the *Install from url* field and hit Install. Wait 'till it finished in a few seconds ;
* Clic on *Enable newly added*.... ;
* Search for the link field module by scrolling. Clic on install. Wait untill it finished in a few time ;

And you can go back to your content type in order to create that new link field with the wright type.

Does that help ?

---
Tags: entities, navigation
---


# Question
Title: How to prevent Rules scheduled within a month may have an offset that is off by 1 or 2 days?
I have been using Rules to send out emails to users based on their user role. Based on the role, they should get emails at different times based on an event.

Whenever a rule is triggered in a month with more or less than 30 days however, the offset doesn't seem to work and my scheduled events are one day off. In the case of February (with 28 days), it's even two days off.

I'm assuming this is because after 30 days it calculates it as a month? I'm at a loss as to how to fix this.

These schedules are tied to certain events and should always be triggered a certain number of days after the event start date.

# Answer
> 0 votes
### Understanding the issue

The explanation for what you're experiencing can be found in the description of the (open) issue about "Dates are poorly handled". Here is part of what it includes:

```
/**
 * Defines possible duration multiplier.
 */
function rules_ui_element_duration_multipliers() {
  return array(
    1 => t('seconds'),
    60 => t('minutes'),
    3600 => t('hours'),
    // Just use approximate numbers for days (might last 23h on DST change),
    // months and years.
    86400 => t('days'),
    86400 * 30 => t('months'),
    86400 * 30 * 12 => t('years'),
  );
}

```

From the above code, it's obvious that there may be a discrepancy of some days if scheduling a rule X months from now (every month is assumed to have exactly 30 days, which is not the case of course). Similar problem when using years, and also a (minor) problem of 1 hour when using *DST*.

### Making it work for MONTHLY executions

So far the bad news ... the good news is that there is a work around for this. If you use the Rules Once per Day module, you can take advantage of these additional facilities of this module (as mentioned on its project page):

> The module also provides a **"Day of the week is a"** Rules condition, to further restrict actions to being run on specific day(s) of the week, on working days only, or at weekends only.
>
> From version 7.x-1.1 there is now a **"Day of the month"** condition, too.

With that, you should be able to adapt any rule to perform its Rules Actions only once a week, or once a month.

### Making it work for YEARLY executions

But, there is even more, for those cases where you want a rule to only execute once a year, you can use a Rule as explained in this issue and which looks like so:

1. Create a rule triggered by the "Once per day" event
2. Add a "Current day of the month" condition:
    * Comparison "equals"
    * Day of the month value "1"
3. Add a "Text comparison" condition:
    * Data selector "site:name" (dummy text, not used)
    * PHP evaluation "return date('m');" **(** ! **)**
    * Matching text "^01$" (for January)
    * Comparison operation value "Regular expression"

The above logic will ensure that your Rules Action(s) are executed on exactly the 1st of January of every year (adapt the "1" and/or "January" to fit whatever other day of a year).

**(** ! **)**: I admit, this solution (only required for "YEARLY" though) requires the PHP filter to be enabled, which I try to avoid at any cost (I've not found an alternative for this yet ...).

PS: I'm assuming this question is about D7.

---
Tags: rules
---


# Question
Title: How to send an email when the content is unpublished?
I'm using the Rules module for sending emails. When the user adds a node, it can only be published when the admin approves it. For this I have used the content approval module.

I have made a rule which sends an email to the user when their content is published.

How do I create a rule which sends an email to the user when their content is not approved or unpublished?

# Answer
> 0 votes
hook\_scheduler\_api() accepts two parameters -

```
1. $node is the node object being processed
2. $action is either 'publish' or 'unpublish'

```

**hook\_scheduler\_api()**

```
<?php
    function yourmodule_scheduler_api($node, $action) {
  if (some condition) {
    // parameters: drupal_mail($module, $key, $to, $language, $params = array(), $from = NULL, $send = TRUE) {
    drupal_mail('yourmodule', 'mail key', $user->mail, etc depending on your needs);
  }
}
?>

```

**hook\_mail()**

```
<?php

function yourmodule_mail($key, &$message, $params) {
  switch ($key) {
    case 'this-mail-key':
      $message['subject'] .= 'your subject';
      $message['body'][] = 'text';
      // etc ...
      break;
    // etc ...
}
?>

```

# Answer
> 0 votes
Here is a rule (in Rules export format) that can be used to **send an email to the node author after the node is unpublished**:

```
{ "rules_send_email_after_node_is_unpublished" : {
    "LABEL" : "Send email after node is unpublished",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "ON" : { "node_update" : [] },
    "IF" : [
      { "data_is" : { "data" : [ "node-unchanged:status" ], "value" : "1" } },
      { "data_is" : { "data" : [ "node:status" ], "value" : "0" } },
      { "NOT data_is" : {
          "data" : [ "node-unchanged:author:uid" ],
          "value" : [ "site:current-user:uid" ]
        }
      }
    ],
    "DO" : [
      { "mail" : {
          "to" : [ "node-unchanged:author:mail" ],
          "subject" : "Your content is unpublished ...",
          "message" : "This is to inform you that your node (with node id = [node-unchanged:nid] and node title = [node-unchanged:title]) has been unplublished ...",
          "language" : [ "" ]
        }
      }
    ]
  }
}

```

If you have the Rules UI enabled, you should be able to import the above rule in your own site.

Some more details about this rule:

* Rules Event: After updating existing content
* Rules Conditions (all of them must be TRUE):
    + Before the update, the node must be **Published**.
    + After the update, the node must be **Unpublished**.
    + The user performing the update must not be the author of the node (otherwise the eMail is useless, no need to send such eMail to yourself).
* Rules Action: Send an appropriate eMail (adapt its content to fit your needs).

Obviously, you could add other Rules Conditions (eg to check the role of the user performing the update), but at its core this rule will get the job done.

---
Tags: 7, rules, nodes, emails
---


# Question
Title: How to send a user an email when a content is published by somebody else?
I want to send an email to a user when the user's earlier unpublished content is published by somebody else (site administrator, moderator, etc).

I tried doing it with Rules but could not figure out how.

Any help?

# Answer
> 1 votes
Programmatically it is easy to do:

On a custom module create a custom table: entity\_notifications

https://api.drupal.org/api/drupal/includes%21database%21schema.inc/group/schemaapi/7

```
Entity_id: Integer Entity_type: varchar | SENT: Boolean

/**
 * Implements hook_schema().
 */
function custommodule_schema() {
  $schema = array();
  $schema['entity_notifications'] = array(
    'description' => 'The base table for entity notifications.',
    'fields' => array(
      'entity_id' => array(
        'description' => 'The primary identifier for the entity.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'entity_type' => array(
        'description' => 'Bundle',
        'type' => 'varchar',
      ),
      'sent' => array(
        'description' => 'Boolean indicating whether a email has been sent.',
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 1,
      ),
    )
    'primary key' => array('entity_id', 'entity_type'),
  );
  return $schema;
}

```

Control node status on hook\_node\_save or presave:

https://api.drupal.org/api/drupal/modules!node!node.api.php/function/hook\_node\_presave/7

```
function custommodule_node_save($node){
  // @TODO: compare $node->status vs $node->original->status (Check first than $node->original exists

  // @TODO: if current status is == "1" and original "0" check that in the DB is not checked

  // @TODO: send email and write to DB that this has been sent (db_query)!

```

https://stackoverflow.com/questions/11986683/how-to-send-email-in-drupal-7 }

---

Another approach could be using module flag: https://drupal.org/project/flag

1. Create a flag (type global: not by user) for example "sent"
2. On your rules condition check that this node has not been flagged with "sent" flag.
3. On rules actions flag this content after the email action

# Answer
> 3 votes
The Workflow module can do it exactly what you want. By using this module you can trigger different action at each flow of content.

> Workflows are made up of workflow states. Transitions between states can be allowed per role. For example, a workflow with the states Draft, Review, and Published could be assigned to the Story node type. Only users with role 'chief editor' can set Stories to the published state. You can set up the Workflow to alter states from form, page, comment and a special workflow tab.

# Answer
> 2 votes
Use two Data Comparison conditions.

One should compare node:unchanged with a status of unpublished. The other should compare node:updated wit ha status of published.

Then fire your action.

# Answer
> 2 votes
The prior answer from filmoreha is close, but a bit incomplete. It does not take into account the "*by somebody else*" part of your question, and does not mention any Rules Event(s) or Rules Action(s).

Here is a rule (in Rules export format) that can be used to **send an email to the node author after the node is published**:

```
{ "rules_send_email_after_node_is_published" : {
    "LABEL" : "Send email after node is published",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "ON" : { "node_update" : [] },
    "IF" : [
      { "data_is" : { "data" : [ "node-unchanged:status" ], "value" : "0" } },
      { "data_is" : { "data" : [ "node:status" ], "value" : "1" } },
      { "NOT data_is" : {
          "data" : [ "node-unchanged:author:uid" ],
          "value" : [ "site:current-user:uid" ]
        }
      }
    ],
    "DO" : [
      { "mail" : {
          "to" : [ "node-unchanged:author:mail" ],
          "subject" : "Your content is published ...",
          "message" : "This is to inform you that your node (with node id = [node-unchanged:nid] and node title = [node-unchanged:title]) has been plublished ...",
          "language" : [ "" ]
        }
      }
    ]
  }
}

```

If you have the Rules UI enabled, you should be able to import the above rule in your own site.

Some more details about this rule:

* Rules Event: After updating existing content
* Rules Conditions (all of them must be TRUE):
    + Before the update, the node must be **Unpublished**.
    + After the update, the node must be **Published**.
    + The user performing the update must not be the author of the node (as per the "*... by somebody else ...*" part of your question).
* Rules Action: Send an appropriate eMail (adapt its content to fit your needs).

Obviously, you could add other Rules Conditions (eg to check the role of the user performing the update), but at its core this rule will get the job done.

---
Tags: 7, rules
---


# Question
Title: Create an exposed filter block from a BLOCK display output
I'm trying to show my views exposed filter as a block (so it's placeable in the block structure), from a block display. I understand if I was using a page display, I could just use "Advanced \> Exposed Form" to show as block, but the option doesn't exist if the views' output is a block.

I've search everywhere, and I can't find any solution. Do you have any idea?

# Answer
In Drupal 7+ ensure that in the "advanced settings-\>other" in your block view, Use ajax=YES.
> 9 votes

# Answer
You can make this happen by following these steps:

1. Create a view with a page display (e.g. myview)
2. In Advanced settings, change the machine name of the display page (e.g. mypagedisplay)
3. Choose "Exposed filter in block"
4. Enable the PHP filter
5. Create a block, and embed this code:

```
<?php
  print views_embed_view("my view", "mypagedisplay");
?>

```
6. Choose the PHP input format for the block
> 3 votes

# Answer
There is also now a module views block filter block, that overrides the block views display type to allow having a block view with exposed filters in a block.
> 3 votes

# Answer
In drupal 8 the only way I could get this work was to have a Page view where I have selected "Expose filters as block" Then On the content type that I want to have the view as a block I use https://www.drupal.org/project/viewsreference and set it as a field I can then have the Page view in this reference field and have my exposed filters block in the sidebar of the page. This might not work for everyone's use case but hopefully helps some people :)
> 1 votes

---
Tags: blocks, views
---


# Question
Title: Rule to Send email to Admin when user points category reaches a certain value
I want to create a rule that sends an email when a user has points for a particular category that reaches a certain value, e.g., 100. Having problems with the condition. I have a User Points category = Contest.

Rule Event: User was awarded points

1st Condition: Data Comparison Data to compare: \[userpoints-transaction:tid\], Data value: Contest

2nd Condition: i) Tried, Data Comparison, userpoints-transaction:points, equals, 100

ii) Tried, Data Comparison, userpoints-transaction, but not correct option as the value to compare doesn't allow an integer

Action: Send mail, I have email, subject and message.

With just the 1st condition, the Rule works, I get an email when someone gets a point for the Contest category, not for other categories.

Can't figure out a condition so that will send an email when someone reaches 100 Contest User Points.

Anyone done this? Thanks

# Answer
Perhaps you can use the patch that's provided here: https://drupal.org/node/1109992.
> 0 votes

# Answer
As an alternative to using the patch mentioned in the previous answer, you may want to use another approach, as detailed below ...

Indeed, there is no Rules *Condition* to ***check a user's current userpoints balance***. However, have a look at this Rules example (in Rules export format):

```
{ "rules_display_userpoints_after_updating_content" : {
    "LABEL" : "Display userpoints after updating content",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "userpoints_rules", "rules", "rules_conditional" ],
    "ON" : { "node_update" : [] },
    "DO" : [
      { "userpoints_rules_get_current_points" : {
          "USING" : { "user" : [ "site:current-user" ], "tid" : "all" },
          "PROVIDE" : { "loaded_points" : { "total_points" : "Number of points in all categories together" } }
        }
      },
      { "drupal_message" : { "message" : "You now have [total-points:value] points" } },
      { "CONDITIONAL" : [
          {
            "IF" : { "NOT data_is" : { "data" : [ "total-points" ], "op" : "\u003C", "value" : "100" } },
            "DO" : [
              { "drupal_message" : { "message" : "You have sufficient points (you have [total-points:value] ...)." } }
            ]
          },
          { "ELSE" : [
              { "drupal_message" : { "message" : "You DO NOT have sufficient points (you only have [total-points:value] ...)." } }
            ]
          }
        ]
      }
    ]
  }
}

```

It does retrieve, as the very first Rules Action (not Rules Condition!) the current amount of user points of a user. If the amount is at least 100, it will display a message starting with "You have sufficient points ...", otherwise the message starts with "You DO NOT have sufficient points ...". It should be straight forward to adapt the display of the message to a corresponding Rules Action to send an eMail.

The example applies for "all categories" together. If you want to limit it to just a single category, just change it to the `tid` of the desired category (like `0`, or `1`, etc).

In this example I'm using the Conditional Rules module. As an alternative to using this module, you can also create corresponding Rules Components, with similar Rules Actions to be performed, but also with additional Rules Conditions equivalent to any Rules Conditions you'd want to include by using the Conditional Rules module. And then perform that Rules Component inside your Rules Actions of your original rule. For more details on that, refer to the answer to "What's the alternative to using the Conditional Rules module?"

So the clue to make this rule work is the very first Rules Action "***Load user points of a user***".

PS: I'm assuming this question is about D7.
> 0 votes

---
Tags: rules, userpoints
---


# Question
Title: How to enable / disable a module in settings.local.php
I'm using a settings.local.php for my local development environment. This is a Drupal 7 site.

I've seen a few references to this via google search, but none of the examples are working for me. I don't want to install a module to make this work if it is possible to accomplish the same result by adding a couple lines to the settings.local.php file.

I use this file all the time for a number of sites so I know it is being read properly. I've also used it to set variables (file\_temporary\_path, for example) and that works too. It is just enabling / disabling modules I'm having trouble with.

Any thoughts / suggestions?

# Answer
> 1 votes
I ended up using the Habitat module (https://www.drupal.org/project/habitat).

It has a UI that allows you to enter the names of modules you want turned off or on in each environment you have. Things like making sure Devel is ON in a local or DEV environment, and Views UI is OFF for a LIVE site.

It is simple to use and I haven't had any issues with it yet on the sites on which I have installed it.

---
Tags: configuration
---


title: What is EntityStorage?

text:
# Question
Title: What is EntityStorage?
I'm attempting to understand the concept of entity storage. For example in this tutorial

https://www.sitepoint.com/drupal-8-version-entityfieldquery/

it's using code to load the nodes from nids in a similar way to this

```
$ids = \Drupal::entityQuery('node')
    ->condition('status', 1)
    ->execute();

$node_storage = \Drupal::entityManager()->getStorage('node');

// Load multiple nodes
$node_storage->loadMultiple($ids);

```

But I'm not sure exactly what this is doing

```
$node_storage = \Drupal::entityManager()->getStorage('node');

```

My best guess is that it's loading the format of how the node is stored in the database so it knows how to load everything based on that format, but that's just a guess.

Also side note: the path I normally take is doing a foreach loop on the query results and loading the node based on the nid inside that. Like so. But I'm not sure what's best practice.

```
        foreach ($ids as $nid) {
            $node  = Node::load($nid);
        }

```

What exactly is entityStorage, and what function is it providing?

# Answer
Entity storage is a storage controller for the entity that handles the actual CRUD operations of entity data in the storage. That means it is responsible for inserting and deleting the entity data in the actual storage/repository.

The storage can be a .yaml file (for config entities) or a SQL database (for content entities). There are some specific use cases for null storage (like e-mail message) which basically means no data is stored anywhere and entity with such storage is just virtual: It exists only per single request as you define it.

You can additionally write your own storage controller and use remote storage, a file, a stream or whatever the requirements are.
> 4 votes

---
Tags: 8, entities, database
---


title: Clean URLs not working

text:
# Question
Title: Clean URLs not working
I just have Drupal 7 and 8 installed in my localhost on Opensuse Leap. With Drupal 7 I cannot pass the clean urls test, however the site is completely functional. By clicking the links on the menu I can access `localhost/drupal7/?q=admin/dashboard` or `localhost/drupal7/?q=admin/people` (for example).

In Drupal 8 I can access the front page `localhost/drupal8` but when I click some link, for example "Log in", I'm redirected to `localhost/htdocs/drupal8/user/login`. And I get an Apache 404 error. I don't understand why the server redirects to another directory when both installations are using the same configuration file.

I already tried all drupal.org apache-related tutorials without success.

Does anybody know how to solve this issue?

# Answer
I ran into this issue as well moving to opensuse leap from another distribution. There was more than one problem.

1. Even if rewrite\_module is listed in loadmodule.conf, this file is not not read without a change to httpd.conf. You can check if the module is loaded with

apache2ctl -M
2. As is posted elsewhere Options and AllowOverride arguments need to be placed within the relevant Directory tags.
3. If there is a subdirectory of the webserver, there needs to be a RewriteBase argument given in the .htaccess file.

### Try this to get things working:

**In file /etc/apache2/default-server.conf**

Within the `<Directory>` tags add or edit the Options and AllowOverride lines to

```
Options All
AllowOverride All

```

**In file /etc/apache2/loadmodule.conf add**

```
LoadModule rewrite_module    /usr/lib64/apache2-prefork/mod_rewrite.so

```

**In file /etc/apache2/httpd.conf uncomment the IfDefine tags**

```
#<IfDefine !SYSCONFIG>
  Include /etc/apache2/loadmodule.conf
#</IfDefine>

```

**In file /srv/www/htdocs/NAMEOFYOURSUBDIRECTORYHERE/.htaccess add a line**

```
RewriteBase /NAMEOFYOURSUBDIRECTORYHERE

```

**Check if the configuration file "Syntax is OK."**

It will probably complain that some modules have already been loaded, but that's alright.

```
 apache2ctl configtest

```

**Restart Apache**

```
systemctl stop apache2; sleep 5; systemctl start apache2

```
> 1 votes

---
Tags: 8
---


# Question
Title: How can I build an FAQ Page with sections?
I am seeking to build an FAQ page that covers a few different types of topics, thus creating a need for sections, preferably with links. Like below:

I am using Drupal 8 and have the FAQ Field module installed. I'm having trouble creating a content type since I cannot add the FAQ Field multiple times to the same content type. Does anyone have any ideas?

# Answer
As an alternative to the FAQ Field module, you may want to use the Views Accordion module instead (for which an official release for D8 is already available), and its related Community documentation.

By "grouping fields", the group header can be used as accordion header. In your case, just use your "*Sections*" (like General, Printing, Binding) as those grouping fields. Obviously, you'd have to have a regular field (like a select list field) to actually indicate for each question in your FAQ what the actual Section for it should be.

With this approach, you have the full power of Views available to make your FAQ look like you'd want it to look.
> 5 votes

# Answer
Using the paragraphs module:

1) Add a "faq\_question\_answer" paragraph type with a field\_question and a field\_answer field

2) If you would like to be able to add FAQS to multiple pages, you can add an "faq" paragraph type with a paragraph field on it referencing your "faq\_question\_answer" paragraph type. Then you can add this to an existing paragraph field on a node type as an option for the types of paragraphs you can add.

3) Alternatively you could just add a "field\_faq" to a content type that references the faq\_question\_answer paragraph type.

4) If you would like groups of questions and answers (such as in the screenshot in the question) that are grouped by topic, you can either add separate fields for each topic on a content type, or you can add a topic taxonomy field to the "faq" paragraph type, and then have a field\_faqs on your content type that allows adding multiple faq paragraphs each with a selected topic that would display as the header of that section.
> 0 votes

---
Tags: 8
---


# Question
Title: Getting Drupal 8 to use an external index?
I have two sites one is maintained by us in drupal 8 and the other is maintained by another company that does the news updates etc for our company. I'm trying to figure out the best way to get a combined search in drupal. So set up a Solr instance and setup a web crawler to crawl the other site, set up drupal 8 to use the search api and solr search. But now i'm not sure what's the best way to integrate the index created by the web crawler with drupal 8. Any ideas?

# Answer
What you could do is use the Migrate module to migrate content from one site to the other. What you need to do is:

* Build a custom source plugin for it so that it fetches its data from an external source (i.e. the other site) and map it to a content type in your Drupal install.
* Then set up a cron job to run the migration periodically to update the data on your end. Make sure you set the migration to "update" since by default, migrations won't happen on already-migrated content.
* Create your search however you want in your site (Views, Search API, etc.) using that content type.

In D7, this was a job for the Feeds module but they don't appear to have a D8 version yet.
> 0 votes

---
Tags: search
---


# Question
Title: Limit which roles can view a node basing on its content type
I'm using Drupal 7 and I created a new content type called "eBook," and I created a new role called "MonthlySubscriber." My intention is to allow only users with the "MonthlySubscriber" to view the "eBook" nodes. When I looked at the permission settings for a role, I saw the checkboxes that allows to create, edit and delete nodes of that content type, but there are no checkboxes for viewing nodes.

How do I limit the users who can view "eBook" nodes to just the users with the "MonthlySubscriber" role?

# Answer
> 13 votes
You need to install Content Access module to add this access control.

> This module allows you to manage permissions for content types by role and author. It allows you to specifiy custom view, edit and delete permissions for each content type.

# Answer
> 5 votes
Here is a simple way protect node pages (node/NID) from unprivileged users.

```
/**
 * Implements hook_menu_alter().
 */
function mymodule_menu_alter(&$items) {
  $items['node/%node']['access callback'] = 'mymodule_check_node_access';
}

/**
 * Determines whether the current user may perform the operation on the node.
 */
function mymodule_check_node_access($op, $node) {
  if ($node->type == 'protected_type' && !user_access('administer site configuration')) {
    return FALSE;
  }
  return node_access($op, $node);
}

```

# Answer
> 5 votes
For drupal 7, try using hook\_node\_access():

```
/**
 * Implements hook_node_access().
 */
function YOURMODULE_node_access($node, $op, $account) {
  if (
    $node->type == 'ebook' &&
    $op == 'view' &&
    !in_array('MonthlySubscriber', $account->roles)
  ) { return NODE_ACCESS_DENY; }
  return NODE_ACCESS_IGNORE;
}

```

# Answer
> 2 votes
Content Access didn't work for my Drupal 7 install, so I used Node View Permissions instead.

# Answer
> 1 votes
For drupal 7, try this one: Access by Term

> Provides very flexible, hierarchical node access control (content access control), for D7.

# Answer
> 1 votes
I perfer using the Node View Permissions module. It's simpler than the Content Access module.

As in D6, it adds "View any content" and "View own content" permissions to any content type that you choose.

Steps to follow:

1. After installing and enabling, go to `/admin/config/content/node-view-permissions` and select which content types that you want to limit access to.
2. Then, go to `/admin/people/permissions#module-node_view_permissions` and select the roles that you want to be able to view the content. Save permissions.

Done!

# Answer
> 0 votes
The hook\_menu\_alter solution posted above by ya.teck does work, but conflicts with the standard hook\_node\_access in its function name. the hook\_menu\_alter is not required in this case, and so the answer posted by Denis above is in my opinion more accurate and the proper way. Altering the menu\_item as is done is the first referenced example could be clobbered by another module further down the pipe.

# Answer
> 0 votes
I used a code snippet found in the D7 api documentation for the hook\_node\_access hook.

This code will grant access to view "ebook" content to users that have the "view ebook" permission.

You need a new permission to control access by implementing hook\_permission().

```
/**
 * Implements hook_permission().
 */
function mymodule_permission() {
  return array(
    'view ebook' => array(
      'title' => t('View Ebook'),
      'description' => t('View Ebook nodes.'),
    ),
  );
}

```

By implementing hook\_node\_access() Drupal can grant or deny the access to the node.

```
/**
 * Implements hook_node_access().
 */
function mymodule_node_access($node, $op, $account) {

  // Checks for an ebook node in view mode.
  if (is_object($node) && $node->type === 'ebook' && $op === 'view') {

    // Grants permission to view the node if the current user has an role
    // with the permission 'view ebook'.
    if (user_access('view ebook')) {
      return NODE_ACCESS_ALLOW;
    }

    // Otherwise disallows access to view the node.
    return NODE_ACCESS_DENY;
  }
  // For all other nodes and other view modes, don't affect the access.
  return NODE_ACCESS_IGNORE;
}

```

Other permissions (edit, delete, etc) can be dealt with via the normal Drupal permissions.

Optionally you can remove the content from the admin overview by implementing hook\_query\_TAG\_NAME\_alter.

```
/**
 * Implements hook_query_TAG_NAME_alter().
 */
function mymodule_query_node_admin_filter_alter(QueryAlterableInterface $query) {
  if (!user_access('view ebook')) {
  $query->condition('n.type', 'ebook', '!=');
  }
}

```

---
Tags: users, nodes
---