# Question
Title: why Cache-tags is different if i am logged?
I try to understand how drupal core cache tags is add :

this is my tags on my home when i am logged :

```
node:121 node:158 node:23945 node:23946 node:43328 node:491 node:514 node:59139

```

It's good, this relate my node on my home.

But if i check my home in anonymous, this is what i get :

```
node:115 node:121 node:153 node:158 node:172 node:18240 node:18244 node:18256 node:23945 node:23946 node:307 node:43328 node:45 node:491 node:514 node:59139 node:59143 node:59144 node:59145 node:59146 node:59147 node:59148 node:59149 node:59193 node:59197 node:59239 node:59269 node:59283 node:59289 node:59293 node:59522 node:59770 node:60375 node:60390 node:60415 node:60418 node:60480 node:60542 node:60606 node:60616 node:60727 node:60785 node:60793 node:60819 node:60824 node:60827 node:60873 node:66011 node:66019 node:66026 node:66028 node:66030 node:66036 node:66039 node:8555 node:8561

```

And most of this tag is wrong for the home page, how drupal find them ?

I know there is a cache context, but its the core who add this tags

**EDIT**

After some debug i got some answer :

Context : my menu is render by core block menu in region.

For anonymous user, drupal add the tag node:id for every item in my menu.

if i remove the block, all node:id tag is removed.

So i have 2 solutions :

* For all user who hasn't **bypass node access** permission drupal add every tag from the menu block render.

So i can try to fix the access check on the menu

* Remove the drupal core block menu from region and build my own block programmatically and load my menu inside with menu\_tree service.

i have try the second point and since its not drupal who render my custom block, tags is not add.

But for me the best way is to find a way for fix the check access.

i can't clear all the node in the cache when someone edit a node in the menu.

For that i want use the tag menu\_link\_item but not the node:id...

# Answer
You don't need to render a node to bubble up its cache tag. There are other reasons, for example access checks, which heavily depend on the current user. A negative access check still could bubble up the node cache tag when the result depends on field values. So the tags of not rendered nodes could be unpublished nodes in views or menus. When you publish one of those nodes you want that the page gets refreshed to include the now published node.

---

**Edit**

You can replace the core menu block with a custom menu block, see

> **Rendering menus**
>
> Once you have created menus (that contain menu links), you want to render them. Drupal provides a block (Drupal\system\Plugin\Block\SystemMenuBlock) to do so.
>
> However, perhaps you have more advanced needs and you're not satisfied with what the menu blocks offer you. If that's the case, you'll want to:
>
> ...

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Menu%21menu.api.php/group/menu/8.8.x

By doing so you have the options to not use access checks at all, add your own version of an access check tree manipulator or use the core one and remove the cache tags from the tree access objects afterwards with AccessResult::resetCacheTags
> 3 votes

---
Tags: 8, caching
---


# Question
Title: How to make a private file visible after changing file URI?
My task is automatically convert image files to pdf, when they are attached to a certain field. So the field accepts both the images and pdf files, but converts uploaded images to pdf. The field saves files to private directory. If I do not apply the conversion, the files are accessible well. But when I apply conversion, I convert images to PDF then save the PDF file into the same directory with the same name but with .pdf extension using the following code in hook\_entity\_presave:

```
$file_field = $entity->get('field_invoice_file');
if ($file_field) {

  $file_value = $file_field->getValue();

  if ($file_value && !empty($file_value[0]['target_id'])) {
    $entity_manager = \Drupal::entityTypeManager();
    $file_entity = $entity_manager->getStorage('file')->load($file_value[0]['target_id']);

    if ($file_entity) {

      $filename = reset_m($file_entity->get('filename')->getValue()); //reset_m is my custom function that extracts string from an array of any deepness, do not focus on it
      $uri = reset_m($file_entity->get('uri')->getValue());

      $type = pathinfo($uri, PATHINFO_EXTENSION);

      if (in_array($type, ['png', 'jpg', 'jpeg', 'gif'])) {

        $file_dir_arr = array_reverse(explode('/', $uri));
        unset($file_dir_arr[0]);
        $file_dir = implode('/', array_reverse($file_dir_arr));

        $file_name_arr = array_reverse(explode('.', $filename));
        unset($file_name_arr[0]);
        $file_name_no_ext = implode('.', array_reverse($file_name_arr));

        $new_uri = $file_dir . '/' . $file_name_no_ext . '.pdf';
        $new_filename = $file_name_no_ext . '.pdf';

        mymodule_image_to_pdf($uri,
            $file_dir . '/' . $file_name_no_ext . '.pdf');

        $file_entity->set('filename', $new_filename);
        $file_entity->set('uri', $new_uri);

        $file_entity->save();
      }
    }

  }
}

```

I made sure that the pdf has been generated successfuly and can be opened in acrobat if downloaded and can be viewed in browser if it is in a public directory. So here is some permissions issue: http://mysite/system/files/myfile.pdf returns dark gray page with a little gray square with white borders in the middle of the page. If I upload pdf without conversion, it works good, if I upload an image without conversion, it also works good. If I use the same conversion behavior but with files in public storage it also works good. Please note that I do not get 403 or 404 error (I checked in browser console too), I get 200 response but it looks as I wrote above.

# Answer
> 1 votes
It sounds like Drupal is telling the browser that the PDF file is an image.

When you're modifying an existing file entity, `File::save()` will not change the `filemime` property of a file automatically. Drupal only does this during execution of `::preCreate()`.

The `filemime` property isn't being used when serving from the public dir, but is being used when serving from the private dir (where Drupal is serving the headers/payload instead of your web server).

Try executing `$file_entity->setMimeType('application/pdf')` or create a new file entity with your PDF artifact.

---
Tags: 8, files
---


# Question
Title: Composer issue after I deleted the vendor directory
We have Drupal 8.8.5 running on CentOS Linux 7 with PHP 7.1.33.

Was trying to update modules using composer. Composer said they were updated, but when I went into program, they weren't. In troubleshooting, I deleted the "vendor" directory. Now, I get this error:

> \[root@ip-172-31-13-94 master\]# composer update --with-dependencies Loading composer repositories with package information Updating dependencies (including require-dev) Your requirements could not be resolved to an installable set of packages.
>
> Problem 1 \- drupal/core-recommended 8.8.0 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.8.0-beta1 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.8.0-rc1 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.8.1 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.8.2 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.8.3 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.8.4 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.8.5 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.8.x-dev requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.9.0-beta1 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.9.0-beta2 requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- drupal/core-recommended 8.9.x-dev requires composer/installers v1.7.0 -\> satisfiable by composer/installers\[v1.7.0\]. \- Conclusion: don't install composer/installers v1.7.0 \- Installation request for drupal/core-recommended ^8.8 -\> satisfiable by drupal/core-recommended\[8.8.0, 8.8.0-beta1, 8.8.0-rc1, 8.8.1, 8.8.2, 8.8.3, 8.8.4, 8.8.5, 8.8.x-dev, 8.9.0-beta1, 8.9.0-beta2, 8.9.x-dev\].

Can someone tell us how to resolve this? Thanks!

# Answer
Resolved the issue:

$ composer selfupdate

Updating to version 1.10.5 (stable channel). Downloading (100%)
Use composer self-update --rollback to return to version 1.6.2

Appaprently, my version of composer was too old.
> 2 votes

---
Tags: composer
---


# Question
Title: How to check if the AMP module (Accelerated Mobile Pages) is working?
I'm testing the drupal AMP module (Accelerated Mobile Pages), well, I've installed it, pre-configured it (I've not created the subtheme..)but I've enabled it for one node (just for a test).

How can I test it ? Doing a google search on my browser ?

Thank you.

# Answer
> 0 votes
The first thing that needs to happen is to get it reindexed by Google so it knows about it. I suggest configuring Google Search Console on your site https://support.google.com/webmasters/answer/4559176?hl=en You can request it to be reindexed there. It was called Google Webmaster Tools before they rebranded it. Its as easy to set up as Google Analytics. It shows a display of what your site looks like on desktop, as Google sees it.

It does show you want it looks like ton AMP.

# Answer
> 0 votes
To test AMP you can go to the node's URL (http://localhost:4000/your-page) and add '?amp' to force Drupal to display the AMP theme. (http://localhost:4000/your-page?amp).

If the amp theme doesn't load, you either haven't configured your AMP subtheme properly in your repo or you haven't configured the AMP module properly within the Drupal admin panel.

If you want to check to make sure your AMP theme is AMP-valid you can install the Amp Validator Chrome Extension (https://chrome.google.com/webstore/detail/amp-validator/nmoffdblmcmgeicmolmhobpoocbbmknc?hl=en). It will be green if the page is valid. If not, it will be red with the number of errors. Click on the extension's icon to read more about each error.

---
Tags: 7, mobile-tools, google-search-console
---


# Question
Title: Include content created through InDesign/RoboHelp
Is there a way to display content under a Drupal site/url that is not managed by Drupal?

Specifically, we have a large manual (1700 pages) that is managed with Adobe InDesign which is used to create a printed version, one large PDF version, PDF versions of each chapter, and also an HTML version of the manual via RoboHelp. Because of the printing requirements, this is not content that we plan to migrate into Drupal (but we still need to display it on/through the site).

Example: Here is the page for the manual. You can see links for the Complete PDF and individual PDF chapters (which we would probably manage as Media - TBD). The question revolves around the HTML version of the manual. As you can see, at this point we have pretty much jumped out of the container of the hosting site (SharePoint), and are now displaying just the pure, rendered HTML that was generated out of InDesign/RoboHelp.

The content is updated annually and we have requirements to archive each version so that it is still accessible. Our current process makes it fairly easy because of the way that the /Manuals\_HTML1 folder is excluded from SharePoint so we just make a copy of the content and give it a new folder based on the year.

So, it doesn't appear to make sense to include this as actual content in Drupal. It feels like it would be some sort of exclusion within Drupal that essentially sends it outside of Drupal. Maybe a mod\_rewrite solution?

Brand new to Drupal and currently in a week-long training. Definitely learning tons about how to handle the rest of the site, but this one is an open item.

# Answer
> 0 votes
Looks like the correct term is HTML or static microsite. These can be managed via .htaccess as seen in Maintaining a static microsite alongside Drupal's docroot.

---
Tags: 8
---


# Question
Title: Javascript loaded via DrupalSettings variable not executing?
I have added a js library and associated code to get all Location nodes onto a Map page

This code works fine if I paste it into the map.js file but if I use the drupalSettings variable, the code is appearing in the map.js file but doesn't appear to be executing

The map.js file

```
(function ($, Drupal, drupalSettings) {

    'use strict';

    Drupal.behaviors.mybehavior = {
        attach: function (context, settings) {

            var map = L.map('mapid').setView([-38.037511118801255, 176.41345152203002], 13);

            var googleSat = L.tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',{
                maxZoom: 20,
                subdomains:['mt0','mt1','mt2','mt3']
            }).addTo(map);

            // the data from basic.theme file, basic_page_attachments_alter function
            // console.log(settings.basic.nr_map.foo);
            settings.basic.nr_map.foo;

        }
    };

})(jQuery, Drupal, drupalSettings);

```

And the code from the theme function

```
function basic_page_attachments_alter(&$page) {
  $node = \Drupal::routeMatch()->getParameter('node');
  if (!empty($node)) { // if empty its a view and has no bundle - causing 503
    $bundle = $node->bundle();
    if($bundle == 'map') {
      $mapid = $node->id();
      $nids = \Drupal::entityQuery('node')->condition('type','location')->execute();
      $nodes = \Drupal\node\Entity\Node::loadMultiple($nids);

      $out = '';

      foreach ($nodes as $key => $location) {
        $map_title = $location->getTitle();

        // lat, lon
        $latlong_arr = $location->get('field_mahere_location')->getValue();
        $lat = $latlong_arr[0]['lat'];
        $lon = $latlong_arr[0]['lon'];

        $out .= 'var ' . strtolower($video_title) . ' = L.popup({ closeButton: false, closeOnClick: false, autoClose: false, className: "static" }).setLatLng([' . $lat . ', ' . $lon . ']).setContent("<p class=\'location static\'>' . $map_title . '</p>").openPopup().addTo(map);' . PHP_EOL;
      }

      $page['#attached']['drupalSettings']['basic']['nr_map']['foo'] = $out;
      $page['#attached']['library'][] = 'basic/nr_map';
    }
  }
}

```

If I copy the code from the console i.e. console.log(settings.basic.nr\_map.foo) and paste it into the map.js file it runs perfectly and creates all of the map markers I'm after, but if it comes from the variable i.e. settings.basic.nr\_map.foo it doesn't execute, and doesn't create any map markers

Any ideas? It seems like it should be simple!

Apologies for the duplicate post but I haven't had any joy on drupal forum.

Thanks

EDIT: And the libraries yml file

```
nr_map:
  js:
    js/map.js: {}
  dependencies:
    - core/drupal
    - core/jquery
    - core/drupalSettings

```

# Answer
> 1 votes
Use `drupalSettings.basic.nr_map.foo` instead of `settings.basic.nr_map.foo` in your JavaScript.

# Answer
> 1 votes
Just to clarify the answer, which is in Anonymous' comment, the variable passed is text and will not execute as I expected. What I need to do is pass several variables and inject them into the js. Final code:

```
function basic_page_attachments_alter(&$page) {
  $node = \Drupal::routeMatch()->getParameter('node');
  if (!empty($node)) { // its a view??
    $bundle = $node->bundle();
    if($bundle == 'map') {
      $mapid = $node->id();
      $nids = \Drupal::entityQuery('node')->condition('type','location')->execute();
      $count = count($nids);
      $nodes = \Drupal\node\Entity\Node::loadMultiple($nids);

      $map_data = array();

      foreach ($nodes as $key => $location) {
        $map_title = $location->getTitle();

        // lat, lon
        $latlong_arr = $location->get('field_mahere_location')->getValue();
        $lat = $latlong_arr[0]['lat'];
        $lon = $latlong_arr[0]['lon'];

        $map_data[] = array($map_title, $lat, $lon);
      }

      $page['#attached']['library'][] = 'basic/nr_map';
      $page['#attached']['drupalSettings']['basic']['nr_map']['map_data'] = $map_data;
      $page['#attached']['drupalSettings']['basic']['nr_map']['count'] = $count;
    }
  }
}

```

And the js:

```
(function ($, Drupal, drupalSettings) {

'use strict';

Drupal.behaviors.mybehavior = {
    attach: function (context, drupalSettings) {
        if($('body').hasClass("page-mahere")) {

            var map = L.map('mapid').setView([-38.037511118801255, 176.41345152203002], 13);

            var googleSat = L.tileLayer('http://{s}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',{
                maxZoom: 20,
                subdomains:['mt0','mt1','mt2','mt3']
            }).addTo(map);

            // map_data array -> [0]=>Title, [1]=>Lat, [2]=>Lon
            for (var i = 0; i <= drupalSettings.basic.nr_map.count; i++) {
                var map_point = drupalSettings.basic.nr_map.map_data[i][0];
                map_point = L.popup({ closeButton: false, closeOnClick: false, autoClose: false, className: "static" }).setLatLng([drupalSettings.basic.nr_map.map_data[i][1], drupalSettings.basic.nr_map.map_data[i][2]]).setContent("<p class='location static'>" + drupalSettings.basic.nr_map.map_data[i][0] + "</p>").openPopup().addTo(map);
            }

        }
    }
};

```

})(jQuery, Drupal, drupalSettings);

Thanks heaps to Anonymous for putting me straight!

---
Tags: 8, javascript
---


# Question
Title: Unable to see page context in cache context
I created a page using Page Manager with Layout Builder. I created a path called: `/my-account/{agent_number}` witch allows me to create the `agent_number` string context. I created my own custom block and able to get the agent\_number like this:

```
$this->getContextValue('agent_number');

```

Now I build my block and would like to use contexts to cache my block:

```
/**
 * {@inheritdoc}
 */
public function build() {
  $data = get_expensive_data($this->getContextValue('agent_number'));
  return [
    '#theme' => 'my_custom_module',
    '#data' => $data,
    '#cache' => [
      'contexts' => ['agent_number'],
      'max-age' => 86400,
    ],
  ];
}

```

I created my own CacheContext service:

```
<?php

namespace Drupal\earc_card_details\Cache\Context;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;

/**
 * Defines the AgentNumberCacheContext service, for caching.
 *
 * Cache context ID: 'agent_number'.
 *
 * @see \Drupal\Core\Session\AccountProxy::setAccount()
 */
class AgentNumberCacheContext implements CacheContextInterface {

  /**
   * The context repository service.
   *
   * @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
   */
  protected $contextRepository;

  /**
   * Creates LanguageInterfaceContext object.
   *
   * @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository
   *   The context repository service.
   */
  public function __construct(ContextRepositoryInterface $context_repository) {
    $this->contextRepository = $context_repository;
  }

  /**
   * {@inheritdoc}
   */
  public static function getLabel() {
    return t("Agent Number");
  }

  /**
   * {@inheritdoc}
   */
  public function getContext() {
     $contexts = $this->contextRepository->getAvailableContexts();
     // Agent number is missing here.
     return $contexts['agent_number'] ?? '';
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheableMetadata() {
    return new CacheableMetadata();
  }

}

```

The problem is that `$this->contextRepository->getAvailableContexts()` does not return the `agent_number` context. Is there a way to get the page bulder context to appear here?

# Answer
Try a route based context extending RouteCacheContext:

Example:

```
<?php

namespace Drupal\Core\Cache\Context;

/**
 * Defines the RouteCacheContext service, for "per route name" caching.
 *
 * Cache context ID: 'route.name'.
 */
class RouteNameCacheContext extends RouteCacheContext {

  /**
   * {@inheritdoc}
   */
  public static function getLabel() {
    return t('Route name');
  }

  /**
   * {@inheritdoc}
   */
  public function getContext() {
    return $this->routeMatch->getRouteName();
  }

}

```

You can use this core example and get instead of the route name a route parameter.

You can improve cache efficiency and prefix the context name with `route.`. Cache contexts are ordered hierarchically, so that the caching system can remove specific cache contexts already covered by more general ones when merging cache metadata.

This leads to further considerations. If the block is only visible on a specific route and the route has only one parameter, then the core `route` context would have the same results as the custom context. So a specific route context only makes sense if you have too many cached block variations because the block is used in different routes or because of other route parameters and the context aware block plugin doesn't have already an appropriate cache context.
> 1 votes

---
Tags: 8, layout-builder
---


# Question
Title: Indexing the term of unpublished entities
I have a views of unpublished contents of content-type **X**, which has the Term Y.

It works fine with published content but a thing that I noticed is that if I unpublished a content that has a taxonomy term, in Views it loses the term associated with it, therefore I cannot filter my list based on taxonomy term anymore.

I also found Taxonomy Entity Index module but it doesn't work at all.

Also a related issue on drupal.org

Is there any workaround for this?

# Answer
> 1 votes
For anyone who might encounter the same issue:

It looks like that it's a common issue in D7 and unfortunately going to be in D8, but hopefully the fix will be in core for D9.

Right now we have to use TEI module as a workaround for D7 and D8.

If you are installing this module into an existing site, visit `admin/config/system/taxonomy-entity-index` to rebuild the Taxonomy Entity Index.

Also note that in Views there will be some new fields/filters to work with, for instance instead of `Content: Has taxonomy terms` in filters section of views, you should use `Taxonomy Entity Index: Has taxonomy terms on Nodes` and for exposing the taxonomy terms also you should use `Taxonomy Entity Index: Has taxonomy terms on Nodes` not the default `Content: Has taxonomy terms`.

# Answer
> 3 votes
"Lookup published nodes with this taxonomy term" is such a common use-case that the Taxonomy module keeps a `taxonomy_index` table in the database to optimize for it. This is what the `Content: has taxonomy term ID` views argument queries. Unfortunately, it is only for published content.

In Drupal 8, there is a workaround. Taxonomy term fields are just a special case of Entity Reference fields, which have their own views argument handler, and do not partake of this special index. So, if Content-type X has a 'Tags' field, you can build a view based around `Content: Tags (field_tags)`, and that will include unpublished content as you'd expect.

# Answer
> 0 votes
On Drupal 8 :

1. Apply the patch from this issue
2. Clear cache : `drush cr`
3. Updade database : `drush updb`

It works for me.

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


title: Call method form custom module Class

text:
# Question
Title: Call method form custom module Class
I tried to call a function inside other class inside the same module on D8 but I have some error on the code. I got a Error: Class 'Drupal\hospitator\TimeTrackerController\TimeTracker' not found.

My main controller (HospitatorController.php):

```
namespace Drupal\hospitator\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\hospitator\TimeTrackerController\TimeTracker;

/**
 * Class HospitatorController.
 */
class HospitatorController extends ControllerBase {

  /**
   * Main Page Function.
   *
   * @return array
   *   Return main page.
   */
  public function mainPage() {
    $element = array(
        '#type' => 'markup',
        '#markup' => $this->t('Welcome to Hospitator!') . '<br/>',
    );
    $test_controller = new TimeTracker;
    $test_text = $test_controller->start();

    return $element;
  }

}

```

My secondary class (TimeTracker.php):

```
<?php

namespace Drupal\hospitator\TimeTrackerController;

use Drupal\Core\Controller\ControllerBase;

/**
 * Class TimeTracker.
 */
class TimeTracker extends ControllerBase {

  /**
   * Test Time Trakcker.
   *
   * @return string
   *   Return test text.
   */
  public function start() {
    $element = 'Test';
    return $element;
  }

}

```

I have been 2 years without coding and my memory have some leaks. Can you help me? Tanhk you,

# Answer
> 1 votes
Since Drupal 8 supports PSR-4 namespaces, as described in the Drupal coding standards, in the Namespaces document page, Modules section, there must be a correspondence between namespace and directory structure. This means that, if *Drupal\hospitator\TimeTrackerController* is the namespace, then the class file must be placed in the *hospitator/src/TimeTrackerController* folder. Furthermore, if `TimeTracker` is the class name, then the file containing its code must be named *TimeTracker.php*.
I assume that *hospitator* is the machine name of the module. If the machine name is different, then *hospitator* must be replaced from the module machine name, in the namespace and in the folder name.

If the file containing the class code is in *hospitator/src/Controller/TimeTracker.php*, then the correct namespace is Drupal\hospitator\Controller, not *Drupal\hospitator\TimeTrackerController*. When you reference that class in a file that is using another namespace, you add `use Drupal\hospitator\Controller\TimeTracker;` on the top of that file, not `use Drupal\hospitator\TimeTrackerController\TimeTracker;`.

Also, if the `HospitatorController` and the `TimeTracker` classes are using the same namespace, which I assume is *Drupal\hospitator\Controller*, there is no need to add `use Drupal\hospitator\Controller\TimeTracker;` on the top of the file containing the `HospitatorController` class.

---
Tags: 8
---


title: How do I add a file upload button?

text:
# Question
Title: How do I add a file upload button?
I have a view and have styled the view with a Twig template. The view show nodes whose content type is *Programs*. I would like to add a *Upload* button in the view so that admininistrator users can add reports. The view structure is the following one.

>

Is this possible through the Drupal UI?

I created the *File upload* field as a file type, but it is allowing administrators to add files only through the node page.
Is there a way to make the upload button appear on the view itself?

# Answer
> 1 votes
There is a beta version of a module that can help you achieve this:

https://www.drupal.org/project/views\_entity\_form\_field

> This module provides the ability to add form field widgets to a view to edit multiple entities at one time.
>
> Form field options will show up in a View's "Add field" list, prefixed with "Form field: " and then the name of the field being added.

---
Tags: views, files
---


# Question
Title: Change existing configuration at theme installation
I am creating a custom Drupal 8 theme, and I want to change the image style of the indexed article content of the frontpage - only the article content type.

To do that properly - avoiding using CSS hack - I have to \*change the image style the image field of the display mode Teaser of the article content type\**, the display mode "teaser" is used by the native view "frontpage" to index content. And I have to do that modification at the theme installation and thus configure the theme properly to do that modification at installation. It's not working with conf file because the configuration already exist. i am asking here advice on how to do that.

**In details**: I need to change the image style of the field "field\_image" of the mode display "teaser" of the content type "article".

By default it use the image style "large" and I want it to use a new image style "hp\_wide" that the theme import - successfully - at theme installation.

From my research, I've found that I've to create a PHP function in MyThEme.theme with `\Drupal::configFactory()->getEditable($name)`, it is the correct way? If yes how can I target that specific field settings, how can I know the "path" of that settings?

# Answer
i've found a solution: define the style of the image directly into the twig template. As a theme can define **new** style of image when it is installed it's possible to use a non native style of image. In the example below i use the style "wide", created at the theme installation, instead of the native style "medium" used in the indexed content in the homepage.

```
 {% for item in content.field_image['#items'] %}
  {% set image = {
    '#theme':      'image_style',
    '#style_name': 'wide',
    '#uri':        item.entity.uri.value,
    '#alt':        item.alt,
    '#width':      item.width,
    '#height':     item.height
  } %}
  {{ image }}

```
> 1 votes

---
Tags: 8, configuration
---


# Question
Title: Show all user profiles and geolocated content on a map
I'm trying to create a map that shows user profiles and other geolocated content (for example, news and events). A view doesn't allow to mix users and other content. I know I can show content that is referenced from a user, but how can I accomplish this without references?

The users and the content share the same taxonomy, though.

edit:

I have tried rovr138 suggestion to no avail, I always get the error (below image) as soon as the both views share the same display name that i have set here:

> Error: Class 'Views' not found in combine\_views\_views\_pre\_render() (row 24 in /var/www/html/myproject/web/modules/custom/combine\_views/combine\_views.module)

Here's the code i adapted minimally:

```
use \Drupal\views\ViewExecutable;

function combine_views_views_pre_render(\Drupal\views\ViewExecutable $view) {
if($view->id() == 'page_test' && $view->current_display == 'map') {

  $args = []; //these are contextual filters on the view
  foreach ($view->argument as $argument_key => $argument_value) {
    if(is_string($argument_value->argument)) {
      $args[] = $argument_value->argument;
    }
    else {
      $args[] = $argument_value->argument[0];
    }
  }

  // Get user view
  $user_view = Views::getView('event_test');
  if (is_object($user_view)) {
    $user_view->setArguments($args);
    $user_view->setDisplay('map');
    $user_view->preExecute();
    $user_view->execute();
  }

  if (!empty($user_view->result)) {
    $view->result = array_merge($user_view->result, $view->result);
  }
}
}

```

# Answer
> 3 votes
Alternative,

Create your 2 views. Let's say they're called, `user_points` and `node_points` and both have a display called `map`.

You could then create a simple module that does,

```
use \Drupal\views\ViewExecutable;
use \Drupal\views\Views;

function hook_views_pre_render(ViewExecutable $view) {
  if($view->id() == 'node_points' && $view->current_display == 'map') {

    $args = []; //these are contextual filters on the view
    foreach ($view->argument as $argument_key => $argument_value) {
      if(is_string($argument_value->argument)) {
        $args[] = $argument_value->argument;
      }
      else {
        $args[] = $argument_value->argument[0];
      }
    }

    // Get user view
    $user_view = Views::getView('user_points');
    if (is_object($user_view)) {
      $user_view->setArguments($args);
      $user_view->setDisplay('map');
      $user_view->preExecute();
      $user_view->execute();
    }

    if (!empty($user_view->result)) {
      $view->result = array_merge($user_view->result, $view->result);
    }
  }
}

```

On your `node_points` view, you'll now have the results from `user_points`.

# Answer
> 1 votes
Here's something that I would do, but I'm not sure if it's the best way to do it.

* Create different views for the various entity types
    + Render these views as a JSON feeds
* Create a custom block which will simply include some JS code
    + Preferably render a DIV with a unique ID inside your block
    + Now, in the JS code, get the ID of unique DIV and render the map yourself.

Personally, I'd choose this solution so that views rendering doesn't get in my way. However, depending on your needs, this approach might be complex (if you want filters, etc).

Some alternate solutions: * Get views to render one of the maps (or an empty map) and add the data points yourself with your JSON feeds.

---
Tags: views, 8
---


# Question
Title: Need a current page's "Content Type" passed to a node.html.twig template (for a different content type) on page load, AND after ajax call
I'm trying to get the Content Type value of a node page (that the user is currently visiting - let's call it CT-1)... and feed that value as a variable into a DIFFERENT content type's node.html.twig template (CT-2). This CT-2 template is being used in a View output, displaying on a CT-1 page. Here's my code...

```
function custom_mods_preprocess_node(array &$variables, $hook) {
   if ($node = \Drupal::request()->attributes->get('node')) {
     $variables['pageNodeType'] = $node->getType();
   }
 }

```

Then I print out the pageNodeType variable into CT-2's node.html.twig template like so...

```
{% if pageNodeType == 'TYPE' %}
<div>TEST</div>
{% endif %}

```

This all works perfectly on page load. But when the view output is filtered with AJAX (via an exposed filter), pageNodeType becomes NULL, and therefore the "if statement" breaks with the CT-2 template.

What can I do to keep that variable active after an ajax update?

I tried leveraging..

```
\Drupal::request()->headers->get('referer');

```

..to pull the previous page, but it seemed like quite a task to get the Content Type via this approach. Is there a better way.

Thanks!!

Edit: May be related to this post as well... but no answers? Views with ajax get current node in hook\_views\_query\_alter

# Answer
Well, here's what I came up with... and it's working as needed. If there are issues with this approach, please feel free to critique. My backend skills leave much to be desired. Thanks!

```
function custom_mods_preprocess_node(array &$variables, $hook) {

// Get the current page's content type on page load
$node = \Drupal::routeMatch()->getParameter('node');
if ($node instanceof \Drupal\node\NodeInterface) {
  $variables['pageNodeType'] = $node->getType();
}

// Keeps the type available if an AJAX call happens
if (\Drupal::routeMatch()->getRouteName() == 'views.ajax') {
  $previousUrl = \Drupal::request()->headers->get('referer');
  $fake_request = Request::create($previousUrl);
  $url_object = \Drupal::service('path.validator')->getUrlIfValid($fake_request->getRequestUri());
  if ($url_object) {
    $route_params = $url_object->getRouteParameters();
    $ent_id = $route_params['entity_id'];
    $node = \Drupal\node\Entity\Node::load($ent_id);
    $variables['pageNodeType'] = $node->getType();
  }
}

```
> 0 votes

---
Tags: 8, ajax
---


# Question
Title: Display comment form without the comment thread
What are some ways of rendering a comment form without also displaying the comments?

What about creating a block contains the form? If that's possible, what are some links to documentation touching on that?

# Answer
To display comment form without comments list, you need to override `field--comment.html.twig` template, and remove the following lines:

```
  {% if comments and not label_hidden %}
    {{ title_prefix }}
    <h2{{ title_attributes.addClass(title_classes) }}>{{ label }}</h2>
    {{ title_suffix }}
  {% endif %}

  {{ comments }}

```

to override it:

1. From your theme, just create one of the following twig file in you templates folder, and put in it `field--comment.html.twig` content without the above section.

```

   * field--node--comment--article.html.twig
   * field--node--comment.html.twig
   * field--node--article.html.twig
   x field--comment.html.twig
   x field--comment.html.twig
   * field.html.twig

```

Note: the above suggestions for article content type, you may have different suggestions.

2. From your module, implement hook\_theme for one of the suggestions like the following:

```

/**
 * Implements hook_theme().
 */
function MODULENAME_theme($existing, $type, $theme, $path) {
  return [
    'field__node__comment__article' => [
      'base hook' => 'field'
    ],
  ];
}

```

And make your changes in `MODULENAME/templates/field--node--comment--article.html.twig`
> 3 votes

---
Tags: 8, comments
---


# Question
Title: Programmatically set the value of a date/Time field
I am trying to copy the value of a **Date/Time Webform element** to a **Date/Time field** set on the article node.

**Below is the source code of the Date/Time Webform element:**

```
expiry_date:
  '#type': datetime
  '#title': 'Expiry Date'
  '#title_display': before
  '#required': true
  '#required_error': 'You must add an expiry date'
  '#date_date_format': ''
  '#date_year_range': '2019:2100'
  '#date_time_format': ''

```

**Below is my custom handler:**

```
// Get an array of the values from the submission.
    $values = $webform_submission->getData();

    // Get 'Expiry Date' Value.
    $ExpiryDate = $values['expiry_date'];
    date_default_timezone_set('UTC');   // Sett the time to 'UTC' time zone.

    // Format the "Expiry Date" to return "Y-m-d\TH:i:s".
    //$FormattedExpiry = date('Y-m-d\TH:i:s', $ExpiryDate);

// Create a new "Article" node.
    $article = \Drupal\node\Entity\Node::create([
        'type' => 'article',
    // Set the node field values.
        'title' => $Title,
        'langcode' => 'en',
        'uid' => $CurrentUid,
        'status' => '1',
        'created' => $current_time,
        'field_expiry_date' => $ExpiryDate, // $FormattedExpiry,
        ]);

// Save the created node.
    $article->save()

```

**But I am facing the below error:**

```
Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'field_expiry_date_value' at row 1: INSERT INTO {node__field_expiry_date} (entity_id, revision_id, bundle, delta, langcode, field_expiry_date_value) VALUES (
:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5);
Array (
[:db_insert_placeholder_0] => 84
[:db_insert_placeholder_1] => 88
[:db_insert_placeholder_2] => article
[:db_insert_placeholder_3] => 0
[:db_insert_placeholder_4] => en
[:db_insert_placeholder_5] => 2021-05-25 11:26:02 +03:00
)
in Drupal\Core\Entity\Sql\SqlContentEntityStorage->saveToDedicatedTables() (line 1414 of /home/username/public_html/example.com/web/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).

```

# Answer
> 2 votes
The `expiry_date` from webform return something like `2021-05-25 11:26:02 +03:00` so you should to format it before you passe it to create like the following:

```
// Get 'Expiry Date' Value.
$ExpiryDate = $values['expiry_date'];
// Format the "Expiry Date" to return "Y-m-d\TH:i:s".
// Here use strtotime to format date correctly
$FormattedExpiry = date('Y-m-d\TH:i:s', strtotime($ExpiryDate));

```

Then passe `$FormattedExpiry` instead of `$ExpiryDate`:

```
$article = \Drupal\node\Entity\Node::create([
    'type' => 'article',
   // Set the node field values.
    'title' => $Title,
    'langcode' => 'en',
    'uid' => $CurrentUid,
    'status' => '1',
    'created' => $current_time,
    'field_expiry_date' => $FormattedExpiry,
    ]);

```

**Update:** your date already has +3h, if you want to not add 3 hours to your time there is two options i guess:

1. Change you webform field settings to work with UTC to get the value of `$values['expiry_date']` something like `2021-05-25 11:26:02` without `+03:00`
2. Remove the `+03:00` before date conversion from `$values['expiry_date']` by change the line `$ExpiryDate = $values['expiry_date'];` with something like:

`$ExpiryDate = explode('+', $values['expiry_date'])[0];`

---
Tags: 8, webforms, datetime
---


# Question
Title: Advanced CSS/JS Aggregation Module Breaks My Site Layout
When I enable my module Advanced CSS/JS Aggregation it breaks my site layout. Is there something I need to do before or after when enabling this module.

To fix the site layout I need to disable the Advanced CSS/JS Aggregation module and it works again.

# Answer
I faced the same issue, here is some steps to check:

1. check if your css loaded and optimised in your page source code some files like `/sites/default/files/css/css_QnKw33sohmgUyVqs9lGXvHTJTZsphXTkXdkVVmt25ts.css` if it's no check if there is any errors in your console, if this is the case **Check your status page and log messages, and permissions**
2. If it's yes all files well loaded **this is was my case** i had some css errors that's why even my css files loaded not taking any effect:
So i had to check / validate all my css files and correct any errors.
I used this https://codebeautify.org/cssvalidate.
there is a lot other websites to validate your css.
I hope this help you !
> 1 votes

---
Tags: performance, css-js-aggregation
---


# Question
Title: Programmatically get field definition for custom user profile fields
I created several custom user profile fields, including **Full Name** (a plain text field) and **County** (a List (text) field). They are displayed on the `/user/#/edit` form. I want to display these fields (and several others) in a different form I am generating via custom module code.

Question: Is it possible to extract the definition of a field, including its label, default value, and, in the case of **County**, the list of allowed values?

I imagine a field is an entity of some kind that can be extracted, but after much reading, I haven't seen how. I'm likely just not using the right terminology.

I could easily hard-code replicas of these fields in the PHP+HTML form, but I want to maintain the label, default value, list of allowable values, etc. for them in just one place--as part of the user profile. Thus, I want to extract their definitions and output them into the form I build.

# Answer
Yes you can get field definition programmatically with field name and entity name, by using `EntityFieldManager::getFieldDefinitions`. For your select list how to get allowed values check this example

```
 $options_array = [];
    $field_name = 'field_country_list';
    $definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions('custom_entity_name', 'bundle');

    if (isset($definitions[$field_name])) {
      $options_array = $definitions[$field_name]->getSetting('allowed_values');
    }

```

source : https://api.drupal.org/comment/63953#comment-63953
> 3 votes

# Answer
You can use a field widget from an entity form in a custom form as follows:

```
$entity_type = 'user';
$bundle = 'user';
// Alter accordingly if you are using custom form modes.
$form_mode = 'default';
$field_name = 'field_fullname';
$element_name => 'fullname';

if (!isset($form[$element_name]['#parents'])) {
  // Required widget to be embedded.
  $form[$element_name]['#parents'] = [];
}

$form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')->load($entity_type .'.' . $bundle . '.' . $form_mode);
if ($widget = $form_display->getRenderer($field_name)) {
  $items = $podcast->get($field_name)->filterEmptyItems();
  $form[$element_name] = $widget->form($items, $form, $form_state);
  $form[$element_name]['#access'] = $items->access('edit');
}

```

The resulting value is buried in the `$form_state->getValues()` array, and differs depending on the widget type, so you'll need to examine that array on submission to find the value you are looking for.
> 1 votes

---
Tags: 8, forms
---


# Question
Title: Folder permission errors on public:// after upgrade to 8.8.5
I'm new to this community, and asking for help because I'm stuck on this problem, and cannot go past. I've also tried asking on StackOverflow, but with no luck so far.

My current setup:

* **Drupal 8.8.5**
* CentOS Linux release 7.5.1804
* PHP 7.2.19 and HTTPD - Apache/2.4.6
* Run user/group: apache:apache

The **/admin/reports/status#warning** admin page reports that *"the sites/default/files directory is not writable. You may need to set the correct folder in the configurations of the File system page or change the permissions of the current folder so that it is writable."*

Obviously, this leads to a number of errors:

```
Drupal\Core\File\Exception\FileException: Failed to unlink file 'public://css/css_Y3zRgmC0P7yIXk_w_H9qyrPs3aMkKRv44SMfupbSCMc.css.gz'. in Drupal\Core\File\FileSystem->delete() (line 340 of/var/www/html/project/core/lib/Drupal/Core/File/FileSystem.php).

Warning: unlink(/var/www/html/project/sites/default/files/css/css_Y3zRgmC0P7yIXk_w_H9qyrPs3aMkKRv44SMfupbSCMc.css.gz): Permission denied in Drupal\Core\File\FileSystem->unlink() (line 124 of /var/www/html/synergie/core/lib/Drupal/Core/File/FileSystem.php)

The specified file 'temporary://fileuJjxaE' could not be moved to 'public://js/js_FKKJ_OhNvc7muQ1i_fQS6OJmZLsZnRvVhbbPaVlNwb8.js'.

Permissions for the file cannot be set for sites/default/files/translations

```

Now, I'm not a full expert on Drupal, but I've already tried doing all the possible basic things that these situations require on a linux system:

* **Setting all 777 to /var/www/html/project/sites/default and subdirectories**
* Changing owner of the directory aforementioned
* Manually debugging lines 124 and 340 of lib/Drupal/Core/File/FileSystem.php
* Sudoing on "apache" user with sudo -s /bin/bash apache and try to create/delete files from the command line (and it works)
* Writing custom scripts that run under apache:apache, outside Drupal, to see if they can manipulate public://. (they work)

I think the problem is not in the filesystem itself, because whatever combination of permissions doesn't work, I believe this problem is connected to Drupal itself.

Fact is, **if I write a custom script to write/read/move** files from/to the */var/www/html/project/sites/default/files*, it just works. It doesn't work "from within" Drupal.

As said before, I'm not a expert of all the "under the hoods" of Drupal like file settings, admin settings, drush, so I'm asking to you to try and issue this problem, because it's driving me crazy. Spent the last 10+ hours watching the command line and not understanding what's happening.

Kind regards,

Maurizio

# Answer
> 0 votes
**Update**:

Find current mode of SELinux and temporarily shut it down. "#" is for comment and can be removed.

```
Getenforce # see current mode.

getsebool -a # find al boolean values

Sudo setenforce 0 # shut it down, but will be back at reboot.

```

Try your thing. If that’s cause, just add rule to allow locations like /var/www/your Docroot.

SElinux will come back with reboot so to add a permanent rules for /var/www/drupal-document-root.

I do the following. Line 2 will work but won't survive rename & restorecon (line 3 will survive such things).

```
 ls -dZ /var/www/html  # See SELinux context of
 sudo chcon -R -t httpd_sys_content_t /var/www/html/drupal-document-root
 sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?"

```

I have also done the following in the past to give apache write permission.

```
# Selinux allow httpd read & write to /var/www/html/my-project
sudo chcon -R -t httpd_sys_script_rw_t /var/www/html/my-project/
sudo chcon -R -t httpd_sys_script_rw_t /var/www/my-Symfony-project/var/log/

```

SELinux references: https://access.redhat.com/documentation/en-us/red\_hat\_enterprise\_linux/7/html/selinux\_users\_and\_administrators\_guide/sect-managing\_confined\_services-the\_apache\_http\_server-types

Beside that, the following is what I do when I setup new site and run into this kind of thing.

1) cat /etc/http/http.conf | grep user , to see user Apache is running as 2) from the vhost file, check the document root Then follow it and make sure Apache can write to it 3) Check your docroot or Symlinks Post and show the following 1&2& then l would love to see Ls -al /document root that Apache is pointing to And output showing Apache user is in right group

Don't forget to reset your drupal permissions to the best practices after resolving the issue. look at 2nd answer of the following.

What are the recommended directory permissions?

Ps: assuming your not setting up multisite as few more things will be needed.

---
Tags: 8, media, files
---


# Question
Title: How to add a filter in view with list of values
I have a content type which has a Number(Integer) field.

I created a view. I would like to expose the price field as a filter to the public like the following with a list of price range.

In view \> filter criteria, I added the price field. How to add the list of values with price range?

# Answer
> 1 votes
To add a list of ranges you can use the **Grouped filters** option with Widget Type: Select, instead of Single filter.

Then you can add your groups below. Each group becomes an option in your select list.

---
Tags: views
---


# Question
Title: Loop through a multi value entity reference field working only on the first selected item
1) I have an entity reference view `articles_per_user` listing all nodes of type `article` authored by the current logged in user.

2) On the Article Entity, there is a taxonomy reference field `field_article_country` referencing the taxonomy vocabulary: "Countries" (One value is allowed)

3) On the User Entity, there is a multi-value taxonomy reference field `field_user_article_countries` referencing the same taxonomy vocabulary: "Countries" (Unlimited value are allowed)

4) On a Webform, I have an entity reference field `articles` referencing the above entity reference view 'articles\_per\_user' with unlimited values where the users can select one or more article.

5) When Webform is submitted, I want to:

1. Load each selected Article.
2. Get value of the `field_article_country`
3. Load the current logged in user entity.
4. Set the retrieved value to `field_user_article_countries`
5. Save the User entity.

**Quick Demonstration:**

Say the `Current User` selected on the Webform 3 articles where:

* **Article 1** has `field_article_country` = United States
* **Article 2** has `field_article_country` = Egypt
* **Article 3** has `field_article_country` = Spain

After the Webform is submitted, the `field_user_article_countries` at the User Entity must have 3 values selected:

* United States
* Egypt
* Spain

**The error I am facing** is at `field_user_article_countries`, I see only one value selected:

* United States

**Below is my code:**

```
// Function to be fired while submitting the Webform.
public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {

    // Load the account of current logged in user.
    $CurrentUid = \Drupal::currentUser()->id();
    $CurrentUser = \Drupal\user\Entity\User::load($CurrentUid);

    // Get the selected 'Articles' Value.
    $ArticleIDs = $values['articles'];     // NIDs

    // Load all "Articles" according to their IDs.
    $Articles = \Drupal\node\Entity\Node::loadMultiple($ArticleIDs);

    // Loop through loaded articles entities.
    foreach ($Articles as $Article) {

    // Get the "Article Country" Value from the loaded article.
    $ArticleCountry = $Article->get('field_article_country')->target_id;

    // Set the 'User Country' value on the user account.
    $CurrentUser->set('field_user_article_countries', $ArticleCountry);
    }

    // Save the User account.
    $CurrentUser->save();

}

```

# Answer
> 0 votes
```
foreach ($Articles as $Article) {

  // Get the "Article Country" Value from the loaded article.
  $ArticleCountry = $Article->field_article_country->target_id; // shorter way

  // Set the 'User Country' value on the user account.
  $CurrentUser->field_user_article_countries[] = ['target_id' => $ArticleCountry]; // use array

}

```

---
Tags: 8, nodes, webforms
---


# Question
Title: How can I programmatically change a system message?
I want to change or hide a message shown from the `CommentForm` class.

In my `entity_insert()` hook I either unset `$_SESSION['messages']` and add a new message or call `drupal_get_message($type, TRUE)`.

The problem is that the new message will be set before the one I want to change; if I unset the message array, the new message will be gone too.

I also tried to hook in the specific form and add a submission handler, but that doesn't work.

```
/**
 * Implements hook_form_FORM_ID_alter().
 */
function my_module_form_comment_form_alter(&$form, FormStateInterface $form_state) {
  $form['actions']['submit']['#submit'][]  = 'my_module_comment_form_submit';
}

/**
 * Submit handler.
 */
function my_module_comment_form_submit(&$form, FormStateInterface $form_state) {
  $message = $_SESSION['messages'];
}

```

How can I programmatically change a system message?

# Answer
System messages are stored in a Symfony Flashbag, so there is no need to hack session variables, which can change from version to version. In Drupal 8.5 a new Messenger service was introduced to encapsulate the symfony flash bag and you can delete messages with deleteAll():

```
\Drupal::messenger()->deleteAll();

```
> 7 votes

# Answer
I was seeking a similar solution. I found How can I remove a message shown from a different module? which show how to achieve it using `hook_preprocess_status_messages()`.

```
/**
 * Implements hook_preprocess_HOOK().
 *
 * @param $variables
 */
function mymodule_preprocess_status_messages(&$variables) {
  if(isset($variables['message_list']['status'])){
    $status_messages = $variables['message_list']['status'];
    foreach($status_messages as $delta => $message) {
      if (strpos((string) $message, 'The message that I am expecting') !== FALSE) {
        $variables['message_list']['status'][$delta] = "Some different message text";
      }
    }
  }
}

```
> 14 votes

# Answer
I think the answer might be not to use hook\_entity\_insert(). By that time, it is too late: the content has already been created, so the system will create the message accordingly.

As the hook\_entity\_insert documentation says: hook\_entity\_insert responds to the creation of a new entity.

Maybe try another hook from the Entity API, one that does not cause the unwanted message to be generated.
> 2 votes

# Answer
Drupal 8 delete message:

```
/**
 * Deletes status message after user registration.
 */
function YOURMODULE_user_register_form_submit($form, &$form_state) {
  $messenger = \Drupal::messenger();
  $messenger->deleteByType('status');
}

/**
 * Implements hook_form_alter().
 */
function YOURMODULE_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  switch ($form_id) {
    case 'user_register_form':
      $form['actions']['submit']['#submit'][] = 'forms_opm_user_register_form_submit';
      break;
  }
}

```
> 2 votes

# Answer
*Assuming the messages in question are `form_error`s from validation of the form:*

Rather than altering the messages after the fact you could override/replace the `#validate` function(s) that produce the errors in the first place (from hook\_form\_alter) and provide your own custom errors.
> 1 votes

# Answer
```
/**
 * Implements hook_preprocess_HOOK().
 */
function comment_limit_preprocess_node(&$variables) {
  if (in_array('node-max', $_SESSION['messages']['status']) && in_array('user-max', $_SESSION['messages']['status'])) {
    drupal_get_messages('status', TRUE);
    drupal_set_message(t('The comment limit for this node has been reached!'));
    drupal_set_message(t('Your comment limit has been reached!'));
  }
  elseif (in_array('node-max', $_SESSION['messages']['status'])) {
    drupal_get_messages('status', TRUE);
    drupal_set_message(t('The comment limit for this node has been reached!'));
  }
  elseif (in_array('user-max', $_SESSION['messages']['status'])) {
    drupal_get_messages('status', TRUE);
    drupal_set_message(t('Your comment limit has been reached!'));
  }
}

```

This looks a little prettier and it works.
> 0 votes

# Answer
You can do `unset($SESSION['_symfony_flashes']['status'][0])`. In my case, `unset($_SESSION['messages']['status'])` didn't work. Then I was able to do `\Drupal::messenger()->addMessage(t('My message here'))`.

Hope this helps someone.
> 0 votes

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


# Question
Title: Cannot install Composer because it doesn't contain any .info.yml files
Newbie using clean Drupal 8 install on a server. Installed module "International Telephone," but got error. Then I read that I needed to also install Composer. When I tried to install Composer, I received the error that there were .info.yml files.

I've spent hours researching without luck...

# Answer
**IMPORTANT EDIT (2020-04-28)**:

You are trying to install this project: https://www.drupal.org/project/composer

But that is not Composer -- it's a Drush extension for managing Composer.

From the project documentation:

> Composer is a PHP package management tool to help manage your project or libraries' dependencies. This project allows use of Composer from Drush.

Installing this module on the server will not allow you to manage your Drupal 8 project using Composer. You need to set up your Drupal 8 project correctly using Composer in the first place, and worry about getting it onto the server later (whether you use the modern DevOps way using git hooks to deploy, the old-school sysadmin way using `rsync` to deploy, or the stone-age way using SFTP with Filezilla or a similar GUI file transfer utility.)

**ORIGINAL ANSWER (2020-04-26)**:

Welcome to Drupal Answers!

Since you just started from scratch, you won't lose much work if you start from scratch again.

First, install Composer *on your local computer:* https://getcomposer.org/

*Don't try to install Composer on the server.* Depending on your hosting, it may be possible to do that, but it is seldom the best way to do things. Composer is a well-known memory hog, and many web hosts will not allow you to run `composer install` on the server. Even if it is allowed, it's a terrible misuse of RAM and CPU cycles on a production server. Don't do it.

Next, install a new Drupal 8.8 site on your local computer (here called "my-project") using the `drupal/recommended-project` template:

```
composer create-project drupal/recommended-project my-project

```

At this point, I recommend using `git init` to put your project in version control.

Then use Composer to manage project dependencies such as installing contrib modules:

```
composer require drupal/phone_international

```

You can create a `.gitignore` file to tell git to ignore the core, contrib and vendor directories, which will be recreated afresh whenever you run `composer install` (from instructions in the `composer.json` and `composer.lock` config files). This keeps your git repo and pull requests small by excluding hundreds of thousands of lines of open-source code that are common to all plain-vanilla Drupal 8 (or 9) projects.

Finally, you'll want to set up some method of deploying the code from your local computer to the server. For tips on that, see my other answer:

https://drupal.stackexchange.com/a/292006/80164

Note that you will probably want to see the local Drupal site in a browser before deploying the code to the server. There are many ways to accomplish this.

Personally I like to use Lando to manage my Drupal projects in Docker containers, but other options include Docksal, DDEV, Vagrant/Virtualbox, LAMP (Linux), MAMP (Mac), WAMP (Windows), XAMPP (Linux, Solaris, Windows, and Mac), and others.

There's a lot to learn, and many of your questions will be outside the scope of this forum (which primarily focuses on issues specific to Drupal core and developing custom module and theme code with Drupal APIs). You might get better support for general questions on Drupal Slack.

Assuming that you want to try Lando, you can install it with all its dependencies using the Hyperdrive installer script for Mac or Linux. Then navigate to the `my-project` directory you created with `composer create-project` and execute something like this:

```
lando init --source cwd --recipe drupal8 --webroot web --name my-project

```

That would set up Docker containers for your appserver and database with a default configuration suitable for a Drupal 8 project. Then you'd just type:

```
lando start

```

Then you can view your local site in the browser at http://my-project.lndo.site to finish installing it and configuring it. After this, you can use Lando to manage your project inside the Docker container. Type `lando` on a line by itself to see what tools are available (including Composer, Drush, Drupal Console, MySQL CLI, log viewer, and tools to import/export database backups.)

Make sure that every time you change the code, you commit it to git and test it locally before deploying it to the server. (Later, you might end up setting up different servers for Dev, Test and Live environments.)

Good luck, and happy Drupaling!
> 6 votes

---
Tags: installation, composer
---


# Question
Title: How to get Taxonomy Term Field Value in twig
I have a taxonomy term with the name 'Colors' and it has 1 image field called field\_color\_image. In my project I have a node type with a field type of Taxonomy term that refer to Colors. My aim is that I want to show the image in the Colors taxonomy to a node. I already used kint and it didn't really help. How do I achieve this? Thank you beforehand.

# Answer
> 5 votes
To get the url of your term reference image inside the node twig try:

```
node.field_color_term.0.entity.field_color_image.entity.uri.0.value

```

Change `field_color_term` by your field name.

There is another way by configuring the display of your content type and your term like the following:

1. Content type display should be like
2. Taxonomy term display should be like

After this configuration you can render your field type of Taxonomy term, it will show the image:

```
{{ content.field_YOURFIELDNAME }}

```

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


# Question
Title: PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table
In my site, I get the following error:

> PDOException: SQLSTATE\[42S02\]: Base table or view not found: 1146 Table 'cambodia\_ohchrProduction.ohchr\_cache\_block' doesn't exist: TRUNCATE {cache\_block} ; Array ( ) in cache\_clear\_all() (line 167 of /home/cambodiaohchr/public\_html/includes/cache.inc).

How can I fix problem?

# Answer
> 0 votes
This error happened to me before, I don't really know why but the only solution that I can really tell you (and it worked for me) is to get some **Database backup** that you may have saved (from a past date) and export the schemas from the tables **cambodia\_ohchrProduction** and **revision\_cambodia\_ohchrProduction** into your actual site .

Remember just the **schemas of those 2 tables**.

And that should work!

# Answer
> 0 votes
try to follow this steps they may work for you :

1. Connect to the **cambodia\_ohchrProduction** database and create the **ohchr\_cache\_block** table
2. clear the cache and test if you have no error.
3. remove the table that has been create at step 1 and clear the cache again.

---
Tags: database, blocks, caching
---


# Question
Title: Is there a way to tell composer about manually updated modules?
I am working on a drupal 8 site and tend to update some modules:

1. I run the `composer outdated 'drupal/*'` command and it shows me the list of modules need update.
2. Running `composer update drupal/module_name --with-dependencies` end up with discard changes output.
3. So I choose to update the module from admin interface, after updating db changes, the status report not shows any update anymore but running `outdated` command in composer list the modules again.

This means I somehow need to announce to composer about this manual update (I think by changing composer.json and/or composer.lock, but I did not find the flow of it, yet.

# Answer
Yes, in the sense if you want to hack `composer.lock` you can make Composer think it got updates it never downloaded.

That requires you to know what `composer.lock` properties have changed (like `content-hash` & `packages[*]`) and apply them manually to the file.

That said, doing this is breaking the entire purpose of Composer (`composer.json` represents a manifest of what you need & `composer.lock` represents a manifest of what Composer retrieved); you run the risk of breaking of what `composer.lock` should do (i.e. `composer install` on any machine will retrieve the exact same files as when you made your last updates); so you should really think about the impacts on other environments/hosts that use your `composer.*` files.

If you're committing to a Composer-driven process, it's better to troubleshoot why your dependencies aren't updating as other commentators have suggested (e.g. too broad versioning in `composer.json`, auto-dropped changes from a non-interactive run)
> 3 votes

---
Tags: updating, composer
---


# Question
Title: Check if it's the front page in the template
Im trying to show content when I'm on the front page of my Drupal 8 test website, but the content shows on every page:

```
{% if front_page %}
  <header role="banner">
    {% if logo %}
      <a href="{{ front_page }}" title="{{ 'Home'|t }}" rel="home">
        <img src="{{ logo }}" alt="{{ 'Home'|t }}"/>
      </a>
    {% endif %}
    <h1 style="color:black">TESTTESTTESTESTAET</h1>
<h1>test</h1

    {{ page.header }}
  </header>
{% endif %}

```

Why doesn't this work and how can I make this work?

# Answer
The variable you're looking for is called `is_front`:

```
{% if is_front %}

```

The available variables for a template are documented at the top of the .html.twig file, however there is also a set of default variables available to all templates (which are not documented in every single template). You can find them in \_template\_preprocess\_default\_variables().
> 31 votes

# Answer
Note that if you want to provide `$variables['is_front']` to templates that doesn't, you can add this into the concerned preprocess function.

```
function themename_preprocess_menu(&$variables) {
  try {
    $variables['is_front'] = \Drupal::service('path.matcher')->isFrontPage();
  }
  catch (Exception $e) {
    $variables['is_front'] = FALSE;
  }
}

```

It is done the same way in template\_preprocess\_page for `page.html.twig`.

Same answer here
> 26 votes

# Answer
Assuming that the template you are using is page.html.twig, then the variable you are looking for is `is_front`; `front_page` contains the URL of the front page, initialized in `template_preprocess_page()` with the following code.

```
$variables['front_page'] = \Drupal::url('<front>');

```

For other template files, Drupal doesn't provide any variables telling you if the user is visiting the front page. Using code similar to the one used from `template_preprocess_page()`, you can set that variable in the preprocess function for the template you are using.

```
function mymodule_preprocess_HOOK(&$variables) {
  // An exception might be thrown.
  try {
    $variables['is_front'] = \Drupal::service('path.matcher')->isFrontPage();
  }
  catch (Exception $e) {
    // If the database is not yet available, set the default value.
    $variables['is_front'] = FALSE;
  }
}

```

Replace `HOOK` with the template type (e.g. *field* for the field.hmtl.twig template).
> 5 votes

# Answer
You can get it directly in html.html.twig using root\_path. It is already output on line 31 to set the body class:

**{% if not root\_path %}**

CODE

**{% endif %}**
> 4 votes

# Answer
for field template this is the code that needs to be placed in mytheme.theme :

```
        function mytheme_preprocess_field(&$vars, $hook) {
          $element = &$vars['element'];
          if ($element['#field_name'] == 'field_page_paragraphs') {
            $vars['is_front'] = \Drupal::service('path.matcher')->isFrontPage();
          }
        }

```
> 1 votes

---
Tags: theming, 8
---


# Question
Title: Removing the upload button in managed files
I want to save a image file into my custom content type using forms api and `node_save()`.

The below code works fine but I also get the upload button as it default in managed\_file .

I don't want the upload button. So I tried `type=file` but it did not work. How can I remove the upload button ?

Also if you just select the file and submit the form it works so I really need to just find a way to remove the upload button.

```
$form['image'] = array(
    '#type' => 'managed_file',
    '#title' => 'File',
    '#upload_location' => 'public://my-files/'
);

```

# Answer
The work to separate out the `managed_file` element is done in `file_managed_file_process()`, which is the default `#process` function for that type of element.

To hide the upload button you need to implement your own simple `#process` function for the element:

```
function MYMODULE_my_form($form, &$form_state) {
  $form['image'] = array(
    '#type' => 'managed_file',
    '#title' => 'File',
    '#upload_location' => 'public://my-files/',
    '#process' => array('MYMODULE_my_file_element_process')
  );

  return $form;
}

function MYMODULE_my_file_element_process($element, &$form_state, $form) {
  $element = file_managed_file_process($element, $form_state, $form);
  $element['upload_button']['#access'] = FALSE;
  return $element;
}

```
> 20 votes

# Answer
@Clive code doesn't work for me

```
function MYMODULE_my_file_element_process($element, &$form_state, $form) {
  $element = file_managed_file_process($element, $form_state, $form);
  $element['upload_button']['#access'] = FALSE;
  return $element;
}

```

Invert params in the function's call does the trick

```
function MYMODULE_my_file_element_process($element, &$form_state, $form) {
  $element = file_managed_file_process($element, $form, &$form_state);
  $element['upload_button']['#access'] = FALSE;
  return $element;
}

```
> 0 votes

# Answer
You can try the Upload File Replace module:

> This is a small utility module that automatically stops Drupal from renaming new files upload via filefield CCK. When 2 files with the same name exist, the older files will be renamed.
> 0 votes

# Answer
Based in this tread I found the way to change the text “\['#value'\]” in the submit button to the file upload in the web form.

Put it in the template.php of your theme and its done.

```
function MYTHEME_form_webform_client_form_FORMID_alter(&$form, &$form_state) {
  $form['submitted']['photo_file_photo']['#process'] = array('MYTHEME_my_file_element_process');
}

function MYTHEME_my_file_element_process($element, &$form_state, &$form) {
  $element = file_managed_file_process($element, $form_state, $form);
  //$element['upload_button']['#access'] = FALSE;
  $element['upload_button']['#value'] = 'Put me in pls';
  return $element;
}

```
> 0 votes

# Answer
In Drupal 8 this works for me: (disable ajax for the field)

```
$form['document'] = [
  '#title' => $this->t('Document'),
  '#type' => 'managed_file',
  '#required' => TRUE,
  '#attached' => [
    'library' => [],
  ],
];

```

And add this to your\_theme.theme file: (hide the upload button).

```
/**
 * Implements template_preprocess_file_managed_file().
 */
function your_theme_preprocess_file_managed_file(&$variables) {
  switch ($variables['element']['#id']) {
    case 'edit-document':
      $variables['element']['upload_button']['#access'] = FALSE;
      break;
  }
}

```
> 0 votes

# Answer
Adding a element process hook works but seems like overkill to me. in situations like this where its just an visual thing, CSS is the best way to go IMO since every upload button has its own id anyway.

```
#edit-image-upload-button{
  display:none;
}

```
> -1 votes

---
Tags: 7, forms
---


# Question
Title: Create Group permission to grant view of all group content
I'm running Drupal 8.7.11 and Group 8.x-1.0-rc5.

I have a situation whereby I have \> 5,000 groups. The majority of the users are members of 10 groups. However I have a small set of users who need an overview of all content from all groups. I have had issues running the site when enrolling users into all of the groups, so I had to give them 'Bypass group access control' in order that they can use the site without it crashing.

However what I would like to do is create a new 'View all group content' permission, which skips the access check, but doesn't give the users the administrative access that comes with 'Bypass group access control'.

Does anyone have an example of how this might be achieved?

# Answer
As per their documentation "The permission layers explained" it should work like this:

> I want my site admins to be able to administer all groups without having to join them.
>
> Assign them a global role, e.g.: "Site admin", and then assign the "Administer group" \>permission to the matching advanced outsider role in the group type configuration \>section. Anyone with the "Site admin" role set to their account will be able to \>administer all groups they are not a member of.
> 0 votes

---
Tags: 8, group
---


title: Alter user's entity label method

text:
# Question
Title: Alter user's entity label method
By default the label() method of the user entity returns the username. So everywhere on the website where user references are used, the username is displayed.

I need to alter this method so everywhere the user name is displayed it will use my custom function. So instead of "custom\_user\_name" will display "Firstname Lastname" for example.

Any idea on how to achieve this? Thanks.

# Answer
> 5 votes
I'm not sure if there's a shortcut for that, but if not the steps are still quite minimal:

1. Sub-class the `\Drupal\user\Entity\User` class in a custom module, and override its `label()` method:

*mymodule/src/Entity/User.php*

```
namespace Drupal\mymodule\Entity;

use Drupal\user\Entity\User as CoreUser;

class User extends CoreUser {

  public function label() {
    return 'something new';
  }

}

```
2. Implement `hook_entity_type_alter()` to set the class for the User entity type:

```
function MYMODULE_entity_type_alter(&$entity_types) {
  $entity_types['user']->setClass(\Drupal\mymodule\Entity\User::class);
}

```
3. Rebuild the cache

# Answer
> 0 votes
The above example is not something you probably want to do, it may not work the way you want it to work. For example, default user listing will show you usernames with class override.

Also overriding the user class may not be even possible in some cases.

There is shortcut to edit the label with hook;

```
/**
 * Implements hook_user_format_name_alter().
 */
function MYMODULE_user_format_name_alter(&$name, \Drupal\Core\Session\AccountInterface $account) {
  $user = $account instanceof \Drupal\user\UserInterface ?
    $account :
    \Drupal::entityTypeManager()->getStorage('user')->load($account->id());
  $name = $user->get('my_field')->value;
}

```

---
Tags: 8, entities
---


# Question
Title: Add prefix / suffix to field by using template_preprocess_field
I remember in Drupal 7, this was possible. I need to add some HTML before a field and I don't want to edit it in the Twig file. Is it somehow possible to add prefixes / suffixes by using the `template_preprocess_field` function?

I already tried something like that, but with no success:

```
function MYTHEME_preprocess_field(&$variables, $hook) {
    $element = $variables['element'];
    if ($element['#field_name'] === 'field_genre') {
        $element[0]['#prefix'] = '<div class="project-info">';
    }
    if ($element['#field_name'] === 'field_duration') {
        $element[0]['#suffix'] = '</div>';
    }
}

```

# Answer
> 0 votes
to prefix a paragraph field, this needs to be put into mytheme.theme .

```
function mytheme_preprocess_paragraph(&$vars) {
  if (isset($vars['elements']['#paragraph']) && ($vars['elements']['#paragraph']->getType() == 'hp_dean')){
    //kint($vars);
    $vars['content']['field_hp_dean_title']['#prefix'] = '<div class="cont-wrap">';
    $vars['content']['field_hp_dean_more']['#suffix'] = '</div>';
  }
}

```

you can adjust this to your specific hook, like hook\_preprocess\_node and similar .

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


# Question
Title: Set value for date field in hook_form_alter
How can I set the default date for a date field in `hook_form_alter()`.?

I tried:

```
$form["field_price_date"]["und"][0]['value']['#default_value'] = $curDate;
$form["field_price_date"]["und"][0]['value']['date']['#default_value'] = $curDate;
$form["field_price_date"]["und"][0]['value']['date'] = $curDate;
$form["field_price_date"]["und"][0]['value'] = $curDate;

```

None of the above work.

# Answer
> 5 votes
The date field's a funny one, normally the field column name is the last in the array (like the first example you tried), and the default value is set on that.

For a date field though, the default value is an array, and it's one level further up, e.g.:

```
$form["field_price_date"]["und"][0]['#default_value']['value'] = $curDate;

```

For future reference, install the `Devel module` and use the `dpm()` function to print a breakdown of the form array to the screen (`dpm($form);`). It makes debugging this kind of thing so much easier.

# Answer
> 2 votes
On Drupal 8, here's an example to set a specific date time field value in a hook form alter :

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

/**
 * Implements hook_form_alter().
 */
function my_module_form_alter(&$form, FormStateInterface &$form_state, $form_id) {
  $date = strtotime(date('Y-m-d 00:00:00'));
  $form['field_datetime']['widget'][0]['value']['#default_value'] = DrupalDateTime::createFromTimestamp($date);
}

```

# Answer
> 1 votes
I was inspired by this response to try the Devel module to solve a similar problem. I tried it and it worked. I posted detailed instructions on how to obtain the field array structure for a field in order to modify it using hook\_form\_alter here: https://drupal.org/node/1243628#comment-7777329

I hope this helps someone the way the Devel module suggestion helped me.

# Answer
> 0 votes
This is the function I use to print the structure:

```
// Custom print for testing purposes
function prnt($element){
  print "<pre>";
  print_r($element);
  print "</pre>";
}

```

# Answer
> 0 votes
Please see below methods to set a value to a date field

Using hook\_form\_alter

```
$form["field_price_date"]["und"][0]['#default_value']['value'] = $new_date;

```

Using hook\_node\_submit or hook\_node\_presave (Saving the value to the database)

```
function MY_MODULE_node_presave($node)
  {
      $node->field_price_date['und'][0]['value'] =  '2014-09-23 00:00:00';
  }

```

Or if you need to save value of one custom field(defined in hook\_form\_alter) to another, see below codes.

```
function MY_MODULE_node_submit($node, $form, &$form_state) {
  if($node->type == 'my_node_type') {
    $test_date =  $form['test_date ']['#value'];
    //Ensure that $test_date format is '2014-09-23 00:00:00'
    $node->field_price_date['und'][0]['value'] =  $test_date ;
   }
}

```

I think it may help anyone who is searching for the solution.

---
Tags: entities
---


title: Alter paragraph fields in closed mode

text:
# Question
Title: Alter paragraph fields in closed mode
I was wondering if there is a way to alter paragraph fields when the paragraph is set to "closed" in the Edit mode setting of form display. Because in that case the `hook_field_widget_WIDGET_TYPE_form_alter` does not return any of the inline paragraph fields inside the `$element['subform']`

To give a little more details, there's a paragraph field that holds some more native fields within itself. When I am trying to add/edit the node with which it is attached, i want to alter some fields within the paragraph. Since the paragraph is closed the fields within will be rendered via ajax call on the fly. I was looking for a way to alter them during this ajax call, that is just before they get rendered in the form so that I can alter their attributes.

Any idea?

# Answer
I think there are two approaches you could take here. In the past I've successfully extended the InlineParagraphsWidget field widget in order to alter the form display for Paragraphs. I think that hook\_ajax\_render\_alter() might also be a good solution.

I have not used `hook_ajax_render_alter()`, but I have successfully extended `InlineParagraphsWidget` for the purpose of altering the AJAX response. Specifically, look into overriding the `::addMoreAjax()` and `::formElement()` methods.

Below is a simplified version of the `::addMoreAjax()` callback that I used. Use `$insert_element = parent::addMoreAjax($form, $form_state);` to get a reference to the triggering element.

```
public static function addMoreAjax(array $form, FormStateInterface $form_state)
    {
        $insert_element = parent::addMoreAjax($form, $form_state);

        // TODO: This is NOT the cleanest way to find the wrapper ID.
        // Find a cleaner way to get these values.
        $wrapper_id = explode('"', $insert_element['#prefix'])[1];
        $pos = strrpos($wrapper_id, '--');
        $wrapper_id = '#' . substr($wrapper_id, 0, $pos);

        // If you needed the field name.
        $field_name = end($insert_element['#parents']);

        $response = new AjaxResponse();
        $response->addCommand(new InsertCommand($wrapper_id, $insert_element));
        return $response;
    }

```

You will probably also want to provide validation by overriding `::elementValidate()`.

You will also likely need to implement hook\_field\_widget\_info\_alter() in order to make your new widget active.

```
function my_module_field_widget_info_alter(array &$info)
{

    $info['entity_reference_paragraphs']['class'] = MyCustomInlineParagraphsWidget::class;
    $info['entity_reference_paragraphs']['provider'] = 'my_module';
}

```

Happy coding!
> 1 votes

---
Tags: 8, forms, paragraphs
---


# Question
Title: How do I theme the core modal with twig?
Drupal 8 comes with built in modals.

This works:

```
<a href="/node/11" class="use-ajax" data-dialog-type ="modal">modal</a>

```

How can I style that modal using twig, to add new classes to the box? The intention is to take over the bootstrap style language.

# Answer
> 3 votes
Modals in Drupal are built with jQuery UI. If you want to add just some class to the modal window, you can make use of the `dialogClass` option.

```
<a href="/node/11"
  class="use-ajax"
  data-dialog-type="modal"
  data-dialog-options="{"dialogClass":"foobar"}">Click me</a>

```

or

```
\Drupal\Core\Link::createFromRoute(t('Click me'), 'entity.node.canonical', [
  'node' => 11,
], [
  'attributes' => [
    'class' => ['use-ajax'],
    'data-dialog-type' => ['modal'],
    'data-dialog-options' => \Drupal\Component\Serialization\Json::encode([
      'dialogClass' => 'foobar',
    ]),
  ],
]);

```

but that won't make you a Bootstrap modal. For that you could either dynamically load the node and build the markup completely following the Bootstrap sample with a button targeting a `<div>` with a certain ID (nah, probably not the best idea, performance-wise).

OR you could make use of view modes and the concept of the View Mode Page module.

> Create separate pages for different view modes for a given content type.

That is, you create a new view mode for your node type for example `mymodal`, where you display only the fields you need and where you have full control over the markup using a view-mode-specific template like for example `node--article--mymodal.html.twig`. Now you can build the markup exactly like Bootstrap needs it. And finally link to this node in that view mode: `/node/11/mymodal`

or

```
\Drupal\Core\Link::createFromRoute(t('Click me'), 'view_mode_page.display_entity', [
  'view_mode' => 'mymodal',
  'entity_type' => 'node',
  'entity_id' => 11,
], [
  'attributes' => [
    'class' => ['use-ajax'],
    'data-dialog-type' => ['modal'],
  ],
]);

```

The only thing that would be missing now is to hide the jQuery UI modal title bar, `'title': FALSE` didn't do it. But just CSS would do.

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


title: Custom Field into Custom Form

text:
# Question
Title: Custom Field into Custom Form
I created a custom field to read qr codes from camera and it's working fine. Now I want to use this field or field widget in a custom form on the same custom module. Is it possible? Thank you,

Field Formatter

```
namespace Drupal\hospitator_qr_decode\Plugin\Field\FieldFormatter;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;

/**
 * Plugin implementation of the 'hospitator_qr_decode_formatter_type' formatter.
 *
 * @FieldFormatter(
 *   id = "hospitator_qr_decode_formatter",
 *   label = @Translation("Hospitator QR Decode field formatter"),
 *   field_types = {
 *     "hospitator_qr_decode_field_type"
 *   }
 * )
 */
class HospitatorQrDecodeFormatterType extends FormatterBase {

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {}

}

```

Field Type

```
namespace Drupal\hospitator_qr_decode\Plugin\Field\FieldType;

use Drupal\image\Plugin\Field\FieldType\ImageItem;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\SNcEH1C3UXSaTcNMHNLGNuLZqjGKbSrEMZce;
use Drupal\Core\TypedData\DataDefinition;

use Drupal\Core\Field\FieldStorageDefinitionInterface;

/**
 * Plugin implementation of the 'image' field type.
 *
 * @FieldType(
 *   id = "hospitator_qr_decode_field_type",
 *   label = @Translation("Hospitator QR decoder"),
 *   description = @Translation("This field stores the ID of an image file from webcam as an integer value."),
 *   category = @Translation("Reference"),
 *   default_widget = "hospitator_qr_decode_widget",
 *   default_formatter = "image",
 *   column_groups = {
 *     "file" = {
 *       "label" = @Translation("File"),
 *       "columns" = {
 *         "target_id", "width", "height"
 *       },
 *       "require_all_groups_for_translation" = TRUE
 *     },
 *     "code" = {
 *       "label" = @Translation("Hospitator QR code decoder"),
 *       "translatable" = TRUE
 *     },
 *   },
 *   list_class = "\Drupal\file\Plugin\Field\FieldType\FileFieldItemList",
 *   constraints = {"ReferenceAccess" = {}, "FileValidation" = {}}
 * )
 */
class HospitatorQrDecodeItem extends ImageItem {

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {}

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {}

  /**
   * {@inheritdoc}
   */
  public function fieldSettingsForm(array $form, FormStateInterface $form_state) {}

  /**
   * {@inheritdoc}
   */
  public function storageSettingsForm(array &$form, FormStateInterface $form_state, $has_data) {}

}

```

Field Widget

```
namespace Drupal\qr_decode\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\image\Plugin\Field\FieldWidget\ImageWidget;
use Drupal\hospitator_qr_decode\Plugin\Field\FieldType\HospitatorQrDecodeItem;

use Zxing\QrReader;

/**
 * Plugin implementation of the 'hospitator_qr_decode_widget_type' widget.
 *
 * @FieldWidget(
 *   id = "hospitator_qr_decode_widget",
 *   label = @Translation("Hospitator Qr code widget"),
 *   field_types = {
 *     "hospitator_qr_decode_field_type"
 *   }
 * )
 */
class HospitatorQrDecodeWidget extends ImageWidget {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {}

  /**
   * Form API callback: Processes a image_image field element from webcam.
   *
   * Expands the image_image type to include the alt and title fields.
   *
   * This method is assigned as a #process callback in formElement() method.
   */
  public static function process($element, FormStateInterface $form_state, $form) {}
}

```

And the custom Form

```
/**
 * @file
 * Contains \Drupal\hospitator_user_interface\Form\TimeTrackerForm.
 */
namespace Drupal\hospitator_user_interface\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class TimeTrackerForm extends FormBase {
  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'time_tracker_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['clock'] = array(
      '#type' => 'checkboxes',
      '#options' => array(
        'clock_in' => $this->t('Clock In'),
        'clock_out' => $this->t('Clock Out')),
      '#title' => $this->t('Select Clock Status'),
      '#required' => TRUE,
    );

    $form['actions']['#type'] = 'actions';
    $form['actions']['submit'] = array(
      '#type' => 'submit',
      '#value' => $this->t('Send'),
      '#button_type' => 'primary',
    );
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    if($form_state->getValue('clock')){
      drupal_set_message($this->t('Clock In submitted!'));
    }
    else{
      drupal_set_message($this->t('Clock Out submitted!'));
    }
  }
}

```

I just want to include my custom field and widget into my custom form.

# Answer
> 0 votes
Finally I solved the problematic creating an empty representative entity form time\_tracker and got the widget with EntityFormDisplay.

```
$node = \Drupal::service('entity_type.manager')->getStorage('node')->create(array('type' => 'time_tracker'));

$entity_form_display = \Drupal::service('entity_type.manager')->getStorage('entity_form_display')->load('node.time_tracker.default');

if ($widget = $entity_form_display->getRenderer('field_clock')) {

  $items = $node->get('field_clock');
  $items->filterEmptyItems();

  $form['tracker'] = $widget->form($items, $form, $form_state);
}

```

---
Tags: 8
---


# Question
Title: Load node by value of a field and update value for another field
I'm trying to load a node by a value in a custom field (field\_one) to change the value of another custom field (field\_two) on that node.

I am using the following code to load the node:

```
$nodes = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->loadByProperties(['field_one' => $fieldValue]);

```

I am then trying to update the value of "field\_two" using the following code:

```
if ($node = reset($nodes)) {

    $node->set('field_two', 'New value');
    $node->save();
}

```

The above results in the error "InvalidArgumentException: Field field\_two is unknown... "

It works if I try to set the value of the title ( $node-\>set('title', 'New value') ) but I can't get it to work for custom fields?

# Answer
> 2 votes
Thanks to the comment by @No Sssweat I realized that I simply needed to specify a content type:

```
$nodes = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->loadByProperties(['field_one' => $fieldValue, 'type' => 'CONTENT_TYPE']);

```

---
Tags: nodes
---


# Question
Title: How to automatically uninstall a module before running a Nightwatch test?
I'm able to run Nightwatch without any problem but I would like to uninstall the Recaptcha module before running my test since the Recaptcha is preventing me from autosubmitting without passing the test.

I'm importing my DB in the `phpunit.xml` file in the core directory.

May be there are some hooks I could use?

# Answer
> 0 votes
I ended up using the Node `exec` command to call drush like this:

```
module.exports = {
  '@tags': ['picostat'],
  before: function(browser) {
    const { exec } = require("child_process");
    exec("drush pmu recaptcha")
  },
  'Check a dataset was likely created correctly.': (browser) => {
    browser
      .drupalRelativeURL('/node/add/dataset')
      .waitForElementVisible('body', 2000)
      .assert.containsText('body', 'Create Dataset')
      .setValue('#edit-title-0-value', 'Test Dataset')
      .click('#edit-field-dataset-input-method-file')
      .click('#edit-field-dataset-header-false')
      .setValue('input[name="body[0][value]"]', 'Test dataset body')
      .end();
  }
};

```

---
Tags: 8, testing
---


title: Create a View from custom database

text:
# Question
Title: Create a View from custom database
I love the features the view provides in Drupal. Sortable tables, Filters, as well as ability to use external modules like views bulk export. My problem is that I want to display a separate database (Call this X), using views. What would be the best way to go about it?

To get around this problem in Drupal 6, I created a content type with all fields that were in Database X, then I created view for that content type by frontend. After that I used hook\_pre\_render\_view() to push data from X to the view. Right now I want to achieve similar results in Drupal 8. I could use this same approach but it doesn't feel very Drupally. I was wondering if there is a better way to achieve this.

# Answer
You can connect a external database inorderto let Drupal Know about it:

```
$databases['external']['default'] = array(
  'database' => 'custom_database',
  'username' => 'root',
  'password' => '',
  'prefix' => '',
  'host' => php_sapi_name() == 'cli' ? '127.0.0.1' : 'localhost',
  'port' => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
);

```

Then you can connect to that database:

```
/*
* Switch to external db
*/
\Drupal\Core\Database\Database::setActiveConnection('custom_database');

/*
* Get connection
*/
$db = \Drupal\Core\Database\Database::getConnection();

```

Then do you stuff and don't footgrt to switch again to the standard database:

```
/*
* Switch back
*/
\Drupal\Core\Database\Database::setActiveConnection();

```

You can store your external database info into a content type programatically and the show in views.
> 0 votes

# Answer
You can by using the Views Database Connector module.

> Views Database Connector is a powerful module that gives Views full access to external database tables found in the settings for your Drupal installation. With this module, you can setup a view around any table in any database configuration. This can be extremely useful to pull external data from a database to show to your users in a view.

See README.txt on how to use.
> 0 votes

---
Tags: views, 8
---


title: Paragraph contextual filter

text:
# Question
Title: Paragraph contextual filter
I would like to create "related item" with paragraphs.

I have 2 content type using paragraph field. This paragraph field has different options, like "quotes, related items, slider" etc.

I want to get some fields from "related item". "Related item" field is a "Entity reference".

Inside paragraphs type I have one called "related item"

Inside this I have a field type "entity reference"

I have different pages where I can add this paragraph and choose the entity.

I want to get specific fields from this entity type.

I know I can acomplish this with a view, relationship and contextual filters, but I don't how to do this with a paragraph or if it is possible.

# Answer
> 2 votes
You may have to jump through several hoops to get the data from the entity reference field.

```
  // Query entity types
  $query = \Drupal::entityQuery('node');
  $query->condition('status', 1);
  $query->condition('type', 'your_content_type');
  $entity_ids = $query->execute();

  // Query paragraph types
  $paragraph = \Drupal::entityQuery('paragraph');
  $paragraph->condition('status', 1);
  $paragraph->condition('type', 'paragraph_type');
  $paragraph_ids = $paragraph->execute();

  // Loop through entity IDs
  $paragraph_output = array();
  foreach($paragraph_ids as $pid){

    // Load each paragraph
    $paragraph = Paragraph::load($pid);

    // Load each entity reference field
    $entity_id = $paragraph->get('field_entity_identifier')->getValue();

    // Get entity parent Node ID
    $parent_node = \Drupal::entityManager()->getStorage('node')->load($parent_id[0]['value']);

    // You'll need to insert another foreach loop here drilling down further into the node that is being referenced.

  }

```

First you have to loop through the content types. Then you have to look to see if those paragraphs are set and have data. Then you loop through the paragraph types data and get the nodes they reference. Then you have to loop referenced nodes.

It's not an exact solution, but it's how I load data in modules and create my own API endpoints for some fairly heavy frontend javascript applications.

---
Tags: 8, paragraphs
---


# Question
Title: Duplicate value fields when creating relationships field collection of views
I have a problem need help. I created one field collection (unlimited value) for content type. Then I create 1 views to ren value fields in tables. I created relationship field collection for the that views and have a problem that the fields of the node duplicate value by the number of the field collection values. How can I remove duplicate of the field value in that content type.

# Answer
on right hand **others** \>\> **query settings** of you view there is one distinct checkbox enable it. Which will distinct your result
> 1 votes

# Answer
You can apply `group by` or `distinct` by enabling views aggregation settings to remove duplicate records.

1- in advanced » other section by enabling `use aggregation`: yes 2- in `fields` or filter criteria section, select and apply aggregation settings for which fields you want to group by or distinct.
> 1 votes

# Answer
This worked for me i had movies and cast list so when i enabled the aggregation field all the actors of a movie in cast list were separated in different rows. In the Aggregation settings of the field(cast list) , choose **aggregation type: group results together**( which is by default) and **group column : entity ID**( by default it was target id) and your duplicates should be removed.
> 0 votes

---
Tags: views, entities
---