# Question
Title: Unable to connect to local MySQL db using drush sql-sync
I'm attempting to use drush sql-sync to sync my prod database to my local dev copy, and everything seems to work until drush attempts to log into the local MySQL. When it does, it throws this error:

```
"ERROR 1044 (42000) at line 39: Access denied for user 'drupal_user'@'localhost' to database 'mydb'"

```

I'm using a group alias file (e.g. mysite.aliases.drushrc.php), and I have my two aliases defined like so:

```
$local_sites = '/Users/steve/Sites/';
$aliases['local'] = array(
  'uri' => 'default',
  'root' => $local_sites . 'mysite/public_html',
  'path-aliases' => array(
    '%files' => $local_sites . 'mysite/public_html/sites/default/files',
    '%dump-dir' => '/Users/steve/Sites/mysite',
   ),
);

$aliases['prod'] = array(
  'uri' => 'default',
  'os' => 'Linux',
  'root' => '/cluster/www_system/www/www.mysite.org/current_build/public_html',
  'remote-host' => 'control.cphwf01.local',
  'remote-user' => 'sedwards',
  'path-aliases' => array(
    '%files' => 'sites/default/files',
    '%dump-dir' => '/scratch',
   ),
);

```

I run sql-sync with --verbose, and I can see the file created on the remote server, and then copied to my local. However, where it fails is at this line:

```
Calling system(mysql --database=mydb --host=localhost --user=drupal_user --password=mypass --silent < /Users/steve/Sites/mysite/mysiteLeW4G5);

```

If I paste this command to the command line like so:

```
mysql --database=mydb --host=localhost --user=drupal_user --password=mypass

```

it connects just fine. Now, I do notice that the temp dump file is then deleted, but it's there at the time sql-sync is attempting to connect. Any ideas why this would be failing?

On a side note, what **flag** do I need to pass to sql-sync to get the dumped file to persist on my local once it's been created? That way I can test w/o having to dump from the server every time. It would also be way to just dump from the remote to my local w/o actually importing into the local db.

Thanks.

EDIT: I've run sql-conf for my local site (with --show-passwords) and it shows the correct information for the local copy.

EDIT 2: Following the advice here, I used the root user, and the sync worked. However, this still doesn't make sense, since using the drush generated connection string with the db user/pw from settings.php at the command line works fine.

# Answer
> 0 votes
I have faced the same issue. My solution was to add more rights to mysql user with this comande line :

```
GRANT ALL PRIVILEGES ON `myDB`.* TO 'mySQLuser'@'localhost' WITH GRANT OPTION

```

Because previous rights :

```
GRANT USAGE ON *.* TO 'mySQLuser'@'localhost' IDENTIFIED BY PASSWORD 'pwd'

```

Do not seem to be enough.

# Answer
> 0 votes
```
$aliases['local'] = array(   'uri' => 'http://yoursite.local',   'root' => $local_sites . 'all/themes/yourtheme/',   'path-aliases' => array(
    '%dump-dir' => $local_sites . 'all/drush/dbdumps',
    '%files' => 'sites/default/files',   ),   'databases' => array(
    'default' =>
      array(
        'default' =>
          array(
            'database' => 'db_name',
            'username' => 'user',
            'password' => 'pass',
            'host' => '127.0.0.1',
            'port' => '',
            'driver' => 'mysql',
            'prefix' => '',
          ),
      ),   ), );

```

# Answer
> -1 votes
I think you are sync db from local to prod, that means you are accessing your local db from remote server. So you have to change configuration of sql db, so that it can be accessed by remotely.

Edit `my.conf` file and change the bind address = 127.0.0.1 to bind address = 0.0.0.0 , mean now you are letting access that db from all IP address.

---
Tags: drush
---


# Question
Title: How to use hook_form_alter to change the cancel link
I am trying to accomplish a very simple thing - changing the cancel link in the invite\_withdraw\_form function - with no success. The function is in this file http://cgit.drupalcode.org/invite/tree/includes/invite.pages.inc#n120 So my custom function looks likes this now:

```
function my_custom_module_form_invite_withdraw_form_alter($form, &$form_state) {
  debug($form['actions']['cancel']);
  $uid = $form['invite']['#value']->uid;
  $cancel = 'user/'.$uid.'/invites/pending';
  $form['actions']['cancel'] = array(
    '#type' => 'link',
    '#title' => 'Cancel',
    '#href' => $cancel,
    '#options' => array ('path' => $cancel),
  );
  debug($form['actions']['cancel']);
}

```

It hooks successfully, because I see output of two debugs, the second of which confirms the array has changed from:

```
array (
  '#type' => 'link',
  '#title' => 'Cancel',
  '#href' => '<front>',
  '#options' =>
  array (
    'path' => '<front>',
  ),
)

```

to

```
array (
  '#type' => 'link',
  '#title' => 'Cancel',
  '#href' => 'user/1/invites/pending',
  '#options' =>
  array (
    'path' => 'user/1/invites/pending',
  ),
)

```

but for some reason when I click the Cancel button it keeps redirecting me to the front page. What I am doing wrong and what is the right code?

# Answer
> 0 votes
I think you're just missing an ampersand (&) in front of $form in the first line of your code.

---
Tags: forms
---


title: Breadcrumb is not visible

text:
# Question
Title: Breadcrumb is not visible
I am a newbi to drupal.I installed breadcrumb in my website.It is showing in all pages but one page it is not showing the breadcrumb.I created the page using panels module.

# Answer
You can try Custom Breadcrumbs module.

> Many new features have been added including support for Views, Panels, Taxonomy vocabularies and terms, paths, and a simple API that allows contributed modules to enable custom breadcrumbs for module pages and theme templates. These are implemented using optional, independent submodules that depend on the main Custom Breadcrumbs module.
>
> In addition to breadcrumb visibility, this version provides an option permitting PHP code snippets to be used in forming the breadcrumb titles and paths. Multiple languages are also supported.

Another option is Panels Breadcrumbs module.

> Panels Breadcrumbs allows you to set your breadcrumbs directly from Panels configuration, and also allows you to take advantage from Panels arguments and contexts as placeholder tokens.
> 0 votes

---
Tags: panels
---


# Question
Title: Changing a plain text field to enable rich editing
In Drupal 8, I set up a plain text field and now I have no way to change it back to rich text editing.

I could take the approach of just setting up a new field and copy the field data from the old one to the new one manually, but I have hundreds of records. What are some other solutions?

>

>

# Answer
> 11 votes
There is no official solution. String and text fields have different structure (text has an additional format column), you could try to convert it by hand, but you also need to update Drupal's internal information about the field and resulting database schema.

Your easiest option is probably to create a new field and then write a simple script that loads all nodes of that type and assigns the value of the old field to the new. If there are too many nodes to load for a single run, you'll need to split it up or do a batch.

```
$nodes = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['type' => 'yourtype']);
foreach ($nodes as $node) {
  $node->newfield->value = $node->oldfield->value;
  $node->newfield->format = 'plain_text';
  $node->save();
}

```

---
Tags: 8, entities, input-formats
---


# Question
Title: Altering an already altered form of Invite module
Trying to learn how to override forms I've read the instructions on https://www.drupal.org/node/1975230 and see I need to identify the form itself. The form that I need to redirect is located on `user/1/invites/invite_by_email`, so looking at the HTML code of the form:

```
<form action="/user/1/invites/invite_by_email" method="post"
 id="invite-form" accept-charset="UTF-8">

```

So taking its id `invite-form` I found its function in the `invite.admin.inc` file of Invite module at line http://cgit.drupalcode.org/invite/tree/includes/invite.admin.inc#n177:

```
function invite_form($form, &$form_state, $invite) {
  $form['#entity'] = $form_state['invite'] = $invite;

  $form['uid'] = array(
    '#type' => 'value',
    '#value' => $invite->uid,
  );

  field_attach_form('invite', $invite, $form, $form_state);

  $submit = array();
  if (!empty($form['#submit'])) {
    $submit += $form['#submit'];
  }

  $form['actions'] = array(
    '#weight' => 100,
  );

  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save invite'),
    '#submit' => $submit + array('invite_form_submit'),
  );

  // Show Delete button if we edit invite.
  $invite_id = entity_id('invite', $invite);
  if (!empty($invite_id) && invite_access('edit', $invite)) {
    $form['actions']['delete'] = array(
      '#type' => 'submit',
      '#value' => t('Delete'),
      '#submit' => array('invite_form_submit_delete'),
    );
  }

  $form['#validate'][] = 'invite_form_validate';

  return $form;
}

```

Then there is another function invite\_by\_email\_form\_invite\_form\_alter() at http://cgit.drupalcode.org/invite/tree/modules/invite\_by\_email/invite\_by\_email.module#n283:

```
function invite_by_email_form_invite_form_alter(&$form, &$form_state, $form_id) {
  $invite = $form['#entity'];

  if (!empty($invite->type_details()->invite_sending_controller['invite_by_email'])) {
    $language_subject = $form['field_invitation_email_subject']['#language'];
    $invite_by_email_settings = isset($invite->type_details()->data['invite_by_email']) ? $invite->type_details()->data['invite_by_email'] : array('use_default' => TRUE);

    if ($invite_by_email_settings['use_default']) {
      $message_editable = variable_get('invite_message_editable', FALSE);
      $replace_tokens = variable_get('invite_default_replace_tokens', TRUE);

      // Override the default mail subject and body with the global defaults.
      $form['field_invitation_email_subject'][$language_subject][0]['value']['#default_value'] = variable_get('invite_default_mail_subject', '');
      $form['field_invitation_email_body'][$language_subject][0]['value']['#default_value'] = variable_get('invite_default_mail_body', '');
    }
    else {
      $message_editable = $invite_by_email_settings['message_editable'];
      $replace_tokens = isset($invite_by_email_settings['replace_tokens']) ? $invite_by_email_settings['replace_tokens'] : TRUE;
    }

    // Hide if message is not editable.
    if (!$message_editable) {
      $form['field_invitation_email_subject']['#type'] = 'hidden';
      $form['field_invitation_email_body']['#type'] = 'hidden';
    }
    else {
      // Add token help if enabled.
      if (module_exists('token') && $replace_tokens) {
        // Add tokens help.
        $form['token_help'] = array(
          '#title' => t('Replacement patterns'),
          '#type' => 'fieldset',
          '#collapsible' => TRUE,
          '#collapsed' => TRUE,
          '#weight' => $form['field_invitation_email_body']['#weight'] + 0.5,
        );

        $form['token_help']['help'] = array(
          '#markup' => theme('token_tree', array('token_types' => array('user', 'profile', 'invite'))),
        );
      }
    }

    $form['#validate'][] = 'invite_by_email_form_invite_form_validate';
    $form['actions']['submit']['#value'] = t('Send Invitation');
  }
}

```

and it looks like more the one I need to redirect.

However this function is already an `alter` function itself and I am confused how can I alter it. Can I alter another alter function? If not and if I need to work with the original invite\_form function at http://cgit.drupalcode.org/invite/tree/includes/invite.admin.inc#n177, then do I need to copy invite\_by\_email\_form\_invite\_form\_alter() at whole as I don't want to change how it works - I only need to redirect it to another page (to user/1/invites/pending in fact) on form submit.

Bear with me if the question is too simple as I am just learning. I would appreciate if someone could give me a code to try.

# Answer
> 0 votes
You don't actually alter the alter, but you can create your own custom module that uses hook\_form\_alter plus a custom function to redirect upon form submittal.

Create a custom module. For this example, let's call it invite\_redirect.

If you haven't created a custom module before, these instructions are fairly good but are missing a very important step:

https://www.drupal.org/docs/7/creating-custom-modules/getting-started

The missing step is creating the .info file which is required. Name yours invite\_redirect.info. It goes inside the sites/all/modules/custom/invite\_redirect along with invite\_redirect.module. All that absolutely has to be in the invite\_redirect.info file is the following...

```
name = Invite Redirect
description = Redirects to custom location upon submittal of the invite_by_email form
core = 7.x

```

In the invite\_redirect.module file, add this code...

```
<?php
function invite_redirect_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'form_invite') {
    $form['#submit'][] = 'invite_form_submit_handler';
  }
}

function invite_form_submit_handler(&$form, &$form_state) {
  $form_state['redirect'] = 'user/1/invites/pending';
}

```

I would enable this and see if it works (flush caches after enabling it). If it doesn't work, you may have to specify a weight for your custom module (so it gets the last word durring rendering). There are several methods for doing this described here: https://www.drupal.org/docs/7/creating-custom-modules/howtos/how-to-update-a-modules-weight

I prefer the .install file method they discuss.

Hope this helps you.

Anne

---
Tags: forms, redirection
---


# Question
Title: How do I change what blocks show up on a user page depending on the user role of that page?
It is possible to filter blocks based on the user role of the current user, but I want to be able to change blocks based on roles of the user whose page I am visiting.

User 1 is an administrator so visiting

```
 /user/1

```

users see

```
  Administrator block

```

no matter what user role the current user logged in has.

if User 1 visits

```
 /user/4

```

where user 4 is RoleX they see

```
RoleX Block

```

Where RoleX block and Administrator block are both created in views.

Is there a way to do this out of the box or do I need to write my own contextual filter

# Answer
> 2 votes
You need to expose that entity as a context to Drupal, then the visibility settings should automatically let you select between the current user and the user on the page.

Drupal core only does that for nodes at the moment, the logic for that is in `\Drupal\node\ContextProvider\NodeRouteContext` with its service definition:

```
node.node_route_context:
class: Drupal\node\ContextProvider\NodeRouteContext
arguments: ['@current_route_match']
tags:
  - { name: 'context_provider' }

```

So you need to duplicate that class and basically do a search and replace for node =\> user, remove the node.add part and put that in a custom module.

---
Tags: 8, views
---


title: How do I avoid API calls are cached?

text:
# Question
Title: How do I avoid API calls are cached?
I'm using Drupal 8 in headless mode with Angular 8 as my client, but Drupal caches the API calls. For example, I have an end point which suppose to give items in random order, but this doesn't happen. I only get cache items in a particular order.

How can I overcome this? I have tried to disable the cache modules, but I still get the same behavior.

# Answer
> 15 votes
There are two level of caching in Drupal.

**1.) Dynamic Page Cache**

You have to provide the correct cache metadata on the json response.

For example use the cache properties from a config or content entity

```
$response->addCacheableDependency($entitiy);

```

or build a cacheable metadata object and add this to the response:

```
$build = [
  '#cache' => [
    'contexts' => ['url.query_args'],
    'tags' => ['node:1', 'node_list'],
    'max-age' => 300,
  ],
];
$cache_metadata = \Drupal\Core\Cache\CacheableMetadata::createFromRenderArray($build);
$response->addCacheableDependency($cache_metadata);

```

You can use this in a custom controller or implement this in an event subscriber to alter responses from other modules (core or contrib).

**2.) Internal Page Cache**

The module *Internal Page Cache* caches all responses for anonymous requests regardless of the cache metadata. You can uninstall this module to disable this cache.

**Alternative solution**

On the client side append a different query string on every request to get a fresh response:

```
node/123?_format=json&time=123456789

```

This will disable the *Internal Page Cache* and parts of the *Dynamic Page Cache*.

Reference: https://www.drupal.org/docs/8/core/modules/rest/javascript-and-drupal-8-restful-web-services

# Answer
> 5 votes
I prefer to disable cache entirely for my endpoints. You can do it adding a cacheable dependency with a zero MaxAge to the *ResourceResponse* object.

Here is an example:

```
$response = new ResourceResponse($data);
$disable_cache = new CacheableMetadata();
$disable_cache->setCacheMaxAge(0);

$response->addCacheableDependency($disable_cache);

return $response;

```

---
Tags: 8
---


title: query string of tid not working on page

text:
# Question
Title: query string of tid not working on page
I need my view to default the exposed filter depending on the ?tid= variable that i put in the url . It was working before, but now it no longer does. Is there a setting in the view that makes that tid variable work?

# Answer
In the view you need an exposed filter on the term field. In the settings for this field, expand on the "More" section near the bottom and you'll see a field called "filter identifier" - enter tid in this field (in this screenshot, you can see I used "category" it can be whatever label you want to give it). Click Apply this display. Save the view.
> 0 votes

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


# Question
Title: Remove and uninstall module in a single patch
One of the modules I maintain contains a sub-module. The sub-module doesn't do much; just provides views integration for the main module, i.e. only have implementation of `hook_views_data`. I would like to move this implementation to the main module.

If it was D7, I would have followed the steps below:

1. Remove the module files.
2. Write an update hook in the main module, to remove the entry from the system table.
3. In the same update hook, would delete the variables (if present).

For D8, I have written an update hook for the same in the module (Reference : #2781805 : Social stats field are not available in views):

```
/**
 * Implements hook_update_N().
 *
 * Removes entry of social_stats_views module.
 */
function social_stats_update_8001(&$sandbox) {
  // Read the configuration.
  $module_data = \Drupal::config('core.extension')->get('module');

  // Unset the modules you do not need.
  unset($module_data['social_stats_views']);

  // Write the configuration.
  \Drupal::configFactory()->getEditable('core.extension')->set('module', $module_data)->save();
}

```

I did not add anything else (like removing config, etc.), as the module only implemented a single hook.

I still see the following error after executing the update hook:

> User warning: The following module is missing from the file system: social\_stats\_views in drupal\_get\_filename() (line 236 of core/includes/bootstrap.inc).

Is there a bullet-proof way to remove the module?

# Answer
> 3 votes
You can use `ModuleInstaller::uninstall()`:

```
\Drupal::service('module_installer')->uninstall(['social_stats_views']);

```

In D8 there is a lot of housekeeping to do. You can see this in the code of `uninstall()`:

https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Extension!ModuleInstaller.php/function/ModuleInstaller%3A%3Auninstall/8.2.x

---
Tags: 8, version-control
---


title: db_condition : nid = tnid

text:
# Question
Title: db_condition : nid = tnid
I need to retrieve all nodes whose node ID is equal to their tnid, or whose tnid is equal to 0. I am using the following code.

```
$db_or = db_or();
$db_or->condition('nid','tnid','=');
$db_or->condition('tnid',0,'=');

$query = db_select('node', 'n')
  ->condition($db_or)
  ->fields('n',array('title','nid','tnid','type','language'))
  ->extend('PagerDefault')->limit(50)
  ->condition('type','article','=')
  ->orderBy('created', 'DESC');

```

It does not work. It returns 0 node IDs, which is not the expected result, since the following code returns a different result.

```
db_query_range("select * from {node} where (nid = tnid or tnid = 0) and type = 'article' order by created DESC",0,1000);

```

If I remove `$db_or->condition('nid','tnid','=');` the first query returns only nodes with tnid equal to 0.

So, why does the first `OR` condition break my code?

# Answer
You need a `where`, `condition` always uses the value literally:

```
$db_or = db_or();
$db_or->where('nid = tnid');
$db_or->condition('tnid',0,'=');

```
> 3 votes

# Answer
The code you are showing doesn't work because `$db_or->condition('nid','tnid','=');` is comparing the value of the *nid* field with the literal string `'tnid'`, not with the value of the *tnid* field.
When you need a more complex condition, you need to use `SelectQuery::where()`, not `SelectQuery::condition()`.

```
$query = db_select('node', 'n')
  ->fields('n',array('title','nid','tnid','type','language'))
  ->condition('n.type','article','=')
  ->where('n.nid = n.tnid OR n.tnid = 0')
  ->orderBy('n.created', 'DESC')
  ->extend('PagerDefault')
  ->limit(50);

```

Keep also in mind that, if you don't need to get only the nodes to which the currently logged-in user has access, or your query is not supposed to be altered from other modules, you should use `db_query()`, which is faster than `db_select()`.

In the case you were interested only to the nodes to which the currently logged-in user has access, the code to use should be the following one.

```
$query = db_select('node', 'n')
  ->fields('n',array('title','nid','tnid','type','language'))
  ->where('n.nid = n.tnid OR n.tnid = 0')
  ->condition('n.type','article','=')
  ->orderBy('n.created', 'DESC')
  ->addTag('node_access')
  ->extend('PagerDefault')
  ->limit(50);

```
> 2 votes

---
Tags: 7, database
---


# Question
Title: Cannot change checkboxes options in drupal form using AJAX callback
I am trying to apply the #options value of a checkboxes in a form inside a Ajax callback.

Even after using `$form['tags']['table']['#options'] = $final;` the value in the form is not changing.

I have tried printing the #options value in the watchdog and the value seems to have changed. But it is not getting reflecting on the form page.

**The form field which needs to be updated**

`$form['tags']['ask_button'] = array(
 '#type' => 'button',
 '#value' => t('Next'),
 '#ajax' => array(
 'callback' => 'ajax_tag_callback',
 'wrapper' => 'replace_tagfield_div',
 ),
 );
$form['tags']['question_tags'] = array(
 '#title' => t("Tags"),
 '#type' => 'textfield',
 '#prefix' => '
',
 );
$form['tags']['table'] = array(
 '#type' => 'checkboxes',
 '#options' => drupal_map_assoc(array(t('SAT'), t('ACT'))),
 '#suffix' => '
',
 );`

**The Ajax callback**

`function ajax_tag_callback($form, &$form_state) {
\\some code\\
 $final = drupal_map_assoc(array(t('SAT'), t('ACT')));
 $form['tags']['table']['#options'] = $final;
 $form['tags']['question_tags']['#value'] = $tag_names;
\\returned the form here
 return $form['tags'];
}` Even after returning the form field, my form is not getting updated. Please suggest me a solution..

# Answer
*** Update using new code ***

Form definition:

```
$form['tags']['ask_button'] = array(
  '#type' => 'button',
  '#value' => t('Next'),
  '#ajax' => array(
    'callback' => 'ajax_tag_callback',
    'wrapper' => 'replace_tagfield_div',
  ),
);
$form['tags']['values'] = array
(
  '#prefix' => '<div id="replace_tagfield_div">',
  '#suffix' => '</div>',
);
if(isset($form_state['values']))
{
  $final = drupal_map_assoc(array(t('SAT'), t('ACT')));
  $form['tags']['values']['question_tags'] = array(
    '#title' => t("Tags"),
    '#type' => 'textfield',
    '#value' => $tag_names, // Note - you didn't show how this is created
  );
  $form['tags']['values']['table'] = array(
    '#type' => 'checkboxes',
    '#options' => $final,
  );
}
else
{
  $form['tags']['values']['question_tags'] = array(
    '#title' => t("Tags"),
    '#type' => 'textfield',
  );
  $form['tags']['values']['table'] = array(
    '#type' => 'checkboxes',
    '#options' => drupal_map_assoc(array(t('SAT'), t('ACT'))),
  );
}

```

And your ajax callback will look like this:

```
function ajax_tag_callback($form, &$form_state) {
  return $form['tags']['values'];
}

```

*** Original response ***

Not enough information provided to say for sure what your problem is, but it's likely one of these:

**Problem 1:**

You are making changes to the form in the ajax callback. You cannot do this. Here is how the form API works.

1) Form is generated

2) Form is cached on server

3) Form is sent to user

4) User initiates some ajax

5) Values are sent to server

6) Form is rebuilt, with submitted values

7) New form is cached on server

8) Form is sent to ajax callback

9) Relevant values are returned from ajax callback

10) Drupal sends data to browser, and the new parts of the form are injected into the page

11) User submits form

12) Drupal checks submitted values to the cached form, to see if the received values match the cached form, giving an error if they don't. This is the major strength of the Form API.

Step 7 and 8 are the key points here - the form has already been cached before it is sent to the ajax callback. So any changes you make won't be part of the cache causing errors.

**Problem 2**

You don't have a #prefix set on $form\['tags'\]. You have only set the suffix. You need to provide a wrapper with your #ajax definition (which you didn't show us), so maybe the wrapper you have provided does not exist.
> 1 votes

---
Tags: 7, forms, ajax
---


# Question
Title: Using hook_form_alter to enter placeholder in mailchimp signup fom
For the signup form I'm using the Mailchimp Signup module. The idea is to hide the label, which I did using the `unset();` function, and put an a placeholder in the input field where people enter their emailaddress.

Here's the code:

```
function bw_custom_form_alter(&$form, &$form_state, $form_id){

  if ($form_id == 'mailchimp_signup_subscribe_block_mysite_group_form') {
    //dpm($form);
    unset( $form['mergevars']['EMAIL']['#title']);
    $form['mergevars']['EMAIL']['#placeholder'] = t('Your emailaddress');
    dpm($form['mergevars']['EMAIL']['#placeholder']);
    }
}

```

`dpm($form['mergevars']['EMAIL']['#placeholder']);` returns the string `Your emailaddress` nicely in the green drupal message frame. Yet, the actual placeholder isn't there in my input element. Looking at the attributes of the particular `input`field in question, the attribute isn't added either:

```
<input id="edit-mergevars-email" class="form-text required" type="text" maxlength="128" size="25" value="" name="mergevars[EMAIL]">

```

# Answer
> 3 votes
You have to use this:

```
$form['mergevars']['EMAIL']['#attributes'] = array(
 'placeholder'=> t('Your placeholder'),
);

```

# Answer
> 0 votes
If you want all field titles as placeholders:

```
$key_blacklist = array('#prefix','#suffix','#tree');

foreach($form['mergevars'] as $key => $var) {
  if ( ! in_array($key, $key_blacklist)) {
    $form['mergevars'][$key]['#attributes'] = array( 'placeholder'=> $form['mergevars'][$key]['#title']);
  }
}

```

---
Tags: 7, forms
---


# Question
Title: How to add one more field in disqus form
i have been installed disqus module in my drupal setup.it gives only one textarea field how to i add one more field to get subject from user.

# Answer
Disqus does not provide titles, therefore, it is not possible.

What the Disqus module does is embed the Disqus chat/comments as an iframe. For security reasons, you cannot modify/alter anything that is inside an iframe.
> 0 votes

---
Tags: 7, comments
---


# Question
Title: META tags module description [node:summary] doesn't work
I have a content type with title, image, body field (long text with summary). I use meta tag module and when I add in Description: \[node:summary\] or \[node:field\_body:summary\] nothing appears in the meta description in view-source.

```
<meta name="title" content="..."
<meta name="image" content="..."

```

Title and image work, but not summary.

Does anyone have a solution?

# Answer
I can confirm, that the token `[node:summary]` works in metatag. But only for the original "body" field with exactly that name. Did you change the field name? Because the original "body" field is not "field\_body".
> 1 votes

---
Tags: 8, meta-tags
---


# Question
Title: How to display a node's last saved date?
Drupal 8 already displays the last saved date in page edit form. I want to add a field to a node that displays it again. I am using `hook_form_alter()` and doing this in my module, but it displays the current date.

```
  if ($form_id == 'node_page_edit_form') {
    $form['field_message2'] = array(
      '#type' => 'item',
      '#title' => t('Changed date'),
      '#weight' => -1,
      '#markup' => format_date(time(), $created),
    );
  }

```

How do I display the last saved date?

# Answer
This is the code that you need:

```
    if ($form_id == 'node_page_edit_form') {
    $form['field_message2'] = array(
      '#type' => 'item',
      '#title' => t('Changed date'),
      '#weight' => -1,
      '#markup' => format_date($form_state->getFormObject()->getEntity()->changed->value),
    );
  }

```

Check the FormStateInterface interface to see in the methods the getFormObject() method.
> 4 votes

# Answer
The arguments you are passing a `format_date()` are wrong: The second argument is the format used for the date, not another timestamp.

You should code similar to the following one.

```
  if ($form_id == 'node_page_edit_form') {
    $node = $form_state->getFormObject()->getEntity();
    $form['field_message2'] = array(
      '#type' => 'item',
      '#title' => t('Changed date'),
      '#weight' => -1,
      '#markup' => format_date($node->getChangedTime(), 'medium'),
    );
  }

```

Even better, you should use the service Drupal provides for formatting dates.

```
  if ($form_id == 'node_page_edit_form') {
    $node = $form_state->getFormObject()->getEntity();
    $form['field_message2'] = array(
      '#type' => 'item',
      '#title' => new \Drupal\Core\StringTranslation\TranslatableMarkup('Changed date'),
      '#weight' => -1,
      '#markup' => \Drupal::service('date.formatter')->format($node->getChangedTime(), 'medium'),
    );
  }

```

Instead of `'medium'`, you can use the default value, or another one you prefer.
> 5 votes

---
Tags: nodes, 8, forms
---


# Question
Title: Rewrite negative number into positive numbers
I'm preparing some charts, with positive and negative values. I would like to create one pie chart, including all the values (the positive and negative). Of course, this doesn't work as only positive numbers should be considered. So I tried to rewrite the results (to cancel the "-") but it doesn't work. I would like to have "-100" displayed as "100", and the "100" staying at "100", so that I can create my graph.

Does somebody has an idea?

# Answer
For Drupal 7 you could use the `Global: Math expression` field to perform a mathematical operation. Load the initial field first, suppress it from display and use the replacement token within the Math field: (`abs([initial_field])`).

For Drupal 8 this field does not exist (yet), though there is a sandbox linked in post #10 here: https://www.drupal.org/node/2544670. It might work.
> 0 votes

---
Tags: views
---


# Question
Title: Why is a custom field I programmatically created shown as disabled?
I created a Drupal 8 module for creating a custom field. I wrote the code basing on the documentation given in Create a custom field widget, Create a custom field formatter, and Create a custom field type.

I created the *.info.yml* file, three directories src/Plugin/Field (*FieldFormatter*, *FieldType*, and *FieldWidget*) where I put the files described in those documentation guides.
I could see the custom field in the field list, but it is shown as disabled.

Why does this happen?

# Answer
After the field is created and the field instance is added, you need to enable the field in the display settings for the form, for example with the following code.

```
entity_get_form_display('node', $bundle, 'default')
  ->setComponent('field_custom', array(
    'type' => 'string'
  ))
  ->save();

```
> 0 votes

# Answer
I had the same problem and the issue in my case was that I was using `default_widget = "options_select"` in my FieldType plugin but the options\_select widget does not allow my custom field type.

The solution was to create a custom FieldWidget plugin which extends the OptionsSelectWidget and in the field\_types declare my custom field type.

This allowed my field to be placed in the form correctly and the options widget to be used.
> 0 votes

---
Tags: 8, entities
---


# Question
Title: How to count the children (elements) inside a fieldgroup?
I use the Field Group module in a website and I'm trying to count the fields within a Field Group.

I tried …

```
$num_of_fields = count($content['group_name']['children']);

echo $num_of_fields;

```

… but it doesn't seem to work. What am I doing wrong?

# Answer
> 0 votes
If you use the following code you will see the value that you need.

```
/**
 * Implements hook_form_alter().
 */
function YOUR_MODULE_form_alter(&$form, &$form_state, $form_id) {
   //you need the devel module to use dpm() function
  //My field group name is group_g2
  dpm(count($form['#groups']['group_g2']->children));
}

```

Is easy to track values if you use the Devel and Search Krumo modules

---
Tags: 7, entities
---


# Question
Title: Changing permission on node access that linked with other nodes
I have a Jobs type content which include a user reference field

I have another content type called Applications which includes a node reference field that links to Jobs.

Register applicants can apply for Jobs via Applications, permissions have been set so only individual applicants can view their own applications and not anyone's else.

I want to set permissions so recruiters can only view applications to their own Job content type and not anyone's else. I can do this in views but if a recruiter knows another recruiters Application url (i.e /application/4) then the recruiter can view that application as well, in this example change the url to /application/5.

# Answer
You can do this in `hook_node_access()`.

You didn't mentioned if this is for D7 or D8, but this hook is available in both.

This hook provides the node and the account object. So you have all data you need to calculate the permission.
> 1 votes

# Answer
This can be done using rules.

For example.

Content is viewed of type Application

Compare the author id of the node in the referenced field with current user id.

If it matches, you can redirect to the home page or can do what ever you want to do at this point.

Here is the exported rule which is working.

```
{ "rules_acces_own_job_applications" : {
"LABEL" : "Acces Own Job Applications",
"PLUGIN" : "reaction rule",
"OWNER" : "rules",
"REQUIRES" : [ "rules" ],
"ON" : { "node_view--application" : { "bundle" : "application" } },
"IF" : [
  { "NOT data_is" : {
      "data" : [ "node:field-job:author:uid" ],
      "value" : [ "site:current-user:uid" ]
    }
  }
],
"DO" : [ { "redirect" : { "url" : [ "site:url" ] } } ]
}
}

```
> 0 votes

# Answer
Okay, so here is an answer using only Views.

The following requirements were identified in the OP:

1. A recruiter creates a Job node
2. An applicant creates an Application for a specific job (linked from Application to the Job using an entity reference field).
3. A recruiter should see all Applications for a Job, only if she created the Job node.

You need to do the following:

1. Create a View that displays Nodes of Type = Jobs.
2. Add the Node's ID as a Contextual Filter to the View
3. Add one "Content: Author" relationship to your View, make it mandatory and name it recruiter. This will allow you to use the current user as a filter.
4. Add a "User: Current" filter to your view, selecting the currently logged-in user to match the content's (in this case Job) author and the "recruiter" relationship.

At this point, your View, running via a URL like "/applications-for-job/4" should allow recruiters to see a list of their jobs only and no one else's.

5. Add a relationship - a reverse one - "Entity Reference: Referencing entity" to your view, to link Jobs to the Applications that point to them. Make this mandatory. It should come with a name like "Content referencing Content from field\_job".
6. Add a second "Content: Author" relationship and this time set it up to use the relationship from step 5. Makes this mandatory. You can call this "applicant".
7. Configure your fields to use the relationship from step 5, so that Application data are displayed; optionally add user data to your fields and use the "applicant" relationship for these.

You should have what you asked for by now, a recruiter can only view Applications for a specific Job, only if here created that Job, by visiting the URL "/applications-for-job/JOB\_NID".

Here is a screenshot of the finished View for reference:

Best of luck!
> 0 votes

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


# Question
Title: Rules: Send mail to author when value in date field has passed
So, I have a content type "contest" which has an "end date" field. I want to setup rules so the author of a "contest" gets an e-mail as a reminder that the contest ended.

As event I used "Cron maintenance tasks are performed" and as condition I try to use "Data Comparison" to check the value of the end date to be smaller than current site time. The problem is I can't use the token of the "end date" field as my event is not node-related. I tried to add a "Content is of type" condition, but also here, I can't select anything node-related.

I feel like overlooking something small but I've been searching now several hours and could use some help..

# Answer
Assuming you are using Drupal 7.

You need to enable the **Rules Scheduler** module, it comes with Rules.

Then for Rule event use After saving new content.

Add condition, content is of type: Contest

Exit out of your Rule, and now create a Rule Component of Data Type: Node

Add condition, content is of type: Contest

Action Send E-mail.

Now exit the component and go back to your rule, for action, schedule rule component, and use your end-date field for schedule evaluation date.

I highly suggest you watch Introducing Rules Scheduler and I am sure my answer will make more sense to you.
> 3 votes

# Answer
To further complete the previous answer, you may also want to look at the answer to "Rule to store user's last post date and scheduled rule based 30 day reminder" (which is a variation of your question here).

It includes a Rules Component (in Rules export format) which, with some minor tweaking, should work for you also. And it includes a Rule (also in Rules export format) that schedules the Rules Component. Just replace the `field_next_article` by your node's field date and you should be close. And replace the Rules Event and/or Condition(s) with what fits for your case.

Also note that this Rule takes care of "rescheduling" such eMail in case the data field gets updated somehow ...
> 2 votes

---
Tags: rules
---


title: HOWTO: Common fields (weak entity)

text:
# Question
Title: HOWTO: Common fields (weak entity)
**Long story short:**

I have various entity types in my system and some of their subsets (bundles) has the very same fields. So far I have 3 "common fields" sets, which are from EntityRelation perspective the weak entities. A set has from 3 to 9 fields in it.

**The following constraints I need:**

1. When changing something in field bundle settings (eg: make it required) I don't want to sync all of the other occurrence of this field.
2. Field content should be translatable (based on the parent)
3. Field content should be revisionable (based on the parent)

So far the following solutions came to my mind:

* Field Collection (bad experiences in D7, still in dev)
* Separate bundle / entity (ECK maybe) + Inline Entity Form (months ago there was a problem with revisions)
* Paragraphs (translation + revisioning good, but I couldn't make it to appear in forms just like Inline Entity Form (it always had the "+ Add new paragraph" and if it was a new content, the form of the paragraph didn't appear, only after clicking the add button)
* Custom entity, which includes these fields as base fields. (a lot of hassle to generate the forms, listers, revision support.. etc.)

Do you have any advice for me to solve this issue?

# Answer
Not a defintive answer, just some input.

We (the paragraphs maintainers) are working on reaching feature and user experience parity (or be better, of course) with the Field Collection module, specifically for non-typical paragraph scenarios (single paragraph type, single cardinality, default paragrapht type, ..). There are discussions on officially deprecating field collections in favor of Paragraphs, this might or might not happen. So I'd recommend to not use FC, but I'm obviously biased there.

The latest Paragraphs dev version has support for setting a default paragraph type now, which means that it will by default show the form fields for that already, and you don't need to add a type. The add button should only be shown if you allow more than one field, which is the default for paragraph fields but can easily be changed.

Revisions should work fine in IEF as well, if you use an Entity Reference Revisions Field. If not, then you'll have to report a but, but I assume the maintainers are actively working on that as it is a critical element of Commerce 2.x.

One important difference between the two is Paragraphs are by definition a composite of the parent node, that means they have a parent reference and *not* re-usable, in case that is a requirement. IEF doesn't have that and allows to search and reference existing entities.

The advantage of custom entitiy types (with base classes or traits to re-use base field definitions) is that they're way more efficient, Paragraphs/IEF both result in separate entities that need to be saved, and all the configurable fields need to be stored in separate tables. With custom entity types, you can add all the fields you need as base fields. We're constantly working on requiring less code for custom entities, listings can be done with views with none or very little custom code, widgets work for base fields too, so anything you can do with configurable fields can be done with base fields as well. One major pain point right now is a revision UI, but we're making improvings there as well and entity.module provides some basic user interfaces there as well, diff.module is also working on supporting all entity types.

Yet another option would be to define base fields/configurable fields in code. That is possible as well, but I personally wouldn't really recommend it, there are still some unfinished areas there, especially uninstalling/removing those fields is really hard, as the delete/purge process only works for configurable fields. You could technically also maintain configurable fields with code and sync them between multiple bundles.
> 3 votes

---
Tags: 8, entities
---


# Question
Title: 8 - Manually adding a user field will delete all programmatically added user fields
In my module i programmatically add user fields for the website owner instead of instructing them to do so. Here's an example of the code i used which runs in mymodule.install:

```
function openid_connect_entity_base_field_info(EntityTypeInterface $entity_type) {

if ($entity_type->id() === 'user') {
    $fields['field_birthdate'] = BaseFieldDefinition::create('string')
      ->setLabel(t('Birthdate'))
      ->setDescription(t('Add a description'))
      ->setRevisionable(TRUE)
      ->setTranslatable(TRUE)
      ->setDisplayOptions('form', array(
        'type' => 'string_text_field',
        'weight' => 30,
        'default_value' => 0,
      ))
      ->setDisplayConfigurable('form', TRUE);
  }

return fields;
}

```

but if you add a field manually all the programmatically added fields will be deleted as shown:

programmatically added fields before adding one manually

Adding a field manually

And boom all the programmatically fields are gone!

If this is a bug in the drupal 8 framework where do i report this?

# Answer
> 1 votes
You just need to move the hook implementation into the .module file.

It works on install in the .install file because that file is included in the request, and when Drupal looks for hook implementations, it can find it.

Wen you're not installing, e.g. when adding fields through the UI, the .install file is not included so the hook won't be found, and Drupal will consolidate the info it has by removing those fields.

---
Tags: 8
---


title: Commerce 2.x Taxes missing

text:
# Question
Title: Commerce 2.x Taxes missing
I installed commerce 2.x and all seemed well. I have recently noticed there's no sign of any settings to configure taxes. When first setting up a store the taxes section (see image) wasn't visible as an option. My "vendor/commerceguys" folder contains zone, intl, enum and addressing.

Do I have to run the composer command "composer require "drupal/tax"" or something? To install commerce in the first place I ran "composer create-project drupalcommerce/project-base mystore --stability dev" as instructed on the drupal commerce site so puzzled no tax setting are available? Also where does composer manager come into it, is this something I need to proceed?

Thanks for any help

# Answer
Short answer: Taxes doesn't exist.

Longer answer:
Taxes have not yet been implemented for Drupal commerce 2.x. You can follow along in the issue queue, git or IRC if you want to track the progress.

One of the relevant issue would be Tax data model.
> 2 votes

---
Tags: commerce
---


# Question
Title: How to subtract the node getChangedTime from 1 year
I created a field that display a nodes last changed date using hook\_form alter like this.

```
function demo3_form_alter(&$form, $form_state, $form_id) {
  if($form_id == 'node_page_edit_form') {
   $node = $form_state->getFormObject()->getEntity();
   $form['field_message'] = array(
     '#type' => 'item',
     '#title' => t('Changed date'),
     '#markup' => format_date($node->getChangedTime(), 'medium'),
   );
}

```

I need to create a new field underneath it for the Review date. This field needs to subtract the getChangedTime from a period of 1 year or 365 days. So if the changed date was 30 days ago. The Review date will be 335 days and display in a medium format.

# Answer
Going under the assumption that this is Drupal 8 (based on the `$node = $form_state->getFormObject()->getEntity();` line, you can do something like this:

```
function demo3_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'node_page_edit_form') {
    /** @var \Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
    $date_formatter = \Drupal::service('date.formatter');

    $node = $form_state->getFormObject()->getEntity();
    $changed = $node->getChangedTime();
    $review = new \DateTime();
    $review->setTimestamp($changed);
    $review->modify('+1 year');

    $form['field_message'] = array(
      '#type' => 'item',
      '#title' => t('Changed date'),
      '#plain_text' => $date_formatter->format($changed, 'medium'),
    );

    $form['field_review'] = array(
      '#type' => 'item',
      '#title' => t('Review date'),
      '#plain_text' => $date_formatter->format($review->getTimestamp(), 'medium'),
    );
  }
}

```

Your other option is to use the timeago methods on DateFormatterInterface.
> 0 votes

---
Tags: forms
---


# Question
Title: How to display a block with menu child items programmatically?
I need to create block with a list of links menu child items (only first level) of a given menu like this:

* Item 1
* Item 2
* Item 3

With this code I can have the menu items but I don't know how to process each element to obtain the menu item title and the menu item url.

```
$menu_name = 'main';
$menu_tree = \Drupal::menuTree();
$parameters = $menu_tree->getCurrentRouteMenuTreeParameters($menu_name);
$parameters->setMinDepth(0);

$tree = $menu_tree->load($menu_name, $parameters);
$manipulators = array(
  array('callable' => 'menu.default_tree_manipulators:checkAccess'),
  array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
);
$tree = $menu_tree->transform($tree, $manipulators);

```

# Answer
> 14 votes
I found the answer based in this question: How to turn a menu tree into an associative array?

You can use each array element as a item of MenuLinkInterface

To see others parameters check the class MenuTreeParameters

```
<?php
/**
 * @file
 * Contains \Drupal\YOUR_MODULE\Plugin\Block\SectionsFooter.
 */

namespace Drupal\YOUR_MODULE\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Link;

/**
 * Provides a 'SectionsFooter' block.
 *
 * @Block(
 *   id = "sections_footer",
 *   admin_label = @Translation("Sections"),
 *   category = @Translation("YOUR_MODULE")
 * )
 */
class SectionsFooter extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    $menu_name = 'main';
    $menu_tree = \Drupal::menuTree();
    $parameters = $menu_tree->getCurrentRouteMenuTreeParameters($menu_name);
    $parameters->setMinDepth(0);
    //Delete comments to have only enabled links
    //$parameters->onlyEnabledLinks();

    $tree = $menu_tree->load($menu_name, $parameters);
    $manipulators = array(
      array('callable' => 'menu.default_tree_manipulators:checkAccess'),
      array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
    );
    $tree = $menu_tree->transform($tree, $manipulators);
    $list = [];

    foreach ($tree as $item) {
      $title = $item->link->getTitle();
      $url = $item->link->getUrlObject();
      $list[] = Link::fromTextAndUrl($title, $url);
    }

    $output['sections'] = array(
    '#theme' => 'item_list',
    '#items' => $list,
    );
    return $output;
  }
}

```

References:

Menu tree building is now a service

---
Tags: 8, routes, blocks, navigation
---


# Question
Title: How to import XML (using an API) via Feeds module?
I have a client who uses a CRM that allows us to download data in XML format via an API. If I create a URL such as:

http://www.crmwebsiteurl.com/API/service.asmx/APISelect\_XML?strCompanyAccount=client\_name&strLogin=client\_user\_name&strPassword=client\_password&strSessionID=&strTable=ClientTableName&strFields=ClientField1,ClientField2&strWhereClause=&strGroupByClause=&strHaving=&strOrderBy=

(and yes, all those empty queries/values in the URL must be as they are or the request will fail)

this URL will load an XML document in my browser, with all the content. I can then save that page (which automatically saves as an XML document) and then use Feeds and XML Xpath parser to import the data into Drupal, which all works perfectly.

The trouble is, I want to import the data directly, without having to download and save the XML file to my desktop. I know Feeds has an HTTP Fetcher, but I've tried what seems like every possibly configuration option (which really isn't that many) and I can get it to "successfully" import, but it always says there are no nodes to import (even if I've deleted all my nodes just to be sure). Obviously its not reading the XML file right.

I've seen other ways API's like to be authenticated and some tutorials on how to to those, but this (seemingly) simple authentication method (if a bit insecure) I haven't seen any tutorial on. And if I just use the entire URL (with the query, username, password, etc) in the URL field (Enter a Feed URL), it just always says "There are no new nodes".

I've also played with Feeds Import, Feeds HTTPFetcher AA, Web Service Client - but still haven't seemed to find anything that I've been able to make work.

Is this a unique situation? Or most likely I'm simply doing something wrong? Is there a tutorial I didn't come across that could help me?

# Answer
You need todo more debugging. As 1 possible debugging example use Chrome Inspector to assure that properly configured, Feeds is requesting the correct URL to get the XML payload. you can do this by logging HTTP persistently before you hit the drupal admin page and recording what Feeds is issuing.

Compare that to hitting the URL by hand in the browser, or whatever steps you take. I suspect that Feeds has an API to alter the outbound request to the remote server and make it 1:1 with hitting the remote url by hand.

There are other HTTP session records you can use depending on your OS.
> 0 votes

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


title: Backing out of Drupal Commons

text:
# Question
Title: Backing out of Drupal Commons
We currently have a Drupal Commons website on version 7.50, commons 3.x. Our site is complex and we are no longer using many of the pre-packaged features in the commons distribution. We would like to simplify and modernize our website by "getting out of Commons."

I am wondering if it is possible to back out of Drupal commons without rebuilding from scratch and if it is possible, can it be done cleanly? E.g. Can we get back to Drupal Core and for every commons-specific feature we are using, could we theoretically replace the commons-specific configurations and modules with a Drupal 7 or native features and what are other the other implications?

This is a fairly arbitrary question but any information is appreciated. As I learn to re-frame the question, it will help to answer it. Guidance on asking is also appreciated, thanks!

Update and background info: I prefer Drush, use GIT and have a staging process as well as have set up sandbox copies of our site from back ups to be sure they work. I lack a good understanding about administrating Drupal itself and how Core differs from other profiles but am familiar with migrating Drupal sites and managing the database and codebase.

# Answer
Nice question, but challenging. Basically you want to switch installation profiles (from commons to regular Drupal core). And that yielded some results on Google, including Profile switcher and This blog page. They might be of help during the process.

Before blindly installing modules, please read on, make sure you have proper backups (in fact try to verify your backup actually works) you might have to recover multiple times. From what I understood these methods are usually from upgrading 'standard' Drupal to another profile, but it might work backwards.

I'd start by disabling and **uninstalling** (use the uninstall tab) all modules that come prepacked with your profile distribution. This will likely be the features, but there might be more. Then attempt the switch. See which method works best...
> 1 votes

---
Tags: 7
---


title: How to migrate revisions

text:
# Question
Title: How to migrate revisions
I'm migrating contents from D7 to D8. I'm exporting nodes with services\_views and importing with migrate.

I would like to import also revisions. How should I do? Revisions on D8 don't seem entities, so what kind of "target" should I use to import them?

# Answer
> 5 votes
The revisions are added to the existing entity. There is an EntityRevision destination in core.

See `core/modules/node/migration_templates/d7_node_revision.yml` here for an example of how you'd migrate revisions.

Note: translated node revisions are not yet supported, but you can look at a good starting point at #2746541.

---
Tags: nodes, 8, migrations
---


title: User Created Accordion With Fields?

text:
# Question
Title: User Created Accordion With Fields?
When a user is creating a node, is it possible to auto generate an accordion based on a field group or field collection? I want the user to enter the title(clickable to expand and show body) and body of their accordion(s).

I see field\_group and bootstrap\_field\_group, but both require me to add the title for example and then give the body of the accordion based on another field... That is admin specific. I'd like to give the user the flexibility to create their own title for each accordion item.

# Answer
The best way I have found to do this was to use Paragraphs. You can create an Accordion paragraph type, and an Accordion Item paragraph type. The Accordion holds Accordion Items. The Accordion Item has 2 fields, Title, and Body.

This allows a user to add an Accordion paragraph to a node, then add as many Accordion Items as they want (and be able to sort them in the form). From there, the theming/js is up to you via templates and js, but that part is fairly easy.

Since Paragraphs are based on fields, it's intuitive for the editor who use used to the node edit interface.
> 2 votes

# Answer
I saw this really cool presentation at MidCamp a couple years ago which covered how to create your own ckeditor widgets like callouts: http://2015.midcamp.org/session-proposal/widgetizing-wysiwyg

After the session, I took the example custom module which included just a callout widget and added an accordion widget. You can download my custom module here: https://github.com/banoodle/drupal-modules/tree/master/banoodle\_widgets

Here is how my module looks/works...

If the user enters '3' in the dialog, they see this...

This is the result...

Hope this helps!

Anne
> 0 votes

# Answer
You could look into Views Accordion.

> Views Accordion provides a display style plugin for the Views module.
>
> It will take the results and display them as a JQuery accordion, using the first field as the header for the accordion rows.

If you add the required fields to the node and allow users to edit those. The changes should be reflected in the view automatically.
> 0 votes

# Answer
Since you indicate you have a problem with Field Group and Titles, you might also want to try Field Group Titles

> This module extends the Field Group module by adding the ability to override the default title of a field group item (horizontal and vertical tabs, accordions, divs and fieldsets) on a per node basis.
>
> ...
>
> The use case that prompted this module included 15 nodes of the exact same format with different tab titles, and it had to be easy for editors. Using Quicktabs for this case would have required each tab to be a separate node, and each instance would have been rendered as a block. So in the above example you end up with 6 nodes and 2 blocks, as opposed to just 2 nodes. Field Groups by itself would require a unique content type for every node where the group's label changes. This module allowed me to add 15 nodes with unique tabs on each using a single content type.

Sounds like something that could fit your needs as well.
> 0 votes

---
Tags: 7, navigation
---


# Question
Title: Module with multiple Blocks in multiple files
I've created a module which creates 2 blocks.

```
function my_module_block_info() {

  $blocks['blockA'] = array(
    'info' => t('blockA'),
    'cache' => DRUPAL_CACHE_PER_ROLE,
  );

  $blocks['blockB'] = array(
    'info' => t('blockB'),
    'cache' => DRUPAL_CACHE_PER_ROLE,
  );
  return $blocks;
}

function my_module_block_view($delta = '') {
  switch ($delta) {
    case 'blockA':
      $block['subject'] = t('subjectA');
      if (user_access('access content')) {
          $block['content'] = 'HelloA';
      }
      return $block;
      break;

    case 'blockB':
      $block['subject'] = t('subjectB');
      if (user_access('access content')) {
          $block['content'] = 'HelloB';
      }
      return $block;
      break;
}

```

Everything good so far. Here is my question:

I would like developers to create blocks using the same module (20 more blocks). How can I add a new block with its view without modifying the my\_module.module? Is there a way to extend and include .php files that declare other blocks? So, instead of having a huge my\_module.module file, I can have multiples .php files (one for each block).

Thank you in advance

# Answer
*** Method 1 - all blocks in separate file ***

You can implement `hook_hook_info()` in your .modules file like this:

```
function hook_hook_info()
{
  $hooks['block_info']['group'] = 'block';
  $hooks['block_view']['group'] = 'block';

  return $hooks;
}

```

This tells the system that when `hook_block_info()` and/or `hook_block_view()` are invoked, any \[MODULE\].block.inc files should be loaded. So you can then put these two hooks into \[MODULE\].block.inc, keeping your block code in a separate file altogether.

*** Method 2 - different file for each block ***

You can add module\_load\_include() to include files for each block. To do this, in hook\_block\_view() you can do the following:

```
function hook_block_view($delta = '')
{
  if($delta == 'block1')
  {
    module_load_include('inc', 'MODULENAME', 'MODULENAME.block1');
  }
  elseif($delta == 'block2')
  {
    module_load_include('inc', 'MODULENAME', 'MODULENAME.block2');
  }
}

```

With this code, you can now put block1 in MODULENAME.block1.inc and block2 in MODULENAME.block2.inc. Note that MODULNAME should be the actual name of your module, though technically the module name isn't required, it's just a good practice.
> 2 votes

---
Tags: 7, blocks
---


# Question
Title: How do I use hook_views_query_alter() to re-write a query?
I have a very simple view that lists all the nodes, which shows the following query:

```
SELECT node.nid AS nid, node.title AS node_title, node.uid AS node_uid, node.created AS node_created, 'node' AS field_data_field_site_node_entity_type, 'node' AS field_data_field_status_node_entity_type
FROM
{node} node
WHERE (( (node.status = '1') AND (node.type IN  ('ticket')) ))
ORDER BY node_created DESC
LIMIT 50 OFFSET 0

```

I am trying to overwrite it with a custom database query to list only nodes of the user referenced in the URL and all his invitees. This is the code I am using.

```
function my_custom_module_views_pre_view(&$view, &$display_id, &$args) {
  if ($view->name == "support" && $display_id == "page" ) {
    // Let's start collecting uids and put current page uid as the first member of array.
    $uids[] = arg(1);

    // Now let's collect all invitees of the page uid author and push into the same array.
   $query = db_select('invite', 'i')
     ->condition('i.uid', arg(1), '=')
     ->condition('i.status', '3', '=')
     ->fields('i', array('invitee'));
   $result = $query->execute();
   foreach ($result as $record) {
     $uids[] = $record->invitee;
   }

   // Now let's pull all the nodes of the inviter (page uid) and his invitees.
  $query = db_select('node', 'n')
     ->condition('n.type', 'ticket', '=')
     ->condition('n.status', '1', '=')
     ->condition('n.uid', $uids, 'IN')
     ->fields('n', array('nid', 'title', 'created'));
   $result = $query->execute();
   foreach ($result as $record) {
     dpm($record->nid.' | '.$record->title.' | '.$record->created);
   }

  }
}

```

`dpm()` shows all the correct nodes, but reading hook\_views\_query\_alter() I still can't figure out how to make my view use this query.

How can I achieve this?

# Answer
> 0 votes
While exploring a site-building alternative (see comments in OP), here is a direct answer to the question:

Implementing the hook\_views\_query\_alter should do what you want:

```
function my_custom_module_views_query_alter (&$view, &$query) {
  $display_id = $view->current_display;
  $uid = $view->args(0); // for a view that is loaded from a URL like /myview_url/UID

  // Your code from the OP follows, modified accordingly
  // You have a query object available as an argument by reference
  // You can add joins and filters to it
  ...
}

```

You would need to implement the hook\_views\_api in addition to placing the above code snippet inside the my\_custom\_module.views.inc file, a minimal implementation would be:

function my\_custom\_module\_views\_api() { return array( 'api' =\> '3', ); }

Cheers!

P.S.: Have a look at this one, if you haven't already =\> http://www.kdweb.co.uk/blog/drupal-module-views-hook-sequence

---
Tags: 7, database, views
---


# Question
Title: Select list ajax callback fire only once to update textfield
I face an issue when fire ajax callback function in my coding. I have a select list and a text box. If there is any change in select list field, the text box will be updated by selected value. I added my code in form\_alter function. But, it fired only one time. Below is my code.

```
 function field_collection_form_alter(&$form, &$form_state, $form_id) {
if($form_id == 'employee_performance_node_form') {

$form['field_my_weight_select'][LANGUAGE_NONE]['#ajax']= array(
      'callback' => 'custom_test_entity_callback',
      'wrapper' =>'custom_test_entity_wrapper',
      'method' => 'replace',
      'effect' => 'fade',
      'event' => 'change',
    );

$form['field_text_for_test']['#prefix']='<div id="custom_test_entity_wrapper">';
$form['field_text_for_test']['#suffix']='</div>';

if(isset($form_state['values']['field_my_weight_select'])){
      $content_type = $form_state['values']['field_my_weight_select'][LANGUAGE_NONE][0]['value'];
      $form["field_text_for_test"][LANGUAGE_NONE][0]['value']['#value']=$content_type;
    }
    else{ $form["field_text_for_test"][LANGUAGE_NONE][0]['value']['#value']=1;}
}
}

function custom_test_entity_callback($form, $form_state){
  return $form['field_text_for_test'];
}

```

Could you tell me what is wrong in my code??

Thank you

# Answer
My issue has been solved. I gave the normal user full permissions and I disable the permissions one by one until I found that the permissions that related to Pathauto module cause this issue. So, I enable them and then my code works.
> 0 votes

# Answer
Quickly tested your code and it works.

The only thing that looks a bit odd in your hook implementation, is the name of the function. It seems you are writing your custom code as if your module was named 'field\_collection'. There is already a contrib module called that, and you may have already installed it. It would be better to place your function into your custom module's "namespace". Event better would be to also use the hook\_form\_FORM\_ID\_alter hook, since it's more efficient.

In any case, with those two small rewrites, the code ran as expected and I was able to get multiple ajax updates of the text\_for\_test field.

```
/**
 * Implements hook_form_FORM_ID_alter().
 */
function YOUR_CUSTOM_MODULE_form_employee_performance_node_form_alter (&$form, &$form_state) {
  $form['field_my_weight_select'][LANGUAGE_NONE]['#ajax'] = array(
    'callback' => 'custom_test_entity_callback',
    'wrapper' => 'custom_test_entity_wrapper',
    'method' => 'replace',
    'effect' => 'fade',
    'event' => 'change',
  );

  $form['field_text_for_test']['#prefix'] = '<div id="custom_test_entity_wrapper">';
  $form['field_text_for_test']['#suffix'] = '</div>';

  if (isset($form_state['values']['field_my_weight_select'])) {
    $content_type = $form_state['values']['field_my_weight_select'][LANGUAGE_NONE][0]['value'];
    $form["field_text_for_test"][LANGUAGE_NONE][0]['value']['#value'] = $content_type;
  }
  else {
    $form["field_text_for_test"][LANGUAGE_NONE][0]['value']['#value'] = 1;
  }
}

/**
 * Ajax callback for updating field_text_for_test.
 */
function custom_test_entity_callback($form, $form_state) {
  $form['field_text_for_test']['#prefix'] = '<div id="custom_test_entity_wrapper">';
  $form['field_text_for_test']['#suffix'] = '</div>';
  return $form['field_text_for_test'];
}

```

Update: If you want to make sure, your form alter hook is called last (in relation to other modules):

```
/**
 * Implements hook_module_implements_alter().
 */
function CUSTOM_MODULE_module_implements_alter(&$implementations, $hook) {
  if ($hook != 'form_employee_performance_node_form_alter') {
    return;
  }
  $module = 'CUSTOM_MODULE';
  $group = array($module => $implementations[$module]);
  unset($implementations[$module]);

  $implementations = $group + $implementations; //You want your implementation to run last.
}

```

Good luck!
> 0 votes

---
Tags: forms
---


# Question
Title: How to get success message in popup using custom form?
**How to get success message in popup form here is my code :**

```
   <?php
 /**
 * Implements security_settings_form().
*/
function security_settings_block_info() {
$blocks['testing'] = array(
'info' => t('testing1'),
'cache' => DRUPAL_NO_CACHE, //there are a number of caching options for this
 );

 return $blocks;
 }

function security_settings_block_view($delta = ''){
  switch($delta){
    case 'testing':
  if(user_access('access content')){ //good idea to check user perms here
     $block['subject'] = t('testing');
     $block['content'] = drupal_get_form('security_settings_form');
     //$block['content'] = security_settings_form();
     return $block;
  }
  break;
  }
  }
function security_settings_form($form, &$form_state) {
$form["wrapper"] = array("#markup" => "<div id='test-ajax'></div>");

   $result = db_select('taxonomy_term_data', 'ttd');
  $result->fields('ttd');
  $result->condition('ttd.vid', 2, '=');
  $results = $result->execute()->fetchAll();
   $termName = '';
   foreach($results as $record){

   $v[]=$record->name;

}
$form['cities'] = array(
'#type' => 'select',
'#title' => t('Click on your city'),
//'#multiple' => true,
'#options' => $v,

 '#attributes' => array('class' => array('my-class-1')),
  );
   $form['email'] = array(
   '#type' => 'textfield',
   '#title' => t('Enter email'),

   '#validate' => array('security_settings_form_validate'),
 );
    $form['save'] = array(
    '#type' => 'button',

    '#value' =>  'Save',

     "#ajax" => array(
  "callback" => "dr_search_test_form_callback",

  "wrapper" => "test-ajax",
  "effect" => "fade")

    );

return $form;
 }

function security_settings_form_validate($form, &$form_state) {
$email = $form_state['values']['email'];

 // Verify that the email address is valid.
   if (!valid_email_address($email)) {
  form_set_error('email',('You must provide a valid email address.'));
  }

}

  function dr_search_test_form_callback($form, $form_state) {

   global $user;
   $v=db_insert('security_settings')
   ->fields(array(
  'uid' => $user->uid,
  'email' => $form_state['values']['email'],
  'cities' => $form_state['values']['cities'],
    ))->execute();

   $email = $form_state['values']['email'];
   if (valid_email_address($email)) {
   $message = array('A new entry has been submitted');
   $to = 'abc@gmail.com';
   $params = array(
    'body' => $body,
    'subject' => 'Website Information Request',
     );
       if (drupal_mail('security_settings', 'some_mail_key',   $to,          language_default(), $params)) {
    drupal_set_message('Thanks, email sent.');  //success message
   } else {
    drupal_set_message('Email not sent.');
  }
  }

return "<div id='test-ajax'>".$v."</div>";
  }
 function security_settings_mail($key, &$message, $params) {
   $message['subject'] = $params['subject'];
   $message['body'] = $params['body'];
  }

```

# Answer
You can return the messages to the ajax form by adding the following to your ajax callback function (you'll need to remove your current return value)

```
$messages = array('#theme' => 'status_messages');
$commands = array();
$commands[] = ajax_command_prepend('#form_id', render($messages));

return array('#type' => 'ajax', '#commands' => $commands);

```

Make sure to change #form\_id to the actual ID of your form, or use whatever jQuery selector you want to prepend the messages to.
> 2 votes

---
Tags: 7
---


# Question
Title: How to create one more registation page in drupal site
In our drupal site we have a Registration page. and the new requirement is creating the one more registration page with same functionality(newly created registration page also use same database to store the user details)

Any ideas for implementing this in drupal is appreciated.

# Answer
> 2 votes
If you need different registration forms for different types of users, you can experiment with the following modules.

https://www.drupal.org/project/profile2
https://www.drupal.org/project/profile2\_regpath

# Answer
> 1 votes
No need to use Profile2 Module to have different registration forms, you can use Auto Assign Role Module and it will allow you to create as many as you want registration pages (/admin/config/people/autoassignrole/pages), also you can assign specific role when user registered using specific registration path or just used the normal role authenticated user.

Try it now on simplytest.me

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


# Question
Title: Getting "The website encountered an unexpected error. Please try again later." on each module installation
Drupal 8. Every time I enable a new module via the admin pages, I get a blank page with this error message: "The website encountered an unexpected error. Please try again later."

When I navigate back to the modules list page, the module installation appears to have worked fine. But I'm guessing that might not always be the case.

Can somebody help me to debug it?

This error doesn't appear when using drush. I'm on a dev setup (Windows 10, xampp).

Nothing is logged in the report page (admin/reports/dblog), except to say that the module was installed.

In the PHP error logs, I find the following:

```
[04-Jan-2017 16:36:21 Europe/Paris] Failed to log error: Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.: INSERT INTO {watchdog} (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array
(
    [:db_insert_placeholder_0] => 1
    [:db_insert_placeholder_1] => php
    [:db_insert_placeholder_2] => %type: @message in %function (line %line of %file).
    [:db_insert_placeholder_3] => a:6:{s:5:"%type";s:45:"Drupal\Core\Database\DatabaseExceptionWrapper";s:8:"@message";s:842396:"SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.: INSERT INTO {batch} (bid, timestamp, token, batch) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3); Array
(
    [:db_insert_placeholder_0] => 15
    [:db_insert_placeholder_1] => 1483544168
    [:db_insert_placeholder_2] => F0e36VAW5PSa8Cjxi0hogaimFU_Z6CpyLaO2FWOS2pw
    [:db_insert_placeholder_3] => a:12:{s:4:"sets";a:5:{i:0;a:15:{s:7:"sandbox";a:0:{}s:7:"results";a:0:{}s:7:"success";b:0;s:5:"start";i:0;s:7:"elapsed";i:0;s:5:"title";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:"

[04-Jan-2017 16:36:21 Europe/Paris] Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.: INSERT INTO {watchdog} (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array
(
    [:db_insert_placeholder_0] => 1
    [:db_insert_placeholder_1] => php
    [:db_insert_placeholder_2] => %type: @message in %function (line %line of %file).
    [:db_insert_placeholder_3] => a:6:{s:5:"%type";s:45:"Drupal\Core\Database\DatabaseExceptionWrapper";s:8:"@message";s:842396:"SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.: INSERT INTO {batch} (bid, timestamp, token, batch) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3); Array
(
    [:db_insert_placeholder_0] => 15
    [:db_insert_placeholder_1] => 1483544168
    [:db_insert_placeholder_2] => F0e36VAW5PSa8Cjxi0hogaimFU_Z6CpyLaO2FWOS2pw
    [:db_insert_placeholder_3] => a:12:{s:4:"sets";a:5:{i:0;a:15:{s:7:"sandbox";a:0:{}s:7:"results";a:0:{}s:7:"success";b:0;s:5:"start";i:0;s:7:"elapsed";i:0;s:5:"title";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:"

```

**UPDATE**

Following Berdir's advice, I have enabled a more dev-friendly Drupal config (example.settings.local.php), and I can now see the error message in its entirety instead of the "unexpected error" generic message.

This error message is HUGE: 2,2MB of text (!), most of it on one line, so I can't reproduce it here entirely. I'll just post a good chunk of its beginning and its ending:

```
The website encountered an unexpected error. Please try again later.
Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.: INSERT INTO {watchdog} (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array ( [:db_insert_placeholder_0] => 1 [:db_insert_placeholder_1] => php [:db_insert_placeholder_2] => %type: @message in %function (line %line of %file). [:db_insert_placeholder_3] => a:6:{s:5:"%type";s:45:"Drupal\Core\Database\DatabaseExceptionWrapper";s:8:"@message";s:2255682:"SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.: INSERT INTO {batch} (bid, timestamp, token, batch) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3); Array ( [:db_insert_placeholder_0] => 17 [:db_insert_placeholder_1] => 1483560842 [:db_insert_placeholder_2] => IULM8yBE6uEsZdvKg8X3RtLYaKgtafNbKHJbfolwoAo [:db_insert_placeholder_3] => a:12:{s:4:"sets";a:4:{i:0;a:15:{s:7:"sandbox";a:0:{}s:7:"results";a:0:{}s:7:"success";b:0;s:5:"start";i:0;s:7:"elapsed";i:0;s:5:"title";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:"*string";s:35:"Updating configuration translations";s:12:"*arguments";a:0:{}s:10:"*options";a:0:{}}s:12:"init_message";s:40:"Starting configuration update<br/> ";s:13:"error_message";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:"*string";s:41:"Error updating configuration translations";s:12:"*arguments";a:0:{}s:10:"*options";a:0:{}}s:4:"file";s:35:"core/modules/locale/locale.bulk.inc";s:9:"completed";s:28:"locale_config_batch_finished";s:16:"progress_message";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:"*string";s:29:"Completed @current of @total.";s:12:"*arguments";a:0:{}s:10:"*options";a:0:{}}s:3:"css";a:0:{}s:5:"total";i:10;s:5:"count";i:10;s:5:"queue";a:2:{s:4:"name";s:17:"drupal_batch:17:0";s:5:"class";s:23:"Drupal\Core\Queue\Batch";}}i:1;a:1:{s:11:"form_submit";s:50:"module_filter_system_modules_recent_enabled_submit";}i:2;a:1:{s:11:"form_submit";s:44:"module_filter_system_modules_redirect_submit";}i:3;a:1:{s:11:"form_submit";s:27:"update_storage_clear_submit";}}s:16:"has_form_submits";b:1;s:10:"form_state";O:26:"Drupal\Core\Form\FormState":33:{s:16:"*complete_form";a:32:{s:11:"#attributes";a:2:{s:5:"class";a:1:{

```

\[...\]

```
a:1:{s:20:"data-drupal-selector";s:11:"edit-submit";}s:14:"#title_display";s:6:"before";s:20:"#description_display";s:5:"after";s:7:"#errors";N;s:3:"#id";s:11:"edit-submit";}}s:12:"*temporary";a:0:{}s:22:"*validation_complete";b:1;s:9:"*errors";a:0:{}s:26:"*limit_validation_errors";N;s:20:"*validate_handlers";a:0:{}s:18:"*submit_handlers";a:0:{}}s:11:"progressive";b:1;s:11:"current_set";i:0;s:3:"url";O:15:"Drupal\Core\Url":11:{s:15:"*urlGenerator";N;s:15:"*urlAssembler";N;s:16:"*accessManager";N;s:12:"*routeName";s:22:"system.batch_page.html";s:18:"*routeParameters";a:0:{}s:10:"*options";a:0:{}s:11:"*external";b:0;s:11:"*unrouted";b:0;s:6:"*uri";N;s:15:"*internalPath";N;s:14:"*_serviceIds";a:0:{}}s:10:"source_url";O:15:"Drupal\Core\Url":11:{s:15:"*urlGenerator";N;s:15:"*urlAssembler";N;s:16:"*accessManager";N;s:12:"*routeName";s:19:"system.modules_list";s:18:"*routeParameters";a:0:{}s:10:"*options";a:0:{}s:11:"*external";b:0;s:11:"*unrouted";b:0;s:6:"*uri";N;s:15:"*internalPath";N;s:14:"*_serviceIds";a:0:{}}s:14:"batch_redirect";N;s:5:"theme";s:5:"seven";s:17:"redirect_callback";N;s:2:"id";s:2:"17";s:13:"error_message";O:48:"Drupal\Core\StringTranslation\TranslatableMarkup":3:{s:9:"*string";s:58:"Please continue to <a href=":error_url">the error page</a>";s:12:"*arguments";a:1:{s:10:":error_url";s:46:"/my-project/www/en/batch?id=17&op=finished";}s:10:"*options";a:0:{}}} ) ";s:9:"%function";s:42:"Drupal\Core\Batch\BatchStorage->doCreate()";s:5:"%file";s:78:"C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Batch\BatchStorage.php";s:5:"%line";i:159;s:17:"@backtrace_string";s:5074:"#0 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Database\Connection.php(635): Drupal\Core\Database\Connection->handleQueryException(Object(PDOException), 'INSERT INTO {ba...', Array, Array) #1 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Database\Driver\mysql\Connection.php(81): Drupal\Core\Database\Connection->query('INSERT INTO {ba...', Array, Array) #2 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Database\Driver\mysql\Insert.php(32): Drupal\Core\Database\Driver\mysql\Connection->query('INSERT INTO {ba...', Array, Array) #3 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Batch\BatchStorage.php(159): Drupal\Core\Database\Driver\mysql\Insert->execute() #4 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Batch\BatchStorage.php(129): Drupal\Core\Batch\BatchStorage->doCreate(Array) #5 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\ProxyClass\Batch\BatchStorage.php(107): Drupal\Core\Batch\BatchStorage->create(Array) #6 C:\xampp\htdocs\my-project\www\core\includes\form.inc(849): Drupal\Core\ProxyClass\Batch\BatchStorage->create(Array) #7 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Form\FormSubmitter.php(62): batch_process() #8 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Form\FormBuilder.php(585): Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object(Drupal\Core\Form\FormState)) #9 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Form\FormBuilder.php(314): Drupal\Core\Form\FormBuilder->processForm('system_modules', Array, Object(Drupal\Core\Form\FormState)) #10 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Controller\FormController.php(74): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\system\Form\ModulesListForm), Object(Drupal\Core\Form\FormState)) #11 [internal function]: Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch)) #12 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array) #13 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\Render\Renderer.php(574): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() #14 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #15 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) #16 [internal function]: Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() #17 C:\xampp\htdocs\my-project\www\vendor\symfony\http-kernel\HttpKernel.php(139): call_user_func_array(Object(Closure), Array) #18 C:\xampp\htdocs\my-project\www\vendor\symfony\http-kernel\HttpKernel.php(62): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #19 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\StackMiddleware\Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #20 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\StackMiddleware\KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #21 C:\xampp\htdocs\my-project\www\core\modules\page_cache\src\StackMiddleware\PageCache.php(99): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #22 C:\xampp\htdocs\my-project\www\core\modules\page_cache\src\StackMiddleware\PageCache.php(78): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true) #23 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\StackMiddleware\ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #24 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\StackMiddleware\NegotiationMiddleware.php(50): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #25 C:\xampp\htdocs\my-project\www\vendor\stack\builder\src\Stack\StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #26 C:\xampp\htdocs\my-project\www\core\lib\Drupal\Core\DrupalKernel.php(652): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #27 C:\xampp\htdocs\my-project\www\index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #28 {main}";} [:db_insert_placeholder_4] => 3 [:db_insert_placeholder_5] => [:db_insert_placeholder_6] => http://localhost/my-project/www/en/admin/modules [:db_insert_placeholder_7] => http://localhost/my-project/www/en/admin/modules [:db_insert_placeholder_8] => ::1 [:db_insert_placeholder_9] => 1483560855 ) in Drupal\dblog\Logger\DbLog->log() (line 79 of core\modules\dblog\src\Logger\DbLog.php).

Drupal\dblog\Logger\DbLog->log(3, '%type: @message in %function (line %line of %file).', Array) (Line: 104)
Drupal\dblog\Logger\DbLog->log(3, '%type: @message in %function (line %line of %file).', Array) (Line: 136)
Drupal\Core\Logger\LoggerChannel->log(3, '%type: @message in %function (line %line of %file).', Array) (Line: 65)
Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->onError(Object) (Line: 92)
Drupal\Core\EventSubscriber\ExceptionLoggingSubscriber->onException(Object, 'kernel.exception', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.exception', Object) (Line: 216)
Symfony\Component\HttpKernel\HttpKernel->handleException(Object, Object, 1) (Line: 70)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 652)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

```

# Answer
I'm wondering if disabling module\_filter fixes this?

EDIT: Unlikely - I think we're just hitting an interesting limit of a batching at the end of the modules form... we add the form state to the batch in \Drupal\Core\Form\FormSubmitter::doSubmitForm()

EDIT2: So the answer turns out to be mysql setting. The innodb\_log\_file\_size needs increasing. See https://stackoverflow.com/questions/15585602/change-limit-for-mysql-row-size-too-large for more. And http://www.md-systems.ch/de/blog/techblog/2012/02/15/improve-mysql-performance is a good place to start for a good my.cnf for Drupal development
> 2 votes

# Answer
So apparently the actual error is "Error updating configuration translations"

I guess you have config\_translation enabled?

The fact that this happens when that err happens is thrown is a core bug that we should fix. Not sure what your actual problem is, though and why it results in this.

It is apparently defined as error\_message in locale\_config\_batch\_build for the batch that is triggered. I do have seen problems before that this batch loops forever but didn't get this error. It doesn't happen on drush because drush afaik doesn't trigger locale/config\_update.

Are you sure that there's nothing else in the logs, some php notices or so?

**Update**

Looks like I misread that a bit, it seems the original exception is this:

SQLSTATE\[42000\]: Syntax error or access violation: 1118 Row size too large (\> 8126). Changing some columns to TEXT or BLOB or using ROW\_FORMAT=DYNAMIC or ROW\_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.: INSERT INTO {batch} (bid, timestamp, token, batch) ...

so apparently the batch callback is storing a huge amount of data in there so that gets too big. Not sure why it does there, looks like there is a form\_state object in there. I suggest you create a core issue.
> 1 votes

---
Tags: 8, debugging
---


# Question
Title: Views related content based same term names in different vocabulary
I'm trying to create a view for a taxonomy term and show a related content based on term name.

For example, i have term name Manchester United in vocabulary teams and i want to show all news nodes that have term Manchester United. The problem is that terms in news are in different vocabulary.

For now i create a View with Contextual filters Content: Has taxonomy term ID which get me ID for term Manchester United from vocabulary teams.

My questions is, how i can use this term name and show related nodes from news which have same term name but in different vocabulary and different ID.

EDIT: it's important to know that i'm getting first term by his ID in url.

# Answer
> 0 votes
**First option (doesn't work as expected though):**

You should be able to do that, by doing the following in your contextual filter:

1. Check the "Specify validation criteria" option.
2. Select "Taxonomy term" as "Validator".
3. Select "Term name" as "Filter value type".

I just tried this however and it returns only one result, which is not what you need.

**Alternative (this one was tested and works):**

You can create a View of Taxonomy Terms, and then use a "Taxonomy term: Name" contextual filter. Afterwards, you can add a relationship to your tagged nodes, using the "Taxonomy term: Content with term" relationship.

That way, you can get all the content tagged with a specific term name, even if the term name belongs to different taxonomies.

Here is a sample View configuration:

and a sample result-set with "ManU" used as a contextual filter:

Good luck!

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


# Question
Title: Upgrading a simple drupal 7 module to drupal 8?
I am new to drupal and currently using version 8. I am trying to convert cricket feed widget module in drupal 7 to drupal 8 based on Community instructions.. But I am unable to understand the routing.yml files. I don't understand the parameters used in the routing.yml file to connect with the controllers. I checked out some of their examples..

I don't understand

what they mean by sub\_name and Path: Path to the page on site.How do I know that? Is it that much difficult to convert a simple drupal 7 module to drupal 8?

# Answer
I've spent the past few months doing a lot of D7 -\> D8 upgrades. I haven't used sub\_name (or even seen it), so I cannot comment on that, but as for the path, it's the same path you declared as the array key in your hook\_menu definition - however note that with D8 you need to include the preceeding forward slash.

So if your D7 hook\_menu() definition for a path was:

```
$menu['path/to/something']

```

In D8 your path in the routing file would be:

```
path: /path/to/something

```
> 3 votes

---
Tags: 8, upgrading
---


title: Best practice: $this->t() versus t()

text:
# Question
Title: Best practice: $this->t() versus t()
I'm looking for a best practice: should contributed modules use `$this->t()` or `t()`?

# Answer
> 28 votes
Best practice depends on where the code is placed.

**OOP Code**

Use `$this->t()`.

If you extend a drupal base class like a controller or a plugin the t() function is provided as class method `$this->t()` out of the box and you should use it. This makes your code testable.

For most tasks you'll find a suitable drupal class to extend from which has `$this->t()` defined, but if you need to build your own class from scratch best practice would be to use the string translation trait and inject this as service if you use this class in a service context:

```
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
class MyClass {
  use StringTranslationTrait;

  /**
   * Constructs a MyClass object.
   *
   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
   *   The string translation service.
   */
  public function __construct(TranslationInterface $string_translation) {
    // You can skip injecting this service, the trait will fall back to \Drupal::translation()
    // but it is recommended to do so, for easier testability,
    $this->stringTranslation = $string_translation;
  }

  /**
   * Does something.
   */
  public function doSth() {
    // ...
    $string = $this->t('Something');
    // ...
  }

}

```

Source: https://www.drupal.org/docs/8/api/translation-api-code-text

**Procedural Code**

Use `t()`.

If you have procedural code, for example a hook, then use `t()`, which is a global function.

Not best practice would be to use the procedural `t()` in OOP Code.

# Answer
> 4 votes
The best practice is to use $this-\>t(), rather than t(). Usage of the module will not change, however, with the advent of Drupal 8, we now have PHPUnit testing built into core. PHPUnit testing allows for tests to be written to confirm everything works, so that anytime code is changed, the tests can be run to ensure nothing has been broken. The relevance of this is that PHPUnit testing tests only against a single class (aka a unit), meaning that core is not bootstrapped for these tests. Global functions such as t() therefore do not exist, and they will throw an error, preventing the tests from being run.

If you never create any unit tests, then you will never see the difference between using t() and $this-\>t(), however creating tests is also a best practice, and therefore if you really want to be doing things right, you should be using $this-\>t(), and creating Unit tests for each of your classes.

*** Edit ***

Updating after reading 4k4's post.

My comments above only relate to OOP code, not procedural code. Procedural code is not unit tested, nor does it have the $this constructor. In procedural code, t() is correct.

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


# Question
Title: Hiding a View if empty when contextual filter is already used
On my content type "page", I give my client the option to upload a sidebar image while editing the page fields. In the manage display of the content type, the image is hidden.

I have a view in the sidebar that shows the side bar images. I placed a contextual filter of Nid, and set it to provide a default value using the Content ID from URL, meaning that only the sidebar image for that page will be displayed.

This works sweet, but on pages where a sidebar image isnt uploaded, the sidebar is empty, but the views headers are there, and forcing the main content to be pushed to the left as if the sidebar region has content.

Reading other solutions, people have used a contextual filter of Global: Null, and set the view to hide if empty. But this isnt working for me, probably as I am already using a contextual filter to determine the content from the URL.

Other advice of setting the "no results behaviour" of the field doesnt do anything, the empty block still renders because it has nothing to do with fields, it is only printing the view headers.

I'm a bit stumped! Any ideas?

# Answer
> 9 votes
I found a very simple answer to this question.

The problem I was having was two contextual filters, Content:NID from URL, and Global:Null Hide If empty, which stopped the view displaying even if full.

Instead, I simply added a Filter Criteria for one of the fields in my view, with :fid on the end. In my case, it was `Content: Sidebar Images:fid (not empty)`

Now the view shows if it has content, and hides completely, including block region if empty.

# Answer
> 2 votes
1. Add a FILTER CRITERIA
2. Select the same field that you are displaying under fields
3. Select the Operator as "Is not empty(NOT NULL)"
4. Save it, and it is done

# Answer
> 0 votes
For me, the problem was that I had a *Global Text Area* defined under *Behavior when no results*, from previous configurations. Got rid of that and the view stopped showing when it had no results.

(I work with Drupal in spanish so maybe the names in italic do not correspond to the actual english texts. Sorry for that)

---
Tags: views
---