# Question
Title: How to send values to an external database with a custom module?
Working on Drupal 7.54

I am more a site builder than a developer but now I have no choice, I need to write a little module for Drupal 7.

So, I was wondering if someone could help me to write this custom module (at least help me to start).

Here is my problem :

I need to send form values to an external database.

For the moment, I managed to tell Drupal that it will need another database (in settings.php, everything is fine here).

Following "Inserting data to external DataBase ", I managed to create a little form to add a new line in the external database (using `hook_form, hook_form_submit, db_set_active and db_insert`).

Now I would like to complete this custom module to achieve this :

* an user open the node edit form
* an user submits changes
* the form is submitted
* the form values are saved as usual on Drupal database
* AND the same values are saved on the external database

Finally, I need a module to synchronize Drupal nodes with external database tables.

I suppose this is something totally doable and easy for someone used to Drupal API. Thanks in advance for any help on this.

PS : you may find a first brainstorming on this problem here : How to edit external database from Drupal 7 interface?

Related questions

How to define and use an external database connection in a custom module

# Answer
> 1 votes
I'm a little fuzzy on the details of what you already have but the code below should help you get you in the right direction (I think). It will check for changes to the fields, make sure the node exists in the external database and then update the external database table.

Just remember to change the db\_set\_active statements to the name of your database and change the table names.

***As a side note***, as you said you are more of a site developer, if you install the Devel module you can use dpm() to print variables, arrays, messages etc. to the Drupal message space. E.g. if you wanted to see what was in $new, after the foreach() where we add the updated fields to $new, adding a new line with just dpm($new) will display the array in a structured and pretty way.

Its an invaluable tool for module development!

```
/**
 * Implements hook_node_update().
 */
function external_update_node_update($node) {
  // Get a list of fields for the content type.
  $fields = field_info_instances("node", $node->type);

  // Set variables as arrays.
  $old = array();
  $new = array();

  // Get the values of the fields for both the original and updated states
  // and add them to the arrays.
  foreach ($fields as $key => $values) {
    $temp_field = field_get_items('node', $node->original, $key);
    if (isset($temp_field[0])) {
      $old[$key] = $temp_field[0]['value'];
    }
    else {
      $old[$key] = NULL;
    }
  }
  foreach ($fields as $key => $values) {
    $temp_field = field_get_items('node', $node, $key);
    // If the field is not empty...
    if (isset($temp_field[0])) {
      $new[$key] = $temp_field[0]['value'];
    }
    // Else add an empty value.
    else {
      $new[$key] = NULL;
    }
  }

  // Check if there are any differences between the new and original states.
  $diff = array_diff($new, $old);

  // If there are differences then an update can occur.
  if (!empty($diff)) {
    // Start the database transaction in case something goes wrong.
    $transaction = db_transaction();

    // Add a try/catch to be able to roll back the database if it errors out.
    try {
      /** Check all node fields exists in external database. **/

      // Get database fields.
      $sql = "SHOW COLUMNS FROM update_save";
      // Switch to external database.
      db_set_active('external');
      $query = db_query($sql);
      // Switch back to drupal db.
      db_set_active();

      // Add list of database fields to array for use later.
      $db_fields = array();
      foreach ($query as $row) {
        $db_fields[$row->Field] = $row->Field;
      }

      // Check if the node contains new fields that are not in the database.
      $field_diff = array_diff_key($fields, $db_fields);
      // If extra fields exits set a log message
      // and remove these fields from the update.
      if (!empty($field_diff)) {
        foreach ($field_diff as $missing_field) {
          watchdog('node_update', "The field $missing_field is missing from the external database.", WATCHDOG_ALERT);
          unset($new[$missing_field]);
        }
      }
    }
    // If something went wrong and it threw an error,
    // catch the exception, roll back any database changes and log the error.
    catch (Exception $e) {
      $transaction->rollback();
      watchdog('node_update', "<pre>$e</pre>");
    }

    try {
      // Check if node already exists in the external database.
      $sql = "SELECT nid FROM update_save WHERE nid = :nid";
      // Switch to external database.
      db_set_active('external');
      $query = db_query($sql, array(":nid" => $node->nid));
      db_set_active();
      $nid = "";
      foreach ($query as $row) {
        // If there are any results add it to the $nid variable.
        $nid = $row;
      }

      // If the query came back with results and therefore $nid is not empty,
      // then the update can continue.
      if (!empty($nid)) {
        // Switch to external database.
        db_set_active('external');
        db_update('update_save')
          ->fields($new)
          ->condition('nid', $node->nid)
          ->execute();
        db_set_active();
      }
      // Else add a watchdog log.
      else {
        watchdog('node_update', "The node currently doesn't exist in the external database.", WATCHDOG_ALERT);
      }
    }
    // If something went wrong and it threw an error,
    // catch the exception, roll back any database changes and log the error.
    catch (Exception $e) {
      $transaction->rollback();
      watchdog('node_update', "<pre>$e</pre>");
    }
  }
}

```

# Answer
> 0 votes
I posted my answer here to keep all elements together so future users can read everything at the same place. Thanks Jimmyb\_1991 for the custom module. I will probably use it later to improve my own solution.

---
Tags: 7, forms, database
---


# Question
Title: Different number of decimals for prices and totals
I use Drupal Commerce and I have a problem with the number of decimals in prices. In Spain (and I suppose in other countries too), I could have prices of products with more than two decimals, but at the end, the totals are rounded to two decimals. With currency settings module I can set the number of decimals, but It is for all (prices and totals). Is there anyway I could have four decimals for prices and two for totals?
Thanks in advance.

# Answer
> 0 votes
If you can set the number of decimal places site wide... I would set it to most precision I am likely to need and shorten it through the theme/js in the places where I need it shorter. It may not be as graceful as variable precision, but if no other answers come up, it will get the job done...

---
Tags: 7, commerce
---


title: Form submit in FieldFormatter

text:
# Question
Title: Form submit in FieldFormatter
I have a custom entity type with a "yield" field. I would like to allow users to see the custom entity (full content view-mode) and change "yield" value to regenerate it with calculated values from the yield changement.

I started with a new fieldFormatter for my "yield" (number\_decimal) field. The formatter extends DecimalFormatter and builds a little form object instead of displaying a simple markup.

```
$element = [
  '#type' => 'form',
  '#tree' => TRUE,
];
$element['yield'] = [
  '#type' => 'number',
  '#title' => $this->t('Change yield'),
  '#default_value' => floatval($this->numberFormat($item->value)),
  '#value' => floatval($this->numberFormat($item->value)),
];

$element['submit'] = [
  '#type' => 'submit',
  '#value' => $this->t('Change'),
  '#submit' => ['changeYield'],
];

```

Form is defined in the full content view, and a click on the submit button send the form. I think this is not the correct way to add a form because #submit callback is never called. I tried different syntax, with static or non-static callback, but it doesn't work.

I would like to find an elegant solution, not hacking and adding JavaScript custom code.

Now the ideal solution is attaching #ajax callback to rebuild the data without sending the page, but I don't know if it possible and if dependencies will be not to strong, because changes done on another fieldFormatter item's values.

# Answer
> 1 votes
You can't add a form field to an entity display. You have to approach this the other way. Build a form class with the field and the submit button and add the entity content to it. Then you can respond to the posted data in the submit method of the form class and save it to the entity.

For the ideal solution you can attach ajax to the submit button to avoid a page reload.

An alternative option is an entity form using a custom form mode containing one field. This could be set up without code by using blocks for both, the entity content and entity form or only one of them and the other as page. This depends on what the end result should look like. You need a module to control the form modes Form mode control and to put an entity form in a block Entityform block. The entity content can be placed in a block with Views. For a custom entity all of this can be done in code as well.

# Answer
> 1 votes
For my uses, I found a solution to embed forms in formatters.

Imagine that an entity type (type A) has a entity-reference field that holds another entity type (type B). Entities of type B holds a third entity type (type C).

Example: A : an entity of type "collection" B : an entity of type "album" C : an entity of type "song".

A collection contains one or more albums, and each album contains some songs.

For the "collection" entity view, I would like to display each album as a little form with a table listing the songs, and allow reorder (draggable) and edit songs data.

In this case, and it work, I created a "album" formatter and a "song\_list" form that contains the logic of the draggable/editable table.

The album formatter has a viewElements method like this:

```
public function viewElements(FieldItemListInterface $items, $langcode) {
    $base_entity = $items->getEntity();

    $elements = [
        '#theme' => 'item_list',
        '#items' => [],
        '#title' => $this->t('Albums listing'),
    ];
    /** @var \Drupal\my_module\Entity\Album $entity */
    foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {

        $name = $entity->label();
        $name = Xss::filter($name, []);
        $item = [];
        $item['name'] = [
          '#type' => 'markup',
          '#markup' => '<h2>'.$name.'</h2>',
        ];

        $form = \Drupal::formBuilder()->getForm('\Drupal\my_module\Form\AlbumSongListForm', $entity);
        $item['form'] = $form;
        $elements['#items'][] = $item;
    }
    return $elements;
}

```

I used this formatter as "album" entity formatter in the "collection" view display mode. When I go the the "collection" page, For each album in the collection is displayed a form listing each song. And off course, each form can be submitted to save values. Be careful with multiple forms of the same class on the same page. Indicate explicitly the "form ID" to have unique identifier for each form. This can be done with

```
$form['#id'] = 'album-'.$album->id().'-song-list-form';

```

Finally, it's possible to use form's in formatters. I don't know if ajax or other behaviors can be used, but #states works with no problems.

# Answer
> 0 votes
Ok. Finally I found a solution based on 4k4 answer.

Instead of attaching ajax or simple submit to the formatter, I created a Form with my needs, and a Block that embed the form.

Form

```
namespace Drupal\my_module\Form;

use Drupal\Core\Form\FormBase;

class YieldChangerForm extends FormBase {

  public function getFormId() {
    return 'my_module_yield_changer';
  }

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

      // Attach some fields here.

      $form['submit'] = [
        '#type' => 'submit',
        '#value' => $this->t('Change'),
      ];
      /*
      $form['submitAjax'] = [
        '#type' => 'button',
        '#value' => $this->t('Change'),
        '#ajax' => [
          'callback' => '::changeYield',
        ],
      ];
      */
    }

    return $form;
  }

  /*
  public function changeYield(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();
    $response->addCommand(new ReplaceCommand(
      '#my-wrapper',
      '<div id="#my-wrapper">Modified content here</div>'
    ));
    return $response;
  }
  */

  /**
   * {@inheritDoc}
   * @see \Drupal\Core\Form\FormInterface::submitForm()
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {

    // Handle submit here
}

```

Block

```
namespace Drupal\my_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;

/**
 * Provide a Yield changer block to display
 * on recipes.
 *
 * @Block(
 *   id = "my_module_yield_changer_block",
 *   admin_label = @Translation("Yield changer"),
 * )
 */
class YieldChangerBlock extends BlockBase {

  /**
   *
   * {@inheritDoc}
   * @see \Drupal\Core\Block\BlockPluginInterface::build()
   */
  public function build() {
    $form = \Drupal::formBuilder()->getForm('\Drupal\my_module\Form\YieldChangerForm');
    $renderArray = [
      'form' => $form
    ];
    return $renderArray;
  }
}

```

The block is placed before the entity content and display the Form. From now, I simply reload the page and set a "yield" key with user selected value in the URL.

In the sample, you can see commented code that use ajax callback to send modified data. I don't use it now because I think it's complex to render the data I want to change.

---
Tags: 8, forms
---


# Question
Title: Add values from feed into the users database table
I am new in Drupal. I am currently building a stand alone website (non Drupal website) but want people to register through the custom form and all the users data to go into the Drupal's database.

So the admin can manage the users through Drupal admin.

I am initially thinking to use a custom form so users can insert the information and then store all the values in JSON file and then install a module in Drupal to get the JSON's information and then store them into the Drupal user's table.

I will really appreciate your support and suggestions.

Thanks.

# Answer
Your best bet is to use HEADLESS Drupal. This means using Drupal as a backend, but with the front end being entirely separate to that. You do this by creating a REST server in Drupal, through which you can perform various actions, such as registering and logging in users.

If you are using (or will use) Drupal 7, a server can be created through the Services module. If you are doing it in Drupal 8, it is part of core.

You should set up your system to use OAuth2 authentication. This requires the OAuth2 server module, though I'm not sure what is necessary for Drupal 8.

With the REST server set up, you can create a form on whatever site you want, and you will then register the user through the REST server. Users can be authenticated (logged in) the same way.
> 2 votes

# Answer
Feeds and Feeds extensible parsers would work for this.

It's a well-known module so have a look at some Youtube videos to get an idea of how to use it.

Feeds extensible parsers simply adds JSON capabilities.
> 1 votes

---
Tags: users, importing-exporting
---


# Question
Title: Pass variables to template using hook_block_view_alter()
I'm trying the change the homepage path based on the current request. The `system_main_block` block renders the logo which is linked to the homepage. If the current path starts with `/foo/...`, I want to change the homepage path to point to `/foo` instead of the default `/`.

I want to pass a custom variable to a block using `hook_block_view_alter()`.

The hook gives me the build array and the Block itself as arguments.

How can I add a variable to the build array that I can then access in the view (twig template)?

The build array looks like this:

```
array
    '#theme' => string 'block'
    '#attributes' =>
        array (size=0)
        empty
    '#contextual_links' =>
        ...
    '#weight' => int -3
    '#configuration' =>
        array (size=4)
            'id' => string 'system_main_block' (length=17)
            'label' => string 'Main page content' (length=17)
            'provider' => string 'system' (length=6)
            'label_display' => string '0' (length=1)
    '#plugin_id' => string 'system_main_block' (length=17)
    '#base_plugin_id' => string 'system_main_block' (length=17)
    '#derivative_plugin_id' => null
    '#id' => string 'my_id' (length=19)
    '#pre_render' =>
        array (size=1)
            0 => string 'Drupal\block\BlockViewBuilder::preRender' (length=40)
    '#block' =>
        object(Drupal\block\Entity\Block)[3592]

```

I can't see where I can assign an extra variable. Am using the wrong hook?

# Answer
I think a better option is to override `PathProcessorFront::processOutbound()`:

```
 public function processOutbound($path, &$options = array(), Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {
    // The special path '<front>' links to the default front page.
    if ($path === '/<front>') {
      $path = '/';
    }
    return $path;

```

Overriding in this case means using a similar outbound pathprocessor with a higher priority and replace `'/<front>'` or a lower priority and replace `'/'`.

**Edit:**

Register the path processor as a service with the tag `path_processor_outbound` in mymodule.services.yml. This is the core service definition from the example before:

```
path_processor_front:
    class: Drupal\Core\PathProcessor\PathProcessorFront
    tags:
      - { name: path_processor_inbound, priority: 200 }
      - { name: path_processor_outbound, priority: 200 }
    arguments: ['@config.factory']

```
> 1 votes

# Answer
The `system_main_block` is not the place to be looking. Whilst it's not a block in the traditional sense. Your logo position, and the URL it links to, are probably controlled by your theme. It should be simple to pass an updated URL as a custom variable in the theme.
> 0 votes

---
Tags: 8, hooks
---


# Question
Title: How to exposed custom profile fields in views
The custom fields were created using a custom form in a module, not user entities or Profile2.

How can I expose these fields to views? My goal is to allow an admin to filter users by exposing those custom fields.

Here's the function that creates the custom profile form:

```
function mymodule_profile_form($form, &$form_state, $account) {
[...]
//
// Basic Info
//
$form['fs_basic'] = array(
  '#title' => 'Basic Info',
  '#type' => 'fieldset',
  '#prefix' => '<div class="row">',
);

$form['fs_basic'][SOME_SF_CONTACT_FIRSTNAME] = array(
  '#title' => 'First Name',
  '#type' => 'textfield',
  '#default_value' => $contact[SOME_SF_CONTACT_FIRSTNAME],
 );
$form['fs_basic'][SOME_SF_CONTACT_LASTNAME] = array(
  '#title' => 'Last Name',
  '#type' => 'textfield',
  '#default_value' => $contact[SOME_SF_CONTACT_LASTNAME],
);
$form['fs_basic'][SOME_SF_CONTACT_MIDDLENAME] = array(
  '#title' => 'Middle Name',
  '#type' => 'textfield',
  '#default_value' => $contact[SOME_SF_CONTACT_MIDDLENAME],
);
$form['fs_basic'][SOME_SF_CONTACT_SUFFIX] = array(
  '#title' => 'Suffix',
  '#type' => 'textfield',
  '#default_value' => $contact[SOME_SF_CONTACT_SUFFIX],
);
//
// Profile Info
//
$form['fs_profile'] = array(
  '#title' => 'Profile',
  '#type' => 'fieldset',
  '#prefix' => '<div class="row">',
);
$form['fs_profile']['name'] = array(
  '#title' => 'Username',
  '#type' => 'textfield',
  '#default_value' => $account->name,
  '#maxlength' => 20,
);
[...]
$form['submit'] = array(
  '#value' => 'Submit',
  '#type' => 'submit',
  '#attributes' => array('class' => array('btn btn-primary align-left push-
down')),
);

$form['#validate'][] = 'user_account_form_validate';
$form['#validate'][] = 'user_validate_picture';
$form['#validate'][] = 'user_profile_form_validate';
$form['#validate'][] = 'mymoduler_profile_form_validate';
$form['#submit'][] = 'mymodule_profile_form_submit';
// Add the final user profile form submit handler.
$form['#submit'][] = 'user_profile_form_submit';

  return $form;
}

```

I want to be able to expose the Last Name in Views to I can allow an admin to search.

# Answer
> 0 votes
In order to use it with Views, one of the following have to be true:

* You are using Profile2
* You are using core User profile
* You are using actual fields from Field API
* The profile storage is an entity
* None of the above, and you are using a custom table

One of these should let you add a relationship in Views from 'User' to 'Profile2' associated to that user, if not, the core profile fields should be available.

However, if you used a custom table, you will have to do some legwork describing your data to Views in order for it to be an option.

Here are some resources that will help you in that direction:

Do know that just because they are 'fields' in a custom form does not mean that it is represented in Drupal the same way. As far as Drupal knows (and from what I see in the provided code) it is your standard form made with FormAPI. They are not really "custom fields" so much as form items abstracting the input to store data.

---
Tags: 7, forms, views
---


# Question
Title: Using an aggregated entity query to find duplicate taxonomy terms
Due to a content migration bug, there are nodes in our site that reference the same taxonomy term multiple times with different deltas:

```
bundle  deleted entity_id   revision_id langcode    delta   field_term_target_id
article 0   1061    1062    en  0   307
article 0   1061    1062    en  1   307

```

I can find these with the following database query

```
SELECT
    entity_id, field_term_target_id, COUNT(*) as count
FROM node__field_industries
GROUP BY entity_id, field_industries_target_id
HAVING count > 1;

```

For building a tool that lists these nodes within Drupal, I would like to use an entity query instead of accessing the database directly.

I've tried the following:

```
\Drupal::entityTypeManager()
  ->getStorage('node')
  ->getAggregateQuery()
  ->groupBy('nid')
  ->groupBy('field_industries')
  ->aggregate('field_industries.delta', 'COUNT')
  ->conditionAggregate('field_industries.delta', 'COUNT', 1, '>')
  ->execute();

```

But this results in an error `Invalid specifier 'delta'`. If I aggregate on 'field\_industries' instead (which seems wrong, as I'm already grouping on that value), I get completely wrong results back (specifically, vastly inflated values for COUNT, which can be as high as 16 even for nodes that are not affected by the bug).

So I guess my question is: How do I aggregate on a non-default column in the field table (such as the `delta` column)?

# Answer
You can use the Database abstraction layer:

```
$connection = Drupal::database();
$query = $connection->select('node__field_industries', 'i');
$query->fields('i', ['entity_id', 'field_term_target_id']);
$query->addExpression('COUNT(*)', 'count');
$query->groupBy('i.entity_id');
$query->groupBy('i.field_term_target_id');
$query->having('COUNT(*) > 1');

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

```

Hope this helps
> 1 votes

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


title: CSS is broken only certain admin pages

text:
# Question
Title: CSS is broken only certain admin pages
Drupal 8.2.7: Similar to this question: Why does my Site have a broken theme/style?

In my case only certain admin pages css are broken and this seems to only affect admin, not unauthenticated users. For example /node/add/article. In the head tag, I see the correct aggregated css listed a few times: /sites/default/files/css/css\_Va4zLdYXDM0x79wYfYIi\_RSorpNS\_xtrTcNUqq0psQA.css?onn5ym

But some stylesheets are not aggregated: /?onn5ym

The common consensus is that the files where css are stored are not writable by Drupal, but I'm not sure this is the case because some stylesheets get aggregated. Or they are coming from another directory I do not know about? I've also tried clearing cache, no luck. Any other suggestions?

# Answer
> -1 votes
Turns out this was a permissions thing after all. The entire web/modules directory needs to be read/writeable by Drupal.

---
Tags: theming, 8, css-js-aggregation
---


title: Performance and Field Collection

text:
# Question
Title: Performance and Field Collection
I have a use case where I want to add multiple fields grouped together to an entity, field collection is perfect for this and I have it working well now this way.

Field collection stores all field collection entities in one table in field\_collection\_item, so if I had another field collection that had a huge number of rows would it effect performance? If so then I would like to store these other fields groups somewhere else, maybe an entity reference so these fields are in their own table. How would I convert my field collection to entity reference.

Can I duplicate the functionality of field collection with entity reference? As essentially an entity reference and field collection are the same. But if I had an entity reference it would be in it's own table that is less crowded.

# Answer
> 1 votes
Not exactly. Field Collection main purpose is to make a field that holds other fields so the data can be logically grouped. So, no, you can't really "convert" it to an entity reference field - they store different data. An entity reference points at another entity; so you'd need an entity to be a container for that data. You can either achieve this via Entity API, or use ECK. I suppose you could write a migration/batch script to port over the data, but I really don't see the point unless the entities were going to be viewed on their own page.

You shouldn't have any issue with the number of rows in the database, the issue will arise when it comes to operating with that data. If you have an entity that has 1500 field collection items, and you load them for display, yes, you will have very severe performance issues. Think of it like calling `entity_load` 1500 times.

This usually rears its ugly head when you try to make some Views to display field collection items. Pro tip there - disable automatic preview in the Views config.

Here are some resources that may help:

This thread also has some good history on a group of people looking for performance improvements with Field Collections: https://www.drupal.org/node/1268620

Edit:

Forgot to link to Entity Cache, which you can bolt on to Field Collection.

In the past, I had came up with two solutions to solve performance bottlenecks revolving around Field Collection.

In one case, I would prime the cache with a nightly cron run, render the field collection field into a variable and cache that variable. If the cache item exists, I pass that as the template variable. This bypasses loading and rendering the field and rendering the data (`entity_load`) for every user requesting the page.

This works, until your cache item grows to over 1MB in which case it can still cause MySQL to slow down. You may also want to look into adding Memcache or Redis on top as the caching backend to alleviate that. Ultimately, MySQL will be your bottleneck - so you should try to offset that work and cache as much as possible in a caching backend.

In another case, I wound up storing the data in Solr. When the node was preprocessed, I would query Solr for that item. I was also storing the rendered result in Solr, so that my result already contained the rendered HTML. This was the *fastest* solution for end users, but came with a bit of work to keep it up to date. This is also beneficial if you also have to search through that data elsewhere, since you'd already (read: should) be working with Solr in that case.

---
Tags: 7, entities
---


# Question
Title: Verify that salt.txt was located and being used by Drupal?
In my settings file in Drupal 8, I am specifying a location for `hash-salt` to a file outside of the docroot.

Example:

```
$settings['hash_salt'] = file_get_contents('/salt.txt');

```

I don't see anything in the status report or way to verify that Drupal was able to locate this file on the webserver and it is using it. I tried setting it to a broken path and/or file that doesn't exist, I even removed the line. However I don't see any noticeable change, so, how can you tell that this setting is being respected?

# Answer
> 3 votes
You can check this with drush by using `Settings::get('hash_salt')`:

```
drush ev "var_dump(\Drupal\Core\Site\Settings::get('hash_salt'))"

```

---
Tags: 8, security
---


# Question
Title: Search Engine returning multiple 404s, Redirect 404 urls based on node id in the url
I am using Drupal 7. Many of my url paths (up to 6,000) have moved to new url paths with no 301 redirect so they are returning lots of 404s on google. i have paths like /articles/bla/bla-bla/12345 which moved to /articles/bla-new/something/12345

Since the old path which now returns a 404 has the node id in the url at the end, i want to redirect a path like this `"/articles/bla/bla-bla/12345"` to `node/12345` once the system detects a 404

Any suggestions for using .htaccess redirect rules or other module to achieve this?

I've tried this: `RewriteRule ^articles/*/+ node/+ [R=301,L]` but it doesnt look right.

I need some help. thank you in anticipation

# Answer
> 1 votes
Try

```
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^articles/.*/.*/(.*)$ /node/$1 [R=301,L]

```

of not worked use your absolute URL

```
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^articles/.*/.*/(.*)$ http://www.yourdomin.com/node/$1 [R=301,L]

```

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


# Question
Title: Date range field misses the minutes when they are the same
\[UPDATE: RESOLVED ON MY OWN! YAY!\] I've got a date range (start and end date) which I'm using to display a start and end time of an event. However, when the minutes are the same for the start and end time (with differing hours), the first time's minute digits are omitted. See the pic:

I've looked through the settings and I cannot, for the life of me, figure out **how to show minutes when the minutes are the same**. When I change it to be different minutes, it looks good:

I'm sure it's some simple setting that I'm just missing, somewhere. But I've searched and googled and can't figure it out. Here's my configuration:

And here is that format:

Set to that date type:

Seems fine everywhere.

It's in military time--not sure how to get an AM/PM dropdown. Don't see any options for that, but I haven't really investigated that yet. But that's neither here nor there. I'm hiding the year, month, day in this Add Event form and just using a default value.

The only modules that affect this that I'm using are Date and Date API, as well as Panelizer to display it. I'm using a custom layout with panelizer, but that shouldn't matter.

I actually do have some code in the template.php file that alters a date range, but can't see, as of yet, why that'd be screwing things up:

```
// template.php

function times_square_date_display_range($variables) {
  $date1 = $variables['date1'];
  $date2 = $variables['date2'];

  //if the same month, omit first num's month
  if (substr($date1, 2, -1) == substr($date2, 2, -1)) {
    $date1 = substr($date1, 0, 2);
  }
  $timezone = $variables['timezone'];
  $attributes_start = $variables['attributes_start'];
  $attributes_end = $variables['attributes_end'];
  $show_remaining_days = $variables['show_remaining_days'];

  $start_date = '<span class="date-display-start"' . drupal_attributes($attributes_start) . '>' . $date1 . '</span>';
  $end_date = '<span class="date-display-end"' . drupal_attributes($attributes_end) . '>' . $date2 . $timezone . '</span>';

  // If microdata attributes for the start date property have been passed in,
  // add the microdata in meta tags.
  if (!empty($variables['add_microdata'])) {
    $start_date .= '<meta' . drupal_attributes($variables['microdata']['value']['#attributes']) . '/>';
    $end_date .= '<meta' . drupal_attributes($variables['microdata']['value2']['#attributes']) . '/>';
  }

  // Wrap the result with the attributes.
  $output = '<div class="date-display-range">' . t('!start-date - !end-date', array(
    '!start-date' => $start_date,
    '!end-date' => $end_date,
  )) . '</div>';

  // Add remaining message and return.
  return $output . $show_remaining_days;
}

```

That's pretty much all the info I have about this.

\[UPDATE: It is an error with the if statement at the top of the template.php code. I used this to alter the display of date ranges and had to qualify it more to only affect date ranges, not time ranges. Here's the code for the fix ( skip date outputs with ':' character):

```
if ( (substr($date1, 2, -1) == substr($date2, 2, -1)) &&
   ( strpos($date1, ':') !== true ) ) {
  $date1 = substr($date1, 0, 2);
}

```

Can I give myself the bounty? :) \]

# Answer
> 0 votes
It is an error with the if statement at the top of the template.php code. I used this to alter the display of date ranges and had to qualify it more to only affect date ranges, not time ranges. Here's the code for the fix ( skip date outputs with ':' character):

```
if ( (substr($date1, 2, -1) == substr($date2, 2, -1)) &&
   ( strpos($date1, ':') !== true ) ) {
  $date1 = substr($date1, 0, 2);
}

```

# Answer
> 4 votes
Hope you are using core date module with end date. If you are, here is my field configuration in content type:

Once have the field configured with custom date format, the display seems working as expected.

Let me know, if I missed configuration details here.

---
Tags: 7, theming, entities, datetime
---


# Question
Title: Field not rewritten even though "Hide rewriting if empty" not selected
Simplified situation:

* A view includes fields `first_name` and `last_name`.
* `first_name` is marked "Exclude from display".
* `last_name` has the label *Full name* (which becomes the column heading in the view).
* `last_name` has "Rewrite the output of this field" checked and the rewrite text `[first_name](space)[last_name]`.
* `last_name` has neither "Hide if empty" nor "Hide rewriting if empty" checked in "No Results Behavior".
* Records with both `first_name` and `last_name` or only `last_name` show properly in the *Full name* column.
* Records with only `first_name` (i.e. empty `last_name`) show nothing.

Seems Drupal should rewrite the field for records with no `last_name` to show `first_name` since there is a specific "Hide rewriting if empty" checkbox that is not checked. Is this expected behavior? Or might there be a module interfering with things?

# Answer
> 1 votes
Although I don't understand why Drupal doesn't behave as I posit in my original question, I have found a solution. It is to use `[first_name]` as the `No results text`. If the last name is empty, the no results text is used, and the first name is displayed. If the last name is non-empty, the rewrite results are used, and the first and last names are displayed. Kind of roundabout, but it works.

# Answer
> 0 votes
It would be hard to debug without having access to code.

Can you please try the following.

* Add two fields first\_name and last\_name
* Both fields should be marked as exclude from display
* Both fields should have Hide if empty and Hide rewriting if empty
* Add a new field Global: Custom Text (Full name)
* Rewrite the field to include first\_name and last\_name

Let me know how you go.

---
Tags: views
---


# Question
Title: Permissions for seeing translated custom menu link items
I have a problem with custom menu link translations.

Only users with permissions to 'Translate custom menu link' (translate menu\_link\_content) are able to see the translated strings.

For example if I log in as admin, I can see the link texts changing when switching languages. But when I switch languages as an anonymous user the link texts fall back to the default language. Translated routes are working correctly.

As a workaround I could just give all users the 'translate menu\_link\_content' -permission but that seems like a possible security flaw.

Is this a bug or am I doing something wrong here?

# Answer
Make sure your menu link translations are actually published, there's a checkbox in the edit form. I think there are some bugs there that this isn't set properly when doing it from a node edit form.
> 3 votes

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


# Question
Title: Retrieve hidden field value & expose to .tpl file
I have a field collection set up for fields that make up a slider, one of these fields is for the alignment of text in the slider & is hidden on output. I'm trying to get the value of this hidden field & use it to set a CSS class in the .tpl file, I've managed to do this but only in the .tpl file itself. If I understand it correctly it's best practise to get the value of this field in a preprocess function & expose it as a variable to the .tpl file, I'm unsure how to do this.

This is what I have written in the .tpl.php file, and it works, but from what I understand it's not best practise.

```
$key = key($items[0]["entity"]["field_collection_item"]);
$alignment = $items[0]["entity"]["field_collection_item"][$key]["field_image"]["#object"]->field_alignment["und"][0]["value"];

```

I'm using the Drupal module fences to modify output so the code above is in the `field--fences-xl-slider.tpl.php` file.

# Answer
> 0 votes
That could *potentially* break and it's pretty gnarly looking, so not the best, but I've been there!

Instead if you have the `field_collection_item`'s ID you can do:

```
// I'd make a more meaningful name... like slider?
// If I understand your example, this should give you the entity Object for the field_collection_item
$entity = array_shift($items[0]["entity"]["field_collection_item"]);

$field_image_data = field_get_items('field_collection_item', $entity, 'field_image');
// I'm less sure here, it looks like the image is an entity and it has sub-fields?
// You'll probably have to dig through $image to see where the entity is kept, I'm guessing
$field_alignment_data = field_get_items('file?', $field_image_data[0]['#entity'], 'field_alignment');

// Now you should be at your field
// If safe_value exists, use that.
$alignment = $field_alignment_data[0]['value'];

```

This is annoying, but more legible. It's what happens when you have nested data objects, things just get kind of annoying.

The other option is you could make it a field that isn't hidden and use `hide('field_alignment')` in the `tpl.php` or `template_preprocess_*` function (guessing it'd be `template_preprocess_entity`?)

---
Tags: 7, theming, entities
---


# Question
Title: Issues importing nodes containing taxonomy terms with &/& using feeds
I have a view that outputs XML either on screen (using Views Datasource) or a file (using Views Data Export), and I'm attempting to import the data generated by the view using the feeds module.

The view contains several taxonomies, some of which contain terms with an ampersand (e.g. "Finance & administration).

The datasource view outputs the term without encoding these ampersands "&", while the views data export seems to encode them regardless of the setting in the view to do it or not. (The value stored in the dB is "&", not "&amp".)

With the datasource feed import, it appears all nodes that have & in at least one term associated to the node are skipped. I say this because those nodes never even show up in the debug output (which sounds like a bug to me).

With the views data export XML file import, all the nodes are imported, but the taxonomies that accept multiple values never get set properly.

Using Feeds tamper, I have tried using html entity decode/encode, and attempted to use it before/after explode, but nothing seems to fix either issue. I believe I should focus on the XML file import since at least all nodes are being imported.

Any thoughts on what may be happening during the XML file import, and how to address the issue? All the modules are the latest stable version.

# Answer
> 1 votes
I am using Feeds XPath Parser to import an XML file that contains a couple of fields that I then map to terms in two different vocabularies. It looks like the parser removes ampersands before Feeds Tamper kicks in. This leaves the terms with three spaces where previously there was a space, an ampersand and another space.

My solution - was to create a Find Replace tamper plugin that looks for three spaces in the imported text and replaces the three spaces with a space, an ampersand and another space.

Not pretty, but it works. Of course, this solution won't work if there are other special characters in the feed that would also be removed. In that case, I'd create multiple Find Replace plugins that look for the specific text strings, such as "Canada Alaska" and replacing them with the corrected string, i.e. "Canada & Alaska". Even less pretty but ...

---
Tags: 7, feeds
---


# Question
Title: How to get the Date, when particular field of a node is equal to some value?
I have Content type called "**Items**", in that i have select list field for **status** referencing to Taxonomy terms(delivered,hold,dispatched etc.) .
I want to store the date in some custom table when the item is "dispatched" and use that date in some other code.
Which is function in which i can write logic to store date in table? or any other way i can get dispatched date of the item?

# Answer
> 0 votes
You have to use one of the events described in Entity CRUD, editing, and view hooks.

One example from the documentation:

```
function hook_ENTITY_TYPE_update(Drupal\Core\Entity\EntityInterface $entity) {
  // Update the entity's entry in a fictional table of this type of entity.
  db_update('example_entity')
    ->fields([
      'updated' => REQUEST_TIME,
    ])
    ->condition('id', $entity->id())
    ->execute();
}

```

You can get the original field values from `$entity->original->status` and check if the status has changed.

---
Tags: 8, nodes, database
---


# Question
Title: "Page cache maximum age" is set to "no caching" but the block seems to be cached
I have a Drupal 8 standard installation on Azure. I wrote a block that uses PHP to load external content; I added a timestamp to the block as well. Under *Page cache maximum age*, the site is set to *no caching*. When I refresh the page, the timestamp doesn't update telling me it's not attempting to reload. If I manually clear the cache, all is good and the timestamp updates.

Why would this be?

As I mentioned before, these blocks are loading external content. Ideally I could set it so that these blocks alone wouldn't be cached. Is this possible?

# Answer
> 0 votes
To disable caching of the block add this to the php code:

```
  $build['#cache']['max-age'] = 0;
  \Drupal::service('page_cache_kill_switch')->trigger();

```

This is a similar question Caching of blocks for anonymous user

---
Tags: caching
---


# Question
Title: Drush installed and running; No Drupal site found even with uri specified
After much trial and tribulation, I thought I had drush all ready to roar. Much excitement. But then, no joy...

Drush is working. The sites operate fine via MAMP. Regardless, a "drush cc all" command returns:

```
No Drupal site found, only 'drush' cache was cleared.                                          [warning]
'all' cache was cleared.                                                                       [success]

```

This question has stumped drupalcon attendees and very experienced developers. Any ideas?

I am on Mac OS 10.9.3 using MAMP (free) Version 3.0.5

Here is my drush status:

```
 Drupal version         :  7.29-dev
 Site URI               :  http://default
 Database driver        :  mysql
 Database hostname      :  localhost
 Database username      :  db_user
 Database name          :  db_name
 PHP executable         :  /usr/bin/php
 PHP configuration      :
 PHP OS                 :  Darwin
 Drush version          :  7.0-dev
 Drush temp directory   :  /tmp
 Drush configuration    :
 Drush alias files      :
 Drupal root            :  /Applications/MAMP/htdocs/mysite.dev
 Site path              :  sites/default

```

Have tried executing drush from `/Applications/MAMP/htdocs/mysite.dev`; from `/Applications/MAMP/htdocs/mysite.dev/sites/default`; and using `drush cc all --uri=http://localhost/mysite.dev`

Tried running drush from sites/default. Same result.

# Answer
> 9 votes
Please double check that all below points are addressed.

1. You're running `drush` in Drupal root folder or folder containing `settings.php` file.
2. The `mysql` command exists (and it's in your `PATH`).

Please note that the database command depends on your database `driver` set in your settings file (e.g. `sqlcmd` for SQL Server; for details check different classes in Drush's `/src/Sql`).

If the command is missing when running in any folder, make sure path to its binary file is added into your `PATH` system variable.
3. Your PHP has PDO extension enabled (check by: **`php -m | grep pdo`** or `drush sqlc`).
4. Your PHP has database extension enabled (e.g. `mysqli`) (check by: **`php -m | grep mysql`**).

To investigate what's exactly wrong, run `drush` with `-v` (verbose) and `-d` (debug) flags, e.g.

```
drush -vd status
drush -vd ev "echo 123"
drush -vd cc all

```

and check for any errors.

---

> mysql extension for PHP PDO is not installed. Check your php.ini to see how you can enable it.

Install database extension (e.g. `mysqli`) (as per above 4th point).

For MAMP, see: Drush does not work on my Mac

---

### MAMP

Since you're using MAMP, make also sure you running the right version of `php` binary (check by `which php`) and it should point to `/Applications/MAMP/bin/php/php5.X.X/bin/php`. If not, please add the path into your `PATH` in your *rc* files (e.g. `~/.bashrc`):

```
# For MAMP (OSX)
PHP_VER="5.6.10" # Or: 5.4.19/5.5.3 (check by: $ ls /Applications/MAMP/bin/php/php*)
export PATH="$PATH:/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php/php$PHP_VER/bin:/Developer/usr/bin"

```

---

### XAMPP

For XAMPP for Windows, similar thing, add your `C:\xampp\mysql\bin` into your environment variable `PATH`.

### Debugging

If your `drush` command fails for some reason, here are the suggested steps to debug drush (shell commands).

1. Install and enable PHP `xdebug` extension. Verify by `php71 -i | grep xdebug`.
2. Verify *Drupal root*, *Settings File* and *Database* are present in `drush status`.
3. Generate trace file:

```
drush ev "xdebug_start_trace(); drush_drupal_cache_clear_all(); echo xdebug_get_tracefile_name(); xdebug_stop_trace();"

```

or:

```
drush ev "xdebug_start_trace(); print_r(_core_site_status_table()); echo xdebug_get_tracefile_name(); xdebug_stop_trace();"

```

If xdebug is enabled for different PHP version, specify with `DRUSH_PHP=/path/to/php`.

If successful, trace output file should be printed at the end, so take a note of it.
4. Now open and check the trace file.
5. To test or compare drush output with clean Drupal, you can install new Drupal in empty folder by:

```
drush -y qd --no-server --core=drupal-8
cd quick-drupal-*/drupal*
drush status

```

# Answer
> 5 votes
Had the same problem with the new Drush 8 on my Mac running MAMP

You need add this to your .bash\_profile export PATH=/Applications/MAMP/Library/bin/:$PATH.

once added make sure to open a new terminal window as it won't work on your current window as bash needs to start up again.

# Answer
> 1 votes
To clear All Cache using Drush, you have to go the directory of the site on the terminal where your site directory located like in www or htdocs directory and then your project folder after that run the command :

```
drush cc all

```

# Answer
> 1 votes
As @kenorb said, use `drush -vd cc all`, it will give you a good idea about what is happening in detail. In my case, it was due to the error `"mysql command not found"`. I solved it by setting up the path for mysql in my environment variables. I feel you need to check your path as well, for Drush and MySQL both and see if it works.

Thanks!!

# Answer
> 0 votes
Running MAMP Pro I got this to work by adding this line into my `~/.bash_profile` file:

```
export PATH=$PATH:/Applications/MAMP/Library/bin

```

# Answer
> 0 votes
Checkout the Drush package configure.md, it has a bunch of helpful hints for platforms, the MAMP section is thus:

> ## Additional Configurations for Mamp:
>
> Users of MAMP will need to manually specify in their PATH which version of php and MySQL to use in the command line interface. This is independent of the php version selected in the MAMP application settings. Under OS X, edit (or create if it does not already exist) a file called .bash\_profile in your home folder.
>
> To use php 5.3.x, add this line to .bash\_profile:
>
> ```
> export PATH="/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php5.3/bin:$PATH"
>
> ```
>
> If you want to use php 5.4.x, add this line instead:
>
> ```
> export PATH="/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php5.4/bin:$PATH"
>
> ```
>
> If you use MAMP 3 (php 5.5.14 by default) and want to use php 5.5.x , add this line instead:
>
> ```
> export PATH="/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php/php5.5.14/bin:$PATH"
>
> ```
>
> If you have MAMP v.1.84 or lower, this configuration will work for both versions of PHP:
>
> ```
> export PATH="/Applications/MAMP/Library/bin:/Applications/MAMP/bin/php5/bin:$PATH"
>
> ```
>
> If you have done this and are still getting a "no such file or directory" error from PDO::\__construct, try this:
>
> `bash
>  sudo mkdir /var/mysql
>  sudo ln -s /Applications/MAMP/tmp/mysql/mysql.sock /var/mysql/mysql.sock`
>
> Additionally, you may need to adjust your php.ini settings before you can use drush successfully. See CONFIGURING PHP.INI below for more details on how to proceed.

---
Tags: drush, 7
---


# Question
Title: How can I understand when a node is being edited or viewed?
I want to add a class to the body to distinguish the node's view page from the edit page.

In classy you have `'page-node-type-' ~ node_type|clean_class`. I'd like to add `page-node-type-' ~ node_type|clean_class ~ '-edit'` if we're on the edit page, but I can't figure out what that `if` statement would have in its condition.

Which code should I use to add that class only when a node is being edited?

# Answer
In this case you'd want to look at parts of the url. The easiest way to do that would be passing in additional classes from a preprocess function in the .theme file, and by looking at the URL path:

```
$current_path = \Drupal::service('path.current')->getPath();
$path_args = explode('/', $current_path);

if ($path_args[0] == 'node' && $path_args[2] == 'edit') {
  // add classes
}

```

This would be similar to using the `arg()` function from previous versions.
> 3 votes

# Answer
The node.html.twig template is just used when the a node is displayed, as the documentation itself says. (Emphasis is mine.) So you don't have any need of using a `if` statement to distinguish the view case from the edit case, since the template files used are two different ones.

> Default theme implementation **to display** a node.

The template used when a node is being edited is a different one. In the comments in the `theme_get_suggestions()` function, you can see which template files are suggested for a path like node/1/edit.

* page\__node
* page\__node\__%
* page\__node\__1
* page\__node\__edit

The last one is more specific for your case, since you need to use it when a node is being edited, independently from the node ID.

If you just need to add a CSS class when a node is being edited, you can take the code in `seven_preprocess_html()` as guide.

```
  $path_args = explode('/', \Drupal::request()->getPathInfo());
  if ($suggestions = theme_get_suggestions($path_args, 'page', '-')) {
    foreach ($suggestions as $suggestion) {
      if ($suggestion === 'page-node-edit' || strpos($suggestion, 'page-node-add') !== FALSE) {
        $variables['attributes']['class'][] = $the_class_you_want_to_add;
      }
    }
  }

```

That code adds a CSS class when a node is created or edited; if you just need to add a CSS class when an existing node is edited, you can simplify the code.

```
  $path_args = explode('/', \Drupal::request()->getPathInfo());
  if ($suggestions = theme_get_suggestions($path_args, 'page', '-')) {
    foreach ($suggestions as $suggestion) {
      if ($suggestion === 'page-node-edit') {
        $variables['attributes']['class'][] = $the_class_you_want_to_add;
      }
    }
  }

```
> 0 votes

---
Tags: theming, nodes
---


# Question
Title: node title preprocess_views_view_field();
I want to save the node title in a variable using: `themename_preprocess_views_view_field()`, becuase I want to print a the node title above the field.

But when I try to save the title with:

```
themename_preprocess_views_view_field() {
$variables['node_title'] = $variables['field']->original_value ->    string;
}

```

I get Error: Cannot access protected property Drupal\Core\Render\Markup::$string in themename\_preprocess\_views\_view\_field() (line 123 of themes/custom/themename/themename.theme).

how can I save this variable so I can print it in the `views-view-field.html.twig` file?

# Answer
Solution: The way to do this is to add an address **Field** in the **View** as **Content datasource: address** in the Admin GUI.

And select **Use entity field rendering**.

Under **REWRITE RESULTS** Select: **Override the output of this field with custom text**

And in the textbox I added in my case:

{{ title }}
{{ field\_address }}
> 0 votes

---
Tags: theming, nodes
---


# Question
Title: user warning messages keep popping up even after uninstall
I have recently disables, uninstalled and removed a few modules from my drupal 7 site but this error keeps popping up no matter what I do, I have researched how to remove them but to my dismay nothing, please help.

User warning: The following module is missing from the file system: admin. For information about how to fix this, see the documentation page. in `_drupal_trigger_error_with_delayed_logging()` (line 1138 of `/opt/lampp/htdocs/drupal/includes/bootstrap.inc`).

# Answer
> 1 votes
Most probably the disabling and uninstalling process of the modules didn't went smoothly. According to this help page on Drupal.org:

> Restore the module and actually disable and uninstall it (recommended if possible): First, restore the module to its original location in the file system. Then either go to the Modules page and disable/uninstall it from there, or use Drush (drush dis module\_name && drush pm-uninstall module\_name, where module\_name should be replaced with the name of the module).

Don't forget to also clear the caches, that "magic" feature also resolves a lot of problems ;)

You could also disable the specific message by using the Disable Messages module. However, I would recommend to try cleaning up your Drupal configuration that are causing the messages.

---
Tags: 7
---


# Question
Title: highlight the menu items related to the particular content type
How to highlight the menu items related to the particular content type? Actually I want whenever the user visits the page related to the particular content type,it should highlight the particular menu item. Context module is the one solution for this. Is any other custom coding solution without installing any module?

# Answer
> 0 votes
You can use **theme\_menu\_link** function. Add this code to template.php of your theme

```
function themename_menu_link(array $variables) {
  $path_parts = array();
  $element  = $variables['element'];
  $sub_menu = '';
  $menuName = $variables['element']["#original_link"]["menu_name"];
  //Check menu name
  if($menuName == 'main-menu')
  {
    $path_parts = explode('/',$element['#href']);
    if($path_parts[0]=='node' && is_numeric($path_parts[1]))
    {
      $menu_load_node = node_load($path_parts[1]);
      //Check node type (In our case 'article')
      if($menu_load_node->type == 'article')
      {
        $element['#attributes']['class'][] = 'highlight';
      }
    }
  }
  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l($element['#title'], $element['#href'], $element['#localized_options']);
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}

```

All links to nodes with type 'article' will have class **highlight**

---
Tags: 7, theming, navigation
---


# Question
Title: How to display select conditionally using states?
I am using the following form item.

```
//データフィールド名項目
$form['media_field_id'] = array(
    '#type' => 'select',
    '#title' => '対象項目',
    '#options' => _load_media_mapping_array($media->media_id),
    '#default_value' => isset($edit->options['media_field_id']) ? $edit->options['media_field_id'] : '',    // bugfix: #65997 somukawa chg
    '#description' => '分割条件の判定を行うフィールドを指定してください。',
    '#required' => FALSE,
    '#disabled' => $disable_mode,
    '#states' => array(
// Only show this field when the 'toggle_me' checkbox is enabled.
'visible' => array(
  ':input[name="export_type"]' => array('value' => 'md5x16'),
    ),
),
);

```

I want to display it only when users select *md5x8* and *md5x16* from the following form item.

```
//出力オプション
$form['export_type'] = array(
    '#type' => 'select',
    '#title' => '出力オプション',
    '#options' => _export_type_options(),
    '#default_value' => isset($edit->export_type) ? $edit->export_type : '',
    '#description' => '',
    '#required' => FALSE,
    '#disabled' => $disable_mode,
);

```

I checked this documentation, but it is not working.

How can I achieve what I am trying to do?

# Answer
It worked by adding below statement:

```
'#states' => array(
        'visible' => array(
        ':input[name="export_type"]' => array(
                array('value' => 'md5x8'),
                array('value' => 'md5x16'),
        ),
        ),
    ),

```
> 0 votes

---
Tags: javascript
---


# Question
Title: How do I import a library from Github when the module is installed
I want to add https://github.com/googleads/googleads-php-lib library to my module **Drupal 8** I try to add composer. json in the folder module but is not load when I installed module this is solution to upload this library without command "composer update "?

this is my **composer.json**

```
{
  "name": "drupal/googleads-php-lib",
  "description": "Integrates the googleads-php-lib library into Drupal",
  "type": "drupal-module",
  "require": {
    "googleads/googleads-php-lib": "25.0.0"
  }
}

```

# Answer
> 3 votes
composer.json has no bearing when you enable a module in the Drupal admin. Drupal only looks at the `info.yml` of a module to ensure any listed dependency (module only) exists and has been met. Using `drush` also won't work. You need Composer for this.

You would need to require your module via `composer require drupal/mymodule` \- at which point any dependencies listed in `require` would also be pulled in. For that to work, your module would need to be posted on drupal.org, with the Drupal packages repository added to your root composer.json file.

You could also add a repository endpoint pointed at GitHub, Bitbucket or any other VCS service, add a baseline composer.json file to your project and require it that way, too.

You can also do `composer require googleads/googleads-php-lib:25.0.0` from your Drupal root to pull in that package, but I would go the module route (so that package is always tied with the module).

---
Tags: 8, composer
---


title: Remove the default value

text:
# Question
Title: Remove the default value
Is it possible to remove the default value an exposed filter (implemented by the *Better exposed filter* module) in a view? I would like to have users choose a value.

I tried using this in the template file, but nothing changed.

```
function custom_theme_form_views_exposed_form_alter(&$form, &$form_state) {
  // dpm($form);
  if ($form['#id'] == 'views-exposed-form-betterexposed-page-1') {
    foreach(element_children($form) as $key => $value) {
      if (isset($form[$key]['#type']) && $form[$key]['#type'] == 'select') {
        array_shift($form[$key]['#options']);
      }
    }
  }
}

```

The HTML markup is now the following.

```
<form action="/be1" method="get" id="views-exposed-form-betterexposed-page-1" accept-charset="UTF-8" class="jquery-once-1-processed"><div><div class="views-exposed-form">
  <div class="views-exposed-widgets clearfix">
          <div id="edit-status-wrapper" class="views-exposed-widget views-widget-filter-status">
                  <label for="edit-status">
            Published          </label>
                        <div class="views-widget">
          <div class="form-item form-type-radios form-item-status">
 <div id="edit-status" class="form-radios bef-select-as-radios"><div class="form-item form-type-radio form-item-status">
 <input class="bef-select-as-radios form-radio" type="radio" id="edit-status-1" name="status" value="1" checked="checked">  <label class="option" for="edit-status-1">Yes </label>

</div>
<div class="form-item form-type-radio form-item-status">
 <input class="bef-select-as-radios form-radio" type="radio" id="edit-status-0" name="status" value="0">  <label class="option" for="edit-status-0">No </label>

</div>
</div>
<div class="description"></div></div>
</div>
        </div>
              </div>

                    <div class="views-exposed-widget views-submit-button">
      <input type="submit" id="edit-submit-betterexposed" name="" value="Apply" class="form-submit">    </div>
      </div>
</div>
</div></form>

```

I also tried the following code.

```
function custom_theme_form_views_exposed_form_alter(&$form, &$form_state) {
foreach(element_children($form) as $key => $value) {
    if (isset($form[$value]['#type']) && $form[$value]['#type'] == 'select') {

      $options = $form[$value]['#options'];
      $newOptions = array();

      for ($i = 0, $optionsCount = count($options); $i < $optionsCount; $i++) {
        $optionsKey = array_keys($options[$i]->option);
        $optionsValue = array_values($options[$i]->option);

        $newOptions[$optionsKey[0]] = $optionsValue[0];
      }

      unset($form[$value]['#multiple']);

      $form[$value]['#type'] = 'radios';
      $form[$value]['#options'] = $newOptions;
      $form[$value]['#theme'] = 'select_as_radios';
    }
  }
}

```

I now get the following notice and warning messages.

> Notice: Trying to get property of non-object in `custom_theme_form_views_exposed_form_alter()` Warning: `array_keys()` expects parameter 1 to be array, null given in `custom_theme_form_views_exposed_form_alter()`

# Answer
May be something like this (with hook\_form\_FORM\_ID\_alter function):

```
function MYMODULE_form_views_exposed_form_alter(&$form, &$form_state) {
  // dpm($form);
  if ($form['#id'] == 'MY_EX_FORM_ID') {
    foreach(element_children($form) as $key => $value) {
      if (isset($form[$key]['#type']) && $form[$key]['#type'] == 'select') {
        array_shift($form[$key]['#options']);
      }
    }
  }
}

```

**EDIT:**

Ok, it seems that better exposed filter doesn't allow to remove default value from radio if settings are default (with default settings, filter -\> is one of, BEF Settings -\> checkboxes/radio buttons). I realized that in my project radios have been made from checkboxes type (with alter function), that's why in my example it's working fine..

here is a working example:

in `hook_form_form_id_alter` function:

```
foreach(element_children($form) as $key => $value) {
    if (isset($form[$value]['#type']) && $form[$value]['#type'] == 'select') {

      $options = $form[$value]['#options'];
      $newOptions = array();

      for ($i = 0, $optionsCount = count($options); $i < $optionsCount; $i++) {
        $optionsKey = array_keys($options[$i]->option);
        $optionsValue = array_values($options[$i]->option);

        $newOptions[$optionsKey[0]] = $optionsValue[0];
      }

      unset($form[$value]['#multiple']);

      $form[$value]['#type'] = 'radios';
      $form[$value]['#options'] = $newOptions;
      $form[$value]['#theme'] = 'select_as_radios';
    }
  }

```
> 1 votes

# Answer
I came across this issue myself, and found a solution. It's not ideal, but it works.

Rather than setting your filter value to be required, allow it to add an *\- Any -* option; in `hook_form_alter()`, remove the *All* option, and set the #value and #default\_value of your form to a falsy value (e.g `0`, `NULL`).

Removing the *\- Any -* option will cause the form to not have a valid default, and instead have no Radio button selected. Unfortunately, in the form validation handler, it will reach a point where the form is determined to be invalid and display an error to the user.

Setting #value and #default\_value to something that PHP interprets as false, will avoid reaching this error condition, and you will be left with your radio button options, but with none selected by default.

You could use code similar to the following one.

```
function YOUR_MODULE_form_views_exposed_form_alter(&$form, $form_state) {
  if(isset($form['field_YOUR_FIELD'])){
    // Set the value and default value to a falsy value, so that when the form is validated in _form_validate,
    // it doesn't throw an error due to the missing option, which we remove ('All').
    // This is done in order to have the radio buttons UNSET by default, which isn't possible with views
    // and Better Exposed Filters. We instead allow the All value to appear, and then remove it.
    if($form_state['input']['field_YOUR_FIELD'] == 'All'){
      $form['field_YOUR_FIELD']['#value'] = NULL;
    }
    $form['field_YOUR_FIELD']['#default_value'] = NULL;
    unset($form['field_YOUR_FIELD']['#options']['All']);
  }
}

```
> 1 votes

---
Tags: 7, views
---


title: How do I submit a form via AJAX?

text:
# Question
Title: How do I submit a form via AJAX?
I'm using the Webform module for Drupal 8. The module confirmation settings for a form are the following:

* Page (redirects to new page and displays the confirmation message)
* Inline (reloads the current page and replaces the webform with the confirmation message.)
* Message (reloads the current page/form and displays the confirmation message at the top of the page.)
* URL (redirects to a custom path or URL)
* URL with message (redirects to a custom path or URL and displays the confirmation message at the top of the page.)

But how am I able to submit a form via AJAX so that the page doesn't reload on submit, but a confirmation message still replaces the form? What did I do wrong?

---

EDIT:

Here is the solution which works:

First you have to hook the form alter function and set an AJAX callback (as in echo's answer):

```
use \Drupal\Core\Form\FormStateInterface;

function MYTHEME_form_alter(&$form, FormStateInterface $form_state, $form_id)
{
  if ( isset($form['#webform_id']) && $form['#webform_id'] == 'MYWEBFORM' )
  {
    // add an AJAX callback to the form submission
    $form['actions']['submit']['#ajax'] = array(
      'callback' => '\Drupal\MYMODULE\Controller\DefaultController::processFormSubmission',
      'event' => 'click',
    );
  }
}

```

Then in the `processFormSubmission` function you can process the form (put `use \Drupal\Core\Form\FormStateInterface;` at the top of your file) like:

```
// Instantiate an AjaxResponse Object to return.
$ajax_response = new \Drupal\Core\Ajax\AjaxResponse();

/* do sth */

// in the DOM: replace the form with the text 'form submitted'
$ajax_response->addCommand(new \Drupal\Core\Ajax\HtmlCommand('#MYFORM', 'form submitted'));

return $ajax_response;

```

# Answer
I can't post all the code you would need, but essentially you will want to do a form alter, and add an `#ajax` item on the submit button and point it at a callback. This callback will perform validation and submission - at the end of it you can issue a ReplaceCommand. Here's an example:

```
function mymodule_form_submit($form, FormStateInterface $form_state) {
  // code here to handle the submission aspect
  // you'll need to manually submit form value data to Webform using webform api

  // if successful, this is the response
  $response = new AjaxResponse();
  $response->addCommand(new ReplaceCommand('selector', 'data'));
  return $response;
}

```

Where `selector` is an HTML element, and `data` is what you want to replace it with.

Sounds like you would want the selector to be the id of the container wrapping the form, and the replacement should be the confirmation message from Webform (you'd have to get it from fetching the config of that form). This will cause a non page refresh and instead, the form will be replaced with the confirmation message.
> 4 votes

---
Tags: 8, ajax, webforms
---


# Question
Title: Scheduler Module crontab job does not publish content
When running the Scheduler lightweight cron through crontab, I am getting a message that the lightweight cron has activated and completed in my D8 log, but content is not publishing. When running the lightweight cron through backoffice, items publish correctly. I've checked the cron log to see if the cron is encountering errors, and am seeing no issues. Is there something I am missing in my crontab command that is causing the cron to run but not update publish status on any of the scheduled nodes?

# Answer
If you use Content Access module, see that issue : https://www.drupal.org/node/2865787

Enzo
> 0 votes

---
Tags: 8, cron
---


# Question
Title: How do I get the host paragraph when a paragraph is referenced in another paragraph?
I have referenced `Paragraph B` in `Paragraph A` and in preprocess of `Paragraph B` I want to access host `paragraph A`. Is this possible with ease. As in case of paragraph references on node we can do `paragraph->getParentEntity()` ? I had tried same but it still get the parent node :(

# Answer
> 12 votes
If you look at the Paragraph class in the module, you will find a public method called `getParentEntity` that return the parent entity of a Paragraph instance.

So, if you do:

```
$parent = $paragraph->getParentEntity();

if (isset($parent)) {
  // Your stuff ...
}

```

You would have the parent entity in the `$parent` variable. You can chain the method if there is multiple nested paragraphs. I also suggest using the `isset` method on the `$parent` variable because I've encounter some weird issues where random paragraphs returns `null`.

---
Tags: 8, paragraphs
---


# Question
Title: Can I set a status message to be displayed when a user clicks a link?
Here's my setup:

I have a page about Pineapples. There is a link to the Pineapples page in the main navigation menu. When a user clicks that link, they go to the page.

I also have a separate link on the homepage to the Pineapples page. When a user clicks the homepage link, I want to send them to the Pineapples page, but I also want to show a status message with a little more information.

Is there a Drupal-y way to do this?

# Answer
> -1 votes
I think you need to make a custom form with a submit button (the button should be your "link" button), and then you can do what you want.

---
Tags: 8, navigation, status-messages
---


# Question
Title: I've Featured some Paragraph Bundles, but they are not showing up on the remote site
I've Featured some Paragraph bundles and have included them as part of a module.

I've merged these files to my remote site and want to 'activate' the Feature to have the Paragraph Bundles appear. I see my Feature there on the remote site and can 'Revert' it to update it but nothing happens - I don't get my new Paragraph Bundles in the existing list, nor do I get any error messages.

Would anyone know what's going on?

What I've pushed up is:

```
module_name.features.field_instance.inc

function module_name_field_default_field_instances() {
  $field_instances = array();

  // Exported field_instance:
  // 'paragraphs_item-module_name-field_grid_number_columns'.
  $field_instances['paragraphs_item-module_name-field_grid_number_columns'] = array( etc...

```

And

```
module_name.features.inc

function
module_name_paragraphs_info() {
  $items = array( etc...

```

And in my module's .info file I have included, eg:

```
features[features_api][] = api:2
features[field_instance][] = paragraphs_item-module_name-field_grid_number_columns
features[field_instance][] = paragraphs_item-module_name-field_paragraphs
features[field_instance][] = paragraphs_item-module_name_item-field_image
features[field_instance][] = paragraphs_item-module_name_item-field_text
features[field_instance][] = paragraphs_item-module_name_item-field_title
features[paragraphs][] = module_name
features[paragraphs][] = module_name_item

```

Is there anything I'm missing?

# Answer
You might try manually creating the paragraph bundle and see if the fields pop in once the bundle is made, or once the bundle is made and the feature is reverted.

Might be that the features integration for paragraphs in D7 is still iffy.
> 0 votes

---
Tags: 7, features, paragraphs
---


# Question
Title: Is there way to rearrange node on front page?
I tried use weight module but it arrange node only on admin interface. Is there way set weight to node on front page?

# Answer
You can create views with weight sorting nodes and set it as front page
> 1 votes

# Answer
Probably easiest if you create a view and list that on the homepage. I believe the listing of nodes on `/node` (the default homepage) are in reverse chronological by created date.

The checkbox "Sticky" under publish settings might be helpful, but a View would give you the most reliable results.
> 1 votes

---
Tags: 7, nodes
---


# Question
Title: Viewing Referenced Field Images in node template
I'm stuck with a probably simple problem, maybe someone can help?

I have a node (representing a **route**) which has a reference to other nodes (**points of interestes**) Like this node.field\_poi

Every field\_poi has it's own images attached

from the node template I'm trying to get the images, but no way!

There are my attempts, where am I wrong?

**{{content.field\_poi.0.entity.field\_image.0.entity.uri.value}}** {{kint(node.field\_poi.0.entity.field\_image.0.entity.uri.value)}}

If I try this, it breaks completely the page: {{kint(node.field\_poi.0.entity)}}

# Answer
Thanks to the slack channel #drupaltwig, I found a solution! I leave it here, in case somebody else needs it

```
{% for curr_poi in node.field_poi %}

{% if curr_poi.entity.field_image.entity.uri.value is not empty %}

<img class="product-image" src="{{curr_poi.entity.field_image.entity.uri.value | image_style('app_list')}}" />

{{curr_poi.entity.title.value}}

{% endif %}

{% endfor %}

```

---

Main hints:

* use **node** instead of **content**
* iterator is **curr\_poi** do not use a index
* I used twig\_tweak drupal module in order to user the filter | image\_style('app\_list')

Thanks to @kekkis @markconroy
> 0 votes

---
Tags: theming
---


# Question
Title: When I should create a new permission in my custom module?
Once I create a custom module where I'll have some kind of administrative tasks like configurations should I create a new permission or just use any available permission?

This question comes to my mind because when we create a custom module for the community we can imagine how this module will be used, but maybe in some scenarios some admins need to give specific permission to others users to configure the site and in this case if we have specific permission for this tasks made this work is very easy, if not this admins need to create a new custom module to handle this situation.

But in the other hand if we create one permission for each administrative task in our custom module maybe we are overloading the site with permission that are rarely used.

When I should create a new permission in my custom module?

**Note:** *I'm not trying to create primarily opinion-based question here, if some user feel this, please help me to improve the question.*

# Answer
If you are creating a custom module for a client-only (or yourself), then you can do whatever is appropriate for the situation.

When creating a contrib module, you have to consider that you probably don't know all of the potential uses. In general, I would make your own permission; typically as a project reviewer, this is something I point out as part of peer review.

I do not see too-many-permissions as a problem. In fact, I see it as a benefit. When I build sites for clients, I try to build out roles that can stack (users can have multiple roles) and roles have the minimum permissions needed to meet the needs of that role.

One common complaint about Drupal is that it is too complicated. By using roles and permissions, you can limit what users can do, and minimize the complexity to exactly what they need to do (no more, no less). When you gang up tasks into a single permission, you may give the option to people to do things that they may not need or want to do.

Another way to look at this, is that permissions can be used as a security method to limit what uses can do. They can also be used by an organization to limit what users need to do as part of their job function.
> 2 votes

---
Tags: users
---


# Question
Title: Unpublish article based on non date type field
So, I know that you need Rules to unpublish articles (after a certain time) based on date fields (https://groups.drupal.org/node/240678#comment-782543). But is this also possible with non date fields? When the user creates an article there should be a select list with items like `1 month`, `3 months`, `6 months`. After submitting the article is saved as unpublished, it is moderated and published by an admin and should then automatically be unpublished after the period selected by the user.

# Answer
If you don't want to write custom code you can use the https://www.drupal.org/project/scheduler module.

Quoting the description: "This module gives content editors the ability to schedule nodes to be published and unpublished at specified dates and times in the future "
> 1 votes

---
Tags: 8, nodes, rules
---


# Question
Title: Exclude taxonomy term from select list on node add page
I have a view that shows guest user generated articles grouped by taxonomy terms. There is just one taxonomy term which I don't want that users add articles with (only logged in users should). So how can I exclude this taxonomy term from the select list on the node add page? I suppose by some function in the theme file?

# Answer
> 0 votes
You need to implement hook\_form\_alter(&$form, \Drupal\Core\Form\FormStateInterface $form\_state, $form\_id) inside a custom module.

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Form%21form.api.php/function/hook\_form\_alter/8.2.x

Inside the form parameter you should be able to unset the specific option that you don't want to be displayed.

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


title: Composer error with Ctools package

text:
# Question
Title: Composer error with Ctools package
I'm trying to update my site using composer.

I was previously using the Composer Manager module, but I've removed this as it's no longer supported, and composer support is built into core.

I'm now getting an error with the Ctools module (though I suspect the problem lies with composer rather than Ctools):

```
# composer require "drupal/ctools ~3.0"
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - The requested package drupal/ctools ~8.3.0-alpha21 is satisfiable by drupal/ctools[8.3.0-alpha27] but these conflict with your requirements or minimum-stability.

Installation failed, reverting ./composer.json to its original content.

```

Copying my composer.json file below in case it offers any insights:

```
{
    "name": "drupal/drupal",
    "description": "Drupal is an open source content management platform powering millions of websites and applications.",
    "type": "project",
    "license": "GPL-2.0+",
    "require": {
        "composer/installers": "^1.0.21",
        "wikimedia/composer-merge-plugin": "~1.3",
        "drupal/address": "~1.0",
        "symfony/intl": ">=1.0"
    },
    "replace": {
        "drupal/core": "~8.2",
        "drupal/entity": "8.*",
        "drupal/pathauto": "8.*",
        "drupal/simple-conreg": "8.*",
        "drupal/swiftmailer": "8.*"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "preferred-install": "dist",
        "autoloader-suffix": "Drupal8"
    },
    "extra": {
        "_readme": [
            "By default Drupal loads the autoloader from ./vendor/autoload.php.",
            "To change the autoloader you can edit ./autoload.php."
        ],
        "installer-paths": {
            "modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ],
            "libraries/{$name}": [
                "type:drupal-library"
            ],
            "drush/{$name}": [
                "type:drupal-drush"
            ]
        },
        "merge-plugin": {
            "include": [
                "core/composer.json",
                "sites/all/modules/entity/composer.json",
                "sites/all/modules/pathauto/composer.json",
                "sites/pasgonreg.lostcarpark.com/modules/simple_conreg/composer.json",
                "sites/all/modules/swiftmailer/composer.json"
            ],
            "recurse": false,
            "replace": false,
            "merge-extra": false
        }
    },
    "autoload": {
        "psr-4": {
            "Drupal\\Core\\Composer\\": "core/lib/Drupal/Core/Composer",
            "Drupal\\composer_manager\\Composer\\": "/var/www/drupal/sites8/all/modules/composer_manager/src/Composer"
        }
    },
    "scripts": {
        "pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
        "post-autoload-dump": "Drupal\\Core\\Composer\\Composer::ensureHtaccess",
        "post-package-install": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "post-package-update": "Drupal\\Core\\Composer\\Composer::vendorTestCodeCleanup",
        "drupal-rebuild": "Drupal\\composer_manager\\Composer\\Command::rebuild",
        "drupal-update": "Drupal\\composer_manager\\Composer\\Command::update"
    },
    "repositories": {
        "0": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        "drupal": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    }
}

```

I'd really appreciate if anyone can offer any insights.

James

# Answer
> 1 votes
Try taking off the "8". "3.0-beta1" works for me.

They have started changing the format of the versions by removing the "8" for some reason. Not all the projects have changed yet.

---
Tags: 8, chaos-tool-suite, composer
---


# Question
Title: How do I alter the route defined by another module?
In other words, what is the Drupal 8 equivalent of hook\_menu\_alter()?

Drupal 8 still uses `hook_menu()`, but for what I can see, the information returned by the hook is different from what the hook returned in Drupal 7. For example, the definition given in `user_menu()` for user is the following.

```
  $items['user'] = array(
    'title' => 'User account',
    'title callback' => 'user_menu_title',
    'weight' => -10,
    'route_name' => 'user_page',
    'menu_name' => 'account',
  );

```

The route\_name property links to an entry in the user.routing.yml file.

```
user_page:
  pattern: '/user'
  defaults:
    _content: '\Drupal\user\Controller\UserController::userPage'
  requirements:
    _access: 'TRUE'

```

This is different from what done with Symphony, and it confuses me about how a module can alter the route defined from another user.

The only function that is still invoking `hook_menu_alter()` is `menu_router_build()`, but that function still contains code that needs to be updated, since it is still using the now deprecated `drupal_alter()`.

```
  // Alter the menu as defined in modules, keys are like user/%user.
  drupal_alter('menu', $callbacks);
  foreach ($callbacks as $path => $router_item) {
    // If the menu item is a default local task and incorrectly references a
    // route, remove it.
    // @todo This may be removed later depending on the outcome of
    // http://drupal.org/node/1889790
    if (isset($router_item['type']) && $router_item['type'] == MENU_DEFAULT_LOCAL_TASK) {
      unset($callbacks[$path]['route_name']);
    }
    // If the menu item references a route, normalize the route information
    // into the old structure. Note that routes are keyed by name, not path,
    // so the path of the route takes precedence.
    if (isset($router_item['route_name'])) {
      $router_item['page callback'] = 'USES_ROUTE';
      $router_item['access callback'] = TRUE;
      $new_path = _menu_router_translate_route($router_item['route_name']);

      unset($callbacks[$path]);
      $callbacks[$new_path] = $router_item;
    }
  }

```

# Answer
> 15 votes
Allow views to override existing routing items just uses existing functionality.

If you want to change the information attached to a route, not the menu, like the actual used controller, or the requirements (permission/role etc.) you can use an event provided by Drupal:

```
  <?php

  use Drupal\Core\Routing\RouteBuildEvent;
  use Drupal\Core\Routing\RoutingEvents;
  use Symfony\Component\EventDispatcher\EventSubscriberInterface;

  class RouteSubscriber implements EventSubscriberInterface {

   /**
    * {@inheritdoc}
    */
   public static function getSubscribedEvents() {
      $events[RoutingEvents::ALTER] = 'alterRoutes';
     return $events;
   }

  /**
   * Alters existing routes.
   *
   * @param \Drupal\Core\Routing\RouteBuildEvent $event
   *   The route building event.
   */
  protected function alterRoutes(RouteBuildEvent $event) {
    // Fetch the collection which can be altered.
    $collection = $event->getRouteCollection();
    // The event is fired multiple times so ensure that the user_page route
    // is available.
    if ($route = $collection->get('user_page')) {
      // As example add a new requirement.
      $route->setRequirement('_role', 'anonymous');
    }
  }

  }

```

Additionally you have to register a service with the tag 'event\_subscriber' for this class.

# Answer
> 15 votes
Since I asked the question, Drupal 8 core code has been changed. Some of the issues about routes have been fixed.

`hook_menu()` isn't used from Drupal 8 anymore; the routes a module uses are defined in a .routing.yml file (for example user.routing.yml). Alter hooks are still used, but since `hook_menu()` isn't invoked from Drupal core, `hook_menu_alter()` won't be invoked.

The steps necessary to alter a route defined from other modules are the following:

* Define a service tagged as *event\_subscriber* (The tag is the important part, or the service would not work as expected.)

```
services:
  mymodule.route_subscriber:
    class: Drupal\mymodule\Routing\RouteSubscriber
    tags:
      - { name: event_subscriber }

```
* Create a class that extends `RouteSubscriberBase`

```
namespace Drupal\mymodule\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
    // Change the route associated with the user profile page (/user, /user/{uid}).
    if ($route = $collection->get('user.page')) {
      $route->setDefault('_controller', '\Drupal\mymodule\Controller\UserController::userPage');
    }
  }

}

```

For real implementation examples of `alterRoutes()`, see `AdminRouteSubscriber::alterRoutes()` or `RouteSubscriber::alterRoutes()` .

```
protected function alterRoutes(RouteCollection $collection) {
  foreach ($collection->all() as $route) {
    if (strpos($route->getPath(), '/admin') === 0 && !$route->hasOption('_admin_route') && static::isHtmlRoute($route)) {
      $route->setOption('_admin_route', TRUE);
    }
  }
}

```

```
protected function alterRoutes(RouteCollection $collection) {
  $mappers = $this->mapperManager->getMappers($collection);
  foreach ($mappers as $mapper) {
    $collection->add($mapper->getOverviewRouteName(), $mapper->getOverviewRoute());
    $collection->add($mapper->getAddRouteName(), $mapper->getAddRoute());
    $collection->add($mapper->getEditRouteName(), $mapper->getEditRoute());
    $collection->add($mapper->getDeleteRouteName(), $mapper
      ->getDeleteRoute());
  }
}

```

Notice that compared with earlier Drupal 8 releases, some details are changed.

* The route name is changed from *user\_page* to *user.page*
* The requirements for that route changed from `_access: 'TRUE'` to `_user_is_logged_in: 'TRUE'`
* The property to set a route controller changed from *\_content* to *\_controller*

# Answer
> 10 votes
See Altering existing routes and adding new routes based on dynamic ones; it worked nicely for me to remove /search handled by the Search module. In my case, I used the following code.

```
<?php
/**
 * @file
 * Contains \Drupal\ua_sc_module\Routing\SearchAlterRouteSubscriber.
 */

namespace Drupal\ua_sc_module\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class SearchAlterRouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
    // Remove the /search route.
    if ($collection->get('search.view')) {
      $collection->remove('search.view');
    }
  }

}

```

---
Tags: routes, 8
---


title: Content approval by roles

text:
# Question
Title: Content approval by roles
here is my question:

I need to implement a content approval process, my client wants content to go through an approval process before being published.

I need to create 3 administrative roles, like Content Editors, Content Publishers and Super Admins.

Content Editors can edit content, but not publish it. Content Publishers can edit and publish content (which includes approving/rejecting any changes made Content Editors). Super Admins would have access to everything in Drupal 7.

Any help is appreciated.

Thanks.

# Answer
> 4 votes
Workbench is a great way to do this if you are OK with installing another module.

Workbench allows you to add moderation states. By default it gives you 'draft', 'published', and 'needs review'. (Drupal 8 also has "archived"). There is also a set of transitions that go with these states (ie, draft -\> needs review)

For the three roles you described above, I would give the Content Editors the states to move from published -\> new draft, draft -\> needs review, needs review-\> draft. Content Publishers would have access to all transitions, and super admins could override workflow entirely. This would produce the result you are looking for (and is what we commonly use with clients who don't need something more complicated).

D7 workbench can be a little confusing (very powerful means there's lots to configure!), but here's a good quickstart guide:https://www.youtube.com/watch?v=8nqWLrxH\_4M

EDIT: As the OP points out, Drafty is a dependency for Workbench Moderation, which is needed for the above described solution. Drafty is no longer supported under Drupal' security advisory policy.

---
Tags: 7, nodes, workflows, workbench
---


title: How do I change the base URL?

text:
# Question
Title: How do I change the base URL?
In Drupal 7, we can quickly change the base URL of the website.
How can I do this, in Drupal 8?

# Answer
> 18 votes
In Drupal 8 this option has been removed. You don't have to configure `base_url` to run your site. Drupal 8 can detect this without your help. If not, you should first check your webserver configuration.

Instead of `base_url` you should configure `trusted_host_patterns` in settings.php. This is not needed to run the site, but important for security reasons.

More info: Removed base\_url option from settings.php and New setting for trusted hostname configuration

Edit:

There are some special use cases when running drupal from command line or reverse proxy, that used $base\_url in the past. This can no longer be supported in the same way because of symfony. There is a discussion going on how to provide a solution for these cases. This does not mean that you cannot run drupal from the command line or reverse proxy. The standard way is of course possible without problems.

You can follow the development here: https://www.drupal.org/node/2753591

# Answer
> 10 votes
I thought once some kind of tweaks were needed when moving between production (http:// example.com/) and dev (http:// localhost/~aviram/example.com/). But no, D8 is smart enough to fix links automatically.

After moving a complete site (PHP files and DB dump), just go through the D8 database update process (**http://example.com/update.php**) even if there is no update for the database model. This fixes the problem.

I learned this is a Drupal 8 cache-related problem probably because some pre-rendered content is kept in sites/default/files/php/. And the update.php process somehow cleans this cache.

---
Tags: 8, uri
---


# Question
Title: Views Pager Add rel="nofollow to ALL Pager Links
In Drupal 7 I am trying to add rel="nofollow" to ALL of the pager links in views. The closest I have got is to add the nofollow to next links, but I want it to include previous pages as well as "First" and "Last".

*P.S. We specifically want the rel="nofollow" attribute to all pager links, we are not looking for other solutions (noindex, block with robots.txt, or rel=next/prev).*

This is the code I am currently using:

```
function mytheme_pager_next($variables) {
  $text = $variables['text'];
  $element = $variables['element'];
  $interval = $variables['interval'];
  $parameters = $variables['parameters'];
  global $pager_page_array, $pager_total;
  $output = '';
  // If we are anywhere but the last page
  if ($pager_page_array[$element] < ($pager_total[$element] - 1)) {
    $page_new = pager_load_array($pager_page_array[$element] + $interval, $element, $pager_page_array);
    // If the next page is the last page, mark the link as such.
    if ($page_new[$element] == ($pager_total[$element] - 1)) {
      $output = theme('pager_last', array('text' => $text, 'element' => $element, 'parameters' => $parameters,'attributes'=>array('rel'=>'nofollow')));
    }
    // The next page is not the last page.
    else {
      $output = theme('pager_link', array('text' => $text, 'page_new' => $page_new, 'element' => $element, 'parameters' => $parameters,'attributes'=>array('rel'=>'nofollow')));
    }
  }
  return $output;
}

```

# Answer
Not sure of a hook right now for something cleaner. An alternative that will allow you to do what you want,

```
function hook_views_post_render(&$view, &$output, &$cache) {
    dpm($output);
}

```

You can use a regex, something like,

```
(<li.*pager-item.*><a)(.*)

```

That will give you two groups. \- Group one with every list of items and the opening tag of the anchor. \- Group two with the rest of the line

You can use this to iterate over and add in between both groups,

```
rel="nofollow"

```

---

Of course, you post an answer and find some information. You may want to see if you find these hooks useful, https://drupal.stackexchange.com/a/140867
> 0 votes

# Answer
After trying several suggestions here and on Drupal forums I found they were all overly complicated and caused the 'white screen of death. Our final solution was to simply make a minor hack to drupal core includes/pager.inc found here: http://bizuns.com/drupal/rel-nofollow-views-pager-links We backed up the file before making the change and it's working great so far, if we upgrade drupal we'll just have to make a note to modify this later. Thanks again for the feedback. If anyone has a cleaner (and simple) method I would gladly try the snippet if you provide it.
> 0 votes

---
Tags: theming
---


# Question
Title: What will happen if a custom module has the same name as a contrib module?
What are the consequences of two modules sharing the same machine name?

For instance, if I write a custom module named 'views' and do not have the contrib module 'views' enabled, will the update manager attempt to update my custom module according to the contrib project status?

# Answer
> I write a custom module named 'views' and do not have the contrib module 'views' enabled, will the update manager attempt to update my custom module according to the contrib project status?

No it won't. The update manager looks at the packaging information added to the .info file for released modules, as long as your module doesn't have that data in the .info file (no reason why it would), then you won't have any problems.

The other answers are of course correct insofar as you can't have both modules enabled at the same time. You'd never even get to the point of seeing the fatal errors though, Drupal simply wouldn't let you install a module that has the same machine name as another module that's already installed.

You should aim to name your modules differently than the most popular module in existence, though, if only to save the sanity of the poor developer who eventually takes over the project from you.
> 6 votes

# Answer
It will most likely end up in fatal PHP errors. If you implement a hook that the contrib module also implements you will get a

```
: Cannot redeclare hook() (previously declared in contrib_module.module)

```

Also, your Drupal website will only pick up one of the two modules.

So in short: **you have to avoid using the same modules (or theme) names**. It will totally mess up your Drupal installation
> 5 votes

# Answer
The second one will not work. You can't have two modules with the same name enabled at the same time.
> 1 votes

---
Tags: updating
---