Talking Drupal
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Help
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # 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.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully