# Question
Title: How do I check the content type of a file using hook_file_presave
I wrote a module to strip Exif data from uploaded file.

```
function modulename_file_presave(Drupal\file\FileInterface $file) {
if ($file->getMimeType() == 'image/jpeg') {
  $filepath = \Drupal::service('file_system')->realpath($file->getFileUri());
  $path = $file->getFileUri();
  $img = new Imagick($path);
  $img->stripImage();
  $img->writeImage($filepath);
  $img->clear;
}

```

it works to all files, but I want to restrict this module to work in only specific content type. How can I get the content type in my module? Thank you.

# Answer
The file itself has no reference to the parent node (it can be referenced by multiple entities). But you can get the node type you are adding or the node you are editing when you upload the file from the route:

```
function modulename_file_presave(\Drupal\file\FileInterface $file) {
  if ($file->getMimeType() == 'image/jpeg') {
    switch (\Drupal::routeMatch()->getRouteName()) {
      case 'node.add':
        $content_type = \Drupal::routeMatch()->getRawParameter('node_type');
        break;

      case 'entity.node.edit_form':
        $node = \Drupal::routeMatch()->getParameter('node');
        $content_type = $node->getType();
        break;

      default:
        $content_type = NULL;
    }
  }
}

```
> 1 votes

---
Tags: 8
---


# Question
Title: Field formatter to display base 64 data image
When I use `echo $src` I get the following result:

> data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4xIiB3aWR0aD0iMTQyIiBoZWlnaHQ9IjkzIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNIDIgNzMgYyAtMC4wMiAtMC4xMiAtMSAtNC43NSAtMSAtNyBjIDAgLTIuMjUgMC40MyAtNC43IDEgLTcgYyAxLjc3IC03LjA5IDQuMzggLTEzLjc4IDYgLTIxIGMgMi4xMSAtOS40IDIuODMgLTE5LjA3IDUgLTI4IGMgMC43NSAtMy4wOSAyLjkxIC03LjkxIDQgLTkgYyAwLjQgLTAuNCAyLjYyIDEuMDkgMyAyIGMgMi40NCA1Ljg2IDMuODYgMTUuMjUgNyAyMiBjIDMuMzYgNy4yMiA4Ljc0IDE0Ljg3IDEzIDIxIGwgMyAyIi8+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTSAxNiA0MCBsIDggLTQiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNIDY3IDIgYyAwLjIxIDAuNjMgOC4zOSAyMy41MiAxMiAzNiBjIDUuMyAxOC4zNSAxNCA1NCAxNCA1NCIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Ik0gMTAyIDIxIGMgLTAuMDkgMC40MiAtMy4wNCAxNS44MiAtNSAyNCBjIC0xLjgyIDcuNjEgLTMuODIgMTUuMTggLTYgMjIgYyAtMC4zNSAxLjA4IC0yLjA4IDMgLTIgMyBjIDAuMDkgMCAxLjg4IC0yLjg0IDMgLTMgYyA2LjYxIC0wLjk0IDE3LjU4IC0yLjM2IDI1IC0xIGMgNy43MSAxLjQyIDI0IDEwIDI0IDEwIi8+PC9zdmc+

If I print `$src` inside `<img>` tags, the image is not rendering properly: *data:* is automatically cut off from the URL.

```
<img src="image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4xIiB3aWR0aD0iMTQyIiBoZWlnaHQ9IjkzIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNIDIgNzMgYyAtMC4wMiAtMC4xMiAtMSAtNC43NSAtMSAtNyBjIDAgLTIuMjUgMC40MyAtNC43IDEgLTcgYyAxLjc3IC03LjA5IDQuMzggLTEzLjc4IDYgLTIxIGMgMi4xMSAtOS40IDIuODMgLTE5LjA3IDUgLTI4IGMgMC43NSAtMy4wOSAyLjkxIC03LjkxIDQgLTkgYyAwLjQgLTAuNCAyLjYyIDEuMDkgMyAyIGMgMi40NCA1Ljg2IDMuODYgMTUuMjUgNyAyMiBjIDMuMzYgNy4yMiA4Ljc0IDE0Ljg3IDEzIDIxIGwgMyAyIi8+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTSAxNiA0MCBsIDggLTQiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNIDY3IDIgYyAwLjIxIDAuNjMgOC4zOSAyMy41MiAxMiAzNiBjIDUuMyAxOC4zNSAxNCA1NCAxNCA1NCIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Ik0gMTAyIDIxIGMgLTAuMDkgMC40MiAtMy4wNCAxNS44MiAtNSAyNCBjIC0xLjgyIDcuNjEgLTMuODIgMTUuMTggLTYgMjIgYyAtMC4zNSAxLjA4IC0yLjA4IDMgLTIgMyBjIDAuMDkgMCAxLjg4IC0yLjg0IDMgLTMgYyA2LjYxIC0wLjk0IDE3LjU4IC0yLjM2IDI1IC0xIGMgNy43MSAxLjQyIDI0IDEwIDI0IDEwIi8+PC9zdmc+">

```

This is the field formatter I am using.

```
class ImageDefaultFormatter extends FormatterBase {
  /**
   * {@inheritdoc}
   */
  public function viewElements(Drupal\Core\Field\FieldItemListInterface $items, $langcode) {
    $elements = array();
    foreach ($items as $delta => $item) {
      if (isset($item->value)) {
        $src = $item->value;
        $elements[$delta] = array('#markup' => '<img src="'.$src.'">');
      }
    }
    return $elements;
  }
}

```

# Answer
> 3 votes
Try this:

```
use Drupal\Component\Render\FormattableMarkup;

$src = $item->value;
$image = new FormattableMarkup('<img src=":src"/>', [':src' => $src]);
$elements[$delta] = [
  '#markup' => $image,
];

```

# Answer
> 2 votes
```
$form['base64_image'] = [
  '#type' => 'inline_template',
  '#template' => "<img width='100px' height='100px' src='{{ data }}' />",
  '#context' => [
    'data' => $base64_image_data,
  ],
];

```

---
Tags: 8, entities
---


# Question
Title: How do I apply a class to a form label via theme?
I have created a form with a label and input fields. I have an abc.theme file.

I tried using the following code.

```
function abc_preprocess_label(&$variables) {
   $element = $variables['element'];
   $variables['attributes']['class'][] = 'test';
}

```

How do I apply a class to the form label?

But seems not working

# Answer
The hook to preprocess is form\_element\_label. This is a working version:

```
function abc_preprocess_form_element_label(&$variables) {
  $attributes = $variables['attributes'];
  $attributes->addClass('class_name');
}

```
> 0 votes

---
Tags: 8, forms
---


title: Writing PHPUnit tests for view plugins

text:
# Question
Title: Writing PHPUnit tests for view plugins
I am trying to test custom views field & filter plugins using PHPUnit, but I keep getting dependency issues. I am curious to know if:

1. It possible to Unit test View plugins?
2. Simulate DB interactions.
3. Is it possible to inject services e.g database, request, response etc via a constructor, setter or property injection?

Thanks in advance.

# Answer
Views plugins are testable, and Drupal core has a lot of examples. I believe most aren't UnitTestCase (or \PHPUnit\_Framework\_TestCase), but rather KernelTestBase tests.

KTB tests will boot a minimal Drupal setup so you don't have to set up extensive mocking for dependencies, especially config and database.

Views in particular has ViewsKernelTestBase, which does basic setup for testing Views plugins. You can use your IDE to find usages of this for example, but I know some are in web/core/modules/datetime/tests/src/Kernel/Views/

Essentially, you make a test module that has YAML for your test views. The test declares this in its `$modules` list, along with the module that is providing the plugin. You also define the test views, and these get imported. You can then use the Views API in your test methods.

Then, as long as you use the new ViewsKernelTestBase, you can run it directly through PhpUnit, assuming you have your phpunit.xml setup properly.
> 4 votes

---
Tags: views, 8, testing
---


# Question
Title: Can a domain redirect work for both http and https?
Currently hosting a site on Pantheon and I would like to redirect traffic to a single domain. There is already a lot of links inside my site that are using:

http://example.com/somepage, http://www.example.com/somepage, https://example.com/somepage, https://www.example.com/somepage

Since Pantheon uses nginx I would have to use settings.php to redirect traffic. My Question is would it be possible to direct traffic to a single domain but it can be served in either http or https?

Some sample code:

```
// Require www.
if (isset($_SERVER['PANTHEON_ENVIRONMENT']) &&
  ($_SERVER['PANTHEON_ENVIRONMENT'] === 'live') &&
  (php_sapi_name() != "cli")) {
  if ($_SERVER['HTTP_HOST'] == 'example.com' ||
      $_SERVER['HTTP_HOST'] == 'https://example.com') {
    header('HTTP/1.0 301 Moved Permanently');
    //or https://www.example.com
    header('Location: http://www.example.com'. $_SERVER['REQUEST_URI']);
    exit();
  }
}

```

# Answer
> 0 votes
* Nginx/settings.php

Try this: `$base_url = 'https://'.$_SERVER['SERVER_NAME'];`

* Apache/.htaccess:

You can simply add the following to your `.htaccess`. It will redirect all traffic from http://example.com and http://www.example.com to https://example.com. Put that below `RewriteEngine on`.

```
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www.example\.com*
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]

```

# Answer
> 0 votes
If Drupal 7 Add the following to the end of your settings.php file (replace www.example.com):

```
if (isset($_SERVER['PANTHEON_ENVIRONMENT']) && php_sapi_name() != 'cli') {
  // Redirect to https://$primary_domain in the Live environment
  if ($_ENV['PANTHEON_ENVIRONMENT'] === 'live') {
    /** Replace www.example.com with your registered domain name */
    $primary_domain = 'www.example.com';
  }
  else {
    // Redirect to HTTPS on every Pantheon environment.
    $primary_domain = $_SERVER['HTTP_HOST'];
  }

  if ($_SERVER['HTTP_HOST'] != $primary_domain
      || !isset($_SERVER['HTTP_X_SSL'])
      || $_SERVER['HTTP_X_SSL'] != 'ON' ) {

    # Name transaction "redirect" in New Relic for improved reporting (optional)
    if (extension_loaded('newrelic')) {
      newrelic_name_transaction("redirect");
    }

    header('HTTP/1.0 301 Moved Permanently');
    header('Location: https://'. $primary_domain . $_SERVER['REQUEST_URI']);
    exit();
  }
}

```

**If Drupal 8 Add the following to the end of your settings.php file (replace www.example.com):**

```
if (isset($_SERVER['PANTHEON_ENVIRONMENT']) && php_sapi_name() != 'cli') {
  // Redirect to https://$primary_domain in the Live environment
  if ($_ENV['PANTHEON_ENVIRONMENT'] === 'live') {
    /** Replace www.example.com with your registered domain name */
    $primary_domain = 'www.example.com';
  }
  else {
    // Redirect to HTTPS on every Pantheon environment.
    $primary_domain = $_SERVER['HTTP_HOST'];
  }

  if ($_SERVER['HTTP_HOST'] != $primary_domain
      || !isset($_SERVER['HTTP_X_SSL'])
      || $_SERVER['HTTP_X_SSL'] != 'ON' ) {

    # Name transaction "redirect" in New Relic for improved reporting (optional)
    if (extension_loaded('newrelic')) {
      newrelic_name_transaction("redirect");
    }

    header('HTTP/1.0 301 Moved Permanently');
    header('Location: https://'. $primary_domain . $_SERVER['REQUEST_URI']);
    exit();
  }
  // Drupal 8 Trusted Host Settings
  if (is_array($settings)) {
    $settings['trusted_host_patterns'] = array('^'. preg_quote($primary_domain) .'$');
  }
}

```

Here's \[a link\] \[https://pantheon.io/docs/guides/launch/redirects/\] Redirect for SEO and Security Contribute

Make sure your DNS is setup & And you see the new domain/ https all in one turned on from Pantheon https://pantheon.io/docs/domains/#redirect-to-https-and-the-primary-domain (You need to see this for the Fastly CDN to use HTTPS

---
Tags: 7, configuration
---


title: Core update error

text:
# Question
Title: Core update error
I'm trying to run a composer update from my webroot directory. When I use `composer update drupal/core --with-dependencies`, it returns:

```
Package "drupal/core" listed for update is not installed. Ignoring.
Loading composer repositories with package information
Updating dependencies (including require-dev)

```

I wasn't sure if I needed to require the drupal/core package with composer? I tried that, but it had no effect. Following the advice of online forums, I adjusted the following settings in the composer.json file:

```
"require": {
    "composer/installers": "^1.0.24",
    "wikimedia/composer-merge-plugin": "~1.4",
    "drupal/drush": "^6.0@RC",
    "drush/drush": "~9.0"
},
"replace": {
    "drupal/core": "~8.4"
},
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
    "preferred-install": "dist",
    "autoloader-suffix": "Drupal8"
},

```

I changed the drush version to **~9.0** and the core version to **~8.4**. I then deleted the /vendor directory and the composer.lock file. After running the update again, it updated a few other packages, but ignored core. I feel like I'm missing something simple. Any help is appreciated!

# Answer
> 5 votes
If you downloaded Drupal from drupal.org (e.g. via the tarball download link, or with `drush dl`), then you cannot use Composer to update Drupal core. The steps you are attempting above only work for sites based on the template project https://github.com/drupal-composer/drupal-project. This is the recommended method to use when managing Drupal 8 sites with Composer.

---
Tags: 8, drush, updating, composer
---


# Question
Title: Crumbs not adding home link to beginning
I have installed Crumbs on the site I am currently working on and for some reason I can't get it to display the "Home" link.

I have tried debugging some of the nodes and according to the results the home link should be displayed.

The home link is definitely enabled and there isn't any CSS or anything like that which may be interfering with it, am I missing something?

# Answer
> 1 votes
How to find out why not seeing the home link in bredcrums Drupal 8.

1. Check your theme (admin/appearance/settings/THEMENAME)

Some themes like bootstrap can set to show or not.
2. Check modules for any 'hook\_system\_breadcrumb\_alter'

These can alter how bredcrums work.
3. Check modules for any services tagged with - "{ name: breadcrumb\_builder" (same as above)
4. Check theme templates for any templates overriding core bredcrums or .theme overrides
5. Check if the block is enabled (admin/structure/block)
6. Cry

# Answer
> -1 votes
Not sure what the cause of the problem was, but this was solved by using jQuery to prepend a "Home" link to the start of the breadcrumbs list.

---
Tags: breadcrumbs
---


# Question
Title: How to rebuild images using Imagemagick?
I have switched the Image toolkit from GD2 to Imagemagick. It’s working great for new images, however previously uploaded images still show up with lowres quality.

How can I regenerate ALL images using Imagemagick?

I've followed up: Rebuild images from image style

* drush: drush image-flush mystyle
* rm -rf sites/default/files/styles
* Clearing Caches a couple of times and hit save on all image styles.

However all images still show up with lowres quality. When I manually update a node, the image quality looks correct. Also, the file size changes. Looks like imagemagick isn’t triggered. What can I do?

# Answer
This issue sometimes occurs when the original files are too large, causing memory exhaustion on the server during thumbnail creation. Since the thumbnail creation on an image style cache flush is generated in a serial queue, just one high res image can prevent all the other image style thumbnails from being generated.

Steps to check and attempt to resolve this include:

1. After immediately trying to reset/flush the image style cache, check your apache and php logs on the server itself (as the memory exhaustion errors don't typically appear in the Drupal watchdog logs).
2. If you in fact encounter the memory exhaustion error, try increasing the server's memory limit. See https://stackoverflow.com/questions/3534274/php-memory-exhausted
3. If after bumping the memory limit you continue to encounter this error, spot check some of the original images- determine the actual pixel dimensions of each image as well as the pixel density and/or dpi. If either is significantly large, you may want to download the original images, batch process/resave at a more reasonable size, and upload back to the server; then trigger the image style flush/thumbnail regeneration again.
4. If #3 resolves the issue, you may want to apply max width/height to the image upload field config itself to prevent content managers from uploading enormous images in the future too. ***Note****: Depending on your settings, this approach may result in saving a downsized version of the original image, if the original image exceeds maximum dimensions; or result in a warning to the content manager prompting them to upload a smaller image.*
5. In conjunction with the max width & height options, you may also want to change the jpeg quality of the images generated for the image styles. While signed in as an admin, go to Configuration \> Media \> Image Toolkit (/admin/config/media/image-toolkit)
> 0 votes

---
Tags: 7, media
---


# Question
Title: How to change the default variant globally?
Is there a way to change the default variation (e.g. size, color) for thousands of Drupal Commerce products on a site? I found the Commerce Default Product Variant module that does it on a per-product basis, but I need to do it globally.

I am open to doing it directly in MySQL if it won't break anything, but I am not sure how to do so at the moment.

# Answer
Typically speaking, the default product variation is the first value in the reference field. You can see this in action on a vanilla install by creating a product display that references multiple products and switching the order of the SKUs in the product reference field (easiest if you're using the autocomplete widget). I doubt there's a way to change the order of your field values en masse, and I'm not sure there's a safe SQL query we can pass on to you.

However, if you're similarly open to writing custom module code to solve this, you can do so using hook\_commerce\_product\_reference\_default\_delta\_alter(&$delta, $products). The products variable will be an array of the fully loaded products on the display and the delta value will be initialized to the first one and available for alteration. You can inspect the field values of the products in the array to find the one whose attributes match what you want the default variation to be and update the delta accordingly.

(If you just wanted to write a script to actually update the storage instead of doing this on run-time, you'd want to process your product displays one at a time and do a similar product load / field value inspection to move the items around in the reference field's values so delta 0 was your desired default variation.)
> 1 votes

---
Tags: 7, commerce
---


# Question
Title: How do I use message stack (or other) to send new blog post (nodes) to "email-only subscribers" like Wordpress?
How can we set up Drupal 7 to let someone simply put in their email and then receive an email notification every time a blog (node) is created?

In my ecosystem I already have rules, views, CiviCRM, and the message-stack/flag, but do not see a clear and easy way to do this without forcing the user to register an account, flag the content, and receive a rules-based email that way.

To summmarize: We want an anonymous user to put in only their email, and then receive an email every time a blog node is posted, automatically.

I am using Drupal 7.

# Answer
There are three modules that support this type of subscription and notification workflow without requiring subscribers to actually be registered users on the Drupal site:

1. Simple Subscription https://www.drupal.org/project/simple\_subscription
2. Total Subscription https://www.drupal.org/project/total\_subscription
3. Simple News https://www.drupal.org/project/simplenews

Below are some notes and caveats to each module/approach:

* ***Simple Subscription***: the 7.x-1.x branch provides the basics, but hasn't seen much maintenance/activity since the move toward the 7.x-2.x alpha in 2016. The alpha has some nice features and intent, but is also just an alpha release. This module has token support and can work nicely with out of the box rules based messaging.
* ***Total Subscription***: This module does not offer to site managers any administrative functionality to unsubscribe email addresses or toggle on/off notifications for testing purposes. You'd have to enable/disable the module to toggle notifications (all or nothing) for any content types or taxonomies setup to publish subscription notifications. Custom html email templates can be generated with the HTML Mail module, but templating only supports the default body/summary field and not any custom fields applied to the content type. Messages are queued and sent via Drupalcron.
* ***SimpleNews***: This module is probably the most stable of the options and offers a D8 version; but it requires the extra step for content managers having to switch to the Newsletter tab and manually send the notifications after node creation.
> 1 votes

---
Tags: notifications
---


# Question
Title: Drupal configuration on non root url (how to change $base_url)?
sorry for my english, I'm french

ok, that's I want to do is to install my drupal site on a url like : www.mymachine.fr/mydrupal/

and the problem is that when I go this url, he dispatch me to www.mymachine.fr/core/install.php instead of www.mymachine.fr/mydrupal/core/install.php

so the install doesn't work

My conf is like this : debian server

in drupal file "sites.php", I have this :

$sites\['mymachine.fr.mydrupal'\] = 'mydrupal';

on /etc/hosts, I add this line : 127.0.0.1 mymachine.fr.mydrupal

on /etc/apache2/sites-available/000-default.conf :

```
<VirtualHost *:80>
    ServerName mymachine.fr.mydrupal
    DocumentRoot /var/www/mydrupal/CORE-DRUPAL8-WEB/web

    ServerAdmin webmaster@localhost

    # Log configuration
    ErrorLog ${APACHE_LOG_DIR}/drupal-error.log
    CustomLog ${APACHE_LOG_DIR}/drupal-access.log combined

    <Directory "/var/www/mydrupal/CORE-DRUPAL8-WEB/web">
            Options FollowSymLinks
            AllowOverride All
            Require all granted
    </Directory>

</VirtualHost>

```

SO I don't know if it's drupal configuration or apache configuration to change $base\_url from drupal site ... thanks a lot

# Answer
If your drupal installation resides on the webserver in a subfolder of the webroot for *www.mymachine.fr*, you can set the base path in the drupal site's .htaccess file.

* Find the line that reads `# RewriteBase /drupal`
* Uncomment it by deleting the "#" `RewriteBase /drupal`
* Edit it to reflect your subpath/subfolder `# RewriteBase /mydrupal`

That block should look like this after the edits.

```
# Modify the RewriteBase if you are using Drupal in a subdirectory or in a
# VirtualDocumentRoot and the rewrite rules are not working properly.
# For example if your site is at http://example.com/drupal uncomment and
# modify the following line:
RewriteBase /mydrupal

```

Then, reset your .conf (vhost entry) to reflect just the top level website (code sample below resets to default .conf setup):

```
<VirtualHost *:80>
  ServerName mymachine.fr.mydrupal
  DocumentRoot /var/www

  ServerAdmin webmaster@localhost

  # Log configuration
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  <Directory "/var/www">
      Options FollowSymLinks
      AllowOverride All
      Require all granted
  </Directory>
</VirtualHost>

```

This setup presumes that your top level domain does not have any redirection rules that forward/process all requests (such as the rules in an out-of-the-box Drupal or Wordpress .htaccess for processing requests with index.php) If your top level domain has such a redirect rule in place, you may need to add another rule to exclude your mydrupal subdirectory.
> 1 votes

---
Tags: uri
---


# Question
Title: How can I aggregate information from about 30 Drupal sites in one place?
I have about 30 websites on Drupal. I'm looking for module or service where i can aggregate information from all websites in one place. I need information about number of nodes, comments, users, Drupal core and modules versions. Something like acquia insight but for more sites and cheaper :)

# Answer
The Similar Module Review's Administration module wiki lists several options.

The following show some usage statistics, as well as Drupal core and module updates:
> 4 votes

# Answer
Take a look at Droptor. And the corresponding Droptor module.

30 websites looks like $696/year (the first one is free)
> 2 votes

# Answer
I have good experience with the Production monitor project.

The prod\_check server module is enabled in the master site, while the prod\_check client module is enabled in all sites. You may tracks modules, alerts, and even performance to verify that the tracked sites are in a good working state.

It's not as extensive as acquia insight, but the module has an API which allows you to extend it to provide more metrics.
> 2 votes

# Answer
Consider looking at the Forena module (disclosure: I'm a co-maintainer of it). It can be used to query the data in other databases. Various DBMS formats are supported, such as another Drupal database also (which your question appears to be about).

Here is how to get you going:

* Install/enable the Forena module.
* Define a Data Source (= database connection) for each of your 30 Drupal sites, probably using a name that reflects each of those sites.
* Use "FrxDrupal" as the "Driver" for the Data Source, to indicate it is a Drupal database.
* Start from the delivered reports in category "Drupal Administration" to clone/enhance them to fit your needs (e.g. the one titled "Enabled Modules and Themes"). And make them use any of the 30 Data Sources (instead of the Drupal Database of the site where you installed Forena).

### More info about Forena

Forena is built of the idea of using SQL to get data out of a database and use XHTML and CSS to format it into web reports. For more details about Forena, 2 types of documentation are available:

* Community documentation.
* Documentation that comes with Forena, which you can access right after install and enable of the module. Checkout the demo site for an online example of the current:

+ **Forena documentation** \- use the link 'Reporting documentation' or visit relative link `/reports/help`.
    + **Forena samples** \- use the link 'Reporting samples' or visit relative link `/reports/samples` (these samples are fully functional, so make sure to experiment a bit with it, such as the drill downs available on the SVG Graph sample).
> 0 votes

---
Tags: nodes
---


# Question
Title: Deduping Views by forcing Views to add a simple GROUP BY to a query
In D8, I need a way to "dedupe" a view with a relationship. This involves a "Course" content type, and a "Sessions" entity (actually, a Commerce Product) that points back to the Course.

I've tried to create views that are based off the content type and related to the Session entity, and visa versa. In both cases, what I really want to do is to get a list of courses searched by both the attributes of the Course (let's say, type of course) and of the session (location).

Since Course :: Session is 1 :: N, we're getting N rows for each Course. This is not what we want. Using the Advanced settings has proved useless so far. Query Setting "Distinct" does not dudupe. The Field Format Setting "Grouping field" does not appear to trigger a GROUP BY in the query. And using Aggregation creates a monster GROUP BY that appears to pull in just about all the fields in the tables, with no way to remove the useless fields from the GROUP BY.

Here's what I'd like to do: use a simple GROUP BY (say, the title of the Course), and compare the entity ID of the sessions with the minimum entity\_id of that group of sessions; if it's not equal, I want to exclude the row either in the WHERE clause or in a HAVING clause if it will work. I'm trying to modify the query via the views hook

```
function my_module_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  if ($view->id() == 'course_listing') {
    $title_alias = 'alias_to_content_table.title';
    $query->addGroupBy($title_alias);
  }
}

```

The problem here is that while the code is definitely called, the call to addGroupBy() is ignored when the query is actually rendered out. Views thinks I didn't mean it :-)

What exactly do I need to clobber Views with to get it to add a GROUP BY statement? If I can get it to do that, I can insert a MIN field into the SELECT statement (see http://tech-tamer.com/drupal-7-using-sql-expressions-in-views-3/ for someone's clever idea of how to do that in D7; it appears to work fine in D8, but will generate a bad query w/o the correct GROUP BY).

# Answer
> 1 votes
It turns out that the solution is similar to what I tried: you do need to use hook\_views\_query\_alter. But playing with GROUP BY is useless unless you can guarantee that you will not be using ORDER BY at all (i.e., you will do no sorting beyond your GROUP BY key). GROUP BY will contain not only the variable you want to group by; it will also contain *every* variable you use in ORDER BY. This appears to be required by the current SQL standard.

The way to do this is this is build your view around the "parent" type ("Course" in my example), and do any filtering you need to do in hook\_views\_query\_alter, using a correlated subquery. This will look something like this:

```
function my_module_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {

  if ($view->id() == 'course_listing') {
    $where_clause = <<<WHERE
    (
      SELECT COUNT(*)
      FROM {node__field_session_course} link_to_course
      WHERE node_field_data.nid = link_to_course.entity_id
    ) > 0
WHERE;

    $query->addWhereExpression(0, $where_clause);
  }
}

```

where `node_field_data` is the base table for Course.

Since there is no left joins or inner joins with the Session table, there are no duplicates, making the deduping problem go away.

# Answer
> 1 votes
This feature is working out of the box, but documentation is not very good. AddField method has third variable, called $params https://api.drupal.org/api/drupal/core%21modules%21views%21src%21Plugin%21views%21query%21Sql.php/function/Sql%3A%3AaddField/8.2.x

```
$query->addField(NULL, 'SUM(' . implode('+', $match_statement) . ')', 'mtch', ['function' => 'groupby']);
$query->addGroupBy('nid');

```

Similar code is fixing this issue.

---
Tags: views, commerce, 8
---


# Question
Title: How to create a link in my view of users to perform an operation like Active or Block?
I am using Views to create a view for user management, which looks like in the image below:

How to create an "`Active`" or "`Block`" link in my view which performs an operation for the selected user like so:

1. When I click on "`Active`" in the Operations column, then the user should be active.
2. When I click on "`Block`" in the Operations column, then the user should be blocked.

**Note**: Views Bulk Operations (VBO) is not working. Refer to the image below. When l select all users in my view results and select "Block current user" as theoperation, then the users are not blocked. I have unstalled the VBO module and re-installed it again. And I also gave permission "user block" to that role. But nothing solved my issue.

# Answer
> 0 votes
Have a look at the Rules Link module. Some details from its project page:

> This module lets you create links which trigger arbitrary functionality with the help of Rules.
>
> Features:
>
> * Attach the link to any entities.
> * Show the link only for certain bundles.
> * Narrow the entities on which the link will be shown using the visibility conditions.
> * The links are usually displayed using Views.
> * For entities that can be displayed, the links can be shown on node view.
> * Supports an arbitrary number of additional Rules parameters for passing context via Views.
> * 3 types of links: Javascript, Normal and Confirmation form links.
> * Use individual permissions for each link.

Some more details (from its README.txt):

> To create a new link go to admin/config/workflow/rules\_links and click on "Add rules link". Enter the title of your link and set all the settings. After clicking on the "Save Rules Link" button, the module will generate a new And- and Rules-Set and their forms will be embedded into the rules link editing form.
>
> The And-Sets are called Visibility Conditions and will define when to render the links. The Rules set is the rule, that will be triggered on clicking the rule. Additionally Rules Links also generates access permission for each link, which you'll have to set in admin/people/permissions.
>
> The best way to display the links is currently using views. Rules Links link will create a Views field for each link, using the title of the link as title for the field. So if you have link for nodes with the delete 'Delete node', you'll find the Views field under name 'Content: Delete node'.
>
> Alternatively you can use render the links directly in the entities that can be displayed, using the option 'Show link in entity' in the Rules Links settings.
>
> Note that this will not work for links were the parameters have multiple paramaters.
>
> If you would like to render a link yourself in a theme or in a module, than use the function `rules_link_render_link()`.

Note the "***The best way to display the links is currently using views***" in the above quoted text, which is pretty close to what you're asking for.

PS: I'm assuming this question is about D7.

---
Tags: views, users
---


# Question
Title: How to create a commenting system for ECK entities, similar to node comments as exposed field under the body?
I have done quite some research to accomplish comments under ECK entities, but all the tried solutions and modules appeared to hamper or be incompatible.

The idea is to create an exposed field for directly entering comments. It should allow for multi-level commenting (replies to comments).

I will update this question with the tried solutions. If you have actually tried or implemented a commenting solution for ECK entities yourself, please post your answer.

If you have suggestions but have not tested it yourself, please post it as a comment to this question, and I will try your suggestion.

---

Option: module Comments Entity. I can't get beyond a bug I posted in the issue about "Cannot save comments".

---

# Answer
As an alternative to the Comments Entity module, and the bug you reported about it, you may want to give the Reply module a try. Some more details about this module, from its project page:

> Reply is a D7 answer to entity comments.
>
> Reply is basically a fieldable entity so you can create a 'review', 'comment', 'forum post' or whatever you like by creating bundles and attaching fields to them. Such bundles can be attached to any fieldable entity by 'reply field'.
>
> You can set access for reading and writing, position the form to the same page as entity or to a custom page, allow or deny replying to replies(= no hierarchy), choose threaded or flatted list. Such settings can be set for bundle, field, instance and entity with build-in inheritance which makes if a four level hierarchy settings system.
>
> Most common usage of this module is comment replacement and reviews.

Even though this module only has an *alfa* release for D7 (as compared to a *beta* release for the Comments Entity module), the issue queue statistics seem to be more healthy:

* **Reply**: 66 open, 166 total (about 40% open issues).
* **Comments Entity**: 10 open, 10 total (= 100% open issues).
> 1 votes

---
Tags: 7, comments, entities
---


title: Combine multiple sources into a field

text:
# Question
Title: Combine multiple sources into a field
I have multiple sources which roughly looks like:

* **Wines** \- Contents: `"1,2,3,4"`
* **Sodas** \- Contents: `"1,2,3,4,5"`

I'd like to combine those into one taxonomy vocabulary, get them to be auto-created and referenced in the destination field. So I'd like to do something like the following. But, if I read the `static_map` documentation correctly, mapping multiple sources like this is not the way it works. Also, I'm not yet exploding the string in the example, which I think is mandatory to be able to map the values.

```
  field_drinks:
    -
      plugin: static_map
      source:
        - wines
        - sodas
      map:
        wines:
          '1': 'Sauvignon Blanc'
          '2': 'Chiraz'
          '3': 'Pinot Noir'
          '4': 'Malbec'
        sodas:
          '1': 'Coca-Cola'
          '2': 'Spa'
          '3': 'Sprite'
          '4': 'Tonic'
          '5': 'Bitter lemon'
    -
      plugin: skip_on_empty
      method: process
    -
      plugin: entity_generate
      entity_type: taxonomy_term
      bundle_key: vid
      bundle: drinks
      value_key: name

```

How do I convert this to suit my needs?

# Answer
> 10 votes
Found it out after a lot of trial and error. Basically it comes down to breaking everything up into individual "pseudo fields" and prepare the data before processing it into the actual field:

```
process:
  # First convert legacy wine id's to regular string names in a pseudo field
  _prepare_wines:
    -
      plugin: explode
      limit: 100
      delimiter: ","
      source: wines
    -
      plugin: static_map
      map:
        '1': 'Sauvignon Blanc'
        '2': 'Chiraz'
        '3': 'Pinot Noir'
        '4': 'Malbec'

  # Secondly convert legacy soda id's to regular string names in a pseudo field
  _prepare_sodas:
    -
      plugin: explode
      limit: 100
      delimiter: ","
      source: sodas
    -
      plugin: static_map
      map:
        '1': 'Coca-Cola'
        '2': 'Spa'
        '3': 'Sprite'
        '4': 'Tonic'
        '5': 'Bitter lemon'

  # Third, get all the pseudo field output together in a new pseudo field and flatten them into a single array
  _prepare_field_drinks:
    -
      plugin: get
      source:
        - '@_prepare_wines'
        - '@_prepare_sodas'
    -
      plugin: flatten

  # Lastly, the data is now all in a nice single level array with only names for the new taxonomy terms so we can use those as source.
  field_drinks:
    -
      plugin: entity_generate
      entity_type: taxonomy_term
      bundle_key: vid
      bundle: drinks
      value_key: name
      source: '@_prepare_field_drinks'

```

*Disclaimer*: I'm not sure if this is the way it should be handled, but it seemed to do the trick without any custom plugins. Also, please be aware that if any of the source fields can be empty, you should prepend a `skip_on_empty` plugin to make sure your rows will not be ignored.

# Answer
> 4 votes
Thank you Ambidex! You gave me the key I needed.

I had a similar problem: I needed to take a collection of independent Boolean variables from an external json feed and direct each into a single, existing, multi-valued taxonomy in Drupal 8. It seemed like a straightforward enough task that I decided to try using just the pre-existing process plugins.

This became more difficult as I discovered that the Boolean values could not be passed directly to a static\_map with any ease (see: https://www.drupal.org/docs/8/api/migrate-api/migrate-process-plugins/process-plugin-static-map). In the end, I had to explicitly convert the booleans to strings, pass these to the static\_map (one per taxonomy term), and then collect these all together, flattened, to hand off to the internal taxonomy. I was only interested in mapping those marked 'true' - so if false, we needed to skip setting anything. The end result was to be a series of checkboxes within a single vocabulary, checked if the incoming booleans were true.

Here's an example for anyone needing to do something similar:

```
_prepare_firstBooleanField:
  -
    plugin: callback
    callable: strtolower # a convenient method to do the conversion to string
    source: firstBooleanField
  -
    plugin: static_map
    bypass: true # skip mapping if the boolean value is false
    map:
     '1': 23 # to the left is the result of
             # converting the boolean to string;
             # to the right is the taxonomy term id (tid)
             # to which we're mapping. Note that we do no mapping
             # at all for false - we just want to skip in that case.

_prepare_secondBooleanField:  # map as many of these as needed
  -
    plugin: callback
    callable: strtolower
    source: secondBooleanField
  -
    plugin: static_map
    bypass: true
    map:
      '1': 18 # etc - keep mapping tids (note: could also
              # map names, but this would require doing an
              # entity_lookup later; if you know the term ids
              # (and we do, because we're mapping to an existing
              # taxonomy) just use them directly. (It also allows
              # the names to change without breaking the import
              # for ongoing data feeds.)

# Now: flatten all the values that we've found together into
# one simple array (thanks to the clue from Ambidex above)
_prepare_someTaxonomyField:
  -
    plugin: get
    source:
      - '@_prepare_firstBooleanField'
      - '@_prepare_secondBooleanField' # etc - can keep adding fields
  -
    plugin: flatten

# Finally, hand the array to the taxonomy field!
# By using the tids above, we can do a direct assignment:
field_some_taxonomy: '@_prepare_someTaxonomyField'

```

---
Tags: 8, migrations
---


# Question
Title: How can I switch language links to master links on a translated page?
On my website currently only one content type gets translated and is therefore available in multiple languages. On this content type/page all the links (logo, menu, footer, etc.) refer to their language version of the current language.

E.g.: I'm currently on the french version of the page. The URL looks like this: "**/fr**/translated-node.html". Now all the links in the menu or footer look like this: "**/fr**/some-page.html".

But it shouldn't be like this. All the links on this page should always look like this: "/some-page.html". So without the language code at the beginning.

How can I achieve that programmatically?

# Answer
> 1 votes
Go to admin/config/regional/language/detection/url and then you must delete the path prefix for the language, you don't need code to do this.

And save the config.

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


# Question
Title: How to properly delete a field collection?
Drupal version: 7.21
Field collection module version: 7.x-1.0-beta5

**Short explanation**: I'm busy trying to import field collections programmatically but when deleting some of them there's always some 'bogus' field collection left.

**Long explanation**: My users have a field collection field on their profile. This field collection contains 3 text fields. I want to import data from a custom sql database into the field collection of the user. This field collection can have multiple values. When I import the data for the first time everything works fine, I see the data in the fields of the field collection. Great.

But here comes the tricky part. Let's say I import for one specific user 5 rows from the custom database. They get added to the field collection, so this field collection has 5 items each containing 3 fields. Then I delete some rows from my custom database so that I have only 3 rows left for this user. I run the import again, updating the first 3 items of the field collection, but then I'm left with 2 items from the previous import. They should be deleted because I have only 3 imported rows but still 5 field collection items.

So I tried to delete these field collection items, but there's always one or more items left. The fields are empty when I look at the user profile but there's still something there. Let's say at this point I add 5 new rows for the user in my custom database, so I have 8 rows in total for this user. Then I run the import again. The first 3 items get updated, but then when I try to add the 4th row it still gets an entity id from the 4th field collection item, tries to update it but fails and returns this error:

```
 Fatal error: Call to undefined method stdClass::save()

```

I tried deleting the field collection items with each of these methods below:

```
// Method 1
entity_delete_multiple('field_collection_item', array($fc_id));

// Method 2
$field_collection_item = field_collection_item_load($fc_id);
$field_collection_item->delete();

// Method 3
$field_collection_item = field_collection_item_load($fc_id);
$field_collection_item->deleteRevision();

```

This is my full code:

```
function import_user_field_collection(&$user, $old_user_id) {

  // I do a query to get the rows I want to import for this specific user.
  db_set_active('custom_sql_database');
  $result = db_query("SELECT * FROM {users} WHERE user_id = :user_id", array(':user_id' => $old_user_id));

  db_set_active('default');
  $i = 0; // Keep count of how many rows I imported.
  foreach($result as $row) {
    // Check if the field collection item already exists.
    if(!empty($user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'])) {
      // If it does exists, update this particular field collection item.
      $fc_id = $user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'];
      $field_collection_item = entity_load('field_collection_item', array($fc_id));
      // These 3 text fields are children of the field collection field.
      $field_collection_item[$fc_id]->field_profile_diploma_instituut[LANGUAGE_NONE][0]['value'] = $row->instituut;
      $field_collection_item[$fc_id]->field_profile_diploma_vakgebied[LANGUAGE_NONE][0]['value'] = $row->vakgebied;
      $field_collection_item[$fc_id]->field_profile_diploma_jaar[LANGUAGE_NONE][0]['value'] = $row->jaar_diploma;
      $field_collection_item[$fc_id]->save(TRUE);
    } else {
      // If the field collection item doesn't exist I want to create a new field collection item.
      $field_collection_item = entity_create('field_collection_item', array('field_name' => 'field_profile_diploma_opleiding'));
      $field_collection_item->setHostEntity('user', $user);
      $field_collection_item->field_profile_diploma_instituut[LANGUAGE_NONE][0]['value'] = $row->instituut;
      $field_collection_item->field_profile_diploma_vakgebied[LANGUAGE_NONE][0]['value'] = $row->vakgebied;
      $field_collection_item->field_profile_diploma_jaar[LANGUAGE_NONE][0]['value'] = $row->jaar_diploma;
      $field_collection_item->save(TRUE);
    }
    $i++;
  }

  $fc_fields = field_get_items('user', $user, 'field_profile_diploma_opleiding');

  // Check if there are more field collection items than imported rows
  if(count($fc_fields) > $i) {
    for($i; $i <= count($fc_fields); $i++) {
      // Run through each field collection item that's left from the previous import and delete it.
      if(!empty($user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'])) {
        // Method 1
        $fc_id = $user->field_profile_diploma_opleiding[LANGUAGE_NONE][$i]['value'];
        entity_delete_multiple('field_collection_item', array($fc_id));

        // Method 2
        //$field_collection_item = field_collection_item_load($fc_id);
        //$field_collection_item->delete();

        // Method 3
        //$field_collection_item = field_collection_item_load($fc_id);
        //$field_collection_item->deleteRevision();
      }
    }
  }
}

```

So my question is: **How do I delete field collection items so that they're actually gone?**

# Answer
I ran into a similar use case where I wanted to map some data into a field collection during hook\_feeds\_presave() since the source structure was too complex for Feeds. I found that entity\_delete\_multiple() removed the field collection items, but when I edited the node, there were still a bunch of empty field collection there. Unsetting and deleting did the trick, which I found here: https://drupal.stackexchange.com/a/31820/2762

If the feeds source has changed, I delete all field collection items and recreate. Hope this is helpful.

```
foreach ($node->field_international_activity[LANGUAGE_NONE] as $key => $value) {
  // Build array of field collection values.
  $field_collection_item_values[] = $value['value'];

  // Unset them.
  unset($node->field_international_activity[LANGUAGE_NONE][$key]);
}

// Delete field collection items.
entity_delete_multiple('field_collection_item', $field_collection_item_values);

```
> 14 votes

# Answer
The best way to do this now is call `$field_collection->delete()` and that will handle everything.

```
 <?php
    /**
     * Deletes the field collection item and the reference in the host entity.
     */
    public function delete() {
      parent::delete();
      $this->deleteHostEntityReference();
    }

    /**
     * Deletes the host entity's reference of the field collection item.
     */
    protected function deleteHostEntityReference() {
      $delta = $this->delta();
      if ($this->item_id && isset($delta)) {
        unset($this->hostEntity->{$this->field_name}[$this->langcode][$delta]);
        entity_save($this->hostEntityType, $this->hostEntity);
      }
    }
 ?>

```
> 9 votes

# Answer
The above answers are not the best way, with unset all the other items disappeared fron the field collection, and the other way with `->delete()` throws a bug with the Entity module.

Correct way. Well what I did was this:

In my case I wanted to delete the last item within the field collection

take a look to this code, (for beginers: "remember that you must have the $entity already loaded")

```
// Remove the field value
unset($entity->field_salida_mercanc_a[LANGUAGE_NONE][count($entity->field_salida_mercanc_a[LANGUAGE_NONE])-1]);

// Reset the array to zero-based sequential keys
$entity->field_salida_mercanc_a[LANGUAGE_NONE] = array_values($entity->field_salida_mercanc_a[LANGUAGE_NONE]);

// Save the entity
entity_save($entity_type, $entity);

```

thats all! the other way is

```
//Get the node wapper
$wrapper = entity_metadata_wrapper($entity_type, $entity);
//Get the last position of the array items, thanks to the ->value() statement you can get the complete Array properties.
$field_collection_item_value = $wrapper->field_collection_mine[count($wrapper->field_collection_mine->value())-1]->value();
//Do not use 'unset' to delete the item due to is not the correct way, I use the entity_delete_multiple provided by the entity API
entity_delete_multiple('field_collection_item', array($field_collection_item_value->item_id));

```

The way above is good using `entity_metadata_wrapper` function but with that way there is a complex bug that I do not know how to solve it, you can check it at https://drupal.org/node/1880312 and after apply the patch in #9 you get the next issue, check it here https://drupal.org/node/2186689 this bug is also if you use `->delete()` function.

Hope it helps someone.
> 0 votes

# Answer
using vbo to delete the field collection items. it will auto remove the field relation with the field collection item host entity.
> 0 votes

# Answer
I had a similar issue, where I am importing data from a feed into a FC item. When an update to a host entity is made from the feed, and I'm importing those changes, I wanted to ensure that any existing FC items that no longer exist from the feed source were removed.

My solution:

```
// Load host entity that I'm updating.
$host_entity = node_load($nid);
$host_entity_wrapper = entity_metadata_wrapper('node', $host_entity);

// Clear out the references to the existing FC items so that I have a fresh start.
$host_entity_wrapper->field_my_fc_items->set(NULL);

// Re-create the FC items from the source feed data.
foreach ($feed_data->items as $feed_item) {
  $fc = entity_create('field_collection_item', array('field_name' => 'field_my_fc_items'));
  $fc->setHostEntity($host_entity);
  // Some some fields on the FC item from the feed data.
  $fc_wrapper = entity_metadata_wrapper('field_collection_item', $fc);
  $fc_wrapper->field_some_fc_item_field->set($feed_item->data);
}

// Sync other field info onto host entity.
...

$host_entity_wrapper->save();

```

And that's it. Field Collection's hook\_field\_update (`field_collection_field_update`) will take care of actually deleting any existing FC items that have been de-referenced.

The only downside to this is if there was no change in the FC data, it's deleted and re-created anyway. But that's not a big deal for me.
> 0 votes

---
Tags: 7, entities
---


# Question
Title: Populating entity fields programmatically
```
public function buildForm(array $form, FormStateInterface $form_state) {
  $form['start_date'] = [
    '#type' => 'datetime',
    '#title' => $this->t('Start Date'),
    '#required' => TRUE,
  ];
  $form['end_date'] = [
    '#type' => 'datetime',
    '#title' => $this->t('End Date'),
    '#required' => TRUE
  ];
  $form['location'] = [
    '#type' => 'entity_autocomplete',
    '#target_type' => 'node',
    '#selection_handler' => 'default',
    '#selection_settings' => ['target_bundles' => ['location']],
    '#title' => $this->t('Location'),
  ];
  $form['show'] = [
    '#type' => 'submit',
    '#value' => $this->t('Create Event'),
  ];
  return $form;
}

/**
  * {@inheritdoc}
  */
public function submitForm(array &$form, FormStateInterface $form_state) {
  $values = $form_state->getValues();
  $location = $form_state->getValue('location');
  $sd = $form_state->getValue('start_date');
  $sd = $sd->format('Y-m-d H:i:s');
  if($location == 1){
    $loc = "ASCET SE Center";
  }
  $node = Node::create(array(
    'type' => 'event',
    'title' =>  $sd . " " . $form_state->getValue('location'),
    'langcode' => 'en',
    'uid' => '1',
    'status' => 1,
    'field_location' => $loc,
    'field_start_date' => $sd,
  ));

```

I'm attempting to populate fields within the content type (event). The Event node type has a start date, end date, and an entity reference to a Location content type. When passing the `$loc` I get a message that says:

*"InvalidArgumentException: Value is not a valid entity. in Drupal\Core\Entity\Plugin\DataType\EntityReference-\>setValue()"*

When I pass `$sd` as a string it doesn't populate. When I pass `$sd` as `$form_state->getValue('start_date');` it says that there is too much data to put into the DB.

# Answer
> 2 votes
You need to pass the ID of the referenced entity in the `target_id` column for the entity reference field, and `value` column for the timestamp field. Something like:

```
$target_id = $form_state->getValue('location');
$date = $form_state->getValue('start_date')->getTimestamp();

$node = Node::create(array(
  'type' => 'event',
  'title' =>  $sd . " " . $form_state->getValue('location'),
  'langcode' => 'en',
  'uid' => '1',
  'status' => 1,
  'field_location' => [
    'target_id' => $target_id,
  ],
  'field_start_date' => [
    'value' => $date,
  ],
));

```

---
Tags: entities
---


# Question
Title: Manage profiles of "people" which might at some point become users
My case is the following: In our company's Drupal "intranet", we need to manage prospective and actual Human Resources, and there's three kinds of them:

1) Candidates: HR people collect CVs and make their assessment after the interview. They want to store those information within an entity for future reference, without creating a User, obviously. On the other hand, when the person is hired, the user is created and it would be handy to link their existing profile

2) Real users: employees with an account on the intranet, with their user account accessible to them, and an HR profile managed by the HR

3) Employees without access: employee without web access, which only have an HR profile, but still need to be listed in orgcharts, have a job title, record training events and so on.

In short, everyone has an "identity", or "profile", but only a subset of them have a proper user account.

Any suggestions about how to go around it, or if there's a module out there for this? I have looked into Profile2 and Identity (RNG) but they do not seem cover my use case.

# Answer
I have a solution for you:

You can create a role "candidate" and by default create all users of role candidate as blocked.. so they would never be able to access their account. and Then once they are hired/employed then depending on that condition you can trigger a rule which will change their role and status to ACTIVE. That will probably solve your problem.
> 1 votes

# Answer
Use "Decoupled User Authentication" (https://www.drupal.org/project/decoupled\_auth) to treat everyone as users, even if they don't yet have login credentials. This way you have one consistent entity type you're working with all through the different stages of a candidates journey.
> 0 votes

---
Tags: users
---


title: How to customize the comments form?

text:
# Question
Title: How to customize the comments form?
For example, How can I add some classes or hide labels and instead of it add placeholder with using of `ThemeName_preprocess_comment` to 'subject' and 'name' comments form elements?

I have tried to use`drupal_set_message(kint($variables));` in `ThemeName_preprocess_comment` section, but it cause the empty screen erroe in my site.

So how can I add some classes to default (or my own created) comments elements so I can target them for adding CSS style.

How can I target default comments form element in CSS?

# Answer
> 2 votes
i would do it:

1) create new file: testmodule.info.yml.

```
name: testmodule
description: Testmodule
type: module
core: 8.x

```

2) create new file: testmodule.module

```
<?php

function testmodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

  if ($form_id=='comment_comment_form') {

    //add class subject
    $form['subject']['widget']['0']['value']['#attributes']['class'][]='newclass_subject';

    //add placeholder subject
    $form['subject']['widget']['0']['value']['#attributes']['placeholder'] = t('Placeholder Subject');

    //add class body
    $form['comment_body']['widget']['0']['#attributes']['class'][]='newclass_body';

    //add placeholder body
    $form['comment_body']['widget']['0']['#attributes']['placeholder'] = t('Placeholder Body');

  }

}

```

# Answer
> 2 votes
if you use Drupal7, you should not use

```
drupal_set_message(kint($variables));

```

but

```
kint($variables)

```

or

```
dpm($variables)

```

An example that you can see, enter in the following link: https://api.drupal.org/api/drupal/modules%21comment%21comment.module/function/template\_preprocess\_comment/7.x

```
function bartik_preprocess_comment(&$variables) {

  $variables['classes_array'][] = 'myclass';
  dpm($variables);

}

```

You can also create a file "comment-wrapper.tpl.php" and add the classes you want and placeholder.

Example:

```
<?php

/**
 * @file
 * Bartik's theme implementation to provide an HTML container for comments.
 *
 * Available variables:
 * - $content: The array of content-related elements for the node. Use
 *   render($content) to print them all, or
 *   print a subset such as render($content['comment_form']).
 * - $classes: String of classes that can be used to style contextually through
 *   CSS. It can be manipulated through the variable $classes_array from
 *   preprocess functions. The default value has the following:
 *   - comment-wrapper: The current template type, i.e., "theming hook".
 * - $title_prefix (array): An array containing additional output populated by
 *   modules, intended to be displayed in front of the main title tag that
 *   appears in the template.
 * - $title_suffix (array): An array containing additional output populated by
 *   modules, intended to be displayed after the main title tag that appears in
 *   the template.
 *
 * The following variables are provided for contextual information.
 * - $node: Node object the comments are attached to.
 * The constants below the variables show the possible values and should be
 * used for comparison.
 * - $display_mode
 *   - COMMENT_MODE_FLAT
 *   - COMMENT_MODE_THREADED
 *
 * Other variables:
 * - $classes_array: Array of html class attribute values. It is flattened
 *   into a string within the variable $classes.
 *
 * @see template_preprocess_comment_wrapper()
 */
?>
<?php
    //add placeholder
    $content['comment_form']['subject']['#attributes']['placeholder'] = t('Title');
    $content['comment_form']['comment_body']['und'][0]['value']['#attributes']['placeholder'] = t('Comment Body');
  ?>
<div id="comments" class="<?php print $classes; ?>"<?php print $attributes; ?>>
  <?php if ($content['comments'] && $node->type != 'forum'): ?>
    <?php print render($title_prefix); ?>
    <h2 class="title"><?php print t('Comments'); ?></h2>
    <?php print render($title_suffix); ?>
  <?php endif; ?>

  <?php print render($content['comments']); ?>

  <?php if ($content['comment_form']): ?>
    <h2 class="title comment-form "><?php print t('Add new comment'); ?></h2>
    <?php print render($content['comment_form']); ?>
  <?php endif; ?>

</div>

```

---
Tags: 8, forms, comments, theming
---


# Question
Title: How to restrict access to specific content types by role?
In D8 core you can either set permission for anonymous users to view all or non publish content, but not set permission different by content type.

I've found this that looked promising, but the functionalities doesn't work for this:

http://drupal.org/project/content\_access

Any others suggestions for how to solve this?

# Answer
> 3 votes
You could use the Group module for this. Group allows for creating arbitrary collections of your content and users on your site, and grant access control permissions on those collections. The Group module creates groups as entities, making them fully fieldable, extensible and exportable.

Some basics about he Group module to be aware of:

* Make sure you enable `gnode`, a submodule of the Group module.
* For each group type you need to define the appropriate permissions (view, edit, delete, etc) for the various Content Types.
* Every group can have users, roles and permissions attached to it (refer to "What are the various roles supported by the Group module?" for more details about that).

With the appropriate permissions configured, it's just a matter of assigning a node to a Group: based on how you configured the roles and permissions, the Group module will allowed/deny access for any user. Refer to "How to create collections of content that can be accessed by users with various access levels?" for more info about all this.

**Resources**

**Notes** (to further address your comment below this answer):

* > ... I want to give access to anonymous users, I guess they can't be part of a group?

True, an anonymous user, by design, cannot be part of a group. But as mentioned in my answer to "What are the various roles supported by the Group module?": the role "Anonymous" (related to a user that is not signed) is one of the *Special Global Roles* (apart from *Outsider* and *Member*). And it is via that Special Global Role "Anonymous" that you can make the magic happen for *any* anonymous user. Have a look at the video tutorial, around `10:53`, where you can see that it is possible to grant **access to anonymous users\*** to (eg) "View content" to a Group node (of content type "Article").
* > ... I would then need to add every person to those groups instead of just assigning permissions to their roles?

If you'd grant appropriate permissions for *Outsider* (combined with the access you want for *Anonymous*), they do not have to be part of those groups.
* > ... It seem like a little bit bad work-around for my need.

With the above details included in this note, I presume you agree that this part of your comment no longer applies.

**Bonus tip**:

A possible solution to "*... make all 'article' nodes be content of an 'articles' group.*" (as in another comment added to this answer) is explained in comment nr 3 of the issue titled Bulk assign of content to groups. This is part of what it says:

> The steps to take are roughly:
>
> 1. Make sure you have a GroupType
> 2. Make sure the GroupType has the right plugins enabled (GroupType::installContentPlugin(); read deprecation notice)
> 3. Create a Group of said GroupType
> 4. Start adding the nodes using `$group->addContent($node, 'group_node:NODE_TYPE_HERE');`

For D7 one can use Views Bulk Operations (VBO) and Rules as detailed in my answer to "How to bulk assign existing content to a group created with the Group module?").

---
Tags: 8, users
---


# Question
Title: Best method of pushing content changes that contains paragraph fields from dev to production?
I manage a very big site with over 30k nodes and these nodes have many fields in them including paragaph fields with many sub fields in them too. Currently when testing and adding in content. I have to manually input them into the dev site and once the client approves, I have to manually do this again on prod. The import feeds module doesnt support paragraphs and neither do others from what I researched.

What would be the best method of deploying content changes from dev to prod that contain paragraph fields data?

# Answer
> 2 votes
One recommendation is to use "Features" to generate:

1. a Feature export of any config changes to the content types, paragraph bundles, and fields
2. a separate Feature export of the content/nodes themselves

To accomplish this, you'll need:

NOTE: this approach generally works well, as long as the effected content/node IDs between production and your staging/dev environment are the same.

---
Tags: 7, entities, paragraphs, deployment, staging
---


# Question
Title: How to remove square brackets from name attribute in webform elements?
Name attribute in rendered webform elements contain square brackets like `submitted[field_machine_name]`.

.

Is there a way to replace square brackets in the name, so the name attribute looks something like "field\_machine\_name", without breaking the webform submission handler?

# Answer
> 1 votes
you can use hook\_form\_alter

Example D8

```
function hook_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

  if ($form_id=='comment_comment_form') {

    $form['subject']['widget']['0']['value']['#name'] = 'field_machine_name';

  }

}

```

Example D7

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

 if ($form_id=='comment_node_article_form')        {
    $form['subject']['#name'] = 'field_machine_name';
 }

}

```

---
Tags: 7, theming, hooks, webforms
---


# Question
Title: Programmatically redirect users to the default "access restricted"
I would like to programmatically redirect my users to the default "access restricted" page. I know that I need a "RedirectResponse" object for a simple redirect, but how do I specify the default "access restricted" page here?

# Answer
You can throw an exception at any point in your code:

**403:**

```
throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();

```

**404:**

```
throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException();

```

The exception is then caught by DefaultExceptionHtmlSubscriber and a subrequest for `/system/403` or `/system/404` is returned, which you can configure in the basic site settings if you don't want to display a generic "access denied" or "not found" page.

Other options depend on where the code is placed:

* Return a 403 or 404 response from a controller or a form
* Set a response in an event if you are in an event subscriber.

What you should never do is to send a response directly. This doesn't stop the code and produces two responses, one you've sent and one returned by the Drupal kernel. This will result in unpredictable behavior.
> 42 votes

# Answer
This seems to be the right way:

```
    $response = new RedirectResponse('/system/403');
    $event->setResponse($response);

```
> 6 votes

# Answer
Build your redirect from the system's access denied route.

```
$url = Url::fromRoute('system.403');
$response = new RedirectResponse($url->toString());

```

This takes you to the Drupal standard access denied page. The route is defined in `system.routing.yml` in core.

The top answer will give you a broken looking browser based Access Denied, which may be what you're looking for. If you want your Drupal UI to show, use the above.
> 4 votes

# Answer
From a page, you can use:

```
return new \Symfony\Component\HttpFoundation\RedirectResponse(\Drupal::url('your.module.route.name'));

```

like : http://www.drupal8.ovh/en/tutoriels/88/page-redirection-on-drupal-8

Or from a from submit:

```
$form_state->setRedirect('your.module.route.name');

```

Then configure access permission of 'your.module.route.name'

If you dont know how to configure access permision, check: http://www.drupal8.ovh/en/tutoriels/66/create-a-custom-permission-drupal-8
> 2 votes

---
Tags: 8
---


# Question
Title: How do I add "Update Status of User" action to a view?
I want to create a user list with the Views module, to change the user status. I use the *Views Bulk Operations* module, but it has no *Change status* or *Active user* action.

How can I enable (or change the status of) users in a view table list with one click?

# Answer
Another approach to roll your own cookies, and create a VBO operation like "change status or active user" (as in your question) yourself. Read on for more details about how to do so ...

### Step 1

Use the Rules module to create a Rules Component, which includes whatever Rules Conditions you might need (if any), and with a Rules Action to **change status or active user**, for the user specified as a parameter for this Rules Component.

Here is such Rules Component you could use for it (in Rules Export format):

```
{ "rules_change_status_of_a_blocked_user_to_active" : {
    "LABEL" : "Change status of a blocked user to active",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "USES VARIABLES" : { "user_to_activate" : { "label" : "User to be activated", "type" : "user" } },
    "IF" : [ { "user_is_blocked" : { "account" : [ "user-to-activate" ] } } ],
    "DO" : [ { "user_unblock" : { "account" : [ "user-to-activate" ] } } ]
  }
}

```

Some details about it:

* It uses a user entity as a parameter.
* The Rules Condition checks that the user to be processed is actually blocked (it doesn't make sense to try to change the status of an `active` user to `active`).
* The Rules Action changes the status of the user to `active`.

If you have the Rules UI enabled, just import the above Rules Component in your own site. After you completed the import, you can unit test it like so:

* Use the "Execute" link in front of the Rules Component.
* On the next screen, where you'll have to enter some value for "*User to be activated*", use the `Switch to the direct input mode` button near the bottom.
* Then enter the `uid` of some blocked user as the value for *User identifier* and hit the `Execute` button below it.
* The (blocked) user should become `active` after doing so (which completes your unit testing of this Rules Component).

### Step 2

Create an appropriate view of the users for which you want to be able to perform a VBO action like "change status or active user". Then transform that view into a view that uses Views Bulk Operations, and use the technique documented in "How to use Rules to create a custom bulk operation for a VBO view?". In doing so, you'll then be able to use the Rules Component from the previous Step 1.

### Tutorial

To get the idea, have a look at the video about Using Rules components with VBO" which uses a Rules Component with (only) 1 parameter. If you want even more, then also watch the subsequent "Using Rules components with more than one parameter" video.

Attention: to process like thousands of users at once is quite a challenge (memory requirements, etc). Therefor you might want to also watch the video about "More details about VBO settings" ... Before you are tempted to use VBO for processing them all at once ...
> 1 votes

# Answer
If you have entity forms and rules, create an entity form with an entity reference to users, add another field for your preferred action, and use rules to perform the action.
> 2 votes

# Answer
A possible approach might be to *process the results of a VBO enabled view via Rules*, whereas your rule performs 2 Rules Actions:

* Load the VBO list of entities (such as nodes) that you want to be processed.
* Add a loop to perform a Rules Action, for each entity (such as a node) contained in your Views results. The actual Rules Action you want to perform is "*change status or active user action*" (as in your question).

For more details, have a look at the tutorial "How to process the results of a VBO enabled view via Rules?".
> 1 votes

---
Tags: 7, views, users, rules
---


title: Check if teaser or full content

text:
# Question
Title: Check if teaser or full content
I want to add an HTML block inside the node.html.twig file, but only in full content view.

I used the following code but it is not working.

```
{% if view_mode %}
  <div class="article-ads hidden-xs hidden-sm">
    <img src="/sites/default/files/banners/ad.jpg" alt="ad" />
  </div>
{% endif %}

```

I would like to move this code to a Drupal 8 block to avoid editing the template file.

How can I achieve it?

# Answer
check like this

```
{% if view_mode == "teaser" %}
  <div class="article-ads hidden-xs hidden-sm">
    <img src="/sites/default/files/banners/ad.jpg" alt="ad" />
  </div>
{% elseif view_mode == "full" %}
  //something else
{% endif %}

```
> 0 votes

---
Tags: theming
---


# Question
Title: Features workflow issue with deleting a field
Suppose I have a content type `Person` with fields: `Name`, `Age`, `Email`

This content type is controlled by a Feature called `test` so I can source control it and push it to the live site.

My workflow goes like this:

* I add a new field on `Person` called `Phone`
* locally I do: `drush fu test -y`
* I edit the `test.info` to increase the version number
* I commit the changes to my repository
* I push the feature to the live site (copy the feature files)
* on the live site I do: `drush fr test -y`
* on the live site I do: `drush cc all`

Then the new field appears on the live site's `Person`.

If on the first step I remove a field of `Person` the field will not be deleted from the live site. How do I solve this? I don't want to have to manually delete it from the UI on the live site.
Is this workflow correct?

# Answer
This is a double edged sword, it's like this to prevent data deletion which is *always* a good thing. There's nothing really to solve, this is expected behaviour.

It's the same workflow we use and have been doing for over a year and it works really well. I'd say it's correct but that's a very subjective answer.
> 8 votes

# Answer
The correct way to remove Features-created content is via hook\_update\_N (which should be implemented in the file `your_module.install`).

---

The main idea with Features is to manage configuration with code. Using `hook_update_N` is consistent with that, since the field deletion is in code (which can be managed with version control) — whereas the equivalent command `drush field-delete field` is not being called from managed code; it's a separate command-line step you need to perform (and to remember to perform).
> 10 votes

# Answer
Create a new file called "your\_feature\_name.install"

Inside the file declare hook\_update\_N, there you can use field\_delete\_field() and specify the name of field that you want to delete as parameter.

Run update.php and the fields will be deleted.
> 2 votes

# Answer
If you are using `field_phone` in other areas, you might just want to remove it from your Person content type, but not delete it entirely from your site. Manually create a `YOUR_FEATURE_NAME.install` file in your feature's folder like so:

```
/**
 * Implements hook_update_N().
 *
 * Removes field_phone from Person content type.
 */
function YOUR_FEATURE_NAME_update_7001() {
  if ($instance = field_info_instance('node', 'field_phone', 'person')) {
    field_delete_instance($instance);
  }
  field_purge_batch(500);
  features_revert_module('YOUR_FEATURE_NAME');
}

```

If you were deleting this from a Person Paragraph instead of a Person Content Type, you could change the first conditional statement to something like this:

```
if ($instance = field_info_instance('paragraphs_item', 'field_phone', 'person')) {
  ...
}

```
> 0 votes

---
Tags: 7, features
---


title: jQuery post data to the database?

text:
# Question
Title: jQuery post data to the database?
I'm creating a system on D7 that tracks how much progress users have made watching various videos on the site. I've set up the jQuery that stores the percentage progress in an array with a modified version of the process at https://www.urbaninsight.com/2014/10/06/tracking-progress-embedded-vimeo-videos. Where I'm lost is where I actually post the data using:

`$.post('/callback', {
 progress: myProgressVariable
});`

I realized that `'/callback'` is just a placeholder, but I don't know what to sub in there. Should I designate a `callback()` function in a custom module that does something with the progress data and just place the function name into the javascript -- and what might that look like? Or do I need to do something something else entirely?

# Answer
> 0 votes
Ended up just using a custom hidden form as suggested by 4k4 and am populating/submitting it via jquery/ajax.

---
Tags: 7, database, javascript
---


title: Drush Make: error "unable to unzip"

text:
# Question
Title: Drush Make: error "unable to unzip"
I'm trying to setup a new project using the Drush `make` command. I'm working on localhost (xampp) on a Windows 8.1 machine.

The problem is that if a module present in my make file requires an external library (e.g. colorbox or plupload), `make` will detect that and will download said dependency, but then will **fail** to decompress it, resulting in the following error:

```
plupload-7.x-1.7 downloaded.                                                [ok]
Found makefile: plupload.make                                               [ok]
plupload downloaded from                                                    [ok]
https://github.com/moxiecode/plupload/archive/v1.5.8.zip.
Unable to unzip                                                          [error]

```

As a result, the whole `make` operation is aborted.

I searched for a solution and found this stackoverflow answer that seems to address my problem but is not very detailed. I tried using Cygwin (x64), found an "unizp" package in it, tried to download it and copy the unzip.exe file in the `Program Files (x86)\Drush\GnuWin32\bin` folder, but now when I run my `make` project I have a new error message, this time as a dialog box (not in the console, then):

```
The program can't start because cygbz2-1.dll is missing from your computer.
Try reinstalling the program to fix the problem.

```

Followed by a `unzip.exe has stopped working` Windows dialog box.

I can find the missing DLL (cygbz2-1.dll) in the `C:\cygwin64\bin` directory. So I tried adding this path to my PATH environment variable (and restarted my computer to be sure), but I still have the same "missing DLL" error.

Is there something I'm doing wrong (I'm not familiar with cygwin at all, so I don't know if I'm using it right...)?

# Answer
Get unzip for windows: http://gnuwin32.sourceforge.net/packages/unzip.htm It solved the "unable to unzip" problem for me.
> 1 votes

---
Tags: drush
---


# Question
Title: What ways to attach a library to a form?
I created a custom form and I use a js library on it. I attached my JS in my template file but in a first time, I tried to attach it directly on my form with

```
$form['#attached']['library'][] = "mymodule/mylibrary"

```

like in D7 but it doesn't work.

I found none references to attach library directly to a form and no references to the "#attached" property so I suppose it has been remove.

My library works fine in the twig template file.

But in the case I don't used a custom template or I use various templates for various cases, can I attach my library directly to my form without pass by a hook function or must I pass necessary by the template file, a hook\_preprocess or a hook\_page\_attachment?

# Answer
Like explain by Clive, add libraries directly in the form via '#attached' parameter works. The mistake in my case was to don't send my form properly to my template file. See Send a form to twig template
> 1 votes

---
Tags: 8, javascript
---


# Question
Title: Can't update form field via ajax on submit
I have two entity types -- `video` and `video progress`.

I've got a form on `video` nodes with a field that is populated with the id of a `video progress` entity that references the current node. If this field is empty when the form is submitted, then I am generating a new `video progress` entity in the submit handler, and am trying to populate my form field value with this new entity id. This form is hidden from the user and is updated dynamically as the user watches a video via jQuery.

My issue is that no matter what I try, I cannot get the submit or ajax callbacks to rebuild my field. Here are the relevant portions of my code.

```
function video_progress_tracking_form($form, &$form_state) {
  // $progress_id is already set

  $form['progress_id'] = array(
    '#type' => 'textfield',
    '#title' => t('Video progress entity id'),
    '#default_value' => $progress_id,
    '#element_validate' => array('element_validate_integer_positive'),
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
    '#ajax' => array(
      'callback' => 'video_progress_tracking_form_ajax_handler',
      'effect' => 'fade',
    ),
  );

  return $form;
}

function video_progress_tracking_form_submit($form, &$form_state){
  if(empty($form_state['progress_id'])) {
    // If a video progress entity doesn't exist, we need to create one
    $entity_type = 'video_progress';
    $entity = entity_create($entity_type, array('type' => 'video_progress'));
    $wrapper = entity_metadata_wrapper($entity_type, $entity);
    $wrapper->save();

    // Pass our new values into the form for further updating
    $form_state['values']['progress_id'] = $wrapper->id->value();
  }
}

function video_progress_tracking_form_ajax_handler(&$form, &$form_state) {
  return $form['progress_id'];
}

```

I have also tried, among other things:

* Setting a `#value` when initially building the form on `$form['progress_id']` with a ternary operator so that if there is a form\_state value for the field then that is set
* Setting `$form_state['rebuild'] = TRUE` in both callbacks
* Returning the entire form instead of just this single field

# Answer
You haven't told the form API *where* to render the content you're returning in the AJAX callback.

That takes the form of a prefix/suffix on the element itself, with a predictable HTML ID:

```
$html_id = drupal_html_id('foo');
$form['progress_id'] = array(
  '#type' => 'textfield',
  '#title' => t('Video progress entity id'),
  '#default_value' => $progress_id,
  '#element_validate' => array('element_validate_integer_positive'),
  '#prefix' => '<div id="' . $html_id . '">',
  '#suffix' => '</div>',
);

```

And providing the AJAX-ified element with the ID of the wrapping HTML:

```
$form['submit'] = array(
  '#type' => 'submit',
  '#value' => 'Submit',
  '#ajax' => array(
    'callback' => 'video_progress_tracking_form_ajax_handler',
    'effect' => 'fade',
    'wrapper' => $html_id,
  ),
);

```

You will need to add/keep `$form_state['rebuild'] = TRUE;` in the submit handler (not the AJAX callback). To isolate that functionality you may wish to add a specific `#submit` handler array to your submit button.
> 1 votes

# Answer
```
$form['progress_id'] = array(
        '#type' => 'textfield',
        '#title' => t('Video progress entity id'),
        '#default_value' => $progress_id,
        '#element_validate' => array('element_validate_integer_positive'),
      );
      $form['submit'] = array(
        '#type' => 'submit',
        '#value' => 'Submit',
        '#ajax' => array(
          'callback' => 'video_progress_tracking_form_ajax_handler',
          'effect' => 'fade',
        ),
      );

```

by

```
 $form['progress_id'] = array(
    '#prefix' => '<div id="my-div-ajax">',
    '#suffix' => '</div>',

    '#type' => 'textfield',
    '#title' => t('Video progress entity id'),
    '#default_value' => $progress_id,
    '#element_validate' => array('element_validate_integer_positive'),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
    '#ajax' => array(

      'callback' => 'video_progress_tracking_form_ajax_handler',
      'wrapper' => 'my-div-ajax',
      'effect' => 'fade',
    ),
  );

```
> 1 votes

---
Tags: forms, ajax
---


# Question
Title: Comments: "You are not authorized to post comments."
I'm using Drupal 7. I'm trying to add comments to a node but I get this error back:"You are not authorized to post comments". I can't find in the code which variables are being checked to don't allow me to post a comment. Can someone tell me where to look in the code? Thank you very much

# Answer
Go to: admin/people/permissions

Check de permission:

* Post comments

Click button "save permission".
> 2 votes

# Answer
You might be looking for the `comment_access()` function.

> Determines whether the current user has access to a particular comment.

There's not much to it:

```
function comment_access($op, $comment) {
  global $user;

  if ($op == 'edit') {
    return ($user->uid && $user->uid == $comment->uid && $comment->status == COMMENT_PUBLISHED && user_access('edit own comments')) || user_access('administer comments');
  }
}

```
> 1 votes

# Answer
If you have not already checked, go to People\>Permissions\>Comments.
> 0 votes

---
Tags: users, comments
---


# Question
Title: module_invoke to create user search block not working
I've done the following to create two search blocks:

```
$content_search = module_invoke('search', 'block_view', 'content_search');
$user_search = module_invoke('search', 'block_view', 'user_search');

```

And I then call the blocks as needed like so:

```
<?php print render($content_search['content']); ?>
<?php print render($user_search['content']); ?>

```

They render correctly and the content search works just fine, but running something through the user search block just searches content. I noticed that regardless of which block I use, they both go to the URL http://example.com/search/node/\[search parameters\]

(This is Drupal 7 BTW)

# Answer
> 0 votes
The search block only works for the default search type. From `search_box_form_submit()`:

```
$info = search_get_default_module_info();
if ($info) {
  $form_state['redirect'] = 'search/' . $info['path'] . '/' . trim($form_state['values'][$form_id]);
}
else {
  form_set_error(NULL, t('Search is currently disabled.'), 'error');
}

```

The third parameters you're passing ('content\_search', 'user\_search') are ignored. Presumably your default search type is content and that's why you're being redirected to the content search in both forms.

You can build the correct search form pretty easily though:

```
$content_form = drupal_get_form('search_form', NULL, '', 'node');
$user_form = drupal_get_form('search_form', NULL, '', 'user');

```

---
Tags: blocks, search
---


# Question
Title: Is there a way to avoid anonymous user can see a node of a specific content type?
Is there a way to avoid anonymous users can see nodes of a content type, like a block or a view?

I can control the access with a view, but if I know the link for a node, I can see it without first logging in.

# Answer
You can control the access to nodes in the hook hook\_node\_access():

*mymodule.module:*

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

function mymodule_node_access(NodeInterface $node, $op, AccountInterface $account) {
  if ($account->isAnonymous() && $node->gettype() == 'article') {
    return AccessResult::forbidden()->cachePerPermissions();
  }
  return AccessResult::neutral()->cachePerPermissions();
}

```

This controls the direct access to the node, not the access in views. But this is what you probably want.
> 11 votes

# Answer
Your best bet is to use Rabbit Hole, or Content Access when it has an updated release.

## Rabbit Hole

> Rabbit Hole is a module that adds the ability to control what should happen when an entity is being viewed at its own page. Perhaps you have a content type that never should be displayed on its own page, like an image content type that's displayed in a carousel. Rabbit Hole can prevent this node from being accessible on its own page, through node/xxx.

## Content Access

> This module allows you to manage permissions for content types by role and author. It allows you to specifiy custom view, edit and delete permissions for each content type. Optionally you can enable per content access settings, so you can customize the access for each content node.

Note that what I *believe* you want is to block *all* access to a node of a content type - and only Content Access will fulfill that over Rabbit Hole.

Beyond that, I think you'd be looking at implementing your own access control if neither of these suit.
> 4 votes

# Answer
You can use the Node View Permissions module.

Enable it and then you can assign what roles that can view what content types under path 'admin/people/permissions' under section 'Node view permissions'
> 2 votes

# Answer
Maybe you want to give it a try to use the Group module, which allows for creating arbitrary collections of your content and users on your site, and grant access control permissions on those collections. It is available as of D7, and has a D8 version also. It creates groups as entities, making them fully fieldable, extensible and exportable. Every group can have users, roles and permissions attached to it (refer to "What are the various roles supported by the Group module?" for more details about that).

For this specific question, you'd enable the `gnode` submodule, and for each group type you would define the appropriate permissions (view, edit, delete, etc) for the various Content Types.

It seems that you would want to grant access to what, in Group, is called "Members" and "Outsiders" (= logged in users who are not a member of a group). But you woudn't allow access to "Anonymous" (site visitors that are not logged it).

# Resources
> 1 votes

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


# Question
Title: How do I change and translate the "completion message" in Commerce checkouts?
I want to change the text of the "completion message" that is shown when an order is paid for successfully. I also want to translate this message.

By default, the completion message text is:

```
Your order number is 1.
You can view your order on your account page when logged in.

```

I'm using Commerce 2 with Drupal 8.4.1.

By default, at `/admin/commerce/config/checkout-flows/manage/default`, the checkout flow looks like this:

There is no option to edit the **completion message**. Also, there is a **translate** link at the top of the page, but this **translate** link only lets me translate the name of the checkout flow, not the completion message.

So how do I edit/translate the completion message?

# Answer
**Template approach (recommended)**

As revealed in the comment by @bojanz, you can just make a copy of the template file in your theme:

`commerce/modules/checkout/templates/commerce-checkout-completion-message.html.twig`

**Custom checkout pane approach**

There is documentation for this.

You can create your own custom checkout pane, which can be done with drupal console or by hand.

`/MYMODULE/src/Plugin/Commerce/CheckoutPane`

```
<?php

namespace Drupal\my_checkout_pane\Plugin\Commerce\CheckoutPane;

use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneInterface;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * @CommerceCheckoutPane(
 *  id = "custom_completion_message",
 *  label = @Translation("Custom completion message"),
 *  admin_label = @Translation("Custom completion message"),
 * )
 */
class CustomCompletionMessage extends CheckoutPaneBase implements CheckoutPaneInterface {

  /**
   * {@inheritdoc}
   */
  public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
    $pane_form['message'] = [
      '#markup' => $this->t('This is a custom completion message.'),
    ];
    return $pane_form;
  }

}

```
> 7 votes

---
Tags: 8, commerce
---


# Question
Title: How can you show taxonomy child terms on the parent term page?
I am trying to figure out if there is a way to modify the default taxonomy view so it shows nodes tagged with that particular term (already done) plus all children of the taxonomy term you are viewing.

I have seen solutions for D7 but nothing for D8.

# Answer
One way of doing this is with the use of https://www.drupal.org/project/eva which lets you attach any entity to any other entity

Just for demonstration I have setup

```
parent 1
  child 1.1
  child 1.2
parent 2
  child 2.1
  child 2.2

```

install and enable eva create a taxonomy terms view called `children` with no block or page display

Then add an `EVA` views display from the dropdown You will need to set a contextual filter `parent term` with following settings

```
Hide when value not available
specify validation criteria
   taxonomy term id:
      [NAME-OF-VOCABULARY]
   hide view

```

and on entity content settings set `entity type: taxonomy term` and `bundle: [vocabulary name]`

I had to clear cache so it does not hurt to do it and visit any of the taxonomy parent pages you should see the children terms

you can change where the children are displayed at your taxonomy term display settings page
> 1 votes

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


# Question
Title: How do I filter a view for untranslated content?
I have a site with many lessons in English, with the option to translate them into Japanese. There is a team of translators working to translate the lessons, but they need an easy way to see which lessons have not yet been translated.

Is there some way to filter or create a view that only shows content that has not yet been translated to a target language?

# Answer
> 0 votes
You could use the following 2 views filters `Content: Revision translation affected (!= False)` `Content: Default translation (= True)`

for more details go to a more complete answer How to create a list of untranslated content in views?

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


title: Get the site base url in template.php

text:
# Question
Title: Get the site base url in template.php
How do i get the base url in template.php?

None of the below works.

```
global $base_url;
global $base_path;
global $base_root;

```

# Answer
You can use the `base_path()` function which should always work.

To be honest though it just returns `$GLOBALS['base_path']` so your `global $base_path` statement should work fine.
> 11 votes

# Answer
`base_path()` only produce `"/"`.

to get the full URL including the domain, you have to use: `$GLOBALS['base_url']`
> 9 votes

# Answer
If you want to get only the base URL, you can use the following line.

```
global $base_url;

```

I used it in many projects.
> 2 votes

# Answer
This does not directly answer the question, but seems relevant. If you're looking for the domain name / base url in order to combine it with the aliased path for a node, instead just get the absolute URL like this:

```
$absoluteurl = url('node/' . $nid, array('absolute' => TRUE));

// http://example.com/content/aliased_path

```
> 1 votes

# Answer
You can get it from

```
$GLOBALS['base_root']

```

For more details see http://www.drupal4hu.com/node/310
> 0 votes

---
Tags: 7, uri, theming
---


title: How to resave all my nodes

text:
# Question
Title: How to resave all my nodes
In D7, it was easy with the VBO module.. But how to do it with D8? (Preferably using a view to select the nodes to resave)

In many places I saw that a small part of the VBO module is now included in the D8 core but I can't figure out how to use it (assuming a simple save should be feasible)

# Answer
What you are asking for is included in core Views, unless I am mistaken.
In a new Content view you will be able to add a "Content: Node operations bulk form" field and that offers you an option for "Save content".

You could even use the default "Content" view...

that already offers that option out of the box:
> 9 votes

# Answer
Latest update:

Drush core now also provide a re-save command! (since v11.0.0-rc1)

```
# Re-save all article entities:
drush entity:save node --bundle=article

# Re-save all shortcut entities:
drush entity:save shortcut

# Re-save nodes 22 and 24:
drush entity:save node 22,24

# Re-save all nodes except node 9, 14 and 81:
drush entity:save node --exclude=9,14,81

# Re-save all users:
drush entity:save user

# Re-save all node entities in steps of 5, defaults to 50 if omitted:
drush entity:save node --chunks=5

```

---

Update:

Aaaand some folks also created an unattributed copy of Resave All Nodes and added some more options: Save All Nodes.

---

Update:

I just created Resave All Nodes. For now it only contains a form and a Drush command to trigger a batch process to resave all nodes of selected node types.

---

For everybody coming here to find a code snippet (to be placed in `MYMODULE.install`):

```
use \Drupal\node\Entity\Node;

/**
 * Resave all pages.
 */
function MYMODULE_update_8001(&$sandbox) {

  // Get an array of all 'page' node IDs.
  $nids = \Drupal::entityQuery('node')
    ->condition('type', 'page')
    ->execute();

  // Load all the nodes.
  $nodes = Node::loadMultiple($nids);
  foreach ($nodes as $node) {
    $node->save();
  }
}

```

Problem with this, of course, is you can reach your memory limit pretty fast when re-saving many thousands of nodes that way. So you have to implement a batch process.

Thankfully `hook_update_N(&$sandbox)` already has this capability built-in. Follow the link for sample code.

> If running your update all at once could possibly cause PHP to time out, use the `$sandbox` parameter to indicate that the **Batch API** should be used for your update. In this case, your update function acts as an implementation of `callback_batch_operation()`, and `$sandbox` acts as the batch context parameter. In your function, read the state information from the previous run from `$sandbox` (or initialize), run a chunk of updates, save the state in `$sandbox`, and set `$sandbox['#finished']` to a value between `0` and `1` to indicate the percent completed, or `1` if it is finished (you need to do this explicitly in each pass).
> 8 votes

---
Tags: 8, views
---