# Question
Title: How to limit access of a view about Group Memberships to the Group's administrator?
I use the modules "Group" and "Views" to display to the administrators of the groups, the lists of their members.

My problem :

* user1 is the administrator of group1.
* user2 is the administrator of group2.

When user1 goes to group2, it has access to the list of members.How limit access to the group administrator?

With the module "Organic Group" there are parameters in "Access" of the view. The "Group" module does not provide any parameters.

```
$view = new view();
$view->name = 'group_members';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'group_membership';
$view->human_name = 'Membres';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['title'] = 'Liste des membres';
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['use_more_text'] = 'plus';
$handler->display->display_options['access']['type'] = 'role';
$handler->display->display_options['access']['role'] = array(
  3 => '3',
  9 => '9',
);
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['exposed_form']['options']['submit_button'] = 'Appliquer';
$handler->display->display_options['exposed_form']['options']['reset_button_label'] = 'Réinitialiser';
$handler->display->display_options['exposed_form']['options']['exposed_sorts_label'] = 'Trier par';
$handler->display->display_options['pager']['type'] = 'none';
$handler->display->display_options['style_plugin'] = 'table';
/* Entête: Global : Texte non filtré */
$handler->display->display_options['header']['area_text_custom']['id'] = 'area_text_custom';
$handler->display->display_options['header']['area_text_custom']['table'] = 'views';
$handler->display->display_options['header']['area_text_custom']['field'] = 'area_text_custom';
$handler->display->display_options['header']['area_text_custom']['empty'] = TRUE;
$handler->display->display_options['header']['area_text_custom']['content'] = '<strong>Légende :</strong></br>
Actif = fait partie du groupe et a accès aux offres groupés.</br>
Bloqué = fait partie du groupe mais n\'a plus accès aux offres groupés.</br>
Invité = a était invité dans le groupe mais n\'a pas encore accepté l\'invitation.';
/* Pied de page: Global : Texte non filtré */
$handler->display->display_options['footer']['area_text_custom']['id'] = 'area_text_custom';
$handler->display->display_options['footer']['area_text_custom']['table'] = 'views';
$handler->display->display_options['footer']['area_text_custom']['field'] = 'area_text_custom';
$handler->display->display_options['footer']['area_text_custom']['empty'] = TRUE;
$handler->display->display_options['footer']['area_text_custom']['content'] = '<strong>Instructions :</strong></br>
<u>Pour démarrer une commande groupée :</u></br>
Étape 1 : mettre à jour la liste des membres.</br>
Étape 2 : aller sur la page du groupe et cliquer sur "Démarrer la vente".</br>
Étape 3 : compléter les dates et confirmer "Démarrer la vente".</br>
<u>Pour arrêter une commande groupée :</u></br>
Étape 1 : aller sur la page du groupe et cliquer sur "Arrêter la vente".</br>
Étape 2 : confirmer "Arrêter la vente".</br>
</br>
<i>Pour plus de détails, veuillez consulter la question suivante :</br>
lien</i>';
/* Comportement en l'absence de résultats: Global : Zone de texte */
$handler->display->display_options['empty']['area']['id'] = 'area';
$handler->display->display_options['empty']['area']['table'] = 'views';
$handler->display->display_options['empty']['area']['field'] = 'area';
$handler->display->display_options['empty']['area']['empty'] = TRUE;
$handler->display->display_options['empty']['area']['content'] = 'Vous n\'avez aucun membre dans votre groupe.';
$handler->display->display_options['empty']['area']['format'] = 'plain_text';
/* Relation: Adhésion au groupe : Groupe gid */
$handler->display->display_options['relationships']['group']['id'] = 'group';
$handler->display->display_options['relationships']['group']['table'] = 'group_membership';
$handler->display->display_options['relationships']['group']['field'] = 'group';
/* Relation: Adhésion au groupe : Utilisateur uid */
$handler->display->display_options['relationships']['user']['id'] = 'user';
$handler->display->display_options['relationships']['user']['table'] = 'group_membership';
$handler->display->display_options['relationships']['user']['field'] = 'user';
/* Champ: Opérations en masse : Adhésion au groupe */
$handler->display->display_options['fields']['views_bulk_operations']['id'] = 'views_bulk_operations';
$handler->display->display_options['fields']['views_bulk_operations']['table'] = 'views_entity_group_membership';
$handler->display->display_options['fields']['views_bulk_operations']['field'] = 'views_bulk_operations';
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['display_type'] = '0';
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['enable_select_all_pages'] = 1;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['row_clickable'] = 1;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['force_single'] = 0;
$handler->display->display_options['fields']['views_bulk_operations']['vbo_settings']['entity_load_capacity'] = '10';
$handler->display->display_options['fields']['views_bulk_operations']['vbo_operations'] = array(
  'rules_component::rules_block_a_group_membership' => array(
    'selected' => 1,
    'postpone_processing' => 0,
    'skip_confirmation' => 1,
    'override_label' => 1,
    'label' => 'Bloquer les membres sélectionnés',
  ),
  'rules_component::rules_unblock_a_group_membership' => array(
    'selected' => 1,
    'postpone_processing' => 0,
    'skip_confirmation' => 1,
    'override_label' => 1,
    'label' => 'Débloquer les membres sélectionnés',
  ),
);
/* Champ: Groupe : ID du groupe */
$handler->display->display_options['fields']['gid']['id'] = 'gid';
$handler->display->display_options['fields']['gid']['table'] = 'groups';
$handler->display->display_options['fields']['gid']['field'] = 'gid';
$handler->display->display_options['fields']['gid']['relationship'] = 'group';
$handler->display->display_options['fields']['gid']['exclude'] = TRUE;
/* Champ: Utilisateur : Uid */
$handler->display->display_options['fields']['uid']['id'] = 'uid';
$handler->display->display_options['fields']['uid']['table'] = 'users';
$handler->display->display_options['fields']['uid']['field'] = 'uid';
$handler->display->display_options['fields']['uid']['relationship'] = 'user';
$handler->display->display_options['fields']['uid']['exclude'] = TRUE;
/* Champ: Groupe : Titre */
$handler->display->display_options['fields']['title']['id'] = 'title';
$handler->display->display_options['fields']['title']['table'] = 'groups';
$handler->display->display_options['fields']['title']['field'] = 'title';
$handler->display->display_options['fields']['title']['relationship'] = 'group';
/* Champ: Utilisateur : Nom */
$handler->display->display_options['fields']['name']['id'] = 'name';
$handler->display->display_options['fields']['name']['table'] = 'users';
$handler->display->display_options['fields']['name']['field'] = 'name';
$handler->display->display_options['fields']['name']['relationship'] = 'user';
$handler->display->display_options['fields']['name']['label'] = 'Nom d\'utilisateur';
$handler->display->display_options['fields']['name']['exclude'] = TRUE;
/* Champ: Global : Texte personnalisé */
$handler->display->display_options['fields']['nothing_3']['id'] = 'nothing_3';
$handler->display->display_options['fields']['nothing_3']['table'] = 'views';
$handler->display->display_options['fields']['nothing_3']['field'] = 'nothing';
$handler->display->display_options['fields']['nothing_3']['label'] = 'Nom d\'utilisateur';
$handler->display->display_options['fields']['nothing_3']['alter']['text'] = '[name]';
$handler->display->display_options['fields']['nothing_3']['alter']['make_link'] = TRUE;
$handler->display->display_options['fields']['nothing_3']['alter']['path'] = 'group/[gid]/member/[uid]';
/* Champ: Utilisateur : Courriel */
$handler->display->display_options['fields']['mail']['id'] = 'mail';
$handler->display->display_options['fields']['mail']['table'] = 'users';
$handler->display->display_options['fields']['mail']['field'] = 'mail';
$handler->display->display_options['fields']['mail']['relationship'] = 'user';
$handler->display->display_options['fields']['mail']['link_to_user'] = '0';
/* Champ: Adhésion au groupe : Statut de membre */
$handler->display->display_options['fields']['status']['id'] = 'status';
$handler->display->display_options['fields']['status']['table'] = 'group_membership';
$handler->display->display_options['fields']['status']['field'] = 'status';
$handler->display->display_options['fields']['status']['label'] = 'Statut';
/* Champ: Adhésion au groupe : Group role */
$handler->display->display_options['fields']['role']['id'] = 'role';
$handler->display->display_options['fields']['role']['table'] = 'group_membership';
$handler->display->display_options['fields']['role']['field'] = 'role';
$handler->display->display_options['fields']['role']['label'] = 'Rôles';
$handler->display->display_options['fields']['role']['separator'] = '';
/* Champ: Global : Texte personnalisé */
$handler->display->display_options['fields']['nothing_2']['id'] = 'nothing_2';
$handler->display->display_options['fields']['nothing_2']['table'] = 'views';
$handler->display->display_options['fields']['nothing_2']['field'] = 'nothing';
$handler->display->display_options['fields']['nothing_2']['label'] = 'Metadata';
$handler->display->display_options['fields']['nothing_2']['exclude'] = TRUE;
$handler->display->display_options['fields']['nothing_2']['alter']['text'] = 'metadata';
$handler->display->display_options['fields']['nothing_2']['alter']['make_link'] = TRUE;
$handler->display->display_options['fields']['nothing_2']['alter']['path'] = 'group/[gid]/member/[uid]/metadata';
/* Champ: Global : Texte personnalisé */
$handler->display->display_options['fields']['nothing']['id'] = 'nothing';
$handler->display->display_options['fields']['nothing']['table'] = 'views';
$handler->display->display_options['fields']['nothing']['field'] = 'nothing';
$handler->display->display_options['fields']['nothing']['label'] = 'Modifier';
$handler->display->display_options['fields']['nothing']['exclude'] = TRUE;
$handler->display->display_options['fields']['nothing']['alter']['text'] = 'modifier';
$handler->display->display_options['fields']['nothing']['alter']['make_link'] = TRUE;
$handler->display->display_options['fields']['nothing']['alter']['path'] = 'group/[gid]/member/[uid]/edit?destination=group/[gid]/member';
/* Champ: Global : Texte personnalisé */
$handler->display->display_options['fields']['nothing_1']['id'] = 'nothing_1';
$handler->display->display_options['fields']['nothing_1']['table'] = 'views';
$handler->display->display_options['fields']['nothing_1']['field'] = 'nothing';
$handler->display->display_options['fields']['nothing_1']['label'] = 'Supprimer';
$handler->display->display_options['fields']['nothing_1']['exclude'] = TRUE;
$handler->display->display_options['fields']['nothing_1']['alter']['text'] = 'supprimer';
$handler->display->display_options['fields']['nothing_1']['alter']['make_link'] = TRUE;
$handler->display->display_options['fields']['nothing_1']['alter']['path'] = 'group/[gid]/member/[uid]/cancel?destination=group/[gid]/member';
/* Champ: Global : Texte personnalisé */
$handler->display->display_options['fields']['nothing_4']['id'] = 'nothing_4';
$handler->display->display_options['fields']['nothing_4']['table'] = 'views';
$handler->display->display_options['fields']['nothing_4']['field'] = 'nothing';
$handler->display->display_options['fields']['nothing_4']['label'] = 'Actions';
$handler->display->display_options['fields']['nothing_4']['alter']['text'] = '[nothing_2]   [nothing]   [nothing_1]';
/* Filtre contextuel: Adhésion au groupe : Groupe gid */
$handler->display->display_options['arguments']['group']['id'] = 'group';
$handler->display->display_options['arguments']['group']['table'] = 'group_membership';
$handler->display->display_options['arguments']['group']['field'] = 'group';
$handler->display->display_options['arguments']['group']['default_action'] = 'default';
$handler->display->display_options['arguments']['group']['exception']['title'] = 'Tout';
$handler->display->display_options['arguments']['group']['default_argument_type'] = 'raw';
$handler->display->display_options['arguments']['group']['default_argument_options']['index'] = '1';
$handler->display->display_options['arguments']['group']['summary']['number_of_records'] = '0';
$handler->display->display_options['arguments']['group']['summary']['format'] = 'default_summary';
$handler->display->display_options['arguments']['group']['summary_options']['items_per_page'] = '25';
/* Critère de filtrage: Adhésion au groupe : Statut de membre */
$handler->display->display_options['filters']['status']['id'] = 'status';
$handler->display->display_options['filters']['status']['table'] = 'group_membership';
$handler->display->display_options['filters']['status']['field'] = 'status';
$handler->display->display_options['filters']['status']['value'] = array(
  'active' => 'active',
  'blocked' => 'blocked',
  'invited' => 'invited',
);
$handler->display->display_options['filters']['status']['exposed'] = TRUE;
$handler->display->display_options['filters']['status']['expose']['operator_id'] = 'status_op';
$handler->display->display_options['filters']['status']['expose']['label'] = 'Filtrer les membres';
$handler->display->display_options['filters']['status']['expose']['operator'] = 'status_op';
$handler->display->display_options['filters']['status']['expose']['identifier'] = 'status';
$handler->display->display_options['filters']['status']['expose']['remember_roles'] = array(
  2 => '2',
  1 => 0,
  5 => 0,
  8 => 0,
  4 => 0,
  9 => 0,
  7 => 0,
  3 => 0,
);
$handler->display->display_options['filters']['status']['expose']['reduce'] = TRUE;

/* Display: Page */
$handler = $view->new_display('page', 'Page', 'page');
$handler->display->display_options['path'] = 'group/%/member';
$handler->display->display_options['menu']['type'] = 'tab';
$handler->display->display_options['menu']['title'] = 'Membres';
$handler->display->display_options['menu']['weight'] = '0';
$handler->display->display_options['menu']['context'] = 0;
$handler->display->display_options['menu']['context_only_inline'] = 0;
$handler->display->display_options['tab_options']['weight'] = '0';
$translatables['group_members'] = array(
  t('Master'),
  t('Liste des membres'),
  t('plus'),
  t('Appliquer'),
  t('Réinitialiser'),
  t('Trier par'),
  t('Asc'),
  t('Desc'),
  t('<strong>Légende :</strong></br>
Actif = fait partie du groupe et a accès aux offres groupés.</br>
Bloqué = fait partie du groupe mais n\'a plus accès aux offres groupés.</br>
Invité = a était invité dans le groupe mais n\'a pas encore accepté l\'invitation.'),
  t('<strong>Instructions :</strong></br>
<u>Pour démarrer une commande groupée :</u></br>
Étape 1 : mettre à jour la liste des membres.</br>
Étape 2 : aller sur la page du groupe et cliquer sur "Démarrer la vente".</br>
Étape 3 : compléter les dates et confirmer "Démarrer la vente".</br>
<u>Pour arrêter une commande groupée :</u></br>
Étape 1 : aller sur la page du groupe et cliquer sur "Arrêter la vente".</br>
Étape 2 : confirmer "Arrêter la vente".</br>
</br>
<i>Pour plus de détails, veuillez consulter la question suivante :</br>
lien</i>'),
  t('Vous n\'avez aucun membre dans votre groupe.'),
  t('Groupe'),
  t('Utilisateur'),
  t('Adhésion au groupe'),
  t('- Choisir une opération -'),
  t('Ajouter le rôle administrateur aux membres sélectionnés'),
  t('Bloquer les membres sélectionnés'),
  t('Supprimer les membres sélectionnés'),
  t('Supprimer le rôle administrateur des membres sélectionnés'),
  t('Débloquer les membres sélectionnés'),
  t('ID du groupe'),
  t('.'),
  t(','),
  t('Uid'),
  t('Titre'),
  t('Nom d\'utilisateur'),
  t('[name]'),
  t('Courriel'),
  t('Statut'),
  t('Rôles'),
  t('Metadata'),
  t('metadata'),
  t('Modifier'),
  t('modifier'),
  t('Supprimer'),
  t('supprimer'),
  t('Actions'),
  t('[nothing_2]   [nothing]   [nothing_1]'),
  t('Tout'),
  t('Filtrer les membres'),
  t('Page'),
);

```

# Answer
> 0 votes
As an alternative to the solution in my prior answer, below is a "Plan B" solution ... with no custom code at all, based on using the Rules module (and a related one).

### Step 1: Add the Group ID as a required filter

Adapt your view, to add a filter, which is "***(Group) Group: Group ID***". Expose this filter, and make it required (if a user want to access a memberlist of a group, they must be willing to enter the group id they are asking for).

Assume you give your view a path like so: `/group/memberlist`. In doing so, to display the list of a members of a group (say with `gid=6`), the relative path of the views results for that group will become something like this: `/group/memberlist?gid=6&status=active` (which assumes you might want to use some other filter also, like in my example with `status=active`).

With that, we have everything in place to introduce some Rules logic to verify access to the views result for the requested group id (see where I'm going?)

### Step 2: Enable the Rules URL Argument module

Enable the Rules URL Argument module, which will be used to create a rule (in the next step). If you wonder what this module is about, have a look at the answer to "Redirect page to existing field value".

With that, all that's left is to "capture" the value of the Group ID (following `gid=` in the URL of the view from Step 1), and use that to perform a validation (using Rules) to check if the user trying to access these views results does have the required Group role for the required Group id (easy, no?).

### Step 3: Create a Rules Component to validate Group access

Create a Rules Component which looks like so (in Rules export format, which you should be able to import in your own site, using the Rules UI):

```
{ "rules_validate_access_to_a_group_role" : {
    "LABEL" : "Validate access to a Group role",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "USES VARIABLES" : {
      "group_id" : { "label" : "ID of group to validate", "type" : "integer" },
      "role_to_validate" : { "label" : "Role to validate", "type" : "group_role" },
      "granted_roles" : { "label" : "Granted group roles", "type" : "list\u003Cgroup_role\u003E" },
      "no_access_url" : { "label" : "No access URL", "type" : "uri" }
    },
    "IF" : [
      { "NOT list_contains" : { "list" : [ "granted-roles" ], "item" : [ "role-to-validate" ] } }
    ],
    "DO" : [
      { "drupal_message" : { "message" : "You are not allowed to view this list of members for the group with \u003Cstrong\u003Egid=[group-id:value]\u003C\/strong\u003E (because you do not have the role \u003Cstrong\u003E[role-to-validate:label]\u003C\/strong\u003E for this group).\r\n\u003Cbr \/\u003E\r\nBelow are the roles you have been granted for the group indicated in the URL as argument value after \u0022gid=[group-id:value]\u0022" } },
      { "LOOP" : {
          "USING" : { "list" : [ "granted-roles" ] },
          "ITEM" : { "role_item" : "Current role item" },
          "DO" : [ { "drupal_message" : { "message" : "---\u003E [role-item:label]." } } ]
        }
      },
      { "redirect" : { "url" : "[no-access-url:value]" } }
    ]
  }
}

```

Some more details about this Rules Component:

* It uses these parameters:
    + `group_id` : ID of group to validate
    + `role_to_validate` : Role to validate
    + `granted_roles` : Granted group roles
    + `no_access_url` : No access URL
* The Rules Condition checks if the list of `granted_roles` contains the role `role_to_validate`. And as per the ***NOT*** part in it, the Rules Actions will be performed if that role is not in the list of roles.
* The Rules Actions consists of 2 parts:
    + Show some Drupal messages (mostly for demo / debug purpose, feel free to remove those if you don't want them).
    + Perform a redirect to `no_access_url` (remember the NOT in the Rules Condition!).

### Step 4: Create a Rules that invokes the Rules Component from Step 3

Create a Rules which looks like so (in Rules export format, which you should be able to import in your own site, using the Rules UI):

```
{ "rules_limit_access_to_group_related_views" : {
    "LABEL" : "Limit access to Group related Views",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "rules_url_argument" ],
    "ON" : { "init" : [] },
    "IF" : [
      { "user_has_role" : {
          "account" : [ "site:current-user" ],
          "roles" : { "value" : { "3" : "3" } }
        }
      },
      { "data_is" : { "data" : [ "site:current-page:path" ], "value" : "group\/memberlist" } },
      { "rules_url_argument_argument_exists" : { "argument" : "gid" } }
    ],
    "DO" : [
      { "rules_url_argument_rules_action_get_argument_from_url" : {
          "USING" : { "type" : "integer", "argument_name" : "gid" },
          "PROVIDE" : { "argument_from_url" : { "gid_from_url" : "Group ID from URL" } }
        }
      },
      { "entity_fetch" : {
          "USING" : { "type" : "group_membership", "id" : [ "gid-from-url" ] },
          "PROVIDE" : { "entity_fetched" : { "group_mbmships_fetched" : "Fetched Group Memberships from URL" } }
        }
      },
      { "drupal_message" : {
          "message" : "Access to the view with URL argument \u0022gid\u0022=[gid-from-url:value] as specified in \u0022\u003Cstrong\u003E[site:current-page:path]\u003C\/strong\u003E\u0022  is only allowed if passing the \u003Cstrong\u003EGroup Access Validation\u003C\/strong\u003E implemented in the Rules Component that will now be executed.",
          "type" : "warning"
        }
      },
      { "component_rules_validate_access_to_a_group_role" : {
          "group_id" : [ "gid-from-url" ],
          "role_to_validate" : "group_admin",
          "granted_roles" : [ "group-mbmships-fetched:roles" ],
          "no_access_url" : "admin\/group"
        }
      }
    ]
  }
}

```

Some more details about this Rules:

* Rules Conditions (in order specified):
    1. Check if the current user has (Drupal, not Group!) role = Administrator. This assumes your view can only be accessed by such roles. That way we don't waste Rules processing time for users who don't have access to the view at all. Feel free to adapt this condition to another role(s), or just remove it if you don't need this condition.
    2. Check if the current path matches the path of the view, which is assumed to be "`group/memberlist`" (adapt to fit your own path).
    3. Check if the current path includes an argument like `gid=` (the ID of the group for which the memberlist is to be shown, remember?). Notice that this the 1st (out of 2) reason why we're using the Rules URL Argument module.
* Rules Actions (in order specified):
    1. Get the ***value*** specified in the current path after the argument like `gid=` (the ID of the group for which the memberlist is to be shown, remember?). Notice that this is the 2nd reason why we're using the Rules URL Argument module.
    2. Perform "Fetch entity by id", to get the memberships of the current user for the specified Group ID.
    3. Show a Drupal message (mostly for demo / debug purpose, feel free to remove if you don't want this).
    4. Invoke the Rules Component (from the previous step), passing it the relevant values for its parameters. If needed, adapt some of the (hardcoded) values to fit your needs, such as for `role_to_validate` and/or `no_access_url`.

### Demo

1. For a user who does have access for the requested group, the above rule will produce a message like so:

> Access to the view with URL argument "gid"=6 as specified in "group/memberlist" is only allowed if passing the Group Access Validation implemented in the Rules Component that will now be executed.

And the actual memberlist for the requested Group ID will be shown.
2. For a user who does NOT have access for the requested group, the above rule will produce a message like so:

> Access to the view with URL argument "gid"=6 as specified in "group/memberlist" is only allowed if passing the Group Access Validation implemented in the Rules Component that will now be executed.

However, on top of that, an additional message like this one will be shown:

> You are not allowed to view this list of members for the group with gid=5 (because you do not have the role Administrator for this group).
>
> Below are the roles you have been granted for the group indicated in the URL as argument value after "gid=5"
>
> ---\> R&D.
>
> ---\> Sales.
>
> ---\> Support.

And the actual memberlist for the requested Group ID will **NOT** be shown. Instead, a redirect to relative path "`admin/group`" will be performed.

Voilà, happy Rules-ing ... with zero custom code!

# Answer
> 0 votes
### Understanding the actual issue

You probably don't realize, but this question is an illustration of the (active) Group issue (feature request) about "Look into group\_access query tag like node\_access", for which this is the current issue summary:

> Work out a query tag like node\_access to prevent private groups from showing in Views, menu links, etc.

I didn't understand that issue at first (cfr my comment nr 2) in it. And even after Kristiaan (Group maintainer) added comment nr 3, it only became partially clear to me what the issue really was.

### Implementing your own access validations

However, later on I stumbled on Comment nr 6 in the issue "Setting Access Restriction in Views based on Group Role", which states:

> I have finally used the module "views\_access\_callback" and implement my own access callback function that checks if the current user belongs to a specific group's role.

So with that I understood that if you have any Views about Group entities (such as Group Memberships), then know that it's up to you to add your own access checking in your view. A possible way to do so, is to use the Views Access Callback module, which you can you in a custom module to make your view perform whatever access check you want. Obviously, for this specific case, some type of Group related permission seems appropriate.

Some more details about this Views Access Callback module (from its project page:

> Provides callback-based access control for Views.
>
> Available callback functions are defined by modules using `hook_views_access_callbacks()` function (in the same way as in `hook_perm()`), then could be set in in view's "Access restrictions" configuration.

The Community documentation for this module provides some extra details to get you goiing with this module.

### There has to be an alternative to custom coding

True, with the Views Access Callback module it has to work somehow (if you wonder how, just use this link).

But there has to be another way that doesn't require custom code ... I might soon post a ***Plan B*** ...

---
Tags: 7, views, users, group
---


# Question
Title: How do I pass a theme variable from a template to another?
Several fields in a node need to be displayed in a particular way depending upon which newsletter body they are a part of. How do I pass a variable from the enclosing newsletter body to enclosed fields so that I can inform the field of its context and control the way the field is displayed?

I have a theme that has preprocess functions both for the newsletter body and for fields contained within the body.

I want to set a variable in the body preprocess function, and its related twig template, that can be inspected by the field preprocess function, and/or its own template.

In other words, I want each field to be aware of the body context in which it is being rendered.

Specifically, I have `mytheme_preprocess_simplenews_newsletter_body()` that sets a variable (`$variables['summons'] = 'placeholder';`) which can be inspected (and also set) by the theme's simplenews-newsletter-body.html.twig template, but (because it's in a different render array) is subsequently neither visible to `mytheme_preprocess_field()` nor field--node--title.html.twig.

How do I communicate between the two render arrays?

Note that

1. There are apparently global variables like `$db_is_active` and `$is_admin`.
2. Sometimes, it is possible to achieve this kind of thing by cascading CSS class attributes from a containing element to a contained element. This is not generally satisfactory and in this particular case, it won't wash on different target mail clients unpredictable treatment of CSS.

# Answer
The solution I am working with is to use `drupal_static()`; simplified essentials in code below - take care with the &ampersands. It is giving me control where I need it.

So, using this approach, I can - taking their global context into account - per field, set variables in the usual way e.g. in `mytheme_preprocess_field()` subsequently to be used in a related template like `field--node--title--agenda.html.twig`

```
function mytheme_preprocess_simplenews_newsletter_body(&$variables) {
  // prepare to alter static var ...
  // get a reference binding to static var
  $var = &myvariable_function();
  // alter static var
  $var = 'simplenews_newsletter';
}

function mytheme_preprocess_field(&$variables, $hook) {
  // prepare to read static var
  // assign static var
  $var = myvariable_function();
  // $element is the render array for the field
  $element = $variables['element'];
  // filter those cases where it matters that we're theming a newsletter
  if ($element['#view_mode'] == 'email_html' and $var == 'simplenews_newsletter') {
    // Do stuff here like setting a variable for twig ...
    $variables['summons'] = 'some text';
  }
}
function &myvariable_function() {
  $var = &drupal_static(__FUNCTION__);
  if (!isset($var)) {
    // generate contents of static variable
    $var =  'initial_value';
  }
  return $var;
}

```

I am sure that there are other ways of communicating common context between different levels of a page's render hierarchy. Let me know how you'd do it.
> 4 votes

# Answer
I use this code:

```
/**
 * Helper function to pass slider variables from preprocess_page to preprocess_page_title_custom
 * @param  string $new_image Image URL
 * @return array             Images URL Array
 */
function _core_slider_images($new_image = NULL) {
  $vars = &drupal_static(__FUNCTION__, array());
  // If a new value has been passed add to the array.
  if ($new_image) {
    $vars[] = $new_image;
  }
  return $vars;
}

```

From this template:

In `page.html.twig` we have access to the $`node` var, and we need to pass the values to another template that don't have access to this var. We will search the values that we need to pass and call the `_core_slider_images()`, this function will be the bridge between the two templates (preprocess functions)

```
/**
 * Implements hook_preprocess_page().
 */
function MODULE_preprocess_page(&$variables) {
  // ...
  // Sending Images URL and titles from page to page_title.
    for ($i = 0; $i < $cant; $i++) {
      // Adding the images to the static function.
      _core_slider_images($variables['node']->field_image[$i]->entity->url());
    }
  }

```

To this template:

`page-title-custom.html.twig` is a custom template and don't have access to $`node`. As `hook_preprocess_page()` is called first we have stored the $`node` values in a static var, and we only need to call the `_core_slider_images()` function.

```
/**
 * Implements hook_preprocess_HOOK().
 */
function MODULE_preprocess_page_title_custom(&$variables) {
  // Searching the variables for sending to the page-title-custom template.
   $images = _core_slider_images();
}

```
> 1 votes

# Answer
I'm still new to D8, so I could easily be missing a trick. Generally in this situation you want to look for the most specific hook that gives you access to everything you want to alter. So altering at the field level is too specific and at the page level (for example) is too general.

Unfortunately `MailEntity` isn't a real (Drupal) entity, so you can't use standard hooks to alter its render array. It doesn't invoke any custom hooks I can see to allow you to alter the content either. In D7 in this situation I'd be tempted to use `hook_page_alter()` which is dirty but would work I think, but that's been removed from D8.

You could always override the `MailEntity` class and provide your own customisations directly there, but needing to do that for theme changes does seem a bit wrong to me.
> 0 votes

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


# Question
Title: How to programmatically get all nodes which are related to the specific term ID?
**What I want to do?**

I want to display all **categories** in first drop down and in second all **titles** of related nodes with the selected **category**.

To get that I have mentioned all the tasks I have done. Please read below.

**1st:** Created taxonomy named `category` with terms listed `Laptop`, `Car`, `Mobile` etc.

**2nd:** Content type named `product` with fields `title`, `description`, `category` etc. The `category` field uses **term reference** of `category` taxonomy. **3rd:** Created a form with WebForm with fields named `category` and `product`as drop down **4th:** First, `categories` drop down field, displayed all categories (Laptop, Car, Mobile) by using WebForm Term Options. **5th:** Second, `product` drop down field is empty yet.

I have used hook\_form\_FORM\_ID\_alter() hook to alter the webForm I created. I have found the solution to get all the nodes pragmatically those are related with specific taxonomy term ID.

**6th:** I have fetched term related all node by this code:

```
$arg = arg();
$query = db_select('node','n');
$query->join('taxonomy_index','ti','n.nid=ti.nid');
$query->fields('n', array('nid', 'title', 'type'))
  ->condition('n.type', 'products')
  ->condition('ti.tid', $arg['2']);
$result = $query->execute()->fetchAll();
$dropdown_array = array('' => t('-Select-'));
foreach ($result as $nid => $node) {
    $dropdown_array[$node->title] = $node->title;
}
echo '<pre>';   print_r($dropdown_array);   echo '<pre>';

```

**My first question is how to display all these nodes' titles in existing drop down field?**

**Another question is on `category` change, `products` must be change according to its nodes like ajax?**

# Answer
> My first question is how to display all these nodes' titles in existing drop down field?

In a custom module you can define your own select option element with the following code:

```
function custom_tweaks_webform_select_options_info() {
  $items = array();

  if (function_exists('_get_products_by_termid')) {
    $items['my-products'] = array(
      'title' => t('My products'),
      'options callback' => '_get_products_by_termid',
    );
  }
  return $items;
}

function _get_products_by_termid($termids) {
  // Debug
  $termids = array(1,2,3);

  $nids = taxonomy_select_nodes($termids);
  $products = [];
  if (!empty($nids)) {
    foreach ($nids as $nid => $value) {
      $products[$value] = node_load($value)->title;
    }
  }
  return $products;
}

```
* Enable this module
* Add a **select option** element to your webform
* Edit this element and select **My products** under the **Load a pre-built option list** field (see screenshots)
* Make sure you also have a **select option** element to your webform with the categories taxonomy vocabulary given (see screenshots)

To answer your second question

> Another question is on category change, products must be change according to its nodes like ajax?

replace the custom code from above with the code below. Still needs default value set and checking for empty values but it should point you in the right direction. The thing is that you ajaxify the category field (bij setting the #ajax property on it) and provide your own products field and fill that with values based on the term id from the categories field.

```
/**
 * Implements hook_form_alter().
 */
function custom_tweaks_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'webform_client_form_41') {
    $form['submitted']['categories']['#ajax'] = array(
        'callback' => '_show_products_based_on_category_term',
        'wrapper' => 'products-div',
        'method' => 'replace',
        'effect' => 'fade',
    );

    $term_id = $form_state['values']['submitted']['categories'];
    $tid = substr($term_id, 4);

    $form['submitted']['products'] = array(
      '#title' => 'Products',
      '#type'     => 'radios',
      '#weight'  => '2',
      '#options'  => _get_products_by_termid(array($tid)),
      '#prefix' => '<div id="products-div">',
      '#suffix' => '</div>',
    );
  }
}

function _show_products_based_on_category_term($form, $form_state) {
  return $form['submitted']['products'];
}

function _get_products_by_termid($termids) {
  $nids = taxonomy_select_nodes($termids);
  $products = [];
  if (!empty($nids)) {
    foreach ($nids as $nid => $value) {
      $products[$value] = node_load($value)->title;
    }
  }
  return $products;
}

```
> 1 votes

# Answer
1) Have you looked at the Hierarchical Select module? https://www.drupal.org/project/hierarchical\_select
> 0 votes

---
Tags: 7, taxonomy-terms, hooks, webforms
---


# Question
Title: User must click Back button twice after adding item in cart
I have added Drupal Commerce in an existing D7 site and I use the existing product nodes, in which I have added the Add to cart form. Everything looks nice and works fine, except for one thing. When a user adds an item into the cart and then tries to go back one step by clicking the browser back button, he or she stays on the same page. So the user must click twice to go back one step. The history information about previuos pages, must still be there since one lands on the correct page, after clicking twice.

Maybe I should mention that I use Authcache with Ajax calls to fetch the Cart block on cached pages, but i think this behaviour started before I installed Authcache.

How can I fix this?

# Answer
While, not an specific answer. Just to point out another possibly cause, this could be caused by JS.

https://developer.mozilla.org/en-US/docs/Web/API/History\_API#Adding\_and\_modifying\_history\_entries

Basically, there are ways of modifying the history via JS. There might be some code somewhere that's introducing this. Not sure which module though.

Assuming JS, what you probably should look into is calls to,

```
 history.pushState()
 history.replaceState()

```
> 0 votes

---
Tags: 7, commerce, ajax, caching
---


# Question
Title: limit access to private files uploaded by webform to specific role
In my Drupal 7 site, I have a webform where anonymous users upload a file (typically, their CV). The webform is configured to save it in the private file system. How can I achieve that the uploaded files are accessible only to authenticated users who belong to a specific role ? (at this moment they are accessible only to the admin user)

thanks

# Answer
By default, users with the 'access all webform results' permission can view all webform private files.

If, for some reason you need them to be able to access the files but not the webform results, you could implement `hook_file_download()` \- you could base your implementation on `webform_file_download()` in webform.module
> 1 votes

# Answer
Think you need Private files download permission
> 0 votes

# Answer
Personally I would use Permissions per Webform and then limit accessing all results for that particular webform to the roles that you need.

The only issue at that point would be if you had multiple roes needing multiple levels of results access.
> 0 votes

---
Tags: webforms, users, files
---


# Question
Title: How to transfer a panel variant from one site to another?
Is there a way to do this with Features? I can't download and install any additional plugins to do this on this site.

Would anyone know if this is possible?

# Answer
Yes, Panels and panel variants can be exported using the Features module. If you are using the panel variant as a part of page manager the option to export variant is shown in the features UI under **page\_manager\_handlers**.

Check the screenshot below to see how sample variants of the node view (`node/%node`) page can be exported via features:
> 4 votes

---
Tags: 7, panels, features
---


title: Calculating Course cost per student

text:
# Question
Title: Calculating Course cost per student
My Scenario:
One admin user is entering these information.
I have 3 content types: student, register, course.
Student is obvious, i.e. student\_number, personal\_info, etc
Course contains: course\_name & course\_costs, etc.
Register contains: ref to course, course\_date, ref to students who attend this course.

My question: How would I go about calculating/working out costs per student, per course?

Do I need to use rules? I assume commerce is out of the picture, as one admin user is entering this information. Any direction would help. Thank you.

# Answer
Is this value stored on the Register Content Type?

You can use the `computed_field` module.

You will need to read every value in `ref_to_course` field. Load each of those nodes. From there, read the `course_cost` and add the values.

Then store the values on the computed field.

---

Another option is using `views` module. You can attach a View to the content type. The view can then use the node `NID`, read the `ref_to_course`. Add relationship, read the `course_cost` and add those.

---

I think the first might be better since you calculate it once.
> 0 votes

---
Tags: views, rules
---


# Question
Title: Gravatar does not work with anonymous accounts
I enabled the avatars\_gravatar submodule from Avatar Kit and configured it to be the only available Avatar Generator in `admin/config/people/avatars`. The Gravatar is rendered for logged in users, but not for anonymous users that leave a comment.

Is this a configuration issue or do I need to alter a template? I'm using the standard Bartik theme.

# Answer
Unfortunately anonymous accounts arn't supported at this time, because they are a special case. Avatar Kit is currently written to work with Drupal user entities, which anonymous accounts are not.

Follow https://github.com/dpi/avatars/issues/30 for progress
> 1 votes

---
Tags: 8, media
---


# Question
Title: how to give path to custom page tpl for content type
I want to give the path for custom page tpl which I have created for specific content type. 'test\_insights' is my content type name.I have created custom page tpl in the folder

```
project_name/themes/themename/templates/page--test_insights.tpl.php

```

I want to know how to give the path for created tpl now I tried `http://localhost/project_name/test_insights`

I caught the error as

> The requested page "/project\_name/test\_insights" could not be found

.

# Answer
If I understood your question correctly, you are looking for `hook_menu`. You can find the API here.

An Example:

```
function mymodule_menu() {
    $items['test_insights'] = array(
      'page callback' => 'mymodule_test_insights',
      'page arguments' => array(),
    );
    return $items;
  }

//The callback function
function mymodule_test_insights(){
    //Do the necessary actions
    return $something;
}

```

Note: After implementing the `hook_menu` you have to clear the drupal cache to access the URL.

To add content type specific page `tpl` you have to use `theme_hook_suggestions` by implementing template\_preprocess\_page. You can add the below code in the `template.php` file of your theme

Example:

```
function themeName_preprocess_page(&$vars, $hook) { //themeName change to your theme name
  if (isset($vars['node'])) {
  // If the node type is "test_insights" the template suggestion will be "page--test--insights.tpl.php".
   $vars['theme_hook_suggestions'][] = 'page__'. str_replace('_', '--', $vars['node']->type);
  }
}

```
> 2 votes

---
Tags: 7, views, theming
---


# Question
Title: How to remove suggestions for a input field?
Many browsers use a sort of autocomplete function. So the moment you already entered data in a field it will be added to there remembering list.

I would like to have no suggestion for fields.

A solution for this is using autocomplete on/off for the input fields http://www.w3schools.com/tags/att\_input\_autocomplete.asp I do not understand the compliance for the different browser...

I use many fields in my system. I do not want this for all fields.

There are some solution with modules but not for all fields: https://www.drupal.org/project/no\_autocomplete = only working for login screens

What ways are there to implement this in a easy way in Drupal 7? I guess to have a hook\_form\_alter but then?

I guess something like this:

```
  ' Setuplist with fields automcomplete should be off
    afields_setautomcompleteoff ("fieldname1", "fieldname2","fieldname3")

    ' Look if the current form contains a fields with should be edited
    if(count(array_intersect(?????, $afields_setautomcompleteoff)) == 1){
        'add att to input field but how?
    };

```

Any suggestions?

# Answer
> 1 votes
Take a look at hook\_form\_alter. Also refer to the drupal FAPI, there are many form controls are available which you can use in a form.

For your case, below example will be helpful.

```
function example_form_alter(&$form, &$form_state, $form_id) {
  if($form_id === 'your_form_id'){
     $form['your_field']['#attributes'] = array('autocomplete' => 'Off');
  }
}

```

Other option is with JS.

```
Drupal.behaviors.exampleModule = {
  attach: function (context, settings) {
    $('input[type="text"]').each(function (i, input) {
      $(input).attr('autocomplete', 'off);
    });
  }
};

```

---
Tags: 7, entities
---


# Question
Title: Why are all files (except index.php) being redirected to 'index.html'?
We have a Drupal 7 Drupal Commerce site that we've just moved to our virtual private apache server, however we're seeing very strange behaviour that's making the site not work.

We're getting a strange problem where many files (images, CSS, JS) are getting "**307: Temporary redirect**"s to 'index.html', which doesn't even exist.

We have a very ordinary apache setup (no unusual settings), and the htaccess file of our website is straight from Drupal core - we haven't edited ourselves.

Is this a problem with the way we've set up Drupal, apache, DNS, or something else?

# Answer
> 0 votes
There is a Rewrite Rule written in `.htaccess` as,

```
# Pass all requests not referring directly to files in the filesystem to
# index.php. Clean URLs are handled in drupal_environment_initialize().
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]

```

This may be your problem.

There are few assumptions that can be the reason why its happening :

* Please check the method you the using to access files.
* It might be your server issue which does not provide correct access rights for accessing the files
* Your files are not properly placed in correct locations.

---
Tags: 7, .htaccess
---


# Question
Title: What is the proper way to add third party script snippets to head tag?
I understand I can hard-code this snippet into html.html.twig but i would prefer a cleaner method. My research is only instructing me how to attach libraries etc, but I can't find any example of injecting code into the header area needed by some third-party services.

I tried the following code, but it doesn't seem to work.

```
/**
 * Implements hook_page_attachments().
 */
function THEME_page_attachments(&$page) {
  /**
   * Initial JS.
   */
  $javascript_header = "-----js code -----";

  $page['#attached']['html_head'][] = [
    // The data.
    [
      // Add a <script> tag.
      '#tag' => 'script',
      // Add JavaScript to the <script> tag.
      '#value' => \Drupal\Core\Render\Markup::create($javascript_header),
      // Give weight so it appears after meta tags, etc.
      '#weight' => -1,
    ],

    'key'
  ];
}

```

# Answer
Your issue seems to be related with hook\_page\_attachments() not called from mytheme.theme file. If you look to the answer, it's written -

> It appears that this function is only callable from a module, as it is listed in Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 module but not listed as a valid method in Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 theme.

I verified with the current documentation & that's correct. You can use hook\_page\_attachments\_alter, which has documented in above given document for **Adding stylesheets and JS to a Drupal 8 theme**.
> 0 votes

---
Tags: 8, theming, javascript
---


# Question
Title: How to generate a Commerce order from a CSV?
I'm using Drupal 7 with commerce. Is there a way to generate an order from a csv or similar? the idea is that users could upload a csv (sku and quantity for now) with the items they want and the system generate an order with that.

i'm trying with feeds and the entity processor but i can't import the line items and create de order in the some process (they have to be related with an order). If this is the way, it's not clear to me how to do that.

# Answer
Im not sure how to make csv directly to order, but this should work:

* create a node type, called "csv order"
* use Feeds module to fetch the data from csv to this node type
* install module hook\_post\_action
* write a custom module, which after saving node "csv order" would take data from this node, and create commerce order with line items
* remove the csv order node if neccesary
> 0 votes

---
Tags: 7, commerce
---


title: Change form input attribute

text:
# Question
Title: Change form input attribute
I have form with an alt attribute like the following.

```
<input type="text" alt="abc">

```

I want to replace that attribute with *data-alt*.

I tried the following code, but it doesn't seem to work.

```
function theme_form_alter(&$form, &$form_state, $form_id) {
    foreach($form["submitted"] as $newForm)
    {
        foreach($newForm as $keyid=>$frmArr)
        {
            if(isset($frmArr[]["#attributes"]["alt"]))
            {
                    $alt = $frmArr["#attributes"]["alt"];
                    unset($newForm[$keyid]["#attributes"]["alt"]);
                    $newForm[$keyid]["#attributes"]["data-alt"] = $alt;
            }
        }
    }
}

```

The following code is not working either.

```
foreach($form["submitted"] as $newForm)
    {

        foreach($newForm as $keyid=>$frmArr)
        {
            if($keyid=='#attributes'){
                $newForm[$keyid]['data-alt']=$newForm[$keyid]['alt'] ;
                 unset($newForm[$keyid]['alt'] );
                $form["submitted"]['#attributes']['alt'] = array("sss");
                form_set_value($form["submitted"]['#attributes']['alt'], array("aaa"), $form_state);
            }
        }

    }

```

What code should I use to achieve what I want?

# Answer
> 0 votes
```
function act_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'the_id_of_your_form') {
    unset($form['submitted']['#attributes']['alt']);
    $form['submitted']['#attributes']['data-alt'] = 'abc';
  }
}

```

Won't this work?

---
Tags: 7
---


# Question
Title: Node post date in views exposed filter as a select list
I want to add a node post date exposed filter to the views in the following format.

The date exposed filter will be a select list with the following options:

```
All
Today
Yesterday
Past Week
Past Month
Past Year

```

It it possible with views or I have to do some workaround?

No one has an answer for this question?

# Answer
I have done it with the following steps.

Added a post date exposed filter, with option `Grouped filter` instead of `single filter`.

Widget type `Select`. With the following options in the table

```
  Label        Operator                       Value

  Today        is greater than or equal to    today

  Yesterday    is greater than or equal to    -1 day

  Past week    is greater than or equal to    -1 week

  Past month   is greater than or equal to    -1 month

  Past year    is greater than or equal to    -1 year

```
> 0 votes

# Answer
You can start with Views, dealing with **Combined** **filters.** Try it with option **Grouped**.
> 0 votes

---
Tags: 7, views, datetime
---


# Question
Title: Access to selected taxonomy terms on user profile field
I have a taxonomy vocabulary `Area`. The terms of this vocabulary are the main menu items. There are no other links in the main menu.

I have a term reference field on user profile.

For every user the main menu should only display those terms which are selected on their profile and have to access to those taxonomy terms only.

Is it possible with any contrib module? Or any idea how to achieve this functionality?

# Answer
I have achieved this functionality with the following method.

Created a `taxonomy term type` view which will list only the top level terms.

Added a relationship to view `Taxonomy term: User using Area`

Added another relationship `Taxonomy term: Parent term`

Added a contextual filter on uid for currently logged in user.

This will list only those terms which are selected on user profile. And then display this view as a main menu in the panels.

And then using rules, I return `Access denied` if a user try to access the taxonomy term page which is not selected on his/her profile.

Hope it will help someone.
> 0 votes

---
Tags: 7, users, taxonomy-terms
---


# Question
Title: Weform: Send email to the email field in the node reference field using rules
I have content type `Organiser`. and it has an email field `Organiser email`.

I have created a webform and added a node reference component which is referencing the `Organiser` content type.

I want to send an email on webform submission to the email address entered in the `Organiser email` in referenced node.

Is it possible with rules without entering the php code in the rules action?

# Answer
> 0 votes
I have done some work around to get this functionality.

Created a `hidden component` to the webform.

Then through `hook_form_alter`, get the organiser email from the `referenced node` and set it as the default value to that hidden field.

Then in the webform email settings, I selected that hidden webform component as the "`Email to address`".

---
Tags: 7, rules, webforms
---


# Question
Title: How to programmatically delete a display from a view?
I am trying to programmatically delete an existing view’s display (at the same time as deleting a node) but I am not able to find the good implementation.

```
HOOK_node_delete(Drupal\Core\Entity\EntityInterface $node) {
//[…]
$view = Views::getView("VIEW_MACHINE_NAME");
$display_name = "block_1";
$views_display = $view->storage->getDisplay($display_name);
//[…]

```

I can access to the view’s display using the view entity (storage) but as the display has protected access I can’t delete it.

Any help?

# Answer
> 3 votes
DisplayPluginCollection has a remove() method:

```
$view->displayHandlers->remove($display_id);

```

But this doesn't work and I couldn't find any code which is trying to actually remove the display from configuration.

So you would have to do this yourself in the view entity (storage):

```
$view = \Drupal\views\Views::getView('myview');
$storage = $view->storage;
$displays = $storage->get('display');
unset($displays[$display_id]);
$storage->set('display', $displays);
$storage->save();

```

The problem is this will not run the remove code of the display. For a block display this doesn't matter, but if you delete a page display you might consider running the remove method mentioned above before deleting the display from storage. This will delete the menu links from the page.

---
Tags: views, 8, hooks
---


# Question
Title: Can payment be done in pop-up rather than using redirect?
We have an online store with a few hundred products, and we'd like to streamline the checkout & payment process.
Currently our payment processor requires the website to be redirected to their site to make the payment, then the user is redirected back to our site for confirmation.

Instead of redirecting our users to the payment processor's site, can we open the payment processor's site in a popup? I think the popup could either be a separate window (though that might be extra complicated), or as a lightbox (possibly using an iframe).

Does Drupal Commerce support this sort of thing, and is it safe to do or not recommended (as a security risk)?

We're using Drupal 7. Our site is a fairly standard online store.

# Answer
> 2 votes
If your gateway tells you to redirect, you redirect. If you need a modal-based gateway, choose another gateway. Changing the flow recommended by your gateway puts you firmly in unsupported waters, and definitely exposes you to additional risk. This is especially true since redirected gateways require PCI A compliance, while modals require the slightly more complex PCI A-EP compliance.

I would also expect most gateways to have protection against this.

# Answer
> 0 votes
Yes it can be done in pop-up/iframe. But that would require development of custom form to take card info & send to payment gateway for further authentication & processing..

Some valuable information available here - https://drupalcommerce.org/user-guide/payments. There is a module authorize.ent shown in the example on this page which enable on-site payment. You can take help from that module's code.

---
Tags: commerce, payment-gateways
---


title: Hide a field from "Manage display"

text:
# Question
Title: Hide a field from "Manage display"
If a field is set a hidden on *Manage display*, unless it's displayed in a view, it cannot be seen anywhere on the site.

Specify how fields are displayed says:

> **Format**
> The format column contains the options to show the field value in different formats. Hidden is the global value which is present in all the format option list. If you choose hidden, it will hide the whole field from showing on the content page.

I understand it hides a field from the view mode, but you can also hide it if you don't try to do by using those modules, which are designed to output fields, like the Views module.

Is there still any possibility that users can see the hidden field even if those modules are not used?

# Answer
If you use, on *Manage display* the *hidden* format (not *label: hidden*), the field won't show for the display mode for that content type. The field could still be shown in another display mode, for example the one for teasers. You need to set the field to hidden for all the display modes.

It is still possible to make a view with the Views module that displays the field. It depends on how you set up the view. If you set up a view of teasers, the standard teaser display is used (and the field is hidden according to the display settings). If you make a view of fields, you just have to avoid picking the "secret field."

If this is an existing Drupal site where this content type and field is a part of many different views and/or other modules, you will need to test this out. Also if the field is searchable or hard-coded in some template.
> 0 votes

---
Tags: 7, entities
---


title: templates, products and teasers

text:
# Question
Title: templates, products and teasers
I do not really know where to look anymore. I'm using D7 and Drupal Commerce and I would like to display a block using a rendered entity. I created my node--product-display--new-teaser.tpl.php and everything works fine, until I try to load a field from the related product: field\_images. The difference is that in the default version field\_images display using an imagezoom, while the new node: new-teaser (that I have created under product display) only display the first image.

What I would like to do, is to render in my node--product-display--new-teaser.tpl.php the field\_images coming from the node: new-teaser new product display mode.

# Answer
There is a way to do what I am trying to do: in your **product\_display** display mode, in your product field, you chose: rendered entity, and in rendered entity options, you will be able to select your new **product** display mode.

I hope this helps somebody.
> 0 votes

---
Tags: 7, theming
---


# Question
Title: Ubercart Coupon - only allow one coupon per order, but always apply the most recently entered one
Currently when someone adds a coupon to a cart which already has a coupon applied, we get the message "This coupon combination is not allowed", leaving the original coupon on the order.

How do we change that behavior so that newly added coupons get applied to the order, while the previous one gets deleted? There is never a case in which two coupons would be allowed on an order.

# Answer
> 0 votes
The answer is very simple but will only work if you **do not** want to allow multiple coupons per order.

Visit /admin/store/settings/coupon and uncheck "Allow multiple coupons to apply to a single order"; Save the configuration. Now the most recently applied coupon will be the only one added to the order.

---
Tags: 7, ubercart
---


# Question
Title: Entity reference field pointing to a Configuration Entity
I develop a custom statistics module to log all node views of a chosen bundles, file downloads and the keywords used to filter a view.

Then I build my Entity Log with a user reference (who does the action), a node reference and a file reference. I want to know if I can make a views reference to point the View (as a configuration entity) that the user searched for some keyword.

I don't know if this is crazy... Is it possible to reference a view from an entity?

I'm using drupal 8

# Answer
> 2 votes
This is no problem, in ui you can configure bundle fields referencing all entity types, content and configuration. And for base fields this is an example from the user entity for a reference field pointing at the configuration entity `user_role`:

```
$fields['roles'] = BaseFieldDefinition::create('entity_reference')
  ->setLabel(t('Roles'))
  ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED)
  ->setDescription(t('The roles the user has.'))
  ->setSetting('target_type', 'user_role');

```

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


# Question
Title: how to add user programatically without interfering with cas module?
I have created a module that bulk create user entities depending on ldap filters and assign selected roles . The problem is the connection with cas is then not working when a user entry has been already created

here is my code so far:

```
<?php /**
* @file
* Contains \Drupal\example\Form\ExampleForm.
*/

namespace Drupal\my_import_ldap\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

/**
* Implements an example form.
*/
class MyImportLdapSettingsForm extends FormBase {

/**
* {@inheritdoc}
*/
public function getFormId() {

return 'my_ldap_import_settings_form';
}

/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {

    $system_roles = user_role_names(TRUE);

    $form['ldap_filter'] = array(
        '#type' => 'textarea',
        '#title' => $this->t('LDAP Filter'),
        '#description' => t('Specify LDAP filter used to populate Drupal user account'),
    );

    $form['actions2']['#type'] = 'actions';
    $form['actions2']['submit'] = array(
        '#type' => 'submit',
        '#value' => $this->t('Save Filter'),
        '#button_type' => 'primary',
    );

    $form['roles_list'] = array(
        '#type' => 'checkboxes',
        '#title' => $this->t('Rôles'),
        '#description' => t('Select the roles to assign created account'),
        '#options' => $system_roles,
    );

$form['actions']['#type'] = 'actions';

$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Import to Drupal People'),
'#button_type' => 'primary',

);
return $form;
}

/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {

}

/**
* {@inheritdoc}
 *
 * @author m.Dandonneau
 *
 *
 * add or update users, corresponding to the LDAP filters and add the selected roles
 *
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
    if ($_POST['op']== 'Import to Drupal People'){

        $filter = $form_state->getValue('ldap_filter');
        $roles =$form_state->getValue('roles_list');
        $selected_roles=array();
        foreach($roles as $key => $value)
        {
            if(is_string($value))
            {
               $selected_roles[]=$value;
            }
        }

        //retrieve ldap settings yml from my_ldap module
        $my_ldap_config = \Drupal::service('config.factory')->getEditable('my_ldap.config_settings');
        $restrictions = explode(",", $my_ldap_config->get('my_ldap_restrictions'));
        $server = $my_ldap_config->get('my_ldap_server');
        $port = $my_ldap_config->get('my_ldap_port');
        $dn = $my_ldap_config->get('my_ldap_dn');
        $rootdn = $my_ldap_config->get('my_ldap_root_dn');
        $rootpw = $my_ldap_config->get('my_ldap_root_pwd');

        $attributes = array();
        $ds = ldap_connect($server, $port);
        if ($ds) {
            $r = ldap_bind($ds, $rootdn, $rootpw);
            $sr = ldap_search($ds, $dn, $filter, $restrictions);
            $info = ldap_get_entries($ds, $sr);

            $selected_users=array();
            if ($info["count"] > 0) {
                for($i=0;$i<$info["count"];$i++)
                {
                    $account=$this->create_update_drupal_user_account($info[$i]["uid"][0],$info[$i]["mymail"][0],$selected_roles);
                    $this->set_cas_user_name($account,$info[$i]["cn"][0]);
                    $selected_users[] = $info[$i]["uid"][0];
                }
                drupal_set_message($this->t('@selected_users ont été ajoutées ou updatées aux utilisateurs avec le(s) roles @selected_roles', array('@selected_users' => json_encode($selected_users),'@selected_roles' => json_encode($selected_roles))));
                \Drupal::logger('my_import_ldap')->notice($this->t('les personnes aux uids suivants @selected_users ont été ajoutées ou updatées avec le(s) roles @selected_roles', array('@selected_users' => json_encode($selected_users),'@selected_roles' => json_encode($selected_roles))));

            }
            else{
                drupal_set_message($this->t("le filtre LDAP @filtre n'a retourné aucun utilisateur", array('@filtre' => $form_state->getValue('ldap_filter'))));
                \Drupal::logger('my_import_ldap')->error($this->t("le filtre LDAP @filtre n'a retourné aucun utilisateur", array('@filtre' => $form_state->getValue('ldap_filter'))));
            }
        }
    }

    if ($_POST['op']== 'Save Filter')
        drupal_set_message($this->t('update filter', array('@number' => $form_state->getValue('ldap_filter'))));

}

   public function create_update_drupal_user_account($user_name,$user_mail,$roles){

       $lang = \Drupal::languageManager()->getCurrentLanguage()->getId();

       $uid = \Drupal::entityQuery('user')
           ->condition('name', $user_name)
           ->execute();

       if(!empty($uid)){
           $uid=(int)reset($uid);
           $user = \Drupal\user\Entity\User::load($uid);
       }

       if (!$user) {
           $user = \Drupal\user\Entity\User::create();
           //table structure is UNIQUE KEY `user__name` (`name`,`langcode`)
           $user->setUsername($user_name);
           $user->set("langcode", $lang);
           $user->enforceIsNew();
           $user->setEmail($user_mail);
          /*$user->setPassword(user_password());*/

       }

        foreach ($roles as $role)
            $user->addRole($role);

       $user->activate();
        $result = $user->save();

        return $user;
    }

    /**
     * @param $account
     */
    public function set_cas_user_name($account,$ldap_common_name){

        $lang = \Drupal::languageManager()->getCurrentLanguage()->getId();
        $uid=$account->get('uid')->getValue()[0];

        $db = \Drupal::database();
        $query=$db->insert('user__field_cn_ldap')->fields(
            array(
                'bundle' => 'user',
                'entity_id' => $uid['value'],
                'revision_id' => $uid['value'],
                'langcode' => 'en',
                'delta' => 0,
                'field_cn_ldap_value' => $ldap_common_name,
            )
        )->execute();

         $cas_user_manager = \Drupal::service('cas.user_manager');
         $cas_user_manager->setCasUsernameForAccount($account, '$ldap_common_name');
    }
}

```

# Answer
my cas common name was wrong cause it is not the same as the ldap common name, here is the lines i have changed to make it work:

```
 $this->set_cas_user_name($account,$info[$i]["cn"][0],$info[$i]["uid"][0]);

 public function set_cas_user_name($account,$ldap_common_name,$cas_common_name){

 $cas_user_manager->setCasUsernameForAccount($account, $cas_common_name);

```
> 0 votes

---
Tags: 8, authentication-authorization, users
---


# Question
Title: Restrict publishing to certain Taxonomy Terms
Greetings and salutations. I am struggling to find a solution to the following matter:

**Goal:**
A Taxonomy named Sections has terms like *Term 1, Term 2, Term 3*. The goal is to only allow users to **publish** content under *'Term 1'* and *'Term 2'* and any content posted under *'Term 3'* **will not be automatically published** and put to the moderation queue.

**Modules tried (with no success):**
Taxonomy Access Control
Taxonomy Tools

# Answer
> 1 votes
I have found a solution with the Rules module.

Here's how I managed to get it to work:

1) install the module
2) activate it
3) GO to /admin/config/workflow/rules and add a new rule
4) set post type to my post type
5) Added an OR condition
6) Under that OR condition added Data Comparision to \[node:field-section:tid\] to my term's ids
7) in Action added unpublish content

Seems to be working so far.

# Answer
> 0 votes
Each Term we can connect with content type by "term reference" Each content type we controlled publish or unpublish

---
Tags: taxonomy-terms, users
---


# Question
Title: Improve extremely slow 'drupal_process_form'
I am having problem investigating why our profile edit page is damn slow.

```
Call Stack
#   Time    Memory  Function    Location
1   0.0003  276344  {main}( )   ...\index.php:0
2   1.6889  39666816    menu_execute_active_handler( )  ...\index.php:21
3   1.6899  39668968    call_user_func_array:{C:\wamp\www\hyperDrupal\includes\menu.inc:527} ( )    ...\menu.inc:527
4   1.6899  39669448    entity_ui_get_form( )   ...\menu.inc:527
5   1.6901  39696720    drupal_build_form( )    ...\entity.module:1282
6   1.7842  40984120    drupal_process_form( )  ...\form.inc:385
(7) 17.3247 58502824    form_execute_handlers( )    ...\form.inc:903
8   17.3247 58503344    profile2_form_submit_handler( ) ...\form.inc:1519
9   17.3265 58492400    profile2_save( )    ...\profile2.module:621
10  17.3265 58492528    Profile->save( )    ...\profile2.module:311
11  17.3265 58491736    Entity->save( ) ...\profile2.module:918
12  17.3265 58492096    EntityAPIController->save( )    ...\entity.inc:333
13  17.3737 58517352    EntityAPIController->invoke( )  ...\entity.controller.inc:462
(14)    23.5502 90243232    module_invoke_all( )    ...\entity.controller.inc:355
15  23.5511 90247648    call_user_func_array:{C:\wamp\www\hyperDrupal\includes\module.inc:951} ( )  ...\module.inc:951
16  23.5511 90248096    bdEvent_entity_update( )    ...\module.inc:951
17  23.5511 90248832    bdE\bdEvent->dispatch( )    ...\bdEvent.module:44
18  23.5567 90332840    bdE\Services\profileService->run( ) ...\bdEvent.php:38
19  23.5568 90333120    bdE\Services\profileService->entity_get_values( )   ...\profileService.php:24

```

I created a stack trace in a new module and times are huge. Check step 7 and 14 both are after long operations.

What could be taking so much between

```
6   1.7842  40984120    drupal_process_form( )  ...\form.inc:385
7   17.3247 58502824    form_execute_handlers( )    ...\form.inc:903

```

and between

```
13  17.3737 58517352    EntityAPIController->invoke( )  ...\entity.controller.inc:462
14  23.5502 90243232    module_invoke_all( )    ...\entity.controller.inc:355

```

# Answer
Based on the backtrace, you won't know why your site is slow.

You should run a proper PHP profiler and analyse the results which can identify the slowest components.

It doesn't have to be Drupal it-self, but could be lack of caching or misconfiguration.

Some suggestions:

* disable modules which you don't need (e.g. Devel, core Database Logging module, etc.),
* upgrade your PHP to the latest or higher branch,
* recompile your PHP for 64-bit or higher architecture depending on your CPU,
* use the faster storage device for your db files or whole LAMP environment (e.g. SSD or memory-based filesystem),
* use PHP debugger or profiler to find out any performance bottleneck (e.g. XDebug Profiler, DTrace or NuSphere PhpED PHP Profiler),
* run some time-consuming drush command under gprof profiling tool, so you can find some performance bottleneck as well.

If disabling slow modules or profiling won't help, see: How do you improve Drupal performance?
> 2 votes

---
Tags: 7, forms, entities, performance, debugging
---


# Question
Title: How to correctly start a website using Git/Drush/Composer workflow?
I am trying to follow this article to start a D8 site: https://www.drupal.org/node/803746

The article is for D7 but I think there are no much differences.

These are the steps I followed so far:

* Cloned Drupal 8.2.x repository to my dev environment
* Branched to 'my-project'
* Created a remote repo, replaced it as my 'origin' and renamed Drupal.org to 'drupal'.
* copied the example .gitignore as is, it by default ignores settings.php and vendor folder.
* Ran `composer install` at root
* Installed Drupal to local MySQL instance (after settings up Apache)
* Committed and pushed files of the entire site to repository
* Created staging environment and cloned from repository
* Copied settings.php, dumped dev database and re-imported it to staging, and re-ran `composer install` at staging environment
* I ran `drush rebuild` to refresh cache.

I expected this to be all and now the staging environment should be up and running, but it is running with now style, apparently the themes are not correctly copied.

So my first question is what did I miss, do I have to use composer to install core themes?

My second question is, do I have to re-install any additional theme or modules using composer on all sites? Or in other words, why is it a good practice to git-ignore vendor folder rather than install once on dev env and pull dependencies from repository?

---

Below is a screenshot for how staging main page looks like:

---

\[EDIT\] Checking the /admin/reports/dblog page, these was the warning that appeared a lot:

```
warning: file_put_contents(temporary://filexmZMo3): failed to open stream: "Drupal\Core\StreamWrapper\TemporaryStream::stream_open" call failed in file_unmanaged_save_data()

```

# Answer
> 0 votes
Because my dev environment was Windows and the staging environment was Linux, the temporary folder differs.

I had to fix it using the admin pages of the file system.

Later I found that I will need to do this every time I use `drush config-import` so I decided to overwrite the value in `settings.php` as following:

```
$conf['file_temporary_path'] = '/tmp';

```

---
Tags: 8, drush, workflows, version-control, composer
---


# Question
Title: How to create a simple form to redirect the user to entered URL?
I want to create a simple form to redirect the visitors to a relative path they enter.

I created a search page with views and it has lots of exposed filters. I don't want to use this exposed filter as block.

On the main page I want to show only a simple search form and if the user enter a `word` then submit search button, it should redirect the user to `example.com/advanced-search?full_text=word`.

How can I do that?

# Answer
> 1 votes
I used a very simple method for this. I created a custom block and add this HTML code:

```
<form action="advanced-search" method="GET">
   <input type="search" name="full_text">
   <button type="submit">Search</button>
</form>

```

# Answer
> 2 votes
Have a look at the Rules Forms Support module. Some more details about it (from its project page):

> Rules Forms Support provides a Rules based method for controlling forms and their elements. The module can be used to alter any form provided by Drupal core or contributed modules. Change element titles, descriptions, weights, and more, or validate form data and set form errors. Rules forms saves time and cost by affording site builders the ability to monitor and alter forms without the need to implement a custom module.
>
> For help getting started with Rules Forms Support, please see the module documentation.
>
> Features
>
> * Activate events for form creation, validation, and submission on a form-by-form basis.
> * Target individual form elements or the entire form in conditions and actions.
> * Manipulate the attributes of a form element like title, description, weight, and more.
> * Validate the values of form elements during form validation.
> * Set form errors when rule-based validation fails.
> * Redirect users to a different page upon viewing or submitting a form.
> * Examine the attributes of elements in active forms with the element inspection tool.

Especially the "***Redirect users to a different page upon viewing or submitting a form***" should help to address your question.

---
Tags: 7, forms, search, redirection
---


# Question
Title: How to set up this view of commerce orders...?
Really hope someone can help me with this as am completely stuck, sorry it's a bit long but I don't know what else to do...

I'm working on a commerce site for a client that offers blocks of pilates classes. Users will purchase blocks of 6 classes in order to book onto them.

I have one product in the store called 'standard-6-block' at a price of £45.

I then have a product display called 'Class (Block)'.

The Class (Block) nodes will list 6 dates using just a text field with an unlimited number allowed (although each block will just have 6 classes added)

Blocks of classes run for 6 weeks, hence the 6 dates in each node, and will be added every week.

For example there may be one Class (Block) node with 11/01/2017, 18/01/2017, 25/01/2017, 1/02/2017, 8/02/2017, 15/02/2017 dates.

There will then be another node added a week later with 18/01/2017, 25/01/2017, 1/02/2017, 8/02/2017, 15/02/2017, 22/02/2017 dates.

This is because users may start blocks of classes at different times so we've agreed blocks will be added each week.

I now need my client to be able to run reports using a views page to show who has booked on to each class. (Not each block of classes (node) but individual classes in blocks (dates in the 'Class Dates' field in the node).

I've created one test order in my store which has purchased just one block of classes. There are currently 4 blocks of classes available to purchase on the website.

My view settings are: View of: Commerce Orders

Relationships: Commerce Order: Line items, (Line items referenced by commerce\_line\_items) Commerce Line item: Product, Commerce Order: Owner, (Products referenced by commerce\_product) Commerce Product: Referencing Node, Commerce Order: Payment Transaction

Filters: (Node referencing products from field\_product\_type) Content: Class Dates (exposed) and is REQUIRED!

Now when I run the report and enter a date for example 18/01/2017, the view doesn't just show the ONE order in the store IE this user has registered and paid for this class, it shows all 4 of the nodes that have been added.

Really hope that makes sense...? Thank you so much for taking the time to help me

# Answer
> 1 votes
Turns out I need to make every block of classes individual products in the store and use 'Auto product display' module to automatically create the node displays. Then have to create a view that lists the commerce products rather than node displays

---
Tags: commerce, views
---


# Question
Title: Programmatically adding fields to specific vocabularies
Is it possible to add fields to vocabulary terms programmatically in a custom module?

I know it can be done at admin/structure/taxonomy/news\_client\_sites/fields in the UI, but I'd like to add the fields during the module install process.

I have specific vocabularies I've created during hook\_install, but I'd like to be able to add fields to them as well.

# Answer
It turns out that with taxonomies, vocabularies are bundles of taxonomy\_term entities.

So, it turned out to be something like this:

Assuming a taxonomy machine name of example\_taxonomy

```
  $field_example = array(
    'field_name' => 'field_example',
    'cardinality' => 1,
    'type' => 'text',
  );
  field_create_field($field_example);

  $field_example_instance = array(
    'field_name' => 'field_example',
    'label' => st('Example Text Field'),
    'bundle' => 'example_taxonomy',
    'entity_type' => 'taxonomy_term',
    'widget' => array(
      'type' => 'text_textfield',
    ),
  );
  field_create_instance($field_example_instance);

```

So, yeah, it turns out that taxonomy\_terms are the entities and vocabularies are the bundles...
> 2 votes

---
Tags: 7, taxonomy-terms
---


# Question
Title: Commerce / Rules - commerce-order:mail is empty for anonymous users
I'm having trouble sending order notification emails to anonymous users. As a bare-bones test I have created a new rule which triggers on 'Completing the checkout process', checks if the current user is authenticated, and if not sends an email to \[commerce-order:mail\]. When it's triggered I get the following error message, suggesting it is not able to get the email address from the order.

`Error sending e-mail (from admin@ourwebsite.com to ).`

I'm fairly sure the problem isn't to do with Rules config as it's so simple, but here is the export anyway:

```
{ "rules_anonymous_order_notification" : {
"LABEL" : "Anonymous Order Notification",
"PLUGIN" : "reaction rule",
"OWNER" : "rules",
"TAGS" : [ "Commerce Checkout" ],
"REQUIRES" : [ "rules", "commerce_checkout" ],
"ON" : { "commerce_checkout_complete" : [] },
"IF" : [
  { "NOT user_has_role" : {
      "account" : [ "site:current-user" ],
      "roles" : { "value" : { "2" : "2" } }
    }
  }
],
"DO" : [
  { "mail" : {
      "to" : [ "commerce-order:mail" ],
      "subject" : "Order received!",
      "message" : "This is to tell you the order has been received.",
      "language" : [ "commerce-order:state" ]
    }
  }
]

```

} }

What else could be causing this?

EDIT: I've just noticed in the db the mail column is empty for anonymous orders in 'commerce\_order' - is this normal?

# Answer
> 1 votes
Have a look at issue # 430274, about an event which is a variation of your event here, and somehow explains that "after saving something" actually happens ... "before saving something" (which is not a bug, simply how the Rules module works ...).

A possible compromise to avoid these kind of issues, is to transform what you're trying to do in your **Rules Action** in a Rules Component, so that your **Rule** "schedules the execution" (using the Rules Scheduler submodule) of that Rules Component. For example after only a few seconds or minutes later on (if your cron job runs frequent enough, otherwise it'll be next time cron runs). This compromise will ensure that, at the time the Rules Component is executed, the "Checkout process" for sure completed, and your "eMail ID" will have been updated as expected.

# Rules debugging

If none of the above helps, then move on to Rules **debugging**, as explained in my answer to "How can I display the value of a variable inside a condition?".

Depending on what the result of that type of debugging is, you may also want to (temporary) enable the Devel module, so that you can (temporary) add a Rules Action like "Display a value" (in your case of your `commerce-order:mail`). It may help to check if the cause of your problem is because of what is written in the comments from james, i.e.:

> anonymous user won't be having any mail, that is why the commerce order also not having any mail. There is an option in commerce to allow the user to login while checkout. I believe the functionality works fine. I usually ask user to login before proceeding to checkout itself. So, I have never faced the above mentioned issue with commerce and rules.

# Answer
> 1 votes
If the mail property for the order isn't being populated, it could be you have disabled the "Account information" checkout pane or allowed customers to bypass it somehow. (For example, an off-site payment method may not result in the mail being properly populated depending on how the payment gateway was integrated.)

---
Tags: 7, commerce, rules, emails
---


# Question
Title: Products discount pinned at the top of the lists
I would like that when a product at a discount, it is "Pinned to the top of the lists" automatically.

And when a product does not have a discount, it is no longer "Pinned to the top of the lists".

How to do this with a rule?

# Answer
Unfortunately you cannot do this with a rule. Whether or not something is sticky depends on how Views sorts a list of products, and there is no sort handler that I'm aware of that would show discounted products first. The closest you could come to would be an extra field on your products that you set when you enable the discount to identify a discounted product. You would then be able to sort by that field value.
> 0 votes

---
Tags: 7, nodes, commerce, rules
---


# Question
Title: How can I tell to the rule I am writing that the value of region field is the value coming from webform data?
I successfully created a webform using the Webform module.

Using Webform Rules I can create a new entity of type user and I fill the requested fields using, for example, `[data:name-value-raw]` for name, `[data:surname-value-raw]` for surname, etc...

This is very easy for text fields but I have troubles with text list fields, in my custom user fields I have two text-list fields (region list and country list), I set the same list in the webform.

In the Rules Action "Create a new entity" the Rules UI tells me to set a value for these fields but I'm forced to choose from a value in the list.

If I `Switch to data selection` I can't find submitted values, so how can I tell to the rule I am writing that the value of region field is the value coming from Webform data?

# Answer
> 0 votes
> If I switch to data selection I can't find submitted values, so how can I tell to the rule I am writing that the value of region field is the value coming from webform data?

You can use a technique similar to what is described in my answer to "How to do a data comparison to submitted webform data when using the Rules module?". For short:

* Add an extra Rules Action to `Add a variable` (call it whatever you want), with a value assigned to it equal to your `[data:ComponentFieldName-value-raw]` (with a data type which equals the data type of your Webform component), and with `ComponentFieldName` whatever you're using for that region field in your Webform).
* In your subsequent Rules Actions you can refer to the value of this variable you just added (that's the clue!).

---
Tags: rules, webforms
---


# Question
Title: How to integrate Lockr encryption key with Ubercart credit card payments
We migrated a client to Pantheon hosting a couple months ago. The site’s ubercart payments worked consistently on the old hosting platform, but have only worked sporadically on pantheon and I’m trying to resolve the issue. It seems that the only payments that go through are ones made immediately after Drupal’s caches have been flushed.

I believe the problem is due to the credit card encryption: while I can set a directory in ubercart’s “Encryption key directory” field and I can see that the key does get generated, most payment transactions fail.

Ubercart wants you to store this key outside your doc root or in sites/default/files/private. I think this probably works perfectly on a normal hosting platform, but on Pantheon, the structure is different with sites/default/files/private not within the site's doc root.

I have read both of these pantheon guides: https://pantheon.io/docs/guides/lockr/ and https://pantheon.io/docs/private-paths/. Based on this info, I have installed the Drupal Key, Encrypt and Lockr modules and have enabled them.

In the Key module admin UI, I was able to signup for a Lockr account and add an encryption key of type Lockr encryption.

But now I don’t know how to make ubercart use this Lockr key. In Ubercart’s payment settings, under “Encryption key directory” it expects/requires a path to the key: what would this be for a Lockr key?

In the README for the Key module under the section "Using Keys" it seems to indicate I will have to write a custom module to make the Lockr key appear as a selectable option in the ubercart key directory settings. But I worry this may be beyond my abilities or consume vast amounts of time to figure out.

Is there an easy way to make ubercart use a Lockr key? Or has anyone written a custom module for this they'd be willing to share?

# Answer
> 0 votes
A kindly developer wrote a patch for Ubercart that integrates Lockr key. It's working great for me.

You can find the patch here: https://www.drupal.org/node/2842813

Note: it's written for version 7.x-3.9 which isn't the latest, so it may have to be modified and rerolled for the current version.

---
Tags: 7, ubercart
---


title: Issues settings up drush + phpunit

text:
# Question
Title: Issues settings up drush + phpunit
I'm trying to set up drush + phpunit, following these two guides:

Here's what I have so far:

* macOS Sierra 10.12.2
* PHPUnit 5.7.5 at `/users/wim.mostrey/.composer/vendor/bin/phpunit`
* Drush 8.1.9 at `/users/wim.mostrey/.composer/vendor/bin/drush`
* Drush tests at `/users/wim.mostrey/.composer/vendor/drush/drush/tests`
* a simple test `migrateManifestTest` at `/users/wim.mostrey/.composer/vendor/drush/drush/tests/migrateManifestTest.php`

I try to run the test using the following command:

```
UNISH_NO_TIMEOUTS=1 UNISH_DRUPAL_MAJOR_VERSION=8 ./unish.sh --filter=migrateManifestTest

```

However I get the following error:

```
PHP Fatal error:  Class 'Unish\UnitUnishTestCase' not found in /Users/wim.mostrey/.composer/vendor/drush/drush/tests/bootstrap.inc on line 51

```

I tried searching online for this error but got no results at all. I tried running both `unish.sh` and `phpunit` from different locations and using different configuration options, to no avail.

Any help would be highly appreciated.

# Answer
> 1 votes
Alright so here's what I did, with help from MegaChriz.

The dev dependencies for Drush need to be installed and the phpunit version that comes with Drush should be used instead of a 'general' phpunit. So not the one I installed through composer.

1. Git clone of Drush from my home folder (`/users/wim.mostrey`)

```
git clone https://github.com/drush-ops/drush.git
cd drush
git checkout 8.1.9

```
2. Install Drush with dev dependencies using Composer while being inside the Drush folder

```
composer install

```
3. Execute built-in tests pointing to the phpunit version from Drush:

```
UNISH_NO_TIMEOUTS=1 /users/wim.mostrey/drush/vendor/bin/phpunit --configuration /users/wim.mostrey/drush/tests --filter=ImageCase

```

or for Drupal 7 tests:

```
UNISH_NO_TIMEOUTS=1 UNISH_DRUPAL_MAJOR_VERSION=7 /users/wim.mostrey/drush/vendor/bin/phpunit --configuration /users/wim.mostrey/drush/tests /users/wim.mostrey/Sites/drupal7/sites/all/modules/feeds/tests/drush

```

---
Tags: testing
---


# Question
Title: Views information not bolding used templates
The templates used in my views are not bolded (template information). I do not know if this due to a module interaction.I have checked with different administration themes but does not show up anything.I would like to know how to get back this valuable information.

I have also tried an alternative solution that did not work. I have enabled the theme debug mode, and looked for the template used in the source code. It show the default template while i have a another (specific) one.

I have been looking around without any success!

# Answer
I finally found out the issue. I was using Role theme switcher and i have selected a new theme to test it. It seems that this does not work well with my production theme, and this conflict between themes makes the views template bug. I have disabled one of the themes and it works. Thanks for your time
> 0 votes

---
Tags: views, theming
---


title: Set number of slides shown for mobile?

text:
# Question
Title: Set number of slides shown for mobile?
I'm using the Slick Carousel module in my D7 layout and it's awesome. My carousel view is currently set to Grid, and to display 9 slides at a time. That said, how can I set the view to display a different number of slides (at different sizes) when the site is being viewed from a mobile device? For example, if the browser is open on a phone and only 414px wide, I want to display 1 slide in the carousel instead of 9 slides with their current image style.

# Answer
> 3 votes
You need to enable the **Slick UI**, then press on configure.

Click on the List tab, and edit the default.

You need to add some breakpoints, make sure you select the correct skin.

---
Tags: 7, theming, javascript
---


title: Image cropping only from top

text:
# Question
Title: Image cropping only from top
I am having some trouble configuring my image cropping styles. I have an image I want to crop and scale from 600x800 to 140x140, But I only want the cropping to be from the top. At the moment the cropping is equally from the top AND bottom. How can I achieve this, because I can't find any offset setting although Drupal 7 cropping functionality in the API supports it.

Thanks in advance

# Answer
I just tried this on my D7 site I am making and if you go to admin/config/media/image-styles/list you can add a new style. Inside the new style you add an effect to crop and then you can choose the anchor point. The anchor point will allow it to crop from the top instead of equally top and bottom. You can then set your field to display using that style in the display settings or in views or whatever you showing it in.
> 6 votes

# Answer
As said, using the "Scale" and then "Crop" effects separately is the way to go, as "Crop" has an "Anchor" option that allows you to crop from top. (In contrast to the "Scale and Crop" effect you tried.)

However, because you want to scale *and* crop and not just crop, this technique gets into troubles when source images can be both in portrait and landscape aspect ratio. (Because Drupal lacks a scale effect that scales to cover the target size – it always scales to fit on a canvas defined by your target size.)

Here's a modification that works:

**Solution that works for mixed aspect ratio images**

1. Create an image style `topcrop_landscape` with these effects:

* "Scale" with "height: 140 px" and "width: " left empty.
    * "Crop" to 140x140 px with "Anchor: center, center".
2. Create an image style `topcrop_portrait` with these effects:

* "Scale" with "width: 140 px" and "height: " left empty.
    * "Crop" to 140x140 px with "Anchor: horizontal center, vertical top".
3. Create an image style `topcrop` with these effects:

* "Aspect Switcher" that selects `topcrop_landscape` and `topcrop_portrait` for the landscape and portrait cases, respectively.

Source: inspired by article "Fitting Portrait and Landscape Images to One Size in Drupal"
> 2 votes

---
Tags: 7, media
---


# Question
Title: Autocomplete field not using Entity Reference list settings
I'm using an Entity Reference field set to **Views: Filter by an entity reference view**. That works. I can choose my view: **maps\_by\_project\_season – Entity Reference**.

I've chosen 3 fields in the view, and added them all to **Format: Entity Reference list** via **settings**, and I see all 3, separated by -, in the preview.

But not in the autocomplete field. That only shows the title. What am I missing?

# Answer
> 2 votes
This is a known bug in Drupal 8, see: View output is not used for autocomplete display you could try the patch in #76

There was also another disccusion about the same thing here Views Filter by an entity reference view not working as expected, before it was closed as duplicate.

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