---
# System prepended metadata

title: Drops of Drupal

---

# Drops of Drupal

## Deploy Hook

Have you been in a situation where a website update includes configuration changes and data update based on those congirations changes?   



## Drupal Slack

Need advice or help?  Slack is a valuable resource.

"Slack is a proprietary, but free to use, platform for real-time threaded online chat. Chatting is organized into Slack workspaces, and within workspaces, into channels. The Drupal community has a primary Slack workspace known simply as "Drupal", which has over 800 channels. Subsets of the Drupal community have also created their own separate workspaces for discussions of particular topics, in particular languages, or in particular geographical areas."

Join [Drupal Slack](https://www.drupal.org/community/contributor-guide/reference-information/talk/tools/slack).

### Channels

There are channels for general topics, specific topic, modules and intiatives.  You can join and existing channel are create a new one.   Start by browsing the existing channels. 

![](https://hackmd.io/_uploads/BkG-72vs3.png)

### Using
**For example**, if (when) you are are switching from CKEditor4 to CKEditor5, you may have some questions.  When the online documentation doesn't answer your questions, Join the CKEditor5 channel.

Before posting a question, do a little research with 

**Bookmarks** - At the top of the channel, you may find shortcuts to useful resources.

![](https://hackmd.io/_uploads/rJCkLnvs2.png)

**Search** - Use the search inside the channel, your issue may have some previous or ongoing discussions.

![](https://hackmd.io/_uploads/SyN8I2woh.png)






## Drops of Drupal

**#14 Dynamic Entity Query Based on Moderation State**

by Martin Anderson-Klutz

As part of my ongoing work on the Event Platform modules for organizing DrupalCamps and similar events, I wanted to add to the recently introduced Scheduler interface, by allowing a site builder to specify a list of workflow (content moderation) states that would be used to restrict which sessions (or other content types) to list. After, it wouldn't make sense to ask an editor to have to pick through the rejected sessions as part of the scheduling interface.

In looking for solutions to filter on content moderation state, the existing solution I was able to find adds a tag to the query:

```
/** @var \Drupal\node\NodeStorage $storage */
$storage = \Drupal::entityTypeManager()->getStorage('node');
$query = $storage->getQuery()
  ->addTag('moderation_state')
  ->condition('type', $content_types, 'IN');
$result = $query->execute();
```

And then, in the module file, it implements a hook to alter the query using a hard-coded definition of what state(s) to check for:

```
/**
 * Implements hook_query_TAG_alter().
 */
function event_platform_scheduler_query_moderation_state_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  $query->addJoin('LEFT', 'content_moderation_state_field_data', 'md', 'md.content_entity_revision_id = base_table.vid');
  $query->condition('md.moderation_state', 'archived', '<>');
}
```

My challenge was that I wanted the list of moderation states to be configurable, so a site builder could customize in which states content would be listed in the scheduler, particularly since they can also customize which content types are available, and they may not all use the same workflow, or content moderation at all.

It turns out, there's a relatively simple fix — add the desired moderation states to the query's metadata:

```
$query = $storage->getQuery()
  ->addTag('moderation_state')
  ->condition('type', $content_types, 'IN')
  ->addMetaData('states', $moderation_states);
```

Then, in the hook implementation, load these to be used in the condition:

```
function event_platform_scheduler_query_moderation_state_alter(AlterableInterface $query) {
  $states = $query->getMetaData('states') ?? [];
  if ($states) {
    $query->addJoin('LEFT', 'content_moderation_state_field_data', 'md', 'md.content_entity_revision_id = base_table.vid');
    $query->condition('md.moderation_state', $states, 'IN');
  }
}
```
[source post](https://www.mandclu.com/blog/dynamic-entity-query-based-moderation-state)

**#013 Symfony Components**

Symfony is a PHP framework used by Drupal.   Symphony components are decoupled libraries that provide common features and functionalities for PHP applications.    Drupal is using fourteen Symfony components.  You can find  them required in core/composer.json:

```
"symfony/console": "^4.4",
"symfony/dependency-injection": "^4.4",
"symfony/event-dispatcher": "^4.4",
"symfony/http-foundation": "^4.4.7",
"symfony/http-kernel": "^4.4",
"symfony/mime": "^5.4",
"symfony/routing": "^4.4",
"symfony/serializer": "^4.4",
"symfony/translation": "^4.4",
"symfony/validator": "^4.4",
"symfony/process": "^4.4",
"symfony/polyfill-iconv": "^1.26",
"symfony/polyfill-php80": "^1.26",
"symfony/yaml": "^4.4.19",
```

A complete list of Symfony components are available at [https://symfony.com/components](https://symfony.com/components) 

As a developer you can use the functionality provided by the Core required components or install other components in your  Drupal project. 

Plural and Singular Word Conversion

The Symfony componment [String](https://symfony.com/doc/current/components/string.html) includes Inflector, a class to convert words to/from singular/plural.   This is a good example of using a Symfony component.  

For example:

```
composer require symfony/string
```


```
use Symfony\Component\String\Inflector\EnglishInflector;

$inflector = new EnglishInflector();

$singular = $inflector->pluralize('car');      // ['cars']
$singular = $inflector->pluralizee('goose');   // ['geese']
$singular = $inflector->pluralize('person');   // ['persons','people']

```




**#012** Shortcuts

The Drupal administration menu is vast and there are likely a few pages you access most often.   Drupal Shortcut allow you to create quick access to specific pages.


**#011 Examples for Developers**

The [Examples for Developers module](https://www.drupal.org/project/examples) is described as "The Examples for Developers project aims to provide high-quality, well-documented API examples for a broad range of Drupal core functionality."

After installing Examples for Developer, you get 33 example categories to enable.  

![](https://hackmd.io/_uploads/rkd51VJP3.png)

Each example category has various various working examples.  For instance, enabling AJAX Examples, provides the following examples:

![](https://hackmd.io/_uploads/ByYBgNkD3.png)


This is a great was learn new techniques and get a coding starting point to work with.   




**#010 Applying a patch with Composer**

While working on your website, you found a patch that fixes your issue.   Now you need to install a patch, but how?

**Step 1**: install the [composer patches project](https://github.com/cweagans/composer-patches).   "Simple patches plugin for Composer. Applies a patch from a local or remote file to any dependency installed by Composer."

```
composer require cweagans/composer-patches
```
**Step 2**:  Add a "patches" section to the "extra" section of your composer.json file.

```
{
    [...],
    "extra": {
        "patches": {
            "the/project": {
                "This is the description of the patch": "https://www.example.com/path/to/file.patch",
                "This is another patch": "https://www.example.com/different/path/to/file.patch"
            }
        }
    }
}
```

Example:

```
    "extra": {
        "patches": {
            "drupal/layout_paragraphs": {
                "Removes icon image thumbnail": "patches/removes-icon-from-layout-paragraph-select.patch"
            },
            "drupal/paragraphs": {
                "fixes add to library checkbox": "https://www.drupal.org/files/issues/2022-09-15/3090101-29.patch"
            },
            "drupal/core": {
                "Fixes deploy Base Field Overrides": "https://www.drupal.org/files/issues/2019-12-24/2321071-39.patch"
            },
            "drupal/entity_reference_revisions": {
                "Fixes isue of not changing non-tranlatable fields" : "https://www.drupal.org/files/issues/2020-06-09/3150084_2.patch"
            }
        },
```

Resources: 
[How to apply patch in Drupal 9 with composer](https://vazcell.com/blog/how-apply-patch-drupal-9-composer)
[Composer Patches Documentation](https://docs.cweagans.net/composer-patches/)



**#009 Drupal.org Switching Admin Theme from the Command Line**

To get the current admin theme:

```
drush config:get system.theme admin
```

To set the admin theme, use the theme's machine name:

```
drush config:set system.theme admin claro
```




**#008 Drupal.org URL Shortener**

dgo.re is a url shortener for Drupal.org.   For example:

**Projects**

`dgo.re/pathauto` takes you to  `https://www.drupal.org/project/pathauto`

**Issues**

`dgo.re/i/pathauto` takes you to `https://www.drupal.org/project/issues/pathauto`



Also availble, shortcuts for Git Repositories, Project Docs, API, Sandboxes, Node numbers, Comments, Users and Groups. 

Read more at https://dgo.re

**#007 Drupal Slack**

There are over 1,000 channels on Drupal Slack to interact with other Drupalers.   If you have modules or topics you are intested in, search for them Channels -> Manage -> Browse Channels.



Some important onces:

#announcements
#support
#security-team
#security-discussion
#talkingdrupal   :)

Don't be shy, I expect you will be enjoy the interaction and support. 




**#006 Learn from Minimal**

A good way to learn what functionality is provided in each Core module and how they interact with each other is to install the Minimal Profile.

During the installation process, the Standard Profile is the default profile.   Choosing the Minimal profile will install and configure the modules necessary to get started.

![](https://i.imgur.com/lOGvZjY.png)

After installation, you will be surprised to see a home page like this.

![](https://i.imgur.com/76coGCm.png)

Happy configuring!




**#005 Multisite Module Clean Up**

During the lifetime of a project you need to remove modules not being used.  Using `drush pm:list` you can find disabled non-core modules, which are candidates for `composer remove`.    Module cleanup can be challenging for a multisite because one site may have a module installed and another may not.  

This Drop provides an approach for gathering the information you need to make multisite`composer remove` decisions.   The script below exports a list of disabled modules of each site to the .csv file.  It also combines the results to a single .csv file.


The script below is uses Lando for a local environment, drush and Miller (https://miller.readthedocs.io) for manipulating the CVS file.  

```
#!/bin/bash

# List of drush alias for each multisite
SiteList="site1 site2 site3 site4"

# Loop through the list of sites
for site in $SiteList; do
 # Run drush pm:list againts dev environment and export to a .csv file
 lando drush @$site.dev pm:list --status=disabled --fields="package,name,status" --no-core --format=csv > $site.csv
 # Remove last line of .cvs file, a drush disconnect message, you may not need this
 sed -i '$d' $site.csv
 # Use miller to add a column with the site name and append to single .csv
 mlr --csv put '$Site = "'$site'"' $site.csv >> all-sites.csv
done
```

The resulting all-sites.csv will look similar to:

![](https://i.imgur.com/ZZKsbdB.jpg)

Will a few formulas you can summarize how many times a module is disabled.  In this example there are four webites, therefore any module is disabled four times is a candidate for removal.  Modules crop and crop_media_entity are not enabled on any of the multisites.

![](https://i.imgur.com/PEEBhiK.jpg)



You can learm more about Miller in the Module of the Week: https://youtu.be/5hhM0oOOuQQ


**#004 PHP Boolean and Conditions**

I was recently bit by a nuance of conditional booleans.  You may see code where the existance of a string is evaluated like:

```
$name = 'Stephen'
if ($name) {
   echo 'Name filled in.';
}
```

This code will echo 'Name filled in' for any value $name is set to, other than two; "" and "0".  The zero is the gotcha.  

A quick review of conditional evaluation of boolean conversion:

```
$bool = true;
$int_zero = 0;
$int_gt_zero = 10;
$int_lt_zero = -10;
$str_fill = "Hello World";
$str_empty = "";
$str_zero = "0";

if ($bool) {
    echo "bool True\n";
}
if ($int_zero) {
    echo "int_zero True\n";
}
if ($int_gt_zero) {
    echo "int_gt_zero True\n";
}
if ($int_lt_zero) {
    echo "int_lt_zero True\n";
}
if ($str_fill) {
    echo "str_fill True\n";
}
if ($str_empty) {
    echo "str_empty True\n";
}
if ($str_zero) {
    echo "str_zero True\n";
}
```

The results:

```
bool True
int_gt_zero True
int_lt_zero True
str_fill True
```

One more thing.  Did you know boolean constants are case-insenstive.  While uppercase is a style most have adopted, the following are all valid:

```
$x = true
$x = True
$x = TRUE
```


**#003 Sharing localhost on the Internet**

Sharing your localhost over the Internet is useful for testing on a Mobile device and sharing your work with a client.  [Ngrok](https://ngrok.com/) makes this ease.

After installing ngrokk, simply start it passing the port of the website. An example using a local website running in Lando:

![](https://i.imgur.com/MtYhLHg.png)


```
stephencross@devone:~/dev/d9$ ngrok http 32928
```

ngrok retuns a temporary URL that tunnels to your localhost.

```
https://c9ae-24-38-170-135.ngrok.io
```

This local website, running on Lando, is now available from my phone from the Internet.  

![](https://i.imgur.com/IpoqfJj.png)


PLEASE NOTE:  It doent's go without saying, USE NGROK WITH CAUTION.  It comes with free and paid tiers.  







**#001 drush pm:list**

Drush, the command line utility for interfacing with Drupal, is not just helpful for clearing the cache. The PM command provides access to modules and themes. PM:LIST is helpful for getting a list of modules and themes. I find it faster and easier than accessing the Extend page from the Admin interface.

For example, to see the versions of enabled, non-core modules:

```
drush pm:list --no-core --status=enabled 
```

The results will be similar to:

```
Package        Name                               Status    Version          

Other          CKEditor 4 (contrib) (ckeditor)    Enabled   1.0.1            
Core           Color (color)                      Enabled   1.0.3            
Administration Admin Toolbar (admin_toolbar)      Enabled   3.0.3            
CKEditor       CKEditor Anchor Link (anchor_link) Enabled   8.x-1.7          
User interface Chosen (chosen)                    Enabled   3.0.2            
User interface Chosen Field (chosen_field)        Enabled   3.0.2            
User interface Chosen Library (chosen_lib)        Enabled   3.0.2            
CKEditor       CKEditor Templ(ckeditor_templates) Enabled   8.x-1.2          
CKEditor       CKEditor Templates User ...        Enabled   8.x-1.4          
Other         Components (components)             Enabled   8.x-2.4
```

To get the results for one project, pipe to grep.

```
drush pm:list --no-core --status=enabled | grep 'chosen'
```

Results:

```
User interface    Chosen (chosen)               Enabled   3.0.2            
User interface    Chosen Field (chosen_field)   Enabled   3.0.2            
User interface    Chosen Library (chosen_lib)   Enabled   3.0.2  
```

For drush commands you use frequently, you can add them as an alias in your shell or command/tooling in your local development environment. For example, your .bash_profile could include:

```
alias dpme='drush pm:list --no-core --status=enabled'
```

by Stephen Cross



## Published

---


**#002 Security Checks**

You can check for security updates for Drupal and package depenencies from the command line.  

`drush pm:security` will identify issues with core and modules.  Success will look like:

```
 [success] There are no outstanding security updates for Drupal projects.
```

[Enlightn Security Checker](https://github.com/enlightn/security-checker) is a command line tool that checks if your application uses dependencies with known security vulnerabilities.  Including this in your project and you can check dependencies locally:

```
app$ /app/vendor/bin/security-checker security:check composer.lock

[OK] 0 packages have known vulnerabilities
```

Adding these tests to your CI process could prevent deployment of code with vulnerabilities.




