# Question
Title: Local json migration: how to set the value of the urls variable?
I'm currently really busy to get the migration work on my desk. I want to import (migrate) a local json file into drupal8 using Migrate\_Plus, Migrate tools. For that I have the following migration yml configuration file

```

# Migration configuration for products.
id: product
label: 'Product'
migration_group: Products
# Here we define the migration source
source:
  plugin: url
  data_fetcher_plugin: file
  data_parser_plugin: json
  urls: /modules/custom/migrate_products/data/data.json
  item_selector: /data
  fields:
    -
      name: uuid
      label: 'uuid'
      selector: uuid/value

    -
     name: name
     label: 'Produkt Name'
     selector: name/value

    -
      name: supplierName
      label: 'Anbietername'
      selector: supplierName/value

  ids:
    uuid:
     type: string

destination:
    plugin: entity:node

process:
  type:
    plugin: default_value
    default_value: produkt

  title: name
  field_uuid: uuid
  field_suppliername: supplierName

  sticky:
    plugin: default_value
    default_value: 0
  uid:
    plugin: default_value
    default_value: 0

migration_dependencies:
  required: {}
  optional: {}

dependencies:
  enforced:
    module:
      - migrate_products

```

Like you can see, the json file is located inside the custom module directory.

The json file looks like this:

```

{
  "data": [
    {
      "uuid": {
        "value": "7d51-4406-a7ef-3a7916b977a9",
        "patient": false
      },
      "name": {
        "value": "Product1",
        "patient": false
      },
      "supplierName": {
        "value": "User1",
        "patient": false
      },
.....

```

After enbaling the required migration module, when running: **drush ms** I get the following output:

```

file parser plugin: could not retrieve data from /modules/custom/migrate_products/data/data.json
 Group: Products (Products)  Status  Total  Imported  Unprocessed  Last imported
 product                     Idle    n. v.  0         n. v.

```

# Answer
> 0 votes
The data fetcher plugin can't find your JSON file because the format is wrong. The plugin is expecting Drupal's `URI` format (e.g. `public://path/to/data.json` or `private://path/to/data.json`) under its private/public file dir. For example, see the included example migration with the module:

```
  # The data_parser normally limits the fields passed on to the source plugin
  # to fields configured to be used as part of the migration. To support more
  # dynamic migrations, the JSON data parser supports including the original
  # data for the current row. Simply include the 'include_raw_data' flag set
  # to `true` to enable this. This option is disabled by default to minimize
  # memory footprint for migrations that do not need this capability.
  # include_raw_data: true
  # Flags whether to track changes to incoming data. If TRUE, we will maintain
  # hashed source rows to determine whether incoming data has changed.
  # track_changes: true
  # Copy the example JSON file in artifacts folder to sites/default/files folder.
  urls:
    - 'public://migrate_json_example/products.json'

```

---
Tags: migrations
---


# Question
Title: What is the procedure for deleting a project in drupal.org?
I created a project in drupal.org but decided that a better name would better suit the project, so I created another one. I need to delete the old project.

What is the official procedure to delete the old project node?

# Answer
> 4 votes
If your project contains code usually it is not deleted. In that case, you can select as Project classification ***Unsupported*** and as a Development status ***Obsolete***.

You can always create a post in the Drupal.org webmasters issue queue explaining your situation and requesting the project deletion.

But I can tell you that if you have people using your module, they will not delete the project.

# Answer
> 2 votes
The official procedure is asking for the project to be deleted in the Drupal.org webmasters issue queue by creating a new issue. The project is not deleted if there is committed code, or there are issues for that project.

If the project has committed code, and you just wanted to change short name to the project, since project short names cannot be changed once the project is created, just mark the project as unsupported, after you created the new project, and committed code.

Possibly, you should also create a stable release for the new project, so the maintainers of those sites using the old project who receive a warning about the project not being anymore supported would find a production release to use.
Together this, you should also add a link to the new project in the old project page.

### Disclaimer

I am a Drupal.org webmaster, and what I described is the procedure we follow when handling requests for deleting projects, and what the Drupal.org Infrastructure Team suggests to the webmasters who handle those requests.

---
Tags: community-official-site
---


# Question
Title: How do you create a link to a modal dialog?
The following code does not work:

```
<div class="topics"><a class="use-ajax" data-dialog-type="modal" href="/topics-listing">All Topics</a></div>

```

Drupal 8.6.5. Bootstrap subtheme. Chrome console log shows no errors. Rather than a modal, the referenced page opens.

So, how do you create a link to a modal dialog in Drupal 8?

# Answer
> 4 votes
This html looks ok, but did you include the `core/drupal.dialog.ajax` js library that attach event to your link ?

In twig :

```
{{ attach_library('core/drupal.dialog.ajax') }}

```

In PHP, it looks like this :

```
$renderArray = [
            '#title' => t('All Topics'),
            '#type' => 'link',
            '#url' => Url::fromRoute('XXX'),
            '#attributes' => [
                'class' => ['use-ajax'],
                'data-dialog-type' => 'modal',
            ],
            '#attached' => [
                'library' => ['core/drupal.dialog.ajax'],
            ],
];

```

---
Tags: modal-dialogs
---


# Question
Title: Create fields programmatically via content type settings
I want to make a module to create custom fields to a content type. But I want to be able to turn the fields on and off via the content type edit page.

So I want to add a tab to the vertical tab part at the bottom of the content type edit page where I have a single on off checkbox. When selected and saved, fields are created. When not selected the fields will be removed (or not created).

I created the option in the node type form. By using this:

```
function HOOK_form_node_type_form_alter(&$form, &$form_state){
$form['new_option'] = array(
    '#type' => 'details',
    '#title' => t('NEW OPTION'),
    '#group' => 'additional_settings',
);

$form['new_option']['new_option_options'] = array(
    '#type' => 'checkbox',
    '#title' => t('Create fields'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#weight' => 10,
);
}

```

But how can I save the value of the checkbox in config and use it as default\_value.

# Answer
Thanks Clive, I ended up using the following code to set and get the config settings.

```
function module_name_form_node_type_form_alter(&$form)
{
    //get node type
    $bundle = $form['type']['#default_value'];
    $node_type = NodeType::load($bundle);

    //create vertical tab
    $form['new_option'] = array(
        '#type' => 'details',
        '#title' => t('New option'),
        '#group' => 'additional_settings',
    );

    //add checkbox to vertical tab
    $form['new_option']['new_option_options'] = array(
        '#type' => 'checkbox',
        '#title' => t('New option checkbox'),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        '#weight' => 10,
        '#default_value' => $node_type->getThirdPartySetting('new_option','new_option_options'),
    );

    //create submit handler
    $form['actions']['submit']['#submit'][] = 'module_name_form_submit';
}

function module_name_form_submit(&$form)
{
    //get node type
    $bundle = $form['type']['#default_value'];
    $node_type = NodeType::load($bundle);

    //set checkbox value to config and save
    $node_type->setThirdPartySetting('new_option','new_option_options',$form['new_option']['new_option_options']['#value']);
    $node_type->save();

   //enable/disable fields
}

```
> 0 votes

---
Tags: 8
---


# Question
Title: Is there a single Drush and or Drupal console command to export and import all configurations?
Normally I goto Config Sync then export all \> save config tar.gz \> import.

Can this be achieved with one command?

# Answer
> 2 votes
Drush has two commands. cex and cim, for export and import.

Example:

`drush cim`

# Answer
> 1 votes
To export config use:

```
drush cex

```

@see https://drushcommands.com/drush-8x/config/config-export/

---

To import config use:

```
drush cim

```

@see https://drushcommands.com/drush-8x/config/config-import/

---
Tags: drush, configuration, console
---


# Question
Title: Adding a cache tag to an entity view display doesn't do anything?
I wrote a module that implements hook\_entity\_view\_display\_alter(). I modify the display settings of one of the fields depending on some configuration setting of my module.

```
/**
 * Implements hook_entity_view_display_alter().
 */
function ps_events_entity_view_display_alter(EntityViewDisplayInterface $display, array $context) {
  // Change the date formats of the date field on the full page display based
  // on configured settings.
  if ($context['entity_type'] === 'node' && $context['bundle'] === 'ps_events' && $context['view_mode'] === 'ps_full_content_no_lb') {
    $eventsSettings = \Drupal::config('ps_events.settings');
    $dateComponent = $display->getComponent('field_ps_events_date');
    if ($dateComponent) {
      $dateComponent['settings']['date_format'] = $eventsSettings->get('detail_page_date_format_day_and_time');
      $display->setComponent('field_ps_events_date', $dateComponent);
      $display->addCacheTags(['config:ps_events.settings']);
    }
  }
}

```

However, the cache tag I add doesn't seem to have any effect. When I inspect the `cache_render` table and look at the entry for this entity view display, my cache tag is not present. Changing the settings of my module does not clear the cache for this entity view display.

As a workaround, I also implement hook\_entity\_view\_alter(), which operates on the complete render array of the entity view display. I add the cache tag here and it works.

This seems like either a bug in core, or maybe I misunderstand the purpose of cache tags on the EntityViewDisplay object?

# Answer
> 2 votes
For that to work, core would have to use getCacheTags() from that config entity, which it doesn't do.

I'm not sure if that should be changed, core currently does not add the cache tags of that entity on purpose, instead it it invalidates the generic {$entity\_type}\_ cache tag on saving such an entity in \Drupal\Core\Entity\Entity\EntityViewDisplay::postSave(). Consdering that this changes only very infrequently once a site is live, this is more performant as there are fewer cache tags to check on each request.

---
Tags: 8, caching
---


title: My Date in Twig is ignoring format

text:
# Question
Title: My Date in Twig is ignoring format
I have a twig file with the following code in my Drupal 8.4.4 site:

`<div class="value col-md-12">{{ node.field_date.value }}</div>`

And in my content type, manage display option, I have it formatted like this:

But on the website, it shows the date as

2019-01-16T23:00:00

What am I missing?

# Answer
You are printing the node value directly, which is bypassing the field formatter and other things (since you are not using the render array).

Do this instead:

`{{ content.field_date }}`

This will render normally and ensure field formatter settings are respected.
> 8 votes

# Answer
Try piping the value to twig's `date` function:

https://twig.symfony.com/doc/2.x/filters/date.html

That approach might give you something like this:

```
<div class="value col-md-12">{{ node.field_date.value | date("D M j G:i T") }}</div>

```
> 1 votes

---
Tags: datetime
---


# Question
Title: Programmatically change webform confirmation page
I've looked at the other similar questions but they don't answer this precise issue.

In my use case, a webform is displayed on an arbitrary entity page (such as "activity/xx"). (This is not a 'node' entity type.)

When completed I want the user to be returned to this page with no message, but we don't know what the value of "xx" is going to be when the webform is created, and the work is going to be done by non-technical staff.

It's possible to:

* Create the webform;
* Build the entity and select the webform;
* Note the entity ID created;
* Go back and modify the webform confirmation page;

But this is not good for non-techies. It's easier if they're told to go to the settings page and add a handler.

I just need to force the confirmation redirect to reload the current page.

I could probably manage if I could use tokens in the confirmation page URL, or in the settings handler but I see nothing that says I can and my testing hasn't worked.

I know I can get the source entity in a handler in the back end, so I ought to be able to jump there. I just don't want to break anything...

# Answer
> When completed I want the user to be returned to this page **with no message**
>
> I just need to force the confirmation redirect to reload the current page.

The following should do the trick:

---

Better yet:
> 1 votes

---
Tags: 8, webforms
---


# Question
Title: Display users webform submission as readonly?
Is there any built-in way to display the questions on a webform and the user's responses as read-only?

The site I'm building allows a user to answer survey questions up to a given cut-off time. Once they've submitted the answers and the time-limit ends they must be able to see what they said, but not change it.

I can't see any obvious way of doing that, is there an easy answer? :-)

I know I can modify each field individually in a form\_alter hook but that's not ideal...

# Answer
I have done an identical task, unfortunately this one of those unique use cases. Here is a snipped in my hook\_form\_alter

Basically, assuming there is no page element (not multi page):

```
if ($cutoff_time > $current_time) {

  $form['elements']['field_name']['#disabled'] = TRUE;

  $messenger = \Drupal::messenger();
  $messenger->addMessage(t('Time has expired, you can no longer change the value'), $messenger::TYPE_WARNING);

}

```

Otherwise (multipage):

```
$form['elements']['page_name']['field_name']['#disabled'] = TRUE;

```
> 0 votes

---
Tags: 8, webforms
---


# Question
Title: Is redirecting a 404 error page to the front page possible?
Is it possible to redirect all the pages returning a 404 error to the front page?

I am not sure the new Drupal 8 *Redirect* module (which combines the Drupal 7 version of the *Global redirect* and the *Redirect* modules) would help me to achieve this exact task.

# Answer
> 2 votes
If you go to the Basic Site Settings (/admin/config/system/site-information) and enter in "/" for the default 404 (not found) page does that work for you?

# Answer
> 0 votes
Couple of points from my system (Drupal8/ELB w/https)

1) Core Option - The core option only gives limited success

```
/admin/config/system/site-information

```

2) Community module - Better option seemed to be 'Redirect':

```
https://www.drupal.org/project/redirect

```

3) HTACCESS - if you have certain matches etc (eg. .asp/.aspx) : add something like this to .htaccess:

```
RedirectMatch 301 "\.asp(.*)$"  /

```

---
Tags: 8, redirection
---


# Question
Title: How to hide checkbox 'Notify user of new account' for roles who can add user
Have scenario in `Drupal 8`, where Editor role can add users with dummy mail and sends login info through phone SMS to added users.

Hence, the checkbox `'Notify user of new account'` should be hidden from the Add User form - so that emails do not bounce from dummy mail ids

Yes, checkbox does not do so when unchecked. But, I want this to be unclickable for Editors or set to unclicked OR hidden for good!

# Answer
> 1 votes
You can create a very simple module to do that

Module and folder name **suppress\_notify** but can be anything you choose

2 files inside

**suppress\_notify.info.yml**

```
name: 'suppress_notify'
type: module
description: 'Suppress notify for non admin users'
core: 8.x
package: 'Custom'

```

**suppress\_notify.module**

```
<?php

use Drupal\user\Entity\User;

/**
 * Implements hook_form_alter().
 */
function suppress_notify_form_alter(&$form, $form_state, $form_id) {
  //for registration form
  if($form_id == "user_register_form"){
    //for non admin users
    if(!User::load(\Drupal::currentUser()->id())->hasRole('administrator')){
      //disable the notify field
      $form["account"]["notify"]["#access"] = false;
    }
  }
}

```

Enable the module and all non `administrator` users should have the `Notify user of new account` hidden

---
Tags: 8, hooks
---


# Question
Title: Display any discounts only at cart / checkout stage
I am selling furniture, I also sell furniture accessories.

Both of these have their own Product Types.

I use 'Commerce Discount', 'Commerce Discount Extra' and a 'Workflow Rule' to offer a 20% discount on the accessories, but only when an item of furniture exists in the cart.

This rule composes of:

* **EVENT**: Calculating the sell price of a product.
* **CONDITIONS**:
    + Product Types: Furniture Accessories **AND**
    + Order Contains Products: \[a list of SKUs of every furniture item I sell\]
* **ACTIONS**: \[The name of the discount I set up in 'Commerce Discount'\] (which applies the 20% discount on any 'Furniture Accessory' products)

My problem is:

As soon as I add a piece of furniture to my cart, any furniture accessory product display price is discounted across the site. I'd like the prices to remain at full price when viewing the product display node, but only discounted once viewing the cart or the checkout process is underway.

It feels like their should be another Event, perhaps "Starting the checkout process" or "Viewing the cart"

# Answer
> 1 votes
When product sell prices are calculated via Rules, they are done so in the context of either a temporary line item (for products not in the cart) or the line item on an order (for products in the cart). This means you can check to see if the commerce-line-item:line-item-id is empty or not using something like the "Data value is empty" condition. In your case, you'd want to negate that condition so that if the line item ID is empty, the discount is not applied.

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


# Question
Title: Assigning new region in a display suite layout does not show contents placed inside newly created region
```
// rmch-content-2.tpl.php
<?php
/**
 * @file
 * Display Suite RMCH Two Column Header template.
 *
 * Available variables:
 *
 * Layout:
 * - $classes: String of classes that can be used to style this layout.
 * - $contextual_links: Renderable array of contextual links.
 * - $layout_wrapper: wrapper surrounding the layout.
 *
 * Regions:
 *
 * - $header: Rendered content for the "Header" region.
 * - $header_classes: String of classes that can be used to style the "Header" region.
 *
 * - $left: Rendered content for the "Left" region.
 * - $left_classes: String of classes that can be used to style the "Left" region.
 *
 * - $right: Rendered content for the "Right" region.
 * - $right_classes: String of classes that can be used to style the "Right" region.
 */
?>
<<?php print $layout_wrapper; print $layout_attributes; ?> class="<?php print $classes;?> clearfix">

  <!-- Needed to activate contextual links -->
  <?php if (isset($title_suffix['contextual_links'])): ?>
    <?php print render($title_suffix['contextual_links']); ?>
  <?php endif; ?>

  <div class="l-content themed-content">
    <div class="inner">
      <<?php print $content_left_wrapper; ?> class="ds-content-left <?php print $content_left_classes; ?>">
        <?php print $content_left; ?>
      </<?php print $content_left_wrapper; ?>>

      <<?php print $content_right_wrapper; ?> class="ds-content-right <?php print $content_right_classes; ?>">
        <?php print $content_right; ?>
      </<?php print $content_right_wrapper; ?>>
    </div>
  </div>

   <<?php print $content_right_wrapper; ?> class="ds-content-footer <?php print $content_footer_classes; ?>">
        <?php print $content_footer; ?>
   </<?php print $content_right_wrapper; ?>>

   <div class="page-links">
    <div class="ds-links">
      <?php print render(block_get_blocks_by_region('page_links')); ?>
    </div>
  </div>

</<?php print $layout_wrapper ?>>

<!-- Needed to activate display suite support on forms -->
<?php if (!empty($drupal_render_children)): ?>
  <?php print $drupal_render_children ?>
<?php endif; ?>

```

So I have added new footer region in the .inc for the layout rmch\_content\_2.inc

```
/**
 * @file
 * Display Suite RMCH Header 2 col, Content 2 col
 */

function ds_rmch_content_2() {
  return array(
    'label' => t('RMCH Content 2 col'),
    'regions' => array(
      'content_left' => t('Content Left'),
      'content_right' => t('Content Right'),
      'footer' => t('Footer'),
    ),
    // Uncomment if you want to include a CSS file for this layout (rmch_two_column_header.css)
    'css' => FALSE,
    // Uncomment if you want to include a preview for this layout (rmch_two_column_header.png)
    'image' => TRUE,
  );
}

```

I have added new region footer which is visible in the screenshot and added **Links field** inside Footer When I add **Links field** in the Content Left , it displays links but when I add it in the footer it does not show up and the variable print $content\_footer; inside tpl.php file turns out to be empty completely.
**What should I do the make sure blocks or fields added inside newly created regions show up.?**

# Answer
> 1 votes
You've made a `footer` definition but printing `$content_footer`. Try printing `$footer` or changing the name of the region to be consistent with the others (`content_`). Clear cache to see your changes.

---
Tags: 7, display-suite
---


title: Subscribe to any order state transition

text:
# Question
Title: Subscribe to any order state transition
I am trying to create a dynamic event subscription, for drupal8 commerce order state.

My use case is the following. I want to create an invoice for any order which goes into state e.g. PENDING. There is a custom state/transition yml which i have created.

Which state transition should trigger an invoice creation, i want to make this configurable.

So, the admin should be able to select specific states, in a custom settings form, and the system should only create invoices when an order enters to one of these states.

I need to create an event subscriber, which is dynamic according to the settings that the admin has entered.

In terms of code, in the event subscriber, i have the following code

```
public static function getSubscribedEvents() {
  $events = ['commerce_order.place.post_transition' =>'onTriggerInvoiceCreation'];
  return $events;
}

public function onTriggerInvoiceCreation(WorkflowTransitionEvent $event) {
  $invoice_creation_states = explode(",", $this->config_factory->get("my_custom_module.settings")->get("invoice_creation_states"));
  $current_state = $event->getToState()->getId();

  if(in_array($current_state, $invoice_creation_states)) {
    //create the invoice
  }
}

```

So, a far as i understand, i need to do one of the following

In function getSubscribedEvents, i read the my\_module.settings from configuration and find a way to construct the correct event subscriber. So, instead of

```
$events = ['commerce_order.place.post_transition' =>'onTriggerInvoiceCreation'];

```

i should do something like the following

```
$invoice_creation_states = explode(",", $this->config_factory->get("my_custom_module.settings")->get("invoice_creation_states"));
for($i=0;$i<count($invoice_creation_states);$i++{
  $events = ['commerce_order.'.$invoice_creation_states[$i].'.post_transition' =>'onTriggerInvoiceCreation'];

```

As this function is static, i don't seem to be able to get hold of the config service in order to get the $invoice\_creation\_states.

So next thought is to create a more generic event listener, for all order state changes, and in the corresponding listener callback e.g. onTriggerInvoiceCreation i could get the custom settings and make the above condition in order to execute or not the invoice creation code.

Question: Is there a more generic transition event than commerce\_order.TRANSITION\_ID.TRANSITION\_PHASE

something like

commerce\_order.ANY\_TRANSITION.ANY\_PHASE ?

# Answer
> 1 votes
This has recently been implemented in Fire generic events when transition are applied \[#2832415\].

---
Tags: 8, commerce
---


# Question
Title: How to do core development with composer-based install?
I'm using drupal-composer/drupal-project.

With that, `installer-paths` in *composer.json* installs core in web/core, it doesn't clone a full git repository.

I'd like a full repository, so I can reroll a patch for core on my dev site, within the project it will be used on, without having to clone https://git.drupal.org/project/drupal.git and configure an entirely new project…

**Is this even possible?**

i.e. a modification to *composer.json* that will install core (or anything else for that matter) as a fully functional repository (i.e. with `.git` directories) - so you can create new branches, run diffs against to generate patches, and so on.

# Answer
> 4 votes
I'm providing an answer to this even though it's probably off-topic and I have a heavy bias here.

For core development we shouldn't use a composer-based install pattern such as drupal-composer/drupal-project because we're modifying the software project itself. Generally `composer require` or `create-project` or `init` is used when we want to create a new library, project or piece of software and dependencies to it, but not when working on an existing library or framework.

1. At the moment the best way to get started if you are *new* to *core* development is to visit https://drupal.org/tools. Use either the ResilioSync option or download the latest quicksprint tools release instead. This is the tool set that the Core Mentoring program currently uses to get started from scratch.
2. This isn't the only place/work flow for core development. Many of the core/strategic initiatives, or working groups within core development, may have a preferred development environment. For instance the Javascript Modernization Initiative has excellent documentation for their unique work flow and challenges.
3. Of course, if you already have an environment, then cloning the repository and running `composer install` works as well.
4. Finally if Composer piques your interest, the Composer Initiative (this is probably only relevant from 2019-2021) may change the way that we can work on core. And this could be a way to contribute and answer your question.

Please ask any questions you might have in #contribute on Drupal Slack or in one of the contribution channels on either IRC or Drupal Chat.

---
Tags: 8, composer
---


# Question
Title: Webform with element that has logged in user's username
In my D8 site i have several webforms created. I would like to have a Webform element that will pull/prepopulate logged in user's username. Is there a way to achieve that from GUI?

The reason i want that element is that from within Webform Submissions i would like to be able to filter per Username of the user who submitted the webform. This way username will be included in submission data.

By default it allows filtering webform submissions per submission data only or administrative notes.

Thanks

# Answer
> 6 votes
You can create a Value element with a token to capture and store the current user's name.

```
name:
 '#title': 'User Name'
 '#type': value
 '#value': '[current-user:name]'

```

---
Tags: 8, webforms
---


title: dynamic drop down menu items

text:
# Question
Title: dynamic drop down menu items
I'm new in drupal and I would like to add a link Projects to the main navigation menu:

* Projects

```
  proj 1
  proj 2
  ...
  proj n

```

This link projects with a drop down menu with N links. Until now I can have this drop down menu but statically.

Q1. I would like to generate this drop down list dynamically. For example if I have 10 projects, the drop down menu will have 10 links. Is there a way to plug into the menu a drop down list result of a view? or a select list but in the menu?

Q2. For each project in the drop down menu, I would like to point to a page sending the node id of this selected node (the page have some block views). So I can use this node id in the contextual filters for the views I have in the pages. Is there a way to do this? Thank you

# Answer
> 0 votes
Q1. The module Menu Views allows you to "insert" views results in place of one menu item.

Q2. You'll need Views Contextual Filter Query and apply it to the views blocks you have on your pages.

Then you need to construct the links that have the project node id in query so it can be picked up by views on pages. The easiest way to do that is probably with Views. Create a new view listing pages, with Link to content as a field but override it to append the project id query, limit results to 1, details depend on your particular case, you haven't included enough info about the connections between projects and pages and possible other configuration.

---
Tags: views, navigation
---


# Question
Title: Override site's registration restriction on accepting invite
We have a custom module that uses the invite module to send invitation to non users. Our site is set to allow registration only by administrator to avoid spam. When the invitees accept the invite they cannot register as its not allowed by the site. Is there a way to override registration restriction when invitees try to register?

We are looking into duplicating registration form on another route then routing the invitees to register there instead of default route.

Any other suggestions to handle this situation?

# Answer
This is a bit hacky, but it could be done with the following:

> * my\_website.com/admin/config/people/accounts
>
> + Who can register accounts? - Visitors
> * Install https://www.drupal.org/project/redirect and add redirect `/user/register` to a basic page which says something like "Sorry, to register you need an invite. Please contact us to receive an invite."

Invited people can now log in to site but there is no way for people to access the user register page, as that page will redirect.
> 0 votes

---
Tags: 8, users
---


# Question
Title: System settings form data access validation
I have created system settings form for an image using `managed_file`.

```
$form['my_image'] = array(
  '#type' => 'managed_file',
  '#name' => 'Upload Image',
  '#title' => t('Upload Image'),
  '#default_value' => variable_get('my_image', ''),
  '#description' => t("Here you can upload setting image!"),
  '#upload_location' => 'public://my_image/',
  '#upload_validators' => array(
  'file_validate_extensions' => array('jpeg png svg jpg'),
  ),
  '#required' => TRUE,
);

```

How can I add the file view/download access on this file based on role?

# Answer
> 0 votes
It looks like the Field Permissions module is the answer to your case.

UPDATE: You could also use '#access' in your field definition, see this post

# Answer
> 0 votes
I have fixed this using hook\_file\_download hook-

```
/**
 * Implements hook_file_download().
 */
function my_module_file_download($uri) {
  // Allow to view/download only Authenticated user.
  global $user;
  if (in_array('authenticated user', $user->roles)) {
    if ($cpdf = variable_get('checklist_pdf')) {
      $file = file_load($cpdf);
      if ($file->uri == $uri) {
        return array(
          'Content-Type' => file_get_mimetype($uri),
        );
      }
    }
  }
}

```

And change upload\_location as private `'#upload_location' => 'private://my_image/',`

A module is also available Private files download permission for this.

---
Tags: 7
---


# Question
Title: how to override module's theme function in a custom module?
I'm a Drupal8 newbie. I installed a third party module simplelogin, and I attempted to change the `{{site_name}}` value in `page--simplelogin.html.twig` but can not find a right way.

I noticed that the variable is defined in simplelogin.module:

```
function simplelogin_preprocess_simplelogin(&$variables) {
  $path = \Drupal::service('path.current')->getPath();
  $module_path = drupal_get_path('module', 'simplelogin');

  $variables['#attached']['library'][] = 'simplelogin/simplelogin-library';

  // Able to use custom variables
  $variables['path'] = $path;
  $variables['base_path'] = base_path();
  $variables['logo'] = file_url_transform_relative(file_create_url(theme_get_setting('logo.url')));
  $variables['background_class'] = simple_login_settings('active');
  $variables['background_opacity'] = simple_login_settings('opacity');
  $variables['wrapper_width'] = simple_login_settings('width');
  $variables['site_name'] = \Drupal::config('system.site')->get('name');
  $variables['site_register'] = \Drupal::config('user.settings')->get('register');
}

```

I guess the second "simplelogin" presented in the hook function is a form element in the theme (I'm not quite clear although), as I found `$form['simplelogin']` appears in the buildForm function of form controller.

```
  public function buildForm(array $form, FormStateInterface $form_state, Request $request = NULL) {

    $form_state->disableCache();

    $simplelogin_config = $this->config('simplelogin.settings');

    $imageid = $simplelogin_config->get('background_image');
    if ($imageid) {
      $file = \Drupal\file\Entity\File::load($imageid[0]);  // File Load
      $fileUrl = $file->getFileUri();

      // check if image is valid.
      $image = \Drupal::service('image.factory')->get($fileUrl);
      if ($image->isValid()) {
        $image_render = array(
          '#theme' => 'image_style',
          '#width' => $image->getWidth(),
          '#height' => $image->getHeight(),
          '#style_name' => 'medium',
          '#uri' => $fileUrl,
        );
      }
    }
    //$renderer = \Drupal::service('renderer');
    //$renderer->addCacheableDependency($image_render, $file);

    $form['simplelogin'] = array(
      '#type'            => 'details',
      '#title'           => $this->t('Configuration'),
      '#open'            => TRUE,

      'background_active' => array(

```

**WHAT I HAVE DONE:**
1. created a custom module named "mylogin", this is the info.yml:

```
name: myLogin
description: my login module
type: module

version: '8.x-1.0'
package: 8.x
core: '8.x'
project: 'mylogin'

dependencies:
  - simplelogin

```

2. override hook\_preprocess\_page in mylogin.module:

```
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\file\Entity\File;
use Drupal\Core\Controller\ControllerBase;
use Drupal\simplelogin\Controller;

function mylogin_preprocess_page(&$variables) {
  if (\Drupal::routeMatch()->getRouteName() == 'user.login') {
    $variables['site_name']= 'test';
  }
}

```

But it cannot work, and I believe the preprocess is not triggered. Is there a simple way to override the needed variable while keep the others in the module's preprocess function? Any help will be very appreciated.

# Answer
> 1 votes
You can create a new module use hook\_theme\_registry\_alter like module simplelogin like this:

```
/**
 * Implements hook_theme_registry_alter
 *
 * {@inheritdoc}
 */
function YOUR_MODULE_theme_registry_alter(&$theme_registry) {
  $theme_registry['page__simplelogin'][preprocess functions] = [
    0 => 'simplelogin_preprocess_simplelogin',
    1 => 'YOUR_MODULE_preprocess_function'
  ];
}

```

---
Tags: 8, theming
---


# Question
Title: The only email header field that can be replaced is the Reply-to field?
Under the heading **E-mail header details** in the e-mail settings for my webform I have set the option **E-mail from address** to the component **E-mail**, from the current webform.

When the webform is submitted and recieved it works to click Answer in the recipient's Outlook client (the user e-mail from the webform is used in the TO field of the new mail).

But unfortunately this does not work when the recipient have enabled an auto reply, such as Out of office. In that case the address used in the auto-reply mail is the site's default e-mail address.

I have cleared all fields where the default FROM e-mail address can be stated (**Default e-mail values** in webform config, **E-mail options** in the SMTP settings) and tried with the option **Use Reply-To header** in the webform config both enabled and disabled.

I have also tried to use the variable $from instead of site\_mail in htmlmail.tpl.php.

Is there really nothing I can do to replace the FROM address with a custom address fetched from the webform? Apparently the only header field that the webform can replace is the **Reply-to** field?

# Answer
Not long after posting this question I found a working answer here The problem can be solved programmatically using hook\_mail\_alter,
> 0 votes

---
Tags: 7, webforms
---


title: How do I divide a row in sub rows?

text:
# Question
Title: How do I divide a row in sub rows?
If I want to divide a row into some sub-rows in Drupal 8, what should the code be?

The following code worked fine for simple tables. I need to do something with the `$rows` array to divide the rows in sub-rows. How can I achieve this?

```
$form['mytable'] = array(
  '#theme'  => 'table',
  '#header' => $header,
  '#rows'   => $rows,
  '#empty'  => t('Not Found.'),
);

```

# Answer
**Drupal 8:**

```
$table = [
  '#type' => 'table',
  '#header' => ['ab', 'cd', 'ef'],
  [
    [
      '#plain_text' => 'rowspan',
      '#wrapper_attributes' => ['rowspan' => 2],
    ],
    ['#markup' => '1'],
    ['#markup' => '1'],
  ],
  [['#markup' => '1'], ['#markup' => '1']],
];

```

**Result:**

See Drupal Documentation for a colspan example
> 3 votes

# Answer
This is still similar to how it was done in Drupal 7 and Drupal 6 with the use of colspan or rowspan attributes. The documentation for template\_preprocess\_table states

> Each cell can be either a string or an associative array with the following keys:
>
> * data: The string or render array to display in the table cell.
> * header: Indicates this cell is a header.
> * Any HTML attributes, such as "colspan", to apply to the table cell.

So the top row of your example image would be like such:

```
$rows = [
  [
    ['data' => '', 'attributes' => ['rowspan' => 3]],
    '',
    '',
    '',
  ],
  ['', '', ''],
  ['', '', ''],
];

```

in order to get the following HTML:

```
<tr>
  <td rowspan="3"></td>
  <td></td>
  <td></td>
  <tD></td>
</tr>
<tr>
  <td></td>
  <td></td>
  <td></td>
</tr>
<tr>
  <td></td>
  <td></td>
  <td></td>
</tr>

```
> 1 votes

---
Tags: theming
---


# Question
Title: Viewing an image file breaks if view mode has responsive image style
I have an image file that I am viewing programmatically. When I set the image format to "responsive image" in file display settings, it breaks with an error

```
Error: Call to a member function getMetadata() on null in file_entity_preprocess_responsive_image_formatter() (line 488 of modules/contrib/file_entity/file_entity.module).

```

My render code:

```
$file = File::load($fid);
$build = [];
if ($file) {
  $view_builder = \Drupal::entityTypeManager()->getViewBuilder($file->getEntityTypeId());
  $build = $view_builder->view($file, 'embed');
}

```

"embed" is the file view mode that sets the image to display as responsive.

There seems to be missing the "item" in the build array resulting from this, which is expected to be a fielditem. Am I doing something wrong?

# Answer
> 1 votes
This is not a proper answer, but a workaround in case someone else has this issue: detect if a responsive style is used, load it, and apply via theme layer (the style name is hard-coded to be "embed"):

```
if ($file) {
  $view_mode = \Drupal::entityTypeManager()
     ->getStorage('entity_view_display')
     ->load('file.' . $file->bundle() . '.embed');
  $content = $view_mode->get('content');

  // Responsive.
  if (!empty($content['uri']['settings']['responsive_image_style'])) {
    $build = [
      '#theme' => 'responsive_image',
      '#responsive_image_style_id' => $content['uri']['settings']['responsive_image_style'],
      '#uri' => $file->getFileUri(),
    ];
  }

  // Non responsive.
  else {
    $view_builder = \Drupal::entityTypeManager()->getViewBuilder($file->getEntityTypeId());
    $build = $view_builder->view($file, 'embed');
  }
}

```

---
Tags: 8, entities, theming
---


# Question
Title: Combine two different fields into one carousel
I have two fields:

* Video embed field
* Image multivalue field

I'm looking for a way to combine both fields into one carousel to display both images and videos.

An example of what I'm looking for can be seen on Steam: https://store.steampowered.com/app/236850/Europa\_Universalis\_IV/

# Answer
> 1 votes
I just started to provide an answer but realized this will result in an opinion-based answer. So I'll just roughly outline some possible procedures.

I'm presuming you have an existing site consisting of some Basic Pages and want to display multimedia slideshows on some of these Basic Pages.

* Option 1: Create a new Paragraphs Type "Slideshow", containing your video and image fields. Then add a Paragraphs field "Slideshow" to your Basic Pages. Use inline entity forms to let editors create slideshows directly where they will be displayed. Create a custom field formatter you then can choose in the display settings for this Paragraphs field. Build the field formatter to provide the markup you need and to attach your slideshow library.
* Option 2: Create a new content type "Slideshow" containing your video and image fields. Attach your slideshow library and adjust the markup to your needs. Then use either a new entity reference field in your Basic Pages to reference slideshow nodes and have them displayed as rendered entity. Or add an entity reference field to your Slideshow content type to let editors choose Basic Pages where they want this slideshow to be displayed and then have a Views block restricted to be displayed on all Basic Pages and this Views block has a contextual filter taking the current Basic Page node ID to display the corresponding slideshow(s).

This is a community wiki post. Please feel free to add other options.

---
Tags: 8
---


# Question
Title: How to implement a mysql date or datetime field correctly in hook_schema()?
I have written a mymodule.install file which contains a schema definition to create a table in my database. This table contains two data fields. Theese fields will be populated by the users when they will fill in the specific content (example: to specific a publish date for a news). Now i didn't used the Date contributed module on purpose, cause i needed that theese two fields were on the same row in the database table for other reasons.

The hook\_schema defines the two fields this way:

```
'pubblish_date' => array(
    'description' => t('The pubblish date for the single news'),
    'mysql_type' => 'datetime',
    'not null' => FALSE,
  ),
  'unpublish_date' => array(
    'description' => t('The unpublish date for the single news'),
    'mysql_type' => 'datetime',
    'not null' => FALSE,
  ),

```

The table is created correctly in the database, but i always get theese advice messages:

Field news\_board.pubblish\_date: no Schema type for mysql type datetime. Field news\_board.unpublish\_date: no Schema type for mysql type datetime. news\_board.pubblish\_date: no type for Schema type :normal. Field news\_board.pubblish\_date: no Schema type for type . news\_board.unpublish\_date: no type for Schema type :normal. Field news\_board.unpublish\_date: no Schema type for type .

Seems strange to me cause I red on the documentation to use the mysql\_type specification in order to store the datetime format in mysql database.

I know that Drupal supports natively timestamps and if you want to store a different date format you have to use specific definitions like mysql\_type or pgsql\_type according on the database yuo are using.

In discussions I found online lot of people used mysql\_type definition and from what I seen they solved the problem, so why it doesn't work for me?

Thanks a lot.

# Answer
> 12 votes
You should provide a fallback type (`varchar`) for the case that the database is *not* mysql.

```
'pubblish_date' => array(
  'description' => t('The pubblish date for the single news'),
  'type' => 'varchar',
  'mysql_type' => 'datetime',
  'not null' => FALSE,
),
'unpublish_date' => array(
  'description' => t('The unpublish date for the single news'),
  'type' => 'varchar',
  'mysql_type' => 'datetime',
  'not null' => FALSE,
),

```

However, the messages you see come from the Schema module. This problem is already recorded as issue #468644.

The implementation of the mysql datetime in your schema is fine. You can safely ignore these messages. I would say that these "advice messages" are caused by a bug in the Schema module.

# Answer
> 0 votes
If you need to use a record type not included in the officially supported list of types , you can specify a type for each database backend.

In this case, you can leave out the type parameter, but be advised that your schema will fail to load on backends that do not have a type specified. A possible solution can be to use the "text" type as a fallback. (https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Database%21database.api.php/group/schemaapi/8.2.x)

`'submit_date' => array(
 'type' => 'varchar',
 'mysql_type' => 'datet',
)`

---
Tags: hooks, datetime, entities, database
---


title: How do I customize breadcrumbs?

text:
# Question
Title: How do I customize breadcrumbs?
The breadcrumbs I get are like the following ones.

* Service

HOme

But I want to change them to the following ones.

* Service HOme\>\>Service

# Answer
> 1 votes
You can use theme\_breadcrumb something like:

```
function yourTheme_breadcrumb($variables) {
  $breadcrumb = $variables['breadcrumb'];

  if (!empty($breadcrumb)) {
    // screen-reader users. Make the heading invisible with .element-invisible.
    $output = '<h2 class="element-invisible">' . t('You are here') . '</h2>';
    $output .= '<ul class="breadcrumb">';
    foreach ($breadcrumb as $key => $value) {
      // Remove Br tags
      $output .= '<li>' . $value . '</li>';
    }
    $output .= '</ul></div></div></div></div>';

    return $output;
  }
}

```

Or if you want just alter the breadcrumb in some pages for example on `node/nid` you can do it in `hook_preprocess_HOOK` or `hook_node_view_alter` something like:

```
function yourModule_node_view_alter(&$build) {
  $breadcrumb = array();
  $breadcrumb[] = l(t('Home'), '<front>');
  $breadcrumb[] = l(t('Service'), '/Service');
  drupal_set_breadcrumb($breadcrumb);
}

```

---
Tags: breadcrumbs
---


# Question
Title: How to grant edit access for specific nodes to 1 or more selected users?
I am building a school site on Drupal 8. Among others, I have two content types, one for teachers, one for courses. Teachers also have user accounts and belong to a role, say 'teacher'.

I want teachers (authenticated site users who belong to the 'teacher' role) to be able to edit the pages of the courses they teach. The problem is, there are courses which are being taught by more than one teacher, hence I can't solve this simply by enabling 'edit own content' and have them as owners.

**So all in all, I want to give 'edit access' for specific nodes, to specific, sometimes multiple, users**.

I researched before asking this fairly simple question.

There is a very similar question here \- however its four years old, and the node access module which is suggested as a solution is not usable for Drupal 8 yet.

There is a mention of another module, flexi access, but that is only available for Drupal 7.

There is also a link to ACL, "an API for other modules to create lists of users and give them access to nodes", but that in itself is only in pre-release for Drupal 8, and a module which seems to be using it, Content Access has open security issues (and also is in pre-release status).

Searching around, I also found Permissions by Term module, seems stable and very well documented, however I didn't find it very intuitive to be honest, and also it seems to cater basically for restricting view access to nodes (as suggested here, but also from its video tutorial).

I want something simpler. And I obviously want all nodes to still be publicly viewable by anyone (even anonymous users, of course). So although Permissions by Term seemed a possible choice, I don't know if I can/should use it.

There is also the Group module which is frequently referenced, but that also seems an overkill and way too complicated for the simple task I want to accomplish.

I 'm a bit lost on this one .. It seems quite simple, yet I can't find a way to do it. Any help would be greatly appreciated ...

# Answer
It's been a long time, but I thought of answering this question so that it could perhaps be more helpful to people ending up here, looking for an answer.

First, I 'd like to thank all those who took the time and effort to write answers and comments - as a Drupal newbie myself, it helps a lot to have this kind of feedback from more experienced users (something that, in my opinion, Drupal lacks a little bit..)

Anyway, as I mentioned in my question, I had found a very similar question but I was reluctant to use the answer there because it was quite old, and the module suggested seemed unstable for Drupal 8 (still in beta - and with that note suggesting: "This module has a pre-release version for Drupal 8. ").

**However, I did solve my problem using the Nodeaccess module mentioned in that (now 5 years old) thread - it works alright, although still in beta for D8. I tested on a development site, and then used it on the production site, and it does what I want (i.e. - grant edit access to specific, sometimes multiple, users).**

So I just leave this here for future reference.
> 1 votes

# Answer
The Group module is what you should be looking at ... It's not °overkill° (as in your question), instead it's the only stable contributed D8 module available today that will also address your needs.

For this specific question, you'd enable the `gnode` submodule, and for each group type you would define the appropriate permissions (view, edit, delete, etc) for the various Content Types. Refer to my answer to "How to configure access to courses for teachers and students?" for a sample configuration.

**Note**:

Let me address (part of) your additional comment below this answer also, which is like so:

> I will need to have quite a few Groups in my case - one for each course taught by more than 1 teacher.

If I was to configure the Group module for your case, I would use an approach like so:

* Create a **Group type** = Courses.
* Create **Group roles** = Teacher and Student.
* Create exactly 1 Group for each possible Course, labeled (say) C1, C2, C3, ....
* Only grant the **Group Permission** to "edit" a node of content type "Course" to users who have been granted the "Group role" Teacher. And as per your "*I want all nodes to still be publicly viewable by anyone (even anonymous users)*", you want to grant "View" access to "Outsiders" and "Anonymous", and probably also to "Students".
* If only teacher (user) T1 is teaching Course C1, then only T1 is granted the Group role "Teacher" for (group) C1.
* If teachers (users) T2 and T3 are teaching Course C2, then only T2 and T3 are granted the Group role "Teacher" for (group) C2.
* When creating nodes of type "Course", assign them to 1 (and only one) Group (so either C1, C2, or C3, or ...). And decide about which teacher(s) (user(s)) Tx the newly created Course will be granted the Group role "Teacher".

Done ...

# Resources
> 8 votes

# Answer
If you have a content type `course` with an entity reference field `field_teachers` you can enable edit for multiple users like this:

*mymodule.module:*

```
use Drupal\node\NodeInterface;
use Drupal\Core\Access\AccessResult;

/**
 * Implements hook_node_access().
 */
function mymodule_node_access(NodeInterface $node, $op, $account) {
  $type = $node->bundle();

  if ($type != 'course' || $op != 'update') {
    return AccessResult::neutral();
  }

  $uids = array_column($node->field_teachers->getValue(), 'target_id');

  return AccessResult::allowedIf(in_array($account->id(), $uids))->cachePerUser()->addCacheableDependency($node);
}

```

If field\_teachers is not referencing users but another content type, then the uid of the teacher is probably stored in the referenced content type and you have to fetch the uid of each teacher from there. In this case add all nodes involved as cacheable dependencies, so that when a teacher's node is modified with a different uid the access result is invalidated.
> 5 votes

# Answer
You can look into the Workbench Access module. This allows you to restrict editing rights to nodes based on menu structure or a taxonomy.

You can create a taxonomy vocabulary for the different editor groups. Example terms may be 4th Grade Math, 5th grade Science, etc, or even just Math, Science, etc. Add a taxonomy reference field to your Courses node, this is used to assign your content to your Groups. Then you can assign your users (teachers) to the correct Group (which are just based on your taxonomy vocabulary) and all teachers in the group can edit the node.

You could implement a situation where each course creates a corresponding taxonomy term *automagically* when a course node is created. You can do this with hook\_ENTITY\_TYPE\_insert.

Something like the following:

```
function hook_node_insert($node) {
  if ($node->bundle() == 'course') {
    // Check if a term with the $node->title() already exists. (See below [1])
    // Or create a term (See below [2])

    // Then set your taxonomy term reference field with the new tid, or existing tid
    $node->field_my_tax_group_field[] = ['target_id' => $the_tid];

    // Then save the node.
    $node->save();
  }
}

```

If you use this technique, the only thing you'll need to do manually after creating a Course node is assign the correct users to the Group to allow them to edit it.

\[1\] Check if a term exists.

\[2\] Create a new taxonomy term
> 2 votes

# Answer
Another option heavily used in some D7 instances, and like other contrib, not fully ready for D8 is Organic Groups. Even if ready for prime time, though, it does have a bit of a learning curve, but can be quite handy. A use case (although still in D7) similar to your needs is COD (Conference Organizer Distribution), which is used to run major events like DrupalCon.

You may want to see if it works for you—but be forewarned—some solutions architects I work with have been pretty frustrated with the D8 version. This is due to the significant architectural changes between D7 and D8, but it may work in your case.
> 1 votes

---
Tags: 8, nodes, users
---


# Question
Title: migration process plugin not registering
My plugin aims to strip out html tags from titles being imported from xml Here is the error I'm receiving: FVFXF0ETHV2F:process$ drush mim complinet\_xml\_to\_node Drupal\Component\Plugin\Exception\PluginNotFoundException: The "stripouthtml" plugin does not exist. in \[error\] /Users/Sites/devdesktop/drupal8test/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php:52 Stack trace:

Here is the plugin which lives in custom/complinetmigration/src/Plugin/migrate/process

```
<?php

/**
 * @file
 * Contains \Drupal\complinetmigration\Plugin\migrate\process\StripOutHTML.
 */

namespace Drupal\complinetmigration\Plugin\migrate\process;

use Drupal\migrate\MigrateException;
use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;

 /**
 * @MigrateProcessPlugin(
 * id = "stripouthtml"
 * )
 *
 */
class StripOutHTML extends ProcessPluginBase {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    // $value: cut off .<nnn>Z and replace by Z
    if( is_null($value) )
    {
      return $value;
    }

    // $old = $value;

    $value= strip_tags($value);
    // drush_print_r( $old . ' -> ' . $value );

    return $value;
  }

}

```

and here is the migration

```
# This migration demonstrates importing from a monolithic XML file.
dependencies:
    enforced:
      module:
        - complimentmigration
id: compliment_xml_to_node
label: XML feed of nodes from compliment
migration_group: compliment
migration_tags:
  - advanced xml import
source:
  # We use the XML data parser plugin.
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: xml
  # Normally, this is one or more fully-qualified URLs or file paths. Because
  # we can't hardcode your local URL, we provide a relative path here which
  # hook_install() will rewrite to a full URL for the current site.
  urls: private://FINRAManual08-08-18.xml
  #  - /migrate_example_advanced_position?_format=xml
  # Visit the URL above (relative to your site root) and look at it. You can see
  # that <response> is the outer element, and each item we want to import is a
  # <position> element. The item_xpath value is the xpath to use to query the
  # desired elements.
  item_selector: '/quickpipe/section/section/section'
  # Under 'fields', we list the data items to be imported. The first level keys
  # are the source field names we want to populate (the names to be used as
  # sources in the process configuration below). For each field we're importing,
  # we provide a label (optional - this is for display in migration tools) and
  # an xpath for retrieving that value. It's important to note that this xpath
  # is relative to the elements retrieved by item_xpath.
  fields:
    -
      name: versionid
      label: 'Version Id'
      selector: 'version[1]/@recordId'
    -
      name: title
      label: 'Title'
      selector: 'version[1]/title'
    -
      name: content
      lable: 'Content'
      selector: 'version[1]/content'

  # Under 'ids', we identify source fields populated above which will uniquely
  # identify each imported item. The 'type' makes sure the migration map table
  # uses the proper schema type for stored the IDs.
  ids:
    versionid:
      type: integer
destination:
  plugin: entity:node
process:
  # Hardcode the destination node type (bundle) as 'migrate_example_beer'.
  type:
    plugin: default_value
    default_value: article
  title:
    plugin: stripouthtml
    source: title
  uid:
    plugin: default_value
    default_value: 1
  sticky:
    plugin: default_value
    default_value: 0
  body: content
migration_dependencies: {}

```

# Answer
The module was in a funky state. I ran `drush pm-uninstall complimentmigration` which gave the following message.

> complimentmigration is already uninstalled.
> There were no extensions that could be uninstalled.

Then I ran `drush en complimentmigration` which gave the following message.

> The following extensions will be enabled: complimentmigration
> Do you really want to continue? (y/n): y
> Drupal\Core\Config\PreExistingConfigException: Configuration objects (migrate\_plus.migration.compliment\_xml\_to\_node) provided by complimenttmigration already exist in active configuration in /Users/Sites/devdesktop/drupal8test/core/lib/Drupal/Core/Config/PreExistingConfigException.php:65
> Stack trace:
> 0 /Users/Sites/devdesktop/drupal8test/core/lib/Drupal/Core/Config/ConfigInstaller.php(496): Drupal\Core\Config\PreExistingConfigException::create('complimenttmigrat...', Array)
> 1 /Users/Sites/devdesktop/drupal8test/core/lib/Drupal/Core/ProxyClass/Config/ConfigInstaller.php(132): Drupal\Core\Config\ConfigInstaller-\>checkConfigurationToInstall('module', 'complimentmigrat...')
> 2 /Users/Sites/devdesktop/drupal8test/core/lib/Drupal/Core/Extension/ModuleInstaller.php(150): Drupal\Core\ProxyClass\Config\ConfigInstaller-\>checkConfigurationToInstall('module', 'complimenttmigrat...')
> 3 /Users/Sites/devdesktop/drupal8test/core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php(83): Drupal\Core\Extension\ModuleInstaller-\>install(Array, true)
> 4 /Applications/DevDesktop/tools/vendor/drush/drush/commands/core/drupal/environment.inc(131): Drupal\Core\ProxyClass\Extension\ModuleInstaller-\>install(Array, true)
> 5 /Applications/DevDesktop/tools/vendor/drush/drush/commands/core/drupal/environment.inc(198): drush\_module\_install(Array)
> 6 /Applications/DevDesktop/tools/vendor/drush/drush/commands/pm/pm.drush.inc(1180): drush\_module\_enable(Array)
> 7 /Applications/DevDesktop/tools/vendor/drush/drush/includes/command.inc(422): drush\_pm\_enable('complimentmigrat...')
> 8 /Applications/DevDesktop/tools/vendor/drush/drush/includes/command.inc(231): \_drush\_invoke\_hooks(Array, Array)
> 9 /Applications/DevDesktop/tools/vendor/drush/drush/includes/command.inc(199): drush\_command('complimentmigrat...')
> 10 /Applications/DevDesktop/tools/vendor/drush/drush/lib/Drush/Boot/BaseBoot.php(67): drush\_dispatch(Array)
> 11 /Applications/DevDesktop/tools/vendor/drush/drush/includes/preflight.inc(66): Drush\Boot\BaseBoot-\>bootstrap\_and\_dispatch() 12 /Applications/DevDesktop/tools/vendor/drush/drush/drush.php(12): drush\_main()
> 13 {main}

I ran `drush ev "\Drupal::service('config.manager')->uninstall('module', 'complimentmigration');"`, followed by `drush en complimentmigration`, which gave the following message.

> The following extensions will be enabled: complimentmigration
> Do you really want to continue? (y/n): y
> complimentmigration was enabled successfully.

This fixed the issue I had.
> 1 votes

---
Tags: migrations, plugins
---


title: Domain Access Source - Canonical

text:
# Question
Title: Domain Access Source - Canonical
for now domain access and source set the correct canonical domain and show the links linked to the correct page.

I can disable that and the links stay within the domain I’m currently on. Visitors won’t get redirected to a “new” page.

I’ve got two domains. Site A and site B. A has content from B but visitors from A should particularly know that there is site B except they land on B by Google search or wise versa. But there is content from B that has to appear on A. Without the penalty of double content, which it is right now.

How can I leave the links alone but set the canonical to the real source? D7 had that ability with tokens, D8 doesn’t because “it’s working as intended”

# Answer
> -1 votes
This can be done with Tokens. Not so elegant, but it works.

---
Tags: 8, domain-access
---


# Question
Title: Allow editing of own content but not show 'node settings' block
Hello all and happy new year! ..

I have a question that I thought would have been answered before, but could not find anything..

I want users of a certain role to be able to edit their own content (nodes of a specific content type). This all works well. However, they can also see the 'Node Settings' option, which is a block on the right hand side with settings such as: 'CSS class(es), layout box' etc. (see picture below)

I don't want the above settings to be available to the particular role, although that role would have the right to edit the node - in other words, I want them to be able to alter **content**, but not be able to mess around with css classes, layout boxes and anything like that ...

Ideally, I would like that **whole 'Node Settings' block to be available only to administrators, and not to users of any role** \- even if they do have permissions to edit the content of that particular node.

I looked carefully into permissions and searched the web, but could not find anything ... My feeling is that this should be done as it must be quite a frequent case ..

Any help would be greatly appreciated.

# Answer
> 1 votes
I think that this is quite easy using `hook_form_FORM_ID_alter` like this,

```
function MY_MODULE_form_node_form_alter(&$form, &$form_state, $form_id) {
  $current_user = \Drupal::currentUser();
  $roles = $current_user->getRoles();
  if (in_array('YOUR_ROLE', $roles)) {
    unset($form['...']);
  }
}

```

if you don't know what the name of the element is called, try to find it using kint($node) if you have devel installed.

Hope it works for you.

---
Tags: 8, users
---


# Question
Title: Is it possible to have 2 sources for migration?
I have a tid (taxonomy ID) and a csv file (which is a list of terms to remove during migration with columns : tid, name, delete ). The tid and CSV file are my sources for the migration.
How can I access (and process) values from both sources in my migration?
The tid is giving me the terms used as tags and the CSV file is to verify if the terms are listed on the CSV as term to be ignored (not added) during migration on the newly created node.

Something like :

```
process:
#create temporary field to call plugin that gets the taxonomy
  _prepare_TaxonomyIssues:
    plugin: sub_process
    source: field_issues_ref
    process:
      target_id:
        -
         plugin: mm_taxonomy_tag_issues_plugin
         source: #tid
           - tid
           - plugin: csv
           path: public://allTagsDec6CleanedUpdated.csv
           header_row_count: 1
           keys:
             - tid
             - name
             - delete
           column_names:
             -
               tid: tid
             -
               name: name
             -
               delete: delete

```

I am getting an error:

```
TypeError: Argument 2 passed to Drupal\Component\Utility\NestedArray::getValue() must be of the type array, null given, called in /var/www/mm/docroot/core/modules/migrate/src/Row.php on line 158 in /var/www/mm/docroot/core/lib/Drupal/Component/Utility/NestedArray.php on line 69 #0 /var/www/mm/docroot/core/modules/migrate/src/Row.php(158): Drupal\Component\Utility\NestedArray::getValue(Array, NULL, NULL)

```

Is it possible to have 2 different sources?
Is there another way to do it?

# Answer
You can't use two sources in the same migration. But if you can split your import into two separate migrations (e.g. taxonomies first, then nodes), you can use either migrate\_lookup (if your 2nd source provides the same primary key as a previous master) or entity\_lookup (if your 2nd source needs to look up the referenced entity by something else than the primary migration key).

Entity lookup is part of Migrate Plus.
> 2 votes

# Answer
You could try the Feeds module. There can be several inputs for one job.
> 0 votes

---
Tags: 8, taxonomy-terms, migrations
---


# Question
Title: How do I programmatically create a view in a custom module?
I currently have a custom module that lets you create an entity. The list page for this has gotten to be really long so I decided to create a view for this to allow filtering. If this were a new module that I was about to install then I could just throw the .yml file into config/staging, but since it has to be done as an update I cannot just put the .yml file there.

It looks like it needs to be created all in code in an update hook.

Is there an easier way of doing this?

# Answer
Place the YAML file in config/optional as you would normally do to create the view on install optionally when Views is enabled.

Then use an update hook to check whether the view exists when updating the module and create it in PHP by reading the YAML file:

```
function dblog_post_update_convert_recent_messages_to_view() {

  // Only create if the views module is enabled and the watchdog view doesn't
  // exist.
  if (\Drupal::moduleHandler()
    ->moduleExists('views')) {
    if (!View::load('watchdog')) {

      // Save the watchdog view to config.
      $module_handler = \Drupal::moduleHandler();
      $optional_install_path = $module_handler
        ->getModule('dblog')
        ->getPath() . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
      $storage = new FileStorage($optional_install_path);
      \Drupal::entityTypeManager()
        ->getStorage('view')
        ->create($storage
        ->read('views.view.watchdog'))
        ->save();
      return t('The watchdog view has been created.');
    }
    return t("The watchdog view already exists and was not replaced. To replace the 'Recent log messages' with a view, rename the watchdog view and uninstall and install the 'Database Log' module");
  }
}

```

Source: dblog\_post\_update\_convert\_recent\_messages\_to\_view
> 4 votes

---
Tags: views, 8
---


# Question
Title: how to get all the fields that have been modified on entity save (form submit)?
I am trying to figure out an efficient way to get the fields names/values that have been updated. It's kind of similar to what the diff module does to calculate changed on a node but not as detailed. I just want to see what fields have been updated when a user saves an entity. For example a user may not change the title but could change the body. I would like to build an api function returns that. something like this pseudo code:

```
// possibly on presave or form submit.
function my_module_entity_presave() {
    // Return only the fields values that are not similar to the original node:
    $modified = $entity->getModifiedFields();
}

```

and the method could be something like this psudo code:

```
public function getModifiedFields() {
  $original = $this->originalFieldsValues();
  $new = $this->newFieldValues();
  // compare original with new
  // finally return only modified fields name values.
  $modified = ['title' => 'new value', 'body' => 'new value' ...];
  return $modified
}

```

# Answer
When you are in the presave hook, the updated `$node` object will have `$node->original`, which is the node before things were changed.

Nodes also have a `$node->toArray()`, method that will flatten the object into a multidimensional associative array.

So, this

```
array_keys(DiffArray::diffAssocRecursive($node->toArray(), $node->original->toArray())

```

should

1. Take the `$node` and `$node->original` and convert them into arrays.
2. Run the two arrays through one of the Drupal helper classes that will generate differences in multidimensional associative arrays.
3. Return the top level keys. Because of the ways nodes are built, this will be all of the changed property and field names.
> 7 votes

# Answer
Here's an excerpt from a method I use to determine if an entity has changed. I adapted it a little bit to return the names for you. You may need to adapt it more for your specific needs.

mymodule \> src \> GaryFunctions.php

```
<?php

/**
 * File for holding helper functions user by Gary
 */

namespace Drupal\mymodule;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\Entity\EntityViewDisplay;

class GaryFunctions {

  /**
   * Check if entity field content has changed
   * @param  EntityInterface $entity     The entity being saved
   * @return array                    A list of changed field names
   */
  public function entityHasChanged(EntityInterface $entity) {
    $changed_fields = [];
    if (!$entity->original) {
      return $changed_fields;
    }
    $field_names = $this->getFieldList($entity->bundle(), $entity->getEntityTypeId());
    foreach($field_names as $key => $field_name) {
      if($entity->hasField($field_name) && $field_name != 'field_comments' && !$entity->get($field_name)->equals($entity->original->get($field_name))){
        $changed_fields[] = $field_name;
        // $entity->get($field_name)->getValue();
      }
    }
     return $changed_fields;
  }

  /**
   * Get list of field names from bundle
   * @param  string $bundle Bundle name
   * @return array         Array of field names
   */
  public function getFieldList($bundle, $entity_type_id) {
    $fields_by_weight = [];
    $bundle_fields = \Drupal::entityTypeManager()
      ->getStorage('entity_view_display')
      ->load($entity_type_id . '.' . $bundle . '.' . 'default')
      ->getComponents();

    foreach ($bundle_fields as $name => $options) {
      $fields_by_weight[] = $name;
    }
    return $fields_by_weight;
  }

}

```

mymodule \> mymodule.module

```
<?php

use Drupal\Core\Entity\EntityInterface;
use Drupal\mymodule\GaryFunctions;

function mymodule_entity_presave(EntityInterface $entity) {
  $helper = new GaryFunctions;

  switch ($entity->bundle()){

    case 'projects':
      $changed_fields = $helper->entityHasChanged($entity);
      if (!empty($changed_fields)) {
        print_r($changed_fields);
      } else {
        print 'didnt change';
      }
    break;

    default:
    break;
  }

}

```
> 2 votes

# Answer
You can use `$node->original`, it does give access to the original node values, so lets assume that the field you desire check is `foo_field` :

```
function myModule_node_presave($node) {
  if ($node->getType() == 'my_content_type') {
    if ($node->original->foo_field != $node->foo_field) {
      // Do what you want here.
    }
  }
}

```
> 0 votes

---
Tags: 8, entities
---


title: robots.txt vs language path prefix

text:
# Question
Title: robots.txt vs language path prefix
The default robots.txt shipped with Drupal contains rules such as this:

`Disallow: /user/register/`

If I understand correctly, the leading slash means this really has to match the beginning of the path. E.g. a path like `/xyz/user/register/` would not match the rule. (Please correct me if I'm wrong)

(For the ending slash I am not sure)

With the language path prefix option, Drupal will have urls like `/fr/user/register` etc.

It can be assumed that if we want to exclude /user/register, we also want to exclude /fr/user/register and other language versions.

However, a `/*/user/register/` might be too generic, as it also would match other urls which we don't want to exclude.

Questions:

* Will Drupal's default robots.txt also exclude language-specific versions of the targeted urls? (according to my own assumption it does not).
* What would be the simplest / cleanest way to exclude all language versions for a given path?

I think this applies equally to Drupal 7 and Drupal 8.

# Answer
> 1 votes
Whatever you are unhappy with, with Drupal's default `robots.txt`, delete it, and install RobotsTxt to provide an UI to let your SEO person edit the `robots.txt` according your needs.

> Use this module when you are running multiple Drupal sites from a single code base (multisite) and you need a different robots.txt file for each one. This module generates the robots.txt file dynamically and gives you the chance to edit it, on a per-site basis, from the web UI.

---

Look what I found. This duplicate issue on drupal.org robots.txt: add wildcarded paths for multilingual sites leads to this open issue Fix path matching in robots.txt, which actually could need your input.

But basically some commenters seem to recommend exactly what you came up with, wildcarding the path prefix.

---
Tags: i18n-l10n
---


# Question
Title: How can I change the value of a field in node / [id] / edit?
I should change the value of a field before it is rendered. I tried with \[NAME\_MODULE\]\_node\_view but it is not invoked when I edit the node.

Thank you so much.

# Answer
I alter my forms with the following:

```
function mymodule_form_test_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // code here...
}

```
> 0 votes

---
Tags: views, nodes, hooks
---


# Question
Title: Digit 2 Appended to Field Name on Column in Entity Field Query
I have an Entity Field Query that has *fieldCondition* for *field\_email*

```
  ->fieldCondition('field_email', 'value', $email , '=');

```

I have verified that this is the name of the field and I have other entity queries that use this field correctly. However, in this example, Drupal is adding the digit *2* on to the field name as I understand the error returned.

```
$dup_query1 = new EntityFieldQuery();
$dup_query1->entityCondition('entity_type', 'node') ->entityCondition('bundle', 'fair_participant')
 ->fieldCondition('field_last_name', 'value', $last_name , '=')
 ->fieldCondition('field_first_name', 'value', $first_name , '=')
 ->fieldCondition('field_email', 'value', $email , '=');

$fpmatch_fandl_email = $dup_query1->execute();

```

> SQLSTATE\[42S22\]: Column not found: 1054 Unknown column 'field\_data\_field\_email2.field\_email\_value' in 'where clause'

Any help is greatly appreciated.

Thanks, Josh

# Answer
If you use Email module, use `email` instead of `value`, because the module store the value in `field_name_email` not `field_name_value` like other field like text ... So you Query should be like:

```
$dup_query1 = new EntityFieldQuery();
$dup_query1->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', 'fair_participant')
    ->fieldCondition('field_last_name', 'value', $last_name , '=')
    ->fieldCondition('field_first_name', 'value', $first_name , '=')
    // use email not value.
    ->fieldCondition('field_email', 'email', $email , '=');

$fpmatch_fandl_email = $dup_query1->execute();

```
> 1 votes

---
Tags: entities
---


# Question
Title: How do I get a list of all taxonomy terms assigned to a node (or any entity)?
What's the best way to get all taxonomy terms assigned to a node?

Should one use the taxonomy\_index table?

Should one iterate through the fields on the node object?

I saw some answers for Drupal 7, but not for Drupal 8.

# Answer
One way to do it is to iterate through each field and check if it's an entity\_reference field with target type taxonomy\_term, then extract the data you need.

```
$terms = [];

foreach ($node->getFields() as $key => $field) {
  if ($field->getFieldDefinition()->getType() == 'entity_reference') {
    $targetType = $field->getFieldDefinition()
      ->getItemDefinition()
      ->getSetting('target_type');
    if ($targetType == 'taxonomy_term') {
      $new_terms = array_map(function (\Drupal\taxonomy\TermInterface $term) {
        return $term->label();
      }, $field->referencedEntities());
      $terms = array_merge($terms, $new_terms);
    }
  }
}

```

One advantage to this approach is it will work with any fieldable entity type.
> 2 votes

# Answer
One way to do it is with the taxonomy\_index table:

```
$terms = [];

$query = \Drupal::database()
  ->select('taxonomy_index', 'ti')
  ->fields('ti', ['tid'])
  ->condition('nid', $node->id());

$results = $query->execute()->fetchCol();

$tids = \Drupal::entityTypeManager()
  ->getStorage('taxonomy_term')
  ->loadMultiple($results);

$terms = [];

foreach ($tids as $term) {
  $terms[] = $term->label();
}

```

Note: this will only work with node entities.
> 1 votes

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


# Question
Title: how to apply exposed filter without apply button in Drupal 8 views?
I have textfield as exposed filter in table view. How I can apply that filter without pressing apply button. any contrib module or suggestion?

# Answer
Try this It may solve your problem. It may not be the proper solution but it will help you apply filter without having to click on apply button.

```
(function($) {
  $(document).ready(function() {
 $(document).ajaxComplete(function(event, xhr, settings) {
 $(".views-exposed-form .form-select").change(
         function(){
           $(".form-submit").click();
         }
);
  });
       });
})(jQuery);

```
> 1 votes

# Answer
In the select.html.twig, override this line:

```
<select{{ attributes.addClass(classes) }}>

```

with this line:

```
<select{{ attributes.addClass(classes) }} {{ attributes.setAttribute('onchange', 'this.form.submit()') }}>

```

This is to add the attribute of onchange to the select tag, and if there are any changes of the selection, submit the form. Therefore no need to click the Apply button.

As for the Apply button, just add a css property `{ display:none; }`

That should do it.
> 1 votes

# Answer
In Drupal 7, that functionality was provided by the CTools module. In Drupal 8, it was dropped in the port of Views to core, but raised as an issue which has yet to be resolved. You should provide your feedback in that issue if you would like to see this added to Views in core.
> 0 votes

---
Tags: views, 8
---


# Question
Title: How can I add {% if %} for a field name?
What would be the correct way to write an {% if %} "field\_name" "is", in Drupal 8 Twig files? I would like to add a CSS style specifically to one field and I believe this will achieve that.

Here is my current code within Twig file:

```
{%
  set classes = [
    'field',
    'field--name-' ~ field_name|clean_class,
    'field--type-' ~ field_type|clean_class,
    'field--label-' ~ label_display,
  ]
%}
{%
  set title_classes = [
    'field__label',
    label_display == 'visually_hidden' ? 'visually-hidden',
  ]
%}

{% if label_hidden %}

  {% if multiple %}
    <div{{ attributes.addClass(classes, 'field__items') }}>
      {% for item in items %}
        <div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
      {% endfor %}
    </div>
  {% else %}
    {% for item in items %}
      <div{{ attributes.addClass(classes, 'field__item') }}>{{ item.content }}</div>
    {% endfor %}
  {% endif %}

{% else %}

  <div{{ attributes.addClass(classes) }}>
    <div{{ title_attributes.addClass(title_classes) }}>{{ label }}</div>
    {% if multiple %}
      <div class='field__items'>
    {% endif %}
    {% for item in items %}

      <div{{ item.attributes.addClass('field__item') }}>{{ item.content }}</div>
    {% endfor %}

    {% if multiple %}
      </div>
    {% endif %}
  </div>

{% endif %}

```

# Answer
You copied `field.html.twig` to a new file, `field--field-additional-text.html.twig`. After clearing the cache, Drupal will *only* use this new file for *that* field only. Now you do not need logic in either template.

So you now can make changes, for example:

```
{% for item in items %}
  <div class="additionalbreaker">{{ item.content }}</div>
{% endfor %}

```

^ This means, for every item in *this* field (single or multiple values), print each value wrapped in this div, with this class. However, within a field template, you cannot output different fields as one, the sole purpose of a field template is to render the current field.

Read up on theming Drupal fields for more information.
> 1 votes

---
Tags: 8, theming
---


# Question
Title: Show child pages in parent node view details in a book
I'm using the Book module to maintain the parent-child relationship between content. I want to see all child pages expanded when I see a parent node details page. How can I achieve it?

I tried with `THEMENAME_preprocess_book_tree()`, but so far I have not been able to achieve that I wanted.
Is this the right hook to use in my case?

# Answer
> 3 votes
I managed to find a solution. I would like to post it here if somebody looking for similar solutions.

Make a view for the parent page with all needed configurations. In my case, I have the main chapter page as the parent, the content type is 'chapter'. And when I see the view in a page I want to see all subchapters coming under it. The further steps are followed:

1. Browse to /admin/structure/views and click on "Add view".
2. Enter a view name, Select content type from view settings
3. Check the "Create a block" checkbox only. Then click on "Save & edit".
4. On the right-hand side, click on "Advanced" so that the advanced menu appears.
5. Click on "add" next to "Relationships" to add a relationship.
6. Select "1st parent" (the parent book node) and click on "Apply and configure relationships".
7. Check the "Require this relationship" checkbox and click on "Apply".
8. Click on "add" next to "Contextual filters" to add a contextual filter.
9. Select "ID" (The node ID) and click on "Add and configure contextual filters". Choose relationship to "Book 1st Parent"
10. In the "when the filter value is not available" section, select "Provide default value" and in the "Type" drop-down menu, select "Content ID from URL"
11. click on "Apply" & Save the view
12. Place the just created block in the page by visiting structure \> block layout

---
Tags: 8, nodes
---


# Question
Title: Programmatically update alt tag on image field
I have a Drupal 8 site with a content type that has an image field. For existing nodes of this type, most have image files, but none have alt tags.

I am writing an update hook where I want to set the alt tag value for existing nodes. However, I have not been able to figure out how, nor find documentation.

This is what I have:

```
$nids = \Drupal::entityQuery('node')->condition('type','sfa_social_post')->execute();
$nodes = \Drupal\node\Entity\Node::loadMultiple($nids);

foreach ( $nodes as $node ) {
  $node->field_sfa_image_file->alt = 'Image for ' . $node->getTitle();
}

```

Where `field_sfa_image_file` is the name of the image field.

When I re-loop through the nodes, I get back the value that I set.

```
$nids = \Drupal::entityQuery('node')->condition('type','sfa_social_post')->execute();
$nodes = \Drupal\node\Entity\Node::loadMultiple($nids);

foreach ( $nodes as $node ) {
  drush_print('Title: ' . $node->getTitle());
  drush_print('Alt: ' . $node->field_sfa_image_file->alt);
}

```

Which gives me

```
Title: Instagram Post ID: 1917569620391415985_3017827348
Alt: Image for Instagram Post ID: 1917569620391415985_3017827348
Title: Instagram Post ID: 1917562614863492125_3017827348
Alt: Image for Instagram Post ID: 1917562614863492125_3017827348

```

So all seems good. However, when I navigate to nodes, I don't see my alt text:

How do I set the alt tag for an existing image field?

# Answer
> 8 votes
As @clive suggested use `$node->save();`. Without node saving, alt of the image will not show up in the edit form.

```
$nids = \Drupal::entityQuery('node')->condition('type','sfa_social_post')->execute();
$nodes = \Drupal\node\Entity\Node::loadMultiple($nids);
foreach ($nodes as $node) {
  $node->field_sfa_image_file->alt = 'Image for ' . $node->getTitle();
  $node->save();
}

```

---
Tags: 8, media
---


# Question
Title: How to properly call dependency classes (Class not found)
I'm creating a custom module that uses PHPMailer, which has been installed in the module's vendor folder via composer.

This is the error I get:

`Error: Class 'PHPMailer' not found in Drupal\multisend\Service\MailerService->__construct()`

PHPMailer is being used in a service class and a PHPMailer object is being created in the service classes constructor. Here is the code:

```
<?php

namespace Drupal\multisend\Service;

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

class MailerService
{
    private $mailer;
    private $config;
    private $attorney_data;

    public function __construct($attorney_data)
    {
        $this->mailer = new PHPMailer(true);
        $this->config = \Drupal::config('multisend.settings');
        $this->attorney_data = $attorney_data;
    }

    ...

```

I've even tried `require()` on the PHPMailer class but no luck. If anyone could give any suggestions, I would appreciate it greatly.

# Answer
Yes this is right the onlything is never try to `composer require X` in a modules directory even though you can include a composer.json file in the module its self always make sure you are in the site root. then the paths will be correct.
> 0 votes

---
Tags: 8, dependency-injection
---


title: Multi-site, shared users, paid access

text:
# Question
Title: Multi-site, shared users, paid access
I'm working on a project that involves multi-sites in Drupal 8. The client specifically wants to have shared user accounts across all 4-5 sites. As of now the sites share a codebase but not a shared database. After researching I came across the CAS module. Can CAS allow for multiple logins? When one account is made can other accounts be generated in the other 3-4 Drupal sites? Is there a better way to do this in Drupal 8? Also, the client eventually wants to have paid account registries. For example, a user would pay on one site and get access to all 4-5 sites. IS there any guidance for accomplishing this? If not with CAS what other modules / resources would I need to make this doable in Drupal 8?

So far I've seen sites that offer advice on this but largely with Drupal 7 with out a clear path for doing this in Drupal 8. CAS seemed the most stable option but not sure if it will work. There was also the option of sharing users through shared tables, though this was discouraged in the forums I read. What is the best / proper way to do this in Drupal 8? Or should I go back to Drupal 7?

# Answer
> 0 votes
CAS module is a nice option, and it is quiet stable in D8 (using it in production site since more than a year). Morerover, SSO looks more confortable for users that don't have to reconnect when they jump from one site to another.

You should know that each D8 site will have its own user table created by the CAS/Externalauth modules'stuff. If you plan to grant different access permissions based on something (many payments methods), imho, you should store these infos somewhere regardless to drupal (more precisly : anywhere your CAS server can retrieve, i have not tryed cas\_server). Those could be retrieved in attributes sent during connection according to CAS protocol (CAS parameters).

Note : Given the fact each of you websites store its user table, and do not necessarily know the existence of an user "x" until its first connection to this site, you just have to pay attention on duplicates. Easiest way is probably to use email as UID but you undestand the idea.

---
Tags: multi-sites
---


# Question
Title: Grant permission to current user at runtime in specific environment
Many Drupal contrib modules have inverse "feature flag" implementations vis-a-vis a killswitch variable added to settings.local.php to disable a feature:

```
// Killswitch setting.
$settings['disable_captcha'] = TRUE;

// Config override.
$config['google_analytics.settings']['account'] = '';

```

However, the Drupal 8 version of CAPTCHA does not yet have the `disable_captcha` killswitch that existed in Drupal 7 (see related issue #2836076).

The module does have another kind of killswitch via a Drupal permission `skip CAPTCHA`. This got me wondering:

**Is it possible to dynamically add a permission to the current site visitor—both anonymous or authenticated users—at runtime for a specific environment without affecting the standard roles & permissions store so that configuration management/sync is not adversely affected by the environment-specific permission?**

Ideally this logic would be located in settings.local.php to avoid the following risks and technical debt

1. the chance that unintended environments would be affected, and
2. to have to copy/paste/commit solutions to this problem in every client project only to have to later remove that code once the proper killswitch solution in issue #2836076 lands.

# Answer
Yes you can but why not just remove the field ? here is a few ideas on to how to do it..

in settings.local.php

```
 //add
$settings['stop_captcha_from_being_stupid'] = TRUE;
// or
$settings['enviroment_name'] = 'dev';

```

in some hook\_form\_alter

```
use Drupal\Core\Site\Settings; // above ^^^
$stop_capcha = Settings::get('stop_captcha_from_being_stupid') ;
if ($stop_capcha === TRUE) {
  unset($form['captcha']);
}

// or enviroment with custom header ;)
$current_request = $request = \Drupal::request();
if (!empty($current_request->headers->get('shutup-captcha'))) {
  if ($current_request->headers->get('shutup-captcha') == 'somesalt') {
    $environment_name = Settings::get('enviroment_name') ;
    $environments_to_allow_bypass_captcha = [
      'dev',
      'int',
      'test',
    ];
    if (in_array($environment_name, $environments_to_allow_bypass_captcha)) {
      unset($form['captcha']);
    }
  }
}

```
> 1 votes

---
Tags: 8, users, configuration
---


# Question
Title: How to get language code of a field in a node
I have a requirement where in hook\_node\_insert I need to get the language code of a field

What I have tried is

```
$langcode = $node->{$field_name}->langcode

```

But this returns null. Any suggestions?

And is it possible that different fields in a node have different langcode?

# Answer
> 1 votes
You can use getLangcode
Try with:

```
$node->{$field_name}->getLangcode()

```

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


# Question
Title: Programmatically disable content translation options in content edit form
I want to **programmatically** disable the content translation options located at the bottom of the content edit form (see yellow area in screenshot):

I know that i can disable the revision information options with the following code in a form\_alter hook:

```
$form['revision_information']['#access'] = false; // <--- works

```

But that doesn't work with the translation options, at least with what I tried:

```
$form['content_translation']['#access'] = false; // <--- doesn't work

```

So ideally, how can i disable the whole yellow area?

# Answer
You can not access to `content_translation` property in the `hook_form_alter` but you can do it in after\_build callback.

> after\_build: runs after the form or element is built for display.

Try with the following:

1. Add `#after_build` to the form:

```

/**
 *Implements hook_form_alter().
 */
function myModule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_YouContentType_edit_form') {
    $form['#after_build'][] = 'myModule_after_build';
  }
}

```
2. Implement your after\_build function

```

    function myModule_after_build($form, &$form_state){
      $form['content_translation']['#access'] = FALSE;
      return $form;
    }

```
> 2 votes

---
Tags: 8, forms
---


title: How many blocks can be handled?

text:
# Question
Title: How many blocks can be handled?
I migrated to drupal 8 and now it has 760 blocks. I plan at least to triple this number. Blocks are placed into nodes content with **Insert Block** module. When I was setting up website the database was 200 mb, now when cache is not cleared it's 2gb+. There are two tables 1gb each.

At the moment when I save or edit block structure it takes 10 seconds to save it. CPU is't at 100, so website is working fine so far, but I'm worried that it might break down due to very large cache tables.

What do you think I should do to save performance other then stop adding blocks?

# Answer
From a capabilities and code perspective, there is no practical limit to the number of entities in a system (blocks, nodes, users). drupal.org is a good example of this; it has tons of users and nodes on it.

That doesn't preclude needing to properly scale out the rest of the system. This is particularly important in a Drupal 8 system, where caching is used extensively. One of the most overlooked aspects of this is properly tuning the database.

Out of the box, MySQL can have some bad default parameters. MySQLTuner can provide some guidance on how to adjust your system, particularly the buffer size. If your cache tables get large, I/O from them can slow down when they are hitting disk.

When you get to the point where you need to squeeze more performance out of a *tuned* site or if you are memory limited for proper tuning, you may want to consider a non-database caching solution like memcache or Redis. These can really help with large systems.
> 1 votes

---
Tags: 8, blocks
---


# Question
Title: Access webform by checking predefined codes
If I set up a webform with one component "authrization code", which is predefined by my side. People can access the form only when they get the authorized unique code from me. Is there any way to realize this? I tried a module "webform invitation", but have the same problem as described "any code is accepted"(my system is D8.64,php7.0). If I add a text field for code validation, I don't know where to predefine those codes and how to check. Another question is how can I produce those unique codes and transfer them to QR codes so that people can scan them to automatically fill in the form? Appreciate for any help in advance!

# Answer
> 1 votes
You can create a custom module with a hook\_webform\_access() callback that looks for authorizations codes.

The below hook grants access to the default Contact form vi**a /form/contact?code=secretcode**. Make sure to go to /admin/structure/webform/manage/contact/access and remove 'Create submissions' access to the Contact form.

```
/**
 * Implements hook_webform_access().
 */
function CUSTOM_MODULE_webform_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account) {
  // List of webform ids and authorization codes.
  $webform_authorization_codes = [
    'contact' => 'secretcode',
  ];

  // Get the current webform.
  /** @var \Drupal\webform\WebformRequestInterface $request_handler */
  $request_handler = \Drupal::service('webform.request');
  $webform = $request_handler->getCurrentWebform();
  if (!$webform) {
    return \Drupal\Core\Access\AccessResult::neutral();
  }

  // Get the webform id.
  $webform_id = $webform->id();
  if (!isset($webform_authorization_codes[$webform_id])) {
    return \Drupal\Core\Access\AccessResult::neutral();
  }

  // Get get the code.
  $code = \Drupal::request()->get('code');
  if (empty($code)) {
    return \Drupal\Core\Access\AccessResult::neutral();
  }

  // If 'submission_page' (aka create) and authorization code is correct,
  // then grant access.
  if ($operation === 'submission_page' && $code === $webform_authorization_codes[$webform_id]) {
    return \Drupal\Core\Access\AccessResult::allowed();
  }
  else {
    return \Drupal\Core\Access\AccessResult::neutral();
  }
}

```

---
Tags: 8, webforms
---


# Question
Title: Database 4 byte UTF-8 support not properly checking
In the status report of my drupal website I got the message that I had to up `Database 4 byte UTF-8 support`. I updated all my tables and database like it's told here: https://www.drupal.org/node/2754539. I checked and all my tables and the database have utf8mb4 encoding and utf8mb4\_general\_ci collation.

I get the following warning:

> Enabled, but database tables need conversion Please convert all database tables to utf8mb4 prior to enabling it in settings.php. See the documentation on adding 4 byte UTF-8 support for more information.

# Answer
> 1 votes
I fixed it by manual setting the `drupal_all_databases_are_utf8mb4` variable to `true`. You can do this by using drush or setting it in the database and then clear all caches.

---
Tags: database
---