# Question
Title: Table in custom form + empty values in form_state
In a custom form I created a table element:

```
  // Table results.
  $form['table'] = [
    '#type' => 'table',
    '#header' => $header,
    '#rows' => $rows,
    '#attributes' => ['id' => 'table-results'],
    '#empty' => t('No results.'),
    '#prefix' => '<div id="ajax-table-results">',
    '#suffix' => '</div>'
  ];

```

This table is ajaxified and updated when I click on a specific button.

I need to get the output HTML of this table in another function. If I use a dpm($form\_state-\>getValue('table')); I get an empty array. Yet, the other values (of other fields) are accessible in the $form\_state.

```
// My second function
public function secondfunction(array $form, FormStateInterface $form_state) {
  dpm($form_state->getValue('table')); // -> empty value...
  dpm($form_state->getValue('textfield')); // I get a value
}

```

What do I change in my code to solve this problem?

# Answer
When you want to get the HTML of the table you must use the `renderer` service.

In Drupal 8:

```
$html = \Drupal::service('renderer')->render($form['table']);

```

Or better, use dependency injection :)

In Drupal 7:

```
$html = drupal_render($form['table']);

```
> 2 votes

---
Tags: 8, forms, ajax
---


# Question
Title: How do you handle multiple feed URLs in a migration?
I have a drupal migration that also uses migrate plus from a feed URL that can be queried. For example the migration can work for a single response from the feed at

```
source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: xml
  urls: http://myfeed.com/newsfeed/get.php?id=123456

```

I would like to migrate content at 123456 and then 123457, then 123458. How could this be done?

# Answer
> 1 votes
You should be able to list any URLs that should be fetched:

```
source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: xml
  urls:
    - http://myfeed.com/newsfeed/get.php?id=123456
    - http://myfeed.com/newsfeed/get.php?id=123457
    - http://myfeed.com/newsfeed/get.php?id=123458

```

The Url plugin in migrate\_plus converts single url values into an array by default: https://git.drupalcode.org/project/migrate\_plus/blob/HEAD/src/Plugin/migrate/source/Url.php#L34

# Answer
> 0 votes
If you only have to migrate to this 3 ids, just create 3 different migrations for each URL.

If the IDs are dinamic I will copy&paste my own solution:

To solve this I had to create a source plugin that for each row calls a new data parse plugin with the URL for this row.

Here is the plugin:

```
/**
*
* @MigrateSource(
*   id = "url_per_row"
* )
*/
class UrlPerRow extends Url {

protected $dataNewParserPlugin;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
  }

  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    $prepare_row = parent::prepareRow($row);

    if (!$row->getIdMap() || $row->needsUpdate() || $this->aboveHighwater($row) || $this->rowChanged($row)) {
      $item_info_settings = $row->getSourceProperty('item_info');
      if (!empty($item_info_settings)) {
        $this->getItemData($row, $item_info_settings);
      }
    }

    return $prepare_row;
  }

  protected function getItemData(Row &$row, $settings) {
    $new_url = str_replace($settings['token'], $row->getSourceProperty($settings['token_replace']), $settings['url']);

    $this->getNewDataParserPlugin($new_url, $settings['item_selector'],     $row->getSource());
    $this->dataNewParserPlugin->rewind();
    $xml_data = $this->dataNewParserPlugin->current();
    if (!empty($xml_data)) {
      $fields = $row->getSourceProperty('fields');
      foreach ($fields as $field) {
        if (!empty($field['item_info']) && !empty($xml_data[$field['name']])) {
          $row->setSourceProperty($field['name'], $xml_data[$field['name']]);
        }
      }
    }
  }

  protected function getNewDataParserPlugin($url, $item_selector, $settings) {
    $settings['urls'] = [$url];
    $settings['item_selector'] = $item_selector;

    $this->dataNewParserPlugin = \Drupal::service('plugin.manager.migrate_plus.data_parser')
      ->createInstance($settings['data_parser_plugin'], $settings);

    return $this->dataNewParserPlugin;
  }

}

```

Then I put some info in the migration .yml definition:

```
source:
  plugin: url_per_row
  data_fetcher_plugin: http
  headers:
    Accept: application/xml
  data_parser_plugin: simple_xml
  urls: https://myws.com
  item_selector: /ResultWeb/data
  item_info:
    url: https://myws.com/[id]
    token: '[id]'
    token_replace: id
    item_selector: /ResultWeb/data

```

Notice that the `id` from `token_replace` is a field with name *id*. You can use other field.

Also, for every field where is needt to rereive information from the specified URL I put a `item_info: true` element.

```
-
  name: myfield
  label: 'My Field'
  selector: fields/field/my
  item_info: true

```

---
Tags: 8, migrations
---


# Question
Title: Adding a Image Upload Button in CKEditor
I have installed CKEditor in Wysiwyg profiles. While publishing any node if i click on the image upload button it shows options to add images by a image link, but what is the way to add a dynamic image upload button so that users will be able to Browse and choose any image from their computer in content?

# Answer
Check out IMCE with IMCE WYSIWYG bridge.

Once you install and configure those two modules, select "IMCE" as a button in CKEditor and then you can upload and insert images in WYSIWYG.
> 7 votes

# Answer
I know I'm somewhat late to this question, but I just found out about One Click Upload which does exactly what you want and may help others that have this same problem and arrive to this question (the only caveat is that it needs flash to be enabled to work).
> 4 votes

# Answer
The easiest way is to use according plugins: http://doksoft.com/soft/ckutils/index.html It allows user to upload images, preview and re-size uploaded images when needed.
> 0 votes

# Answer
There is also the media module but it is much more than a simple image uploader and you should use it only if you want to be able to manage files through Drupal.
> 0 votes

# Answer
in drupal 7 you can work with ckeditor and imce modules. after you've installed these two modules:

1. in imce config, under "Configuration profiles" you can add new profile and edit it's setting and under "Directories" add directories that you want the user access and add images.
2. go back to imce config page and under "Role-profile assignments" attach a role that the user have to the profile that you've created.
3. then go to ckeditor config page. profile advance -\> edit. under file browsing setting, set "File the browser type" to imce.

that's it . now the user can click on picture icon on ckeditor and upload a new image in directories that you've set.

hope it helps.
> 0 votes

---
Tags: 7, media, wysiwyg
---


# Question
Title: How to write test(s) with specific config to test custom access checks?
I have built a custom module that alters some of the User routes (view, edit, delete) to do 3 things:

* Forbid account editing, except a user who has 'administer users' permission
* Forbid account deleting, except a user who has 'administer users' permission
* Forbid account page viewing (`/user/{user}`) unless that account being viewed has a specific role AND has a boolean field value of TRUE

The accounts are synced from a remote source and logins provisioned by SSO, so, there is no point for anyone to access edit/delete except an admin/dev checking if accounts look correct.

The first two seem straightforward enough as it requires nothing but setting up some test users with different role permissions and checking the response from an edit or delete route.

For the third, what is the best way to provide simple configuration to get the field added to the User entity under test? Do I install my entire project config (seems heavy)? Is there a way I can selectively install some config for test only? I think I would just need one or two of the 800 config files to be installed. I checked some of the core tests, but couldn't quite locate one close to what I am asking.

# Answer
Wound up figuring this out I suppose, although I have no idea if this is the proper way.

Under the custom module I wanted to test, I created a 'tests' directory with a test module and within that new module placed 3 configuration files from my project config ("Show Profile" field storage, "Show Profile" field instance, user form display configuration).

In a functional test, I required that module:

```
<?php

namespace Drupal\Tests\mymodule\Functional;

use Drupal\Tests\BrowserTestBase;
use Drupal\user\Entity\Role;

/**
 * Class ProfileAccessTest
 * @package Drupal\Tests\mymodule\Functional
 */
class ProfileAccessTest extends BrowserTestBase {

  /**
   * A set of test users.
   */
  protected $user1, $user2, $user3, $user4;

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['node', 'user', 'mymodule', 'system', 'mymodule_test'];

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();

    $anon_role = Role::load(Role::ANONYMOUS_ID);
    $this->grantPermissions($anon_role, ['access user profiles']);

    $this->user1 = $this->drupalCreateUser(['access content', 'access user profiles'], 'regular_user');
    $this->user2 = $this->drupalCreateUser(['administer users'], 'john', TRUE);
    $this->user3 = $this->drupalCreateUser([], 'zzz', FALSE);
    $this->user4 = $this->drupalCreateUser([], 'yyy', FALSE);
  }

  public function testProfileAccess() {
    // The average user should not be able to do anything to their own account.
    $this->drupalLogin($this->user1);
    $this->drupalGet('/user/' . $this->user1->id());
    $this->assertResponse(403);
    $this->drupalGet('/user/' . $this->user1->id() . '/edit');
    $this->assertResponse(403);
    $this->drupalGet('/user/' . $this->user1->id() . '/cancel');
    $this->assertResponse(403);

    $this->drupalLogin($this->user2);
    $this->drupalGet('user/' . $this->user3->id() . '/edit');
    $edit['edit-field-show-profile-value'] = 1;
    $this->drupalPostForm("user/" . $this->user3->id() . "/edit", $edit, t('Save'));

    $this->drupalGet('user/' . $this->user4->id() . '/edit');
    $edit['edit-field-show-profile-value'] = 0;
    $this->drupalPostForm("user/" . $this->user4->id() . "/edit", $edit, t('Save'));

    // Any user should be able to view an account with SHOW PROFILE true.
    $this->drupalLogin($this->user1);
    $this->drupalGet('/user/' . $this->user3->id());
    $this->assertResponse(200);

    // But not if SHOW PROFILE is false.
    $this->drupalGet('/user/' . $this->user4->id());
    $this->assertResponse(403);
  }
}

```

The tests all pass, which is good.
> 1 votes

---
Tags: 8, routes, testing
---


# Question
Title: Login link in menu showing to logged-in user
On a Drupal 7 site, I created a login link on the main menu with the path user/login. For some reason, the link remains visible to users that are already logged in. I thought this link is supposed to automatically disappear when a user is logged in.

I also have a logout link that works correctly and only appears to users that are logged in.

Any ideas to get this working correctly?

**EDIT:** I went to /admin/structure/menu/manage/main-menu and added a new link. In the path field I entered "user/login."

# Answer
The menu per role module does exactly like you want. It allows you to set a menu link to only be visible by a specific role, in this case anonymous users.
> 1 votes

---
Tags: 7, navigation
---


title: Syncing content between stage and prod

text:
# Question
Title: Syncing content between stage and prod
Drupal 8, two versions of a site - dev and production.

How to move changes, especially changes in content from dev to production without destroying DB on production?

I know we have Features for configuration, but what about content?

Ideally, I would like to be able to add nodes, pages and edit existing ones, and then carry changes to the prod site, without destroying changes users created on the dev site - comments, new registrations and such.

What's the solution here? Export content to code?

Can someone give step-by-step on dev cycle?

# Answer
> 1 votes
I think the content synchronization module might be a good bet.

https://www.drupal.org/project/content\_sync

It has its own documentation page here:

https://www.drupal.org/docs/8/modules/content-synchronization

There is mention of Drush commands in it.

# Answer
> 0 votes
Today I've discovered this site: http://www.drupaldeploy.org:

> A next generation comprehensive yet easy to use content staging solution built for Drupal developers and end users

There are several modules that work together, the "base" module should be Deploy:

> The Deploy module is designed to allow users to easily stage and preview content for a Drupal site. Deploy automatically manages dependencies between entities (like node references). It is designed to have a rich API which can be easily extended to be used in a variety of content staging situations.

On drupaldeploy.org you can find related modules.

# Answer
> 0 votes
There are modules that export content to code: https://www.drupal.org/project/defaultcontent https://www.drupal.org/project/default\_content

You may also be able to get something working using Migrate, which is very powerful in D8.

---
Tags: 8, staging
---


title: Strip HTML tags from validation errors

text:
# Question
Title: Strip HTML tags from validation errors
I am using Services 3.x for creating web services for mobile application, and I am using the JSON format.

The validation errors given from the user register services comes with HTML tags; for example the *email already exists* error is the following one.

```
<em> the@email.com</em> is already in use.  Have you forgotten your password?".

```

How do I strip those HTML tags from the error message?

# Answer
`hook_services_request_postprocess_alter()` looks like a good candidate. I don't have an installation to test with right now but something like this ought to work:

```
function MYMODULE_services_request_postprocess_alter($controller, $args, &$result) {
  if (isset($result['form_errors'])) {
    array_walk($result['form_errors'], function(&$error) {
      $error = strip_tags($error);
    });
  }
}

```
> 2 votes

# Answer
In Drupal 8 you can do it by using Markup:

```
use \Drupal\Core\StringTranslation\TranslatableMarkup;
...
$message = new TranslatableMarkup('<b>@message!</b>', array('@message' => 'A bold error'));
$form_state->setError($message);

```

OR

```
$mainMessage = "<em> the@email.com</em> is already in use.  Have you forgotten your password?";
$rendered_message = \Drupal\Core\Render\Markup::create($mainMessage);
\Drupal::messenger()->addMessage($rendered_message);

```
> 2 votes

---
Tags: theming, services
---


# Question
Title: Migrating csv data as array into multi-field
**How do I migrate a sequence of data into a multi-value field?**

I am learning D8 migration and working on a large CSV of historic census data from around the world. Example below:

```
id,Country Name,Country Code,Indicator Name,Indicator Code,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018
1,Aruba,ABW,"Population, total",SP.POP.TOTL,54211,55438,56225,56695,57032,57360,57715,58055,58386,58726,59063,59440,59840,60243,60528,60657,60586,60366,60103,59980,60096,60567,61345,62201,62836,63026,62644,61833,61079,61032,62149,64622,68235,72504,76700,80324,83200,85451,87277,89005,90853,92898,94992,97017,98737,100031,100834,101222,101358,101455,101669,102046,102560,103159,103774,104341,104872,105366,105845

```

My migration yml file is as follows:

```
uuid: 6c54b8f4-96c7-4678-8919-b20c8b318c82
langcode: en
status: true
dependencies: {  }
id: World_Census_Data
class: null
field_plugin_method: null
cck_plugin_method: null
migration_tags:
  - CSV
migration_group: random_migrations
label: 'International census csv data'
source:
  plugin: csv
  path: /var/www/random-migrations/modules/custom/random_migrations/sources/census-58-years.csv
  ids:
    - id
  delimiter: ','
  track_changes: true
process:
  type:
    plugin: default_value
    default_value: census
  title: 'Country Name'
  field_country_code: 'Country Code'
  field_count:
    plugin: array_build
    default_value: 0
    value:
      - 1960
      - 1961
destination:
  plugin: 'entity:node'
migration_dependencies: {}

```

Instead of manually creating an individual field for each year, I created the **field\_count** field which is an Interger field set to allow unlimited entries. My idea is to import all the population numbers from 1960 to 2018 as new entries of field\_count for each country.

**My problem is the population data is not being imported.** Can anyone advice if my proposed solution possible and if it is, what I need to change/fix in my yml to get my migration working?

Help, please.

# Answer
> 2 votes
I figured it out. The issue was the plugin. Rather than * array\_build\*, I should have been using the **get** plugin, as follows:

```
process:
  type:
    plugin: default_value
    default_value: census
  title: 'Country Name'
  field_country_code: 'Country Code'
  field_count:
    plugin: get
    default_value: 0
    source:
      - 1960
      - 1961
      - 1962
     .
     .
     .

```

That migrates the value of the array indexed by those years into the **field\_count** field. And because the field has multiple cardinality, each row is written in as a new value.

---
Tags: 8, migrations
---


# Question
Title: Modifying page title with THEME_preprocess_page_title
I'm running Drupal 8.2.6, and an Adaptive subtheme and I am trying to modify the page title. I have created the following function in THEME.theme

```
function THEME_preprocess_page_title(&$variables) {
  $color_title = str_ireplace('some text', 'Some <span class="ct-green">TEXT</span>', $variables['title']);
  $variables['title'] = $color_title;
}

```

unfortunately, it's not working, at all. I've even tried just

```
$variables['title'] = 'Hello World';

```

to see if it would work, but no dice.

*EDIT* So the hunt goes on!

Apparently AdaptiveTheme doesn't use the page title block, it writes it into node.html.twig via field--node--title.html.twig

so far, I have edited THEME\_preprocess\_field\__node\__title(&$variables) with no luck, but THEME\_preprocess\_node() seems to work. kind of. if i do

```
$variables['title'] = 'hello world';

```

it works, but it still won't let me put the span tags in. I have found the reason for that, titles aren't allowed to have code because of XSS threats.

OK. Fine. Fair enough.

There is options in the code to allow you to to allow certain tags (i found documentation, then i lost it ... argghh)

I will keep this question updated as I go

# Answer
I think you are looking in wrong place. As far as i remember, in Drupal 8 title is rendered trough block called page\_title\_block

```
function MODULE_preprocess_block(&$variables) {
  if ($variables['plugin_id'] == 'page_title_block') {
    $color_title = str_ireplace('some text', 'Some <span class="ct-green">TEXT</span>', $variables['content']['#title']);
    $variables['content']['#title'] = $color_title;
  }
}

```
> 3 votes

# Answer
Not sure it is still relevant after more than 2 years of inactivity, but I just wanted to point out that your approach isn't working most likely because the title is not a string but a Markup object which can't be modified.

You need to create a new one and then assign it to the title variable. Your function should be something like this:

```
function THEME_preprocess_page_title(&$variables) {
  $color_title = str_ireplace('some text', 'Some <span class="ct-green">TEXT</span>', $variables['title']);
  $variables['title'] = Drupal\Core\Render\Markup::create($color_title);
}

```

Further reading here.
> 2 votes

---
Tags: 8, theming
---


title: import address data from CSV

text:
# Question
Title: import address data from CSV
I migrate my content from an old D7 site to D8 site. All went well, except the addresses from field address where not migrated to the new address field.

Then I use feeds, feeds\_migrate, content-import... Nothing work for this.

Then finaly start learning how to do this in a custom module. I used the plugin from the module addres, I wrote my own plugin. No migration seems to work.

I have a CSV file with the addresses. There is also a NID row that is unique, I also try with the title field who also is unique. I try to import this csv file into my content type business. The nodes are existing with the NID numbers. Just try to fill the address in each content. All addresses are in Belgium.
Below my YML file in a custom module.

```
    id: migzaal
label: Adres veld migratie
source:
   plugin: csv
   path: modules/custom/adresmigratie/assets/adresinvoer.csv
   header_row_count: 1
   ids:
     - Nid
process:
   nid: Nid
   field_adres:
     plugin: addressfield
destination:
  plugin: 'entity:node'
  default_bundle: business
  overwrite_properties:
    - 'field_adres/address_line1'
    - 'field_adres/locality'
    - 'field_adres/postal_code'
    - 'field_adres/country'

```

Can someone guide me in the right direction. Thanks.

# Answer
> 0 votes
I've been through a similar situation and I resolved it depending on the feeds module.

You need to use the following patch to allow the address field to be recognized by the feeds module https://www.drupal.org/project/address/issues/2882589

This is might not be what you're looking for at this stage but I thought this might help.

---
Tags: nodes, migrations
---


title: Duplicate content between multi-sites

text:
# Question
Title: Duplicate content between multi-sites
I'm working on a feature of a Drupal 8 multisite with separated databases for each site trying to implement the following requisite.

When posting news to the main site (all the other sites are subdomains) the user has to have the option to choose other sites where he wants the same news to be available.

I"m starting doing this with a module and hooks, BTW I never worked with Drupal before, and I'm guessing if there is an existing module that could do that.

Would someone recommend a module I could try?

Thanks for any help

# Answer
> 1 votes
On the publishing end, you'd need to categorize the data by site (e.g. use term references). Then expose that data as JSON using the built-in Views module. Allow that view to filter by site, to allow the subsites to select the content it wants to import.

On the consuming end:

* There used to be the Feeds module that allowed a Drupal site to fetch data from a source and load that data onto content types on the site. But that module is still in development.
* Alternatively, you could build a migration that is triggered in a `hook_cron()`. Migrate is already in core, I recommend also installing Migrate Plus and Migrate Tools for additional utilities.

In both cases, they would hit the main site at the url that Views is exposing, filter by the site term they want, and consume the JSON it returns.

# Answer
> 0 votes
Now there is a new approach using Deploy - Content Staging module which allows, in collaboration with Multiversion, Replication, and RELAXed Web Services modules to share content between different Drupal 8 sites.

You can find very good documentation on how to use Deploy module for sharing content on multisite here Also, you can visit the official module website from here

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


# Question
Title: Hide one form element until another is selected
Is there any way to disable the field 'model\_article\_nr' until 'model' is selected

this is what i have and as it is now i can select 'model\_article\_nr' before i have choosen a model which leads to wrong article nummer if i change model afterwords, because when no model is selected the first model is standard in my '$article\_list\[$curent\_model\]' and beeing displayed as options in 'model\_article\_number'

```
$model_list = array();
$article_list = get_model_article_list();

foreach($article_list as $key => $value) {
        if ( empty($curent_model) ) $curent_model = $key;
        $model_list[$key] = $key;
    }

$form['model'] = array(
        '#type' => 'select',
        '#title' => t('Model'),
        '#title_display' => 'invisible',
        '#empty_option' => t('Select Model'),
        '#options' => $model_list,
        '#ajax' => array(
            'callback' => 'form_model_callback',
            'wrapper' => 'article-number-ajax-wrapper',
        ),
        '#prefix' => '<div class="clearfix"></div><div class="form-helper-container">',
        '#suffix' => '<button type="button" class="btn tooltip-btn" data-toggle="modal" data-target="#model-help"><span class="glyphicon glyphicon-question-sign"></span></button></div>',
    );

    $form['model_article_nr'] = array(
        '#type' => 'select',
        '#title' => t('Article Number'),
        '#title_display' => 'invisible',
        '#attributes' => array('placeholder' => t('Article Number'), 'class' => array('space-bottom')),
        '#empty_option' => t('Select Article Number'),
        '#validated' => TRUE,
        '#options' => $article_list[$curent_model],
        '#prefix' => "<div id='article-number-ajax-wrapper'>",
        '#suffix' => "</div>",
    );

```

And my callback

```
function form_model_callback($form, &$form_state) {
    return $form['model_article_nr'];
}

```

# Answer
As @leymannx stated you can achieve this using #states. Here is a simple example:

```

 $form['show_textbox'] = array(
  '#type' => 'checkbox',
  '#title' => t('Show text Box 1'),
        '#attributes' => [
        'id' => 'show_textbox',
        'name' => 'field_show_textbox',
      ],
);

    $form['text_box1'] = [
      '#type' => 'textfield',
      '#size' => '60',
      '#placeholder' => 'Enter Name',
      '#attributes' => [
        'id' => 'text_box1',
        'autocorrect' => 'none',
        'class' => 'text_box1',
        'autocapitalize' => 'none',
        'spellcheck' => 'false',
      ],
      '#states' => [
        //show this textfield only if the radio button 'show_textbox1' is selected
        'visible' => [
                ':input[name="field_show_textbox"]' => array('checked' => TRUE),
        ],
      ],
    ];

```

You can always change the condition.
> 0 votes

# Answer
Thank you Hunde Tekle and leymannx it works :D

```
$form['model'] = array(
        '#type' => 'select',
        '#title' => t('Model'),
        '#title_display' => 'invisible',
        //'#attributes' => array('placeholder' => t('Model')),
        '#empty_option' => t('Select Model'),
        '#options' => $model_list,
        //'#default_value' => $curent_model,
        //'#disabled' => TRUE,
        '#ajax' => array(
            'callback' => 'form_model_callback',
            'wrapper' => 'article-number-ajax-wrapper',
        ),
        '#prefix' => '<div class="clearfix"></div><div class="form-helper-container">',
        '#suffix' => '<button type="button" class="btn tooltip-btn" data-toggle="modal" data-target="#model-help"><span class="glyphicon glyphicon-question-sign"></span></button></div>',
    );

    $form['model_article_nr'] = array(
        '#type' => 'select',
        '#title' => t('Article Number'),
        '#title_display' => 'invisible',
        '#attributes' => array('placeholder' => t('Article Number'), 'class' => array('space-bottom')),
        '#empty_option' => t('Select Article Number'),
            '#states' => array(
            'visible' => array(
              array(
                'select[name="model"]' => array('!value' => ''),
              ),
            ),
        ),
        '#validated' => TRUE,
        '#options' => $article_list[$curent_model],
        '#prefix' => "<div id='article-number-ajax-wrapper'>",
        '#suffix' => "</div>",
    );

```
> 0 votes

---
Tags: 7, forms
---


# Question
Title: How do I update a user profile with entity_metadata_wrapper()?
I got an error while updating user profile data such as name,password and email. I am using `entity_metadata_wrapper()` for processing update.

> exception 'EntityMetadataWrapperException' with message 'Unknown data property original.' in C:\xampp\htdocs\phone\_bay\sites\all\modules\entity\includes\entity.wrapper.inc:335\nStack trace:\n#0

This is my code.

```
require './includes/password.inc';
function commerce_services_user_update($uid, $data, $flatten_fields) {
    $user = user_load($uid);
    $wrapper = entity_metadata_wrapper('user', $user);
    dpm($wrapper->value());

    $name = $data['name'];
    $password = $data['password'];
    $email = $data['email'];

    if ($name != null) {
        $wrapper -> name  = $name;
    }
    if($password != null){
        $wrapper -> pass = user_hash_password($password);
    }
    if ($email != null) {
        $wrapper -> mail = $email;
    }

    try {
        user_save($wrapper);
        $message = "successessfully update!";
    } catch (Exception $e) {
        $message = "not success! -> ". $e;
    }

    $reply = (array('status' => $status,'message' => $message));
    return $reply;
}

```

# Answer
> 1 votes
Since you are using an entity wrapper, you must use `$entity->save` to save the updated user object. In your case, use `$wrapper->save`.

`user_save()` can be used when the user entity is loaded using `user_load()`.

# Answer
> 0 votes
The user entity needs to be also saved. The full code for changing the username and the email address is then the following one.

```
$wrapper->name->set('Jean louis');
$wrapper->mail->set('mail@mail.com');
$wrapper->save();

```

---
Tags: 7, entities
---


# Question
Title: How to add file to root in multisite installation?
I have a multisite setup.

```
public html
 - Sites
 - - All
 - - site1.com
 - - site2.com
etc.

```

I need to .txt files to the root of each website such as site1.com/ads.txt or site2.com/robots.txt

If I upload to public\_html the .txt file will be accessible on all sites on the installation. If I install in the individual files folder the .txt file is shown as site1.com/sites/site1.com/files/filename.txt.

How can I show the .txt file at the root of site1.com but not site2.com?

# Answer
> 0 votes
I have multisite installation and there are multiple common code or files I am able to access in each site.

* You can add your common php, txt or html etc files in the rootsite folder(or you can make assets directory and specify the path "/assets/ads.txt" while accessing) and just try to access e.g site1.com/ads.txt site2.com/ads.txt.
* Another thing is you can create pages using page-ui, page-manager modules (for templates, html or php pages).
* Also you can write controller for the common page and in controller class just simply use the markup to render that page and add routing path for the same.

---
Tags: multi-sites
---


# Question
Title: Show rendered node in jQuery modal through JSON
Whenever a link has a specific class I want to show it as a jQuery modal. I have added the neccesarry data attributes to the link in order to be able to use it as a modal.

I have also created a route for nodes that has a custom controller that is run when a node is viewed with `?_format=json`. The controller returns the rendered node as JSON which seems to work fine.

To see the route definition look here.

Here's my controller:

```
public function json(EntityInterface $node, $view_mode = 'full', $langcode = NULL) {
  $build = $this->entityTypeManager->getViewBuilder('node')->view($node, $view_mode);
  $output = $this->renderer->renderRoot($build);

  return new JsonResponse($output);
}

```

And here's the JS that makes the link a modal:

```
if ($(context).find('.class').length > 0) {
  $(context).find('.class').each(function () {
    $(this).attr('data-dialog-type', 'modal').addClass('use-ajax');
  });
}

```

The only problem is that when clicking the link it gives an error saying:

> SyntaxError: JSON.parse: unexpected character at line 2 column 1 of the JSON data

Why does `JSON.parse` fail to parse the JSON data that `JsonResponse` generates?

# Answer
I can suggest you to check with `AjaxResponse`, it will return the json response object.

```
$response = new AjaxResponse();

```

And use below to open content in modal or as dialog.

```
$response->addCommand(new OpenModalDialogCommand($title, $content, ['width' => '700'])); // To open a modal window

```

OR

```
$response->addCommand(new OpenDialogCommand('#some-element', $title, $content, ['width' => '700'])); // to open a dialog window

```

`$title` refers to title of your node and `$content` refers to content that you want to show in the modal. It is also possible to define some properties like width in it.

And in the end just return it's response like below:

```
return $response;

```

Remember to include `AjaxResponse` in it your controller file.

```
use Drupal\Core\Ajax\AjaxResponse;

```

I hope the above will solve your problem.
> 1 votes

---
Tags: 8, modal-dialogs
---


title: How to access session in twig?

text:
# Question
Title: How to access session in twig?
I wondering how to access to session in twig ?

In my Controller I have this part of code :

```
   $tempstore = \Drupal::service('user.private_tempstore')->get('mdm_user');
   $tempstore->set('num_donateur', $num_donateur);

```

I tried to display the session in my twig template :

```
  {% set mdm_session = app.session.get('mdm_user') %}
  {{ dump(mdm_session) }}

```

But nothing is displayed. Even session is inaccessible.

```
  {{ dump(session) }}

```

Any help would be appreciated.

# Answer
> 0 votes
I would suggest you to firstly check if the data is stored in num\_donateur variable successfully using **$tempstore-\>get('num\_donateur')**

If not stored then try to save it using **\Drupal::service('tempstore.private')**, As i have just googled it and seen **user.private\_tempstore is deprecated** \[ https://www.drupal.org/project/entity/issues/2951683 \]

If data is stored successfully then use code to print the variable

**{% set mdm\_session = app.session.get('mdm\_user') %} {{ mdm\_session }}**

# Answer
> -1 votes
Try this:

```
{% set varname = app.session.get('varname') %}

```

This is the session value `{{varname}}`

---
Tags: 8, theming, sessions
---


# Question
Title: How can I change the taxonomy term title?
Simple as that. I want to change the H1 tag from taxonomy views to something like "Articles from %term" to make it more user friendly and not redundant (breadcrumbs shows the term *alone*).

I couldn't find that information in the template or in taxonomy views options.

# Answer
The `Title` for the `Taxonomy term` Views is set to `None`, so using the `Override title` from the Contextual filters won't display.

The `<h1>` on that Views actually comes from the `Header` option: **Global: Rendered entity - Taxonomy term (Global: Rendered entity - Taxonomy term)**.

That is where you need to change it:
> 0 votes

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


# Question
Title: Feeds: How to import content from multiple xml files
I have around 100 xml files. Each xml file contains a single item.

I have created a feeds importer which is working fine for single xml file.

But I don't know if feeds can work with multiple xml files?

Something like loop on the files and import content from each file?

Is it possible with feeds? As I didn't find anything useful.

# Answer
> 1 votes
# D7

You can import a series of files by using the **File upload** fetcher and enabling the option "Supply path to file or directory directly" on the fetcher settings.

Steps:

1. Select the **File upload** fetcher, enable the option "Supply path to file or directory directly".
2. Store the XML files to import in the public or private directory. On `Administration > Configuration > Media > File system` (/admin/config/media/file-system) you can see which paths are configured for the public or private file system.
3. On the import form, enter the path to the directory with XML files. If you placed these for example in a folder called "mydir" on the public file system, enter `public://mydir`.

*Public file system*

*Import form*

# D8

In the D8 version of Feeds you would select the **Directory** fetcher. The next steps would be similar as for the D7 version of Feeds.

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


title: Feed's Regex find replace problem

text:
# Question
Title: Feed's Regex find replace problem
Hello Drupal community,

I'm finding some issues in a tamper used in feed's module. I want spaces to be deleted in a field that contains numbers. Something that changes "00 00 00 00 00" into "0000000000". I've tried the following :

```
    Regex to find : #(\d{2})[ ](\d{2})[ ](\d{2})[ ](\d{2})[ ](\d{2})#
    Replacement pattern : $1$2$3$4$5

```

Note that the expression was validated in https://regex101.com/ :

But it doesn't seem to work. Anyone please ?

# Answer
What you need to do is something like this

```
#(\d{2})\s+#

```

and then replace with $1

then if you need to limit it, use the limit field.

Its better to try and match the pattern thank the whole string- that one matches 2 numbers, followed by at least one space, and replaces it with the captured number (in brackets) - so it'll match the whole thing.

you could add a positive look ahead (?\d) to make sure it matches 2 numbers then space followed by a number, but testing the above worked
> 1 votes

# Answer
Try giving **Limit number of replacements** value as `-1` This will solve your issue.
> 1 votes

# Answer
Not a solution to this exact issue, but a troubleshooting guide:

What was helpful to me was to dpm the module's parameters and variables. In this file: \sites\all\modules\feeds\_tamper\plugins\find\_replace\_regex.inc - modify this code to insert dpm() functions. (you'll need the devel module for this)

```
function feeds_tamper_find_replace_regex_callback($result, $item_key, $element_key, &$field, $settings, $source) {
  dpm($field);
  $field = preg_replace($settings['find'], $settings['replace'], $field, $settings['real_limit']);
  dpm($field);
}

```

Then go to your importer page /import and run the import you've created.

Regex101 doesn't emulate php exactly from my personal experience. My tests would return "" in conflict with Regex101. For a quick php-test use: http://phptester.net/

like this:

```
$string = 'echoMyString';
$regex = '/(echo)(MyString)/';
$replace = '$2';

echo preg_replace($regex, $replace, $string, '-1');

[Output:] MyString

```

This procedure helped me troubleshoot why my regex wasn't working for Feeds Tamper Importer
> 1 votes

---
Tags: feeds
---


# Question
Title: .htaccess not working in files folder to disable php files from executing in files folder
I have the following in my default/files/.htaccess file:

```
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
Options None
Options +FollowSymLinks

```

But I am still able to execute php files in my files folder. What is wrong with my .htaccess file or how do I even verify if my .htaccess file is even working.

# Answer
I found the correct .htaccess file in another drupal install. The file should contain:

```
# Turn off all options we don't need.
Options None
Options +FollowSymLinks

# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>

# Override the handler again if we're run later in the evaluation list.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>

# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
php_flag engine off
</IfModule>

```

php files wont work now in the files folder.
> 1 votes

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


# Question
Title: Why can't I debug twig templates with intellij idea?
I can't get intellij idea to break on twig files. It is breaking on theme and module files fine. This means that xdebug must be setup correctly. I don't believe that it is caching as I've deleted the cache files

```
drush ev '\Drupal\Core\PhpStorage\PhpStorageFactory::get("twig")->deleteAll();'

```

# Answer
The problem was that the twig cache path was not set for the project.

See https://blog.jetbrains.com/phpstorm/2019/05/twig-and-blade-templates-debugging-2/
> 1 votes

---
Tags: theming, debugging
---


# Question
Title: Query fieldCondition for custom content type
I am attempting to query a custom content type called players (machine name) in a Drupal 7 module and it seemed to be working fine up until an hour ago. Nothing has changed on my side but now the 'Select' works ( with no fieldCondition, but when I add a fieldCondition I am getting empty results.

Here is my query:

```
$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'players')
  ->fieldCondition('field_email_address', 'value', $email_address)
  ->fieldCondition('field_password', 'value', $password)
  ->range(0, 1);

$results = $query->execute();

```

I have verified and reverified the bundle name, each machine name for the fields, and the values being passed in, but when I dump and die the query results, they come up empty.

Any ideas?

# Answer
> 2 votes
Assuming you're using the Email field module, the column name is `email`, rather than `value`.

If that's the case, just change that line to:

```
->fieldCondition('field_email_address', 'email', $email_address, '=')

```

You may need to make a similar change for the password field, depending on what type it is. The easiest way to check for valid column names is in the .install file of the module that provides it, within its implementation of `hook_field_schema()`.

# Answer
> 0 votes
You may need to actually execute the query:

```
$query
  ->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'players')
  ->fieldCondition('field_email_address', 'value', $email_address, '=')
  ->fieldCondition('field_password', 'value', $password)
  ->range(0, 1);

$results = $query->execute();

```

# Answer
> 0 votes
Ok, for some stupid reason you can query a whole database as an unauthenticated user but not with a where clause so you need to add -\>addMetaData('account', user\_load(1)) before the -\>range(0,1). Hope this helps someone else.

---
Tags: 7, database
---


title: Why ajax button calls submitForm?

text:
# Question
Title: Why ajax button calls submitForm?
I have no problems with using Ajax in every form element other then button. When I'm clicking this button

```
  '#type' => 'submit',
  '#ajax' => [
    'callback' => '::ajax_function',
    'wrapper' => 'my-button-wrapper',
  ],

```

it reloads the page ... well it does what would normal submit button do - calls submitForm(). And I don't need that. I need this button only to call ajax\_function()

# Answer
In Drupal, the submitHandler() method of your form definition will always be called UNLESS you have a custom handler attached to the submit button that is clicked. In the case of #ajax buttons, you add your own custom handler, then rebuild the form in that handler.

```
'#type' => 'submit',
'#ajax' => [
  'callback' => '::ajax_function',
  'wrapper' => 'my-button-wrapper',
],
'#submit' => ['::ajaxButtonSubmit'],

```

Then:

```
public function ajaxButtonSubmit(array &$form, FormStateInterface $form_state) {
  $form_state->setRebuild(TRUE);
}

```

By doing this, the default submit handler is not called, and your ajax submit handler is called instead, which then ensures the form is rebuilt instead of reloaded.
> 4 votes

---
Tags: 8, forms
---


# Question
Title: how to make a form field be required with hook form alter
I want to alter a form to make the revision log be required. with drupal 8, I am adding this in a module

```
$form['revision_information']['#required'] = TRUE;

```

but the field does not become required. What am I missing?

# Answer
> 12 votes
this was the answer:

```
$form ['revision_log']['widget'][0]['value']['#required']=TRUE;

```

thanks for the tip about the widget Kevin

# Answer
> 2 votes
I know this is an old case but wanted to share (for those new comers) my experience on how I managed to nail the issue in D7 for the above case.

Sol: $form\['FIELD\_NAME'\]\[LANGUAGE\_NONE\]\[0\]\['value'\]\['#required'\] = TRUE;

Note: Remember to replace the "FIELD\_NAME" part with your referring field.

Cheers.

# Answer
> 0 votes
Generally to make a field required on form alter what you need is

```
$form['FIELD_MACHINE_NAME']['#required'] = TRUE;

```

In your case it didn't work because it's not the nested field and it's a group

https://www.drupal.org/project/drupal/issues/2177469

```
$form ['revision_log']['#required'] = TRUE;

```

**if you want to make the email field required, the following snippet works**

```
$form['account']['mail']['#required'] = TRUE;

```

---
Tags: 8, forms
---


# Question
Title: Installing / updating modules in multi-site environment
I am in the middle of configuring a Drupal 8 installation with multiple domains in a multi-site configuration. One thing that occurred to me, is if one domain/site updates a module, the other site that may use that module won't know of that update.

Should I either : a) move the modules into the sites//site name//modules directory, or b) make another drupal8 instance for each site

Or is there something else that i am missing. Recommendations most helpful.

# Answer
You have described the options for multisite pretty well:

1. Lots of shared code by putting modules in /modules
2. Lots of copies of module code by moving to /sites/\[sitename\]/modules but only one copy of core to update.
3. Use multiple instances instead of multisite (lots of copies of the same code but the ability to update one without risk to others).

Multisite is most useful when there is low variation in the configuration between the sites and therefore you can safely use the same copies of core and the modules on most (if not all) sites. The more variation you have between copies the more likely it makes sense to ditch multisite and move to multiple instances.

While there are some very large instances of multisite in use, there are also people in the community who feel pretty strongly that multisite brings more headaches than it is worth.
> 3 votes

# Answer
I have a D7 multi-site setup with over 20 sites on one hosting! Here are some things I would suggest:

**Organizing extensions**

* If your sites plan to share many of the modules then it is perfectly fine to have those contrib/custom modules in the global modules directory.
* Site-specific contrib/custom modules go to the relevant site's directory (example: `sites/greenpillp.com/modules`).

**For Updating core/modules/themes**

* First read the update descriptions thoroughly to see if they would require any changes to your custom code / dependencies (if any).
* Very important! Back up the database and files to avoid suicidal tendencies if something goes wrong on all sites. lol.
* For module/theme updates, you can have any one site check for all updates (even for modules which are not enabled) and use the UI to download the updates. I usually add an `exit('Site is under maintenance');` in the `index.php` before I do this - this disables all sites temporarily.
* As for database updates, you can do them in two ways:
    + Time-consuming way: Run the `update.php` for each site - one by one.
    + Time-saving way: Use `drush` to update all sites one by one from command line without having to visit them! May be create and save a script which would help you automate it the next time you do it.

I hope this helps. If I missed something or if there's any easier way to manage this, please leave me a comment so that I can try it out the next time I update my multi-site install of Drupal!
> 0 votes

# Answer
If the module is common for all sites them make it global i.e place that module in /modules/custom directory. So it will share the same code on all sites e.g sites/site1.com, sites/site2.com. Now if you do changes in the code of the module you need to cache or re-install the module in all the sites which uses the module via drush to take that changes.
> 0 votes

---
Tags: 8, multi-sites, configuration
---


# Question
Title: Composer using old JSON for contrib module?
I maintain skilling, a contrib module. This...

```
composer require drupal/skilling

```

... reports...

\[RuntimeException\] Could not load package drupal/skilling in https://packages.drupal.org/8: \[UnexpectedValueException\] Could not parse version constraint ~1.0@alpha2: Invalid version string "~1.0@alpha2"

\[UnexpectedValueException\] Could not parse version constraint ~1.0@alpha2: Invalid version string "~1.0@alpha2"

An older version of composer.json did use the string "~1.0@alpha2", but it was removed a while ago. Download the module's zip from D.O, and there is no such string in the file set once the zip file is expanded.

BTW, use the zip file, or Git the source files into contrib/modules, and Drupal installs everything just fine. It's just the composer install that's the problem.

I tried composer clearcache, but no dice. Using -vvv on 'composer require' didn't give me any info that I could interpret. Looking at composer's cache shows Strange Things. The file $skilling.json refers to the right release, but has '"drupal/token\_custom":"~1.0@alpha2"' from long ago.

Help appreciated! The module can't be installed with Composer at the moment.

----- Update ARGH!! ----

@Clive is probably right, but I don't know how to fix it. Tried removing the line with the bad Composer version string in Git history with:

```
git filter-branch -f --tree-filter 'sed -i "/drupal\/token\_custom/d" composer.json' -- --all

```

Also tried BFG repo rewrite tool to replace the bad string.

Pushed. Created new releases. Cleared composer cache. composer require generates the same errors.

Afraid I don't understand Clive's suggestion to rebase a fix onto the branch containing the invalid version string. How is that done?

# Answer
> 1 votes
Im the maintainer of packages.drupal.org - I went ahead and deleted the invalid data out of the database, and this will install now.

I've also opened and issue on drupal.org to put more defensive measures in place. https://www.drupal.org/project/project\_composer/issues/3076342

I think something must have changed in how permissive composer is with certain bad version constraints.

---
Tags: composer
---


# Question
Title: Composer update still shows an older version of a module
Updating dependencies according to these instructions offers an older version of the module. Composer.json file has the package required as `"drupal/h5p": "^1.0@RC",` and it used to update just fine. It seems to be stuck with version **rc14** and unable to recognise any changes. It seems like a problem with packages.drupal.org being unable to update the package info.

The instructions on creating an issue about it here seem to be outdated as that is for a Drupal version 7 project.

Any ideas how could that be resolved? A newer version has been released in the meantime and the package manager is still showing the **rc14** one.

# Answer
The `h5p` module has 2 dependencies and must therefore be updated like this:

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

```
> 1 votes

---
Tags: 8, composer
---


# Question
Title: Exposed filter only allowing content types in list
I have a view called (*Resources*) that displays content filtering by content type. These are the selected options:

* Expose this filter to visitors, to allow them to change it: ✅
* Filter type to expose: **Single filter**
* Operator: **Is one of**
* Content types: **Article**, **Post**, **Story** (NOTE: I have other content types, such as *Basic Page* that shouldn't be included in this view at all)
* Allow multiple selections: ✅

However, when *none* of the options are selected, it also brings in other content types, such as *Basic Page*, which shouldn't be.

How can I make it so that when *none* of the content types in the exposed filter are selected, the results are still filtered such that the nodes must be of one of the chosen content types (Article, Post, Story)?

In other words, I would like the view to behave such that, when *none* of the content types are selected, it acts as though *all* of them are checked.

# Answer
OK, I figured it out.

I simply added a duplicate of my "Content type" filter, except this filter *is not* exposed. Same settings as above ("Is one of", Article/Post/Story, etc.), just an extra restriction on the results to *always* filter by all of the desired content types, with the exposed filter being an *additional* option to *further* narrow down the results.
> 1 votes

---
Tags: views, 8
---


# Question
Title: How to load a file located in core/includes?
I'd like to execute PHP code that requires functions available in the includes files of core located in `core/includes`.

I found `ModuleHandler()->loadInclude()` and `module_load_include()` but I am afraid this 2 options can load files from *core/modules* directory only, according to the doc, but may be I misinterpreted it:

> Loads a module include file.

For example if I execute:

```
\Drupal::moduleHandler()->loadInclude('core', 'inc', 'install');
drupal_rewrite_settings(); // the func that I want located in install.inc

```

I get:

```
Call to undefined function drupal_rewrite_settings()

```

which means `install.inc` has not been loaded.

# Answer
You can use a good old fashioned `include_once` (or `require_once`):

```
include_once DRUPAL_ROOT . '/core/includes/install.inc';

```

Core uses the same method any time it needs to source a file in core/includes. Case in point, `ModuleHandler::loadInclude` itself does exactly that if the file extension provided is "install":

```
public function loadInclude($module, $type, $name = NULL) {
  if ($type == 'install') {
    // Make sure the installation API is available
    include_once $this->root . '/core/includes/install.inc';
  }

  ...

```
> 1 votes

---
Tags: 8
---


title: Custom Validator on Custom Form

text:
# Question
Title: Custom Validator on Custom Form
I see all kinds of examples of how to add a custom validator to an "existing form." Which means, you would use hook\_form\_alter. I want to add one in the code for my custom form.

I'm adding this in my buildForm():

```
$form['#validate'][] = 'mycustom_form_validate';

```

However, that function never seems to get called. I know naming the validation function "validateForm()" would make it work automatically. But I want to specifically call this validation function because things are going to get more complex. But I seem stuck on this baby step.

```
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['#attributes']['novalidate'] = 'novalidate';
    $form['#cache']['max-age'] = 0;
    $form['#action'] = '#email_subscription';
    $form['#validate'][] = 'mycustom_form_validate';

    $form['fname'] = [
      '#type' => 'textfield',
      '#title' => $this->t('First Name'),
      '#maxlength' => 255,
      '#size' => 64,
      '#required' => TRUE,
      '#required_error' => 'Please provide your first name.',
    ];

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('send'),
    ];

    return $form;
  }

  public function mycustom_form_validate(array &$form, FormStateInterface $form_state) {
    $valid = $this->validateEmail($form, $form_state);
    if (!$valid) {
      $form_state->setErrorByName('email', $this->t('Invalid email address.'));
    }
  }

```

# Answer
> 1 votes
You just need to change the line to:

```
$form['#validate'][] = '::mycustom_form_validate';

```

Drupal has special handling for that `::` prefix (see `FormState::prepareCallback`), and processes the above to an equivalent callback of:

```
[$form_object, 'mycustom_form_validate']

```

Which will correctly resolve to your custom method.

---
Tags: 8, forms
---


# Question
Title: Upload file to S3 directly instead of using temporary storage
I have one file uploading form in Drupal 8 where I am uploading 3 different assets and they might be around 2gb or more in size.

I have the s3fs module enabled and configured properly, but (due to temporary storage) it is consuming lot of time to upload to web server. First it uploads in the "/tmp" directory and then to "s3". I have also tweaked apache settings to handle large file uploads.

Is there any way to speedup this upload process? If it's possible how to fetch the uploaded file properties for edit action on the same form?

# Answer
The s3fs module page mentions the use case of uploading very large files directly to S3:

> If your users need to upload very large files to your site, you might want to use the S3FS CORS Upload module. It enables CORS-based uploads, allowing files to be uploaded directly to S3, rather than being routed through your server.

The s3fs module alone only has a S3 client for PHP and will not do what you want. However it is still useful as the recommended module depends on it.
> 2 votes

# Answer
A simple workaround will be to upload the file directly to S3 using AWS CLI.

Just in order to create the file in your Drupal database upload a small file with the same name which will later be overwritten by the file you are going to upload using AWS CLI.
> 0 votes

---
Tags: 8, files
---


# Question
Title: Unresolved dependency updating the module
I'm updating the Views module on a Drupal 7 site, and I'm receiving this message when I update the database.

How do I resolve this dependency issue when I need to update the Views module first?

# Answer
Just download a newer version of views and replace in your project.

https://www.drupal.org/project/views/releases

If you're using composer just require a newer version.

Then, you should be able to install your drupal.

Best regards :)
> 0 votes

---
Tags: 7, views
---


# Question
Title: Additional field settings without creating a new field type
I'm trying to add 2 options to the field settings of all fields of a particular field type, in this case file field. To add the fields to the form I'm using `MYMODULE_form_field_config_edit_form_alter()` instead of extending the base class so it will work with other modules and I won't need to use a custom field type.

Using ThirdPartySettings to store the data doesn't add it to the base config for the field therefore the settings won't be automatically available to other modules.

e.g.

```
function MYMODULE_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  $field = $form_state->getFormObject()->getEntity();
  if ($field->getType() == 'file') {

    $settings = $field->getSettings();

    $form['my_checkbox'] = [
      '#type' => 'checkbox',
      '#title' => t('My Checkbox'),
      '#default_value' => isset($settings['my_checkbox']) ? $settings['my_checkbox'] : '',
      '#description' => t('Check to check my checkbox.'),
    ];

    $form['#entity_builders'][] = 'MYMODULE_form_builder';
  }
}

function MYMODULE_form_builder($entity_type, FieldConfig $field, &$form, FormStateInterface $form_state) {
   // What goes here? I can't do $field->set() on properties which don't exists.
}

```

I've tried setting up a schema file as `src/config/scheme/mymodule.schema.yml` but I'm not sure how to extend the relevant settings in `core/modules/file/config/schema/file/schema.yml`.

`base_file_field_field_settings` seems to have the relevant entries I'm wanting to add to. Do I need to add a class or an install yml file?

# Answer
This works for me:

```
$field->setThirdPartySetting('mymodule', 'my_checkbox', $form_state->getValue('my_checkbox'));

```

After you save your field settings, the new third party setting should be available in your field config:

```
third_party_settings:
  mymodule:
    my_checkbox: 1

```

Here is a good article about this: https://www.webomelette.com/drupal-8-custom-data-configuration-entities-using-thirdpartysettingsinterface
> 2 votes

---
Tags: 8, entities
---


# Question
Title: View display plugin "entity reference" not using translation
> UPDATE: This bug was just fixed in Issue 2174633 and Drupal v8.7.9 will no longer have this problem.

For some of my entity reference fields I'm using *"Views: Filter by an entity reference views"* as reference method. I've configured those views to use the current interface language for rendering (with fallback to default lang).

The interface language selection basically works (in other view blocks, or when previewing in /admin/structure/views), but it does not work when used as source for an entity reference field:

* In my admin interface I'm using I've got a paragraph with an ER field using such a view as source. The paragraph always shows the title in default lang
* On the frontend I've got a webform select field using the same view as source. The select options are always rendering in default lang.
* When using the default reference method I do get translated titles in both use cases.
* As stated above, the correct language is used in preview on /admin/structure/views

How can I select the correct language for my view-filtered ER fields?

(Please note that I can not use the interface language as filter criteria, because this would disable the language fallback.)

# Answer
> 1 votes
I have created a patch for `@4k4's` answer that also uses dependency injection.

To apply this patch:

Take the code snippet below and paste it into a new file e.g `test.patch`.

Then run `git apply /path-to-file/test.patch`.

For a UI only solution, see my other answer.

```
diff --git a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
index 79707af..e092ba9 100644
--- a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
+++ b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
@@ -4,6 +4,7 @@

 use Drupal\Core\DependencyInjection\DeprecatedServicePropertyTrait;
 use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginBase;
+use Drupal\Core\Entity\EntityRepositoryInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormStateInterface;
@@ -59,6 +60,13 @@ class ViewsSelection extends SelectionPluginBase implements ContainerFactoryPlug
    */
   protected $currentUser;

+  /**
+   * The entity repository.
+   *
+   * @var EntityRepositoryInterface
+   */
+  protected $entityRepository;
+
   /**
    * Constructs a new ViewsSelection object.
    *
@@ -74,13 +82,16 @@ class ViewsSelection extends SelectionPluginBase implements ContainerFactoryPlug
    *   The module handler service.
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
+   * @param \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository
+   *   The entity repository.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler, AccountInterface $current_user, EntityRepositoryInterface $entityRepository) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);

     $this->entityTypeManager = $entity_type_manager;
     $this->moduleHandler = $module_handler;
     $this->currentUser = $current_user;
+    $this->entityRepository = $entityRepository;
   }

   /**
@@ -93,7 +104,8 @@ public static function create(ContainerInterface $container, array $configuratio
       $plugin_definition,
       $container->get('entity_type.manager'),
       $container->get('module_handler'),
-      $container->get('current_user')
+      $container->get('current_user'),
+      $container->get('entity.repository')
     );
   }

@@ -231,6 +243,7 @@ public function getReferenceableEntities($match = NULL, $match_operator = 'CONTA
     if ($result) {
       foreach ($this->view->result as $row) {
         $entity = $row->_entity;
+        $entity = $this->entityRepository->getTranslationFromContext($entity);
         $return[$entity->bundle()][$entity->id()] = $entity->label();
       }
     }

```

# Answer
> 4 votes
Comparing TermSelection::getReferenceableEntities and ViewsSelection::getReferenceableEntities it seems like the Views entity reference selection plugin doesn't translate the entity before returning the entity labels. It should work with a core patch adding one line:

*/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php:*

```
public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
  $display_name = $this->getConfiguration()['view']['display_name'];
  $arguments = $this->getConfiguration()['view']['arguments'];
  $result = [];
  if ($this->initializeView($match, $match_operator, $limit)) {
    // Get the results.
    $result = $this->view->executeDisplay($display_name, $arguments);
  }

  $return = [];
  if ($result) {
    foreach ($this->view->result as $row) {
      $entity = $row->_entity;
      // add this line to translate the entity
      $entity = \Drupal::service('entity.repository')->getTranslationFromContext($entity);
      $return[$entity->bundle()][$entity->id()] = $entity->label();
    }
  }
  return $return;
}

```

Edit:

This won't be necessary anymore, when https://www.drupal.org/project/drupal/issues/2174633 is fixed, then resolving the underlying problem, that the selection plugin ignores the views output.

# Answer
> 1 votes
Here's a UI solution if you don't want to apple a core patch.

You'll need to use the `translation_views` module.

Here's a screenshot of the needed filter configuration:

The logic is simple, if the node has no translations then show the original language, otherwise show the translation language.

I use the `translation_views` module to get the `Translation counter filter`.

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


title: watchdog truncate or delete

text:
# Question
Title: watchdog truncate or delete
Watchdog table has become so big that, truncate cascade or delete command in the table is not working at all. The moment the server encounter a DELETE command in watchdog, it gets busy in executing that, all resources are being occupied by DELETE command and server gets very slow. The total functionality can be considered to be null.

Even vacuum full/ananlyze is yielding any result even after waiting for 1 or 2days.

# Answer
You can use truncate command which is faster than Delete. And try using this command directly from Terminal rather than doing "clear log" option available in Recent Log Messages in Drupal 7.

You can find more details on Truncate vs Delete on here.

Hope this helps.
> 0 votes

# Answer
I would suggest you to use one of below methods.

1. Delete entries by range, like you can delete 10000 entries first and check if it takes time then lower the range to 5000 and ... you can also use mysql query to delete the entries

DELETE FROM table LIMIT range;
2. If you have access to mysql console than you can directly call mysql commands to delete or truncate table from terminal.
> 0 votes

---
Tags: log-messages
---


# Question
Title: RewriteRule causing internal redirect limit error
I am trying to server a static HTML site from `/sites/default/files/staticsite` and make it available via a subdomain. I'm hosting the site on Acquia Cloud, and their docs describe Maintaining a static microsite alongside Drupal's docroot.

This solution is working, with the exception of index.html page (homepage) which returns a 404.

* `http://subdomain.example.com/` returns a 404
* `http://subdomain.example.com/index.html` success

## The setup describe in the docs

I have added the required domain to my Acquia Cloud dashboard so the server will accept requests for the subdomain.

I have updated `docroot/.htaccess` with the following RewriteRule to redirect requests to the static files. The following rules are the first lines in the `.htaccess` file.

```
<IfModule mod_rewrite.c>
  RewriteEngine on
  # Only serve the static site for a particular host.
  RewriteCond %{HTTP_HOST} ^subdomain\.example\.com\.au$ [OR]
  RewriteCond %{HTTP_HOST} ^dev-subdomain\.example\.com\.au$ [OR]
  RewriteCond %{HTTP_HOST} ^stage-subdomain\.example\.com\.au$
  # Don't loop anything targeting the actual mask directory, to allow
  # for linked scripts, stylesheets etc in the static HTML
  RewriteCond %{REQUEST_URI} !^/sites/default/files/staticsite/
  #Any requests that made it this far are served from the /staticsite/ directory
  RewriteRule ^(.*)$ /sites/default/files/staticsite/$1 [PT,L]
</IfModule>

```

The files have been uploaded to `sites/default/files/staticsite`

## Things I've tried

I thought `DirectoryIndex` must be `disabled` for these directories so I tried adding `DirectoryIndex index.html` in both `/sites/default/files` and `/sites/default/files/staticsite` but neither have had an effect.

I tried elevating the `DirectoryIndex` directive to the top of the existing `/sites/default/files/.htaccess` file, as well as placing it last. Neither fixed the 404 error.

I've tried removing the `/sites/default/files/.htaccess` and adding a new `.htaccess` file with just `DirectoryIndex index.html` to test if the `SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006` was impacting things. No change still got 404.

I've tried adding the `[END]` flag to the `RewriteRule` to stop the current rewrite process and subsequent rewrite processes, but still got the 404.

## Log entries

When making a request to \`http://subdomain.example.com/ I see the following entry in the Apache error log:

> Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

I'm unable to define 'LogLevel\` because Acquia Cloud do not provide access to the server config, virtual host, and directory contexts which this directive can be defined in.

# Answer
> 0 votes
Start by getting the base site working at your Drupal domain then slowly add Rewrite rules. First remove everything you've added to the .htaccess files and elsewhere, upload the site to the directory you want and see if you can access it.

```
http://www.example.com/sites/default/files/staticsite

```

If that doesn't works then the problem is probably the current .htaccess configuration (docroot or files directory). If it does work, move on to the next stage.

The next step is to get your custom hostname working. This seems pretty straight forward from the Acquia docs:

```
RewriteCond %{HTTP_HOST} ^subdomain\.example.com\.com$
# Don't loop anything targeting the actual mask directory, to allow
# for linked scripts, stylesheets etc in the static HTML
RewriteCond %{REQUEST_URI} !^/sites/default/files/staticsite/
# pass-through the matching file from beneath /sites/default/files/ and stop processing
RewriteRule ^(.*)$ /sites/default/files/staticsite/$1 [PT,L]

```

**Important:** The above needs to be inserted before the following. If it's not, non-file requests (such as directory index / ) may redirect to index.php instead.

```
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^ index.php [L]

```

If that works, start adding the other domains one by one and testing.

# Answer
> 0 votes
i solved this by http://willcodeforcoffee.com/2007/01/31/cakephp-error-500-too-many-redirects/ just uncomment or add this:

```
RewriteBase /
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

```

to your .htaccess file

---
Tags: 7, files, .htaccess, acquia-cloud
---


# Question
Title: Is it normal for a database to have 3600 tables?
I recently inherited a Drupal site and while trying to migrate the site and DB I noticed that the DB is 1GB+ and had 1000s of tables. This is the first time i work with Drupal so I'm not sure what these tables are.

A lot of them are exactly 128KB and named something like drupal\_field\_data\_style\_abc or drupal\_field\_revision\_abc. Is it safe to delete these? Not really sure what they are for at the moment.

# Answer
> 3 votes
Those tables are tables for fields. Whenever you add a field to a content type Drupal creates two tables, one to store the field value and another one to store historical data of that field.

Deleting those table will break your site.

This just means that you have a lot of fields. Usually, in drupal 7 it is a `watchdog` table that contributes to the size of your database unless you want to keep historical log data feel free to clear some data from `watchdog` table.

# Answer
> 1 votes
As @hunde already mentioned that Drupal stores fields data in two type of tables one is field\_data\_\[field\_name\] and field\_revision\_\[field\_name\].

However its not the best practice to remove the tables directly from database, it can break the site. Because the tables are related with the \[field\_name\] and \[field\_name\] is stored in **field\_config** and **field\_config\_instance** tables.

It is best to delete the field from admin panel only in case the field is not used anywhere on the site.

---
Tags: 7, database
---


title: Non-Clickable Menu Items

text:
# Question
Title: Non-Clickable Menu Items
In a Drupal 8 site, I want to add menu items with "no link", I was thinking that nolink is allowed but when I entered this, I got error

> Manually entered paths should start with /, ? or #.

Is there a way for adding menu items not clickable without adding "#" because "#" add attribute \[data-drupal-link-system-path=""\] and \[class="is-active"\]

# Answer
You need to use `route:<nolink>` to achieve this. Then it will validate and render without a link.
> 56 votes

# Answer
To create a menu item without link in a custom module add to \[module\_name\].links.menu.yml:

`url: 'internal:##'`

You need to add a second # character (or any other letter or word `url: 'internal:#nolink'`) in order to the href attribute will not rendered empty, which will cause a page reload if the user click the link.
> 5 votes

# Answer
and add class or style for item \[a style="pointer-events:none; cursor:default; text-decoration:none;" ...\]\[/a\]

```
pointer-events:none; cursor:default; text-decoration:none;

```
> 2 votes

# Answer
For Drupal 8 you can create a link programmatically using Link::fromTextAndUrl not linkable like that:

```
$my_link = Link::fromTextAndUrl(t('This is my link text'), Url::fromUri('route:<nolink>'));

```

Optionally you can convert it to an array using: `$my_link = $my_link->toRenderable();`
> 1 votes

---
Tags: 8, navigation
---


# Question
Title: LIKE clause not working in hook query alter
I'm trying to replace the default search with a LIKE clause in Drupal 7. I tried to alter the query according to Adding an OR condition to an existing query:

```
function MYMODULE_query_node_access_alter(QueryAlterableInterface $query) {
  foreach ($query->getTables() as $table) {
    // LIKE for search results.
    if ($table['table'] == 'search_index') {
      // Get the query args and then the search term
      $args =& $query->getArguments();
      $search = $args[':db_condition_placeholder_1'];

      // Get a reference to the existing query conditions.
      $conditions =& $query->conditions();

      // Save the former conditions
      $former_conditions = $conditions;

      // Reset the condition array. It needs a default #conjunction for which AND is fine
      $conditions = array('#conjunction' => array_shift($former_conditions));

      // Replace the search condition in the query
      foreach ($former_conditions as $key => $condition) {
        if ($key != 1) {
          $query->condition($condition['field'], $condition['value'], $condition['operator']);
        }
        else {
          $query->condition('i.word', '%' . db_like($search) . '%', 'LIKE');
        }
      }
    }
  }
}

```

Searching with the word "declaration" displays the same results as the default drupal search, but searching with "decl" doesn't find any results.

Any ideas why my code isn't working?

# Answer
Have you tried changing the hook you are using to `MYMODULE_query_alter`?

You are implementing hook\_query\_TAG\_alter(), and I don't see where the Search query is tagged as such.

Per the Node API:

> This is the hook\_query\_alter() for queries tagged with 'node\_access'. It adds node access checks for the user account given by the 'account' meta-data (or global $user if not provided), for an operation given by the 'op' meta-data (or 'view' if not provided; other possible values are 'update' and 'delete')
> 0 votes

# Answer
```
module_query_tagName_tag_alter(QueryAlterableInterface $query)

```

Use this and put a tag name in `view->query` setting. By using this you can differentiates views too.
> 0 votes

# Answer
To add a new condition you can also try the above with add\_where

`$query->add_where(1,'i.word', '%' . db_like($search) . '%', 'LIKE');`

I hope this will give the result you are looking for.
> 0 votes

---
Tags: 7, database
---


# Question
Title: Webform Error Occurs During Configuration Import
Currently we are having some trouble handling webform module configuration on our various environments.

When running a configuration import `drupal config:import --directory=$SYNC_DIR` on our dev environments with a fresh database from production we receive the following error:

`[ERROR] An error occurred while trying to write the config file: "Entities exist of type Webform submission and Webform Borough Newsletter. These entities need to be deleted before importing."`

This particular web form (Borough Newsletter) has not been exported as config from production and has no associated yaml file, additionally it has some submissions in the database. When we remove all submissions of this particular webform the import completes, but removes any webforms not stored as config (no surprise there). We also tried to use the Config Ignore to prevent webforms from importing configuration, but we still got the above error. I have three main questions:

1. Our webforms are created on production by non-developers. Is the proper workflow to start exporting webform config from prod and bring it to our dev environments top down?
2. What exactly was the cause of the error we got during import (mentioned above)?
3. How come we still get an import error when we explicitly attempted to block any webform config from being imported? Was it due to a dependency on webforms from some other configuration item?

**Webform Module Version:** 8.x-5.3

**Drupal Core Version:** 8.6.17

Thank you in advance!

# Answer
**UPDATE 2:** I posted a question on Drush's GitHub concering this issue and have received an answer that clears it up.

Essentially, Config Ignore only modifies the default sync storage and when using config-import with no args it takes effect, passing the source argument changes the default sync storage and this is not affected by config-import. More details can be found here.

---

**UPDATE 1:** It turns out that the module Webform Config Ignore (and Config Ignore) depends on, Config Filter, doesn't yet support Drupal Console so that solves the mystery of why that command didn't respect the rules for ignoring webform configuration.

Still looking into why `drush config-import --source` differs from `drush config-import`

---

So after some investigation and a little luck we discovered the issue, though why it occurred is something we're still trying to figure out.

In our deploy process we run a db update (`drush -y updb --entity-updates`) and then run `drupal config:import --directory=$SYNC_DIR` to start the configuration import. As I mentioned earlier even with the Config Ignore (or Webform Config Ignore) module the webform config still attempts to import and the error occurs. An external vendor we are working with on this site had a similar deploy script, but they used the command `drush -y config-import` to run the config import process, when that command is used the webform config is actually ignored and the process completes.

It gets even stranger, if the command `drush -y config-import --source=$SYNC_DIR` is used it fails with the same error as the drupal console command. Only when using the `drush config-import` command with no args (so it uses the sync dir within settings.php, which is the same as $SYNC\_DIR) does the configuration import actually ignore webform configuration and complete successfully.

I'll post an update when I figure out why is this is the case.

**Drush Version:** 8.3.0

**Drupal Console Version:** 1.9.1
> 0 votes

# Answer
Ad 1)
I guess the proper workflow is *never do any config changes on prod, completely disable all config UIs on prod and do only one-way forward-syncs from stage to prod*. But I'm also working for small businesses, who do their work directly on the prod server, so I also can't use the "proper" workflow.

My personal workflow is

1. Prod always is the source of truth (no config ignore).
2. Before development, always pull config from prod.
`drush @prod site:ssh drush_cex_and_git_push.sh "Backsync"`
`git_pull_and_drush_cim.sh`
3. During development, don't change config on prod to avoid merging troubles.
4. After development, push to repository and pull changes on prod.
`drush_cex_and_git_push.sh "New awesome feature"`
`drush @prod site:ssh git_pull_and_drush_cim.sh`

This workflow is NOT safe for concurrent config changes, so this will not work well if you have frequent config changes on prod or long-term or multi-person development jobs!

Prerequisites:

* SSH access on prod. Add dev machine's SSH key on prod's `~/.ssh/authorized_keys`.
* Create drush site environment entries for `@dev` and `@prod` in `~/drush/sites/self.site.yml` to execute drush commands on prod environment while working on dev machine. (doc)
* Use git with SSH keys for quick syncing config between environments without password prompts.
* Use some bash scripts for single-command syncs between environments

`git_pull_and_drush_cim.sh`

```
#!/usr/bin/env sh
echo ""
echo "PULL and IMPORT all updates..."
echo ""

git pull
echo ""
echo "DELETING unused config files"
echo ""
git clean -fd config/sync
echo ""
./composer.phar install --no-dev
./vendor/bin/drush state:set system.maintenance_mode 1 -y
./vendor/bin/drush cache:rebuild
./vendor/bin/drush updatedb -y
./vendor/bin/drush config:import -y
./vendor/bin/drush core:cron -y
./vendor/bin/drush state:set system.maintenance_mode 0 -y
./vendor/bin/drush cache:rebuild

```

`drush_cex_and_git_push.sh`

```
#!/usr/bin/env sh

if [ -z "$1" ]; then
  echo "Usage: drush_cex_and_git_push.sh <commit message>"
  echo ""
  exit 1
fi

echo ""
echo "EXPORT and PUSH all updates..."
echo "Commit Message: $1"
echo ""

./vendor/bin/drush config:export -y
git add -A
git commit -m "$1"
git push

```

I'm also using those scripts as part of my semi-automated maintenaince script running `composer update`s for all my projects.

---

Ad 2)
`drush config:import` deletes all existing configs from the DB that are not present in the sync directory. Since you cannot delete an entity config while there are dependent entity instances in the database, you get this error message.
It would be the same as if deleting `node.type.article.yml` config while still having `article` nodes in the database.

---

There are a lot of blog posts on large enterprise projects with a strict `dev --> stage --> prod` workflow. I'd love to see more info on how to handle a small `dev <--> prod` workflow.
> 1 votes

---
Tags: webforms, configuration
---


# Question
Title: How to add v1 when specifying the URL of an API?
I'm creating an API service using Services (Drupal 7) and would like to create an URL like /api/avu/v1/{id}.

I have *api* in Path to endpoint and in hook\_services\_resources() I have $resources\['avu'\] with

```
"args" => array(
   array(
     "name" => "id",
     "optional" => false,
     "source" => array("path" => 0),
     "type" => "int",
     "description" => "The id of the course to retrieve."
   )
),

```

So /api/avu/{id} works but I can't figure out how to add v1.

# Answer
> 1 votes
All I had to do was to add another argument and clear the cache.

```
"args" => array(
   array(
     "name" => "version",
     "optional" => false,
     "source" => array("path" => 0),
     "type" => "string",
     "description" => "The API version."
   ),
   array(
     "name" => "id",
     "optional" => false,
     "source" => array("path" => 1),
     "type" => "int",
     "description" => "The id of the course to retrieve."
   )
),

```

---
Tags: 7, services
---


# Question
Title: Is there a way to update custom packages with composer?
The project is using Drupal 8 composer template to manage dependencies. Some of the packages are defined locally to look like Drupal modules and be installed in a specific location.

An example could be found here

The issue is that Composer does not store the data about these packages and their version within the .lock file. This means that there does not seem to be a meaningful way to update those custom defined modules with composer itself.

Is there a better way than just writing some custom script, probably relates to some post install procedure that would just visit all of the subdirectories that could possibly be these custom modules and would issue the `git pull`? Or is there a way to just force composer to reinstall these packages on each `composer install` run?

We fully control the codebase for these packages/modules and master branches should be safe to use.

# Answer
You do this with requiring the Composer Merge Plugin in your Drupal project's `composer.json` and then define in which additional locations it should look for `composer.json` files to be merged.

> Composer Merge Plugin is intended to allow easier dependency management for applications which ship a `composer.json` file and expect some deployments to install additional Composer managed libraries. It does this by allowing the application's top level `composer.json` file to provide a list of optional additional configuration files. When Composer is run it will parse these files and merge their configuration settings into the base configuration. This combined configuration will then be used when downloading additional libraries and generating the autoloader.
> 0 votes

---
Tags: 8, composer
---


# Question
Title: "The website encountered an unexpected error. Please try again later." error show on cache clear
My Drupal 8 site is working fine but when I am clearing the cache then my site display below errors.

> > The website encountered an unexpected error. Please try again later.

Please suggest me what is the problem ? I have checked status report and it shows the error below

# Answer
> 1 votes
I was also getting the same error. The reason is given in the error message,i.e. Drupal is not able to find the specified controller. In my case, in the routing yml, the controller's path is "hello\_world\Controller\HelloController", whereas my HelloController.php file was contained in the **hello\_world\src** folder instead of the required path (\**hello\_world\src\Controller\** folder).

*My hello\_world.routing.yml contents*

```
hello_world.content:
 path: '/hello'
defaults:
 _controller: '\Drupal\hello_world\Controller\HelloController::content'
_title: 'Hello World'
requirements:
_permission: 'access content'

```

# Answer
> -1 votes
this work for me:

1. update script in settings.php i.e $settings\['update\_free\_access'\] = TRUE;
2. and then run { website url}/update.php

Note: After running update.php set 'update\_free\_access' to FALSE.

---
Tags: 8
---


title: How do I deploy a site?

text:
# Question
Title: How do I deploy a site?
I am following this link to set-up a Drupal 8 site, I am installing drupal-composer/drupal-project as a template for my composer install for the first time, as I forced myself into drupal 8 for future reasons. I am not a developer myself.

Forth point of the installation says that:

> ...
>
> 4. Modify the composer.json file to configure your preferred installation paths. It is highly recommended to use a sub-directory such as webroot, www, html, web, etc... when scaffolding your Drupal web site.
>
> ...

Why?

Why is it recommended and what would happen if I don't do it.

I am not able to find any decent documentation anywhere mentioning this, and I am pretty sure though that it is not drupal-specific, so please give some light on this.

How do I deploy this site, as on my localhost, I access the site as `my.dev/web` and I want to use `mysite.com` instead of `mysite.com/web` when I put it online. I am avoiding redirecting with .htaccess

# Answer
> 1 votes
A Drupal project is often/usually more than just the webroot, there are other files/folders that can be part of a project. Two specific examples are the private files folder, and the configuration folder. Storing these out of the webroot acts as a layer of security, as they are not web accessible. The configuration folder is one that is managed with Git, allowing for deployment of a project to different environments.

> on my localhost, I access the site as `my.dev/web` and I want to use `mysite.com` instead of `mysite.com/web` when I put it online.

You do not need to put your site in a sub-directory. Using cpanel as an example, the default webroot is at `/home/example/public_html`. You can create a symlink from `/home/example/web` to `/home/example/public_html` (or the other way around, I get them mixed up). Then you create your project at `/home/example`. The `web` directory then becomes `/home/example/web` \- which points at `/home/example/public_html` due to the symlink.

I wrote a blog post that gets into the topic in more depth: https://www.morpht.com/blog/drupal-and-composer-part-2-managing-drupal-8-site-composer

---
Tags: 8, composer
---


# Question
Title: How can I import a local database remotely without having a local database copy?
I am working on database security and with using Drupal we have daily backups from a cloud server which we access remotely. What I normally do is grab a daily DB copy from the cloud server, move the file over unto my local machine, and create a local copy that I can freely work on (to mess up or fix) how I choose.

However as the company grows and more people start to work on this project, having every individual have a local copy of a DB on their machine when it contains proprietary data is a huge security risk.

Is there a way for me to import a local copy of the DB to use, without actually having a physical copy on my machine? Or would this be inevitable?

Edit: For whoever down voted this, can you at least list why so I could fix it? I am trying to get genuine answers. Not have this post deleted because you think it didn't fit the right format.

# Answer
Well, there are two things that can be done with this.

1) Database sanitisation

You can write custom Drush sql-sanitize scripts that will sanitize the database, for example changing all usernames and passwords, as well as any other custom alterations required.

Drush SQL Sanitize scripts can be set up as webhooks, to ensure the sanitization happens automatically.

2) With D8, you mostly shouldn't need to give anyone the database at all. Functionality is migrated through configuration and the configuration API. Developers can work on code, then export their configuration, and push both the code changes as well as the exported configuration to the remote server. The configuration is then imported into the remote environment's active configuration in the database, providing the new functionality on the remote server.

I wrote a blog series on the Configuration API to help understand it better: https://www.morpht.com/blog/drupal-8-configuration-part-1-configuration-api
> 1 votes

---
Tags: 8, security
---


# Question
Title: Cache pages/variables in hook_preprocess() for anonymous user
So I am having trouble understanding the caching of variables set in hook\_preproccesses for anonymous users. It seems that the entire page is cached, and not rebuilt, even when set to no caching. With the following simplified example I am troubleshooting:

```
/**
* Implements hook_preprocess_node().
* @param $variables
*/
function hook_preprocess_node(&$variables) {

  $variables['testing_1'] = [
      '#markup' => date('m/d/Y h:i:s a', time()),
      '#cache' => ['max-age' => 0]
  ];

  $variables['testing_2'] = date('m/d/Y h:i:s a', time());
}

```

then in twig template:

```
{{ testing_1 }}

{{ testing_2 }}

```

Both seem to work fine for logged in users, but these variables never seem to update for anonymous users except upon:

* Manually clearing cache
* Saving content on the node, which then clears node cache.

Even when page caching is set to "no caching" on /admin/config/development/performance, but that does not seem to matter. Its as though the hook\_preproccess does not run for anon users once first page hit from anon user happens.

It seems like from Anonymous user cache control and others, this is due to internal page cache module. Uninstalling this DOES solve the problem, but I am unsure that this is the best way to solve this issue, especially since it is enabled by default. Per the docs, internal page cache says "This module assumes pages are identical for all anonymous users". This is true, I simply want the pages to rebuild (rerun the preproccess hook) for ALL anon users when page cache (set on /admin/config/development/performance) clears.

After a day or so of troubleshooting, I am considering simply creating a cron job to flush caches at this point, but there has to be a better way I am missing. What is the best way to ensure that pages rebuild for anonymous users after a set time?

# Answer
> 0 votes
You may have encountered a core bug where a page cache is not respecting the max-age, or in other words, max-age is not bubbling up to the page cache. There's a workaround on the issue summary but the workaround has a few problems of its own so make sure you consider the implications carefully. The bug issue is postponed until 3 of the linked issues are resolved. Hope this helps.

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


# Question
Title: How to show a field value instead of the node title for nodes displayed through an entity reference field?
*Edit*: I think I found the place, just not the method yet. If correct, I will close this question. Sorry.

I have no clue which hook or direction to look into. I would like to have a label or title preprocess function, but that doesnt exist I think.

Its only for a specific content type that I need to show a field's value as title for the referenced nodes.

So it's not about the entity reference widget when editing nodes but rather the title display wherever that reference field is rendering the nodes' titles.

# Answer
No code necessary, Drupal has built-in features for this:

1. Create a new view mode `singlefield` for the referenced content type `foo`, showing only the field value
2. Optionally, create a very minimalistic template for this `node--foo--singlefield.html.twig`
3. In `/admin/structure/types/manage/foo/display` change the view mode of the host entity reference field to `Rendered entity`, using view mode `singlefield`
> 2 votes

---
Tags: 8, entities
---


title: Extra Content Appears Below Footer

text:
# Question
Title: Extra Content Appears Below Footer
I have an issue where I have the page for a specific role showing up on every page and additionally an error message. These show up below the footer on the pages. I've gone through the theme files and the blocks and I can't figure out what is causing them to appear. I think the best way to show it is probably from the DevTools and inspecting the page. You can see where the footer-bottom is and the EOF: #footer is for the theme. Everything below that before /body and /html shouldn't be there.

Has anyone ever experienced something like this before? I'm on Drupal 7, using Corporate Clean Theme.

Update: The extra content also appears to append itself at the bottom when editing certain pages, so if I saved it without deleting it, it would appear within the main content and at the bottom of the page again.

Update 2: It's definitely something that changed within the database and not the theme files. When I import the last database before this happened, the extra content goes away, when I import the new one, it comes back again. Additionally, there are a few pages when looking at in edit mode that are not showing up with the wysiwig editor, it looks like I'm editing them in plain text.

# Answer
This was being caused by Cron run failing to complete for some reason. We were able to solve the issue by installing the Cron Debug module and Cron would run successfully from there and clear up the extra text.
> 0 votes

---
Tags: theming
---


# Question
Title: Calendar/datepicker popup not working on safari
Below is the date type form field I have in some form which renders on chrome correctly.

```
$form['date']['air_date'] = array (
  '#type' => 'date',
  '#title' => t('Air Date:'),
  '#required' => TRUE,
  '#default_value' => !empty($arr['air_date']) ? $arr['air_date'] : '',
);

```

But the same code gives me following error in console of safari browser and displays **textfield** instead of **calendar** -

> TypeError: `$context.find('input[data-drupal-date-format]').once is not a function. (In '$context.find('input[data-drupal-date-format]').once('datePicker')', '$context.find('input[data-drupal-date-format]').once' is undefined)`

# Answer
> 0 votes
The below workaround helped me to achieve working date-picker in all browser.

```
    <script type="text/javascript">

      if ($('.form-date').prop('type') != "date"){ //if browser doesn't support input type="date", load files for jQuery UI Date Picker
        document.write('<link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />\n')
        document.write('<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"><\/script>\n')
        document.write('<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"><\/script>\n')
      }
    </script>
    <script>
      jQuery(function($){ //on document.ready
        $('.form-date').datepicker({ dateFormat: 'yy-mm-dd' });
      })
    </script>

```

Also I have added custom placeholder to the date field as safari displaying text-field instead of date field. The typeError still exist in console but the above solution works for me in safari and other borwsers.

---
Tags: 8, javascript, datetime
---