Skip to content

Instantly share code, notes, and snippets.

@gorkdesign
Forked from cesarmiquel/drupal-8-cheatsheet.md
Created October 20, 2023 08:52
Show Gist options
  • Save gorkdesign/d36648c69aa70adf6b124f7b1a96e91c to your computer and use it in GitHub Desktop.
Save gorkdesign/d36648c69aa70adf6b124f7b1a96e91c to your computer and use it in GitHub Desktop.

Revisions

  1. @cesarmiquel cesarmiquel revised this gist Oct 19, 2023. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -165,6 +165,17 @@ $node->toUrl()->setAbsolute()->toString()
    $node->toUrl()->toString();
    ```

    To search nodes by properties:

    ```php
    $nodes = \Drupal::entityTypeManager()
    ->getStorage('node')
    ->loadByProperties([
    'type' => 'article',
    'title' => 'Some title',
    ]);
    ```

    ### Access entity reference fields

    In this sample code `$article` is a content type with a `$field_author` field that is an entity reference to a content-type called `author`.
  2. @cesarmiquel cesarmiquel revised this gist Aug 16, 2023. No changes.
  3. @cesarmiquel cesarmiquel revised this gist Apr 17, 2023. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -1017,7 +1017,6 @@ drupal/entity_usage 2.x-dev
    ```

    will show you the available versions and other information. The `-a` option show uninstalled packages.
    ```

    To install a specific version you can do:

  4. @cesarmiquel cesarmiquel revised this gist Apr 17, 2023. 1 changed file with 42 additions and 0 deletions.
    42 changes: 42 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -983,6 +983,48 @@ class MyDrushCommands extends DrushCommands implements SiteAliasManagerAwareInte
    ```
    - More `drush` documentation here: [Creating Custom Drush Commands](https://docs.drush.org/en/9.x/commands/)

    ## Composer

    Some useful composer commands:

    ```
    $ composer show -a 'drupal/layout_paragraphs'
    Info from https://repo.packagist.org: #StandWithUkraine
    name : drupal/layout_paragraphs
    descrip. : Layout Paragraphs
    keywords : Drupal
    versions : 2.0.x-dev, 2.0.2, 2.0.1, 2.0.0, 2.0.0-beta9, 2.0.0-beta8, 2.0.0-beta7, 2.0.0-beta6, 2.0.0-beta5, 2.0.0-beta4, 2.0.0-beta3, 2.0.0-beta2, 2.0.0-beta1, 2.0.0-alpha4, 2.0.0-alpha3, 2.0.0-alpha2, 2.0.0-alpha1, 1.0.x-dev, 1.0.0, 1.0.0-beta5, 1.0.0-beta4, 1.0.0-beta3, 1.0.0-beta2, 1.0.0-beta1, dev-2.0.x, dev-1.0.x
    type : drupal-module
    license : GNU General Public License v2.0 or later (GPL-2.0+) (OSI approved) https://spdx.org/licenses/GPL-2.0+.html#licenseText
    homepage : https://www.drupal.org/project/layout_paragraphs
    source : [git] https://git.drupalcode.org/project/layout_paragraphs.git baa872d56cc1e741966b43258c8a0a050f8f4b6c
    dist : []
    names : drupal/layout_paragraphs
    support
    source : http://cgit.drupalcode.org/layout_paragraphs
    issues : https://www.drupal.org/project/issues/layout_paragraphs
    requires
    drupal/core ^9.2 || ^10
    drupal/paragraphs ^1.6
    requires (dev)
    drupal/paragraphs-paragraphs_library *
    drupal/block_field ~1.0
    drupal/entity_usage 2.x-dev
    ```

    will show you the available versions and other information. The `-a` option show uninstalled packages.
    ```
    To install a specific version you can do:
    ```
    $ composer require 'drupal/layout_paragraphs:2.0.0-beta9
    ```
    ## Resources
    - Drupal 8 Themeing Guide: https://sqndr.github.io/d8-theming-guide/
  5. @cesarmiquel cesarmiquel revised this gist Feb 24, 2023. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -7,10 +7,11 @@
    $file = File::load($fid);

    // Get uri (public://foo/bar/baz.png)
    $uri = $file->getFileUri(););
    $uri = $file->getFileUri();

    // Get path in FS (/var/www/drupal/sites/default/files/foo.txt)
    $path = drupal_realpath($file->getFileUri());
    $path = drupal_realpath($file->getFileUri()); // Drupal 8.9
    $path = \Drupal::service('file_system')->realpath($file->getFileUri()); // Drupal 9

    // Relative path in FS: /sytes/default/files/... (if public://)
    $relative_path = file_url_transform_relative(file_create_url($uri));
  6. @cesarmiquel cesarmiquel revised this gist Jan 23, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -965,7 +965,7 @@ class MyDrushCommands extends DrushCommands implements SiteAliasManagerAwareInte

    public function myCommand() {
    // Run a configuration import without interaction
    $this->runDrushCommand('cim', ['-y');
    $this->runDrushCommand('cim', ['-y']);
    // ...
    }

  7. @cesarmiquel cesarmiquel revised this gist Jan 23, 2023. 1 changed file with 58 additions and 0 deletions.
    58 changes: 58 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -924,6 +924,64 @@ Each thing that is rendered has one or multiple cache tags (inspect the `X-Drupa
    - Debugging: https://www.drupal.org/docs/8/api/responses/cacheableresponseinterface#debugging
    - Cachability of REST responses: https://blog.dcycle.com/blog/2018-01-24/caching-drupal-8-rest-resource/

    ## Drush

    When you upgrade from Drush 8.x to Drush +9.x you need to port your drush commands. Here are some pointers:

    - [Porting Commands to Drush 9](https://weitzman.github.io/blog/port-to-drush9) - Nice, short blog post with the basic information.
    - You can port existing commands with:

    ```
    $ lando drush generate dcf
    Welcome to drush-command-file generator!
    ––––––––––––––––––––––––––––––––––––––––––
    Module machine name:
    ➤ gop_admin
    Absolute path to legacy Drush command file (optional - for porting):
    ➤ profiles/pagina12/modules/custom/gop_admin/gop_admin.drush.inc
    The following directories and files have been created or updated:
    –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
    • profiles/pagina12/modules/custom/gop_admin/composer.json
    • profiles/pagina12/modules/custom/gop_admin/drush.services.yml
    • profiles/pagina12/modules/custom/gop_admin/src/Commands/GopAdminCommands.php
    ```
    - This will generate the necesary code. You need to then migrate your commands from your `module.drush.inc` to `module/src/Commands/MyDrushCommands.php`
    - To execute a Drush command within a Drush command you can do:

    ```php
    <?php

    use Drush\SiteAlias\SiteAliasManagerAwareInterface;
    use Consolidation\SiteAlias\SiteAliasManagerAwareTrait;

    class MyDrushCommands extends DrushCommands implements SiteAliasManagerAwareInterface {

    // Need this trait to use siteAliasManager()
    use SiteAliasManagerAwareTrait;

    public function myCommand() {
    // Run a configuration import without interaction
    $this->runDrushCommand('cim', ['-y');
    // ...
    }

    /**
    * Execute a drush command and output results to TTY.
    */
    private function runDrushCommand($cmd, $args = []) {
    $this->processManager()
    ->drush($this->siteAliasManager()->getSelf(), $cmd, $args)
    ->setTty(true)
    ->run();
    }
    }
    ```
    - More `drush` documentation here: [Creating Custom Drush Commands](https://docs.drush.org/en/9.x/commands/)

    ## Resources

    - Drupal 8 Themeing Guide: https://sqndr.github.io/d8-theming-guide/
  8. @cesarmiquel cesarmiquel revised this gist Jul 21, 2022. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -129,6 +129,10 @@ $node = Node::load($nid);
    $prev_changed = $node->getChangedTime();
    $node->title = "New Title";
    ...
    $node->save()

    // You need to reload and only modify changed for this to work!!
    $node = Node::load($nid);
    $node->setChangedTime($prev_changed);
    $node->save();
    ```
  9. @cesarmiquel cesarmiquel revised this gist Jul 21, 2022. 1 changed file with 8 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -123,6 +123,14 @@ $field_item_list = $

    $node->get('field_slug')->getString();
    $node->field_slug->getString();

    // Make changes and preserve changed:
    $node = Node::load($nid);
    $prev_changed = $node->getChangedTime();
    $node->title = "New Title";
    ...
    $node->setChangedTime($prev_changed);
    $node->save();
    ```

    Get the path of a node with:
  10. @cesarmiquel cesarmiquel revised this gist Jul 15, 2022. 1 changed file with 22 additions and 1 deletion.
    23 changes: 22 additions & 1 deletion drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -877,10 +877,31 @@ $tempstore->set('my_variable_name', false);

    more info here: https://atendesigngroup.com/blog/storing-session-data-drupal-8

    ## Rendering templates in view:
    ## Rendering

    - Complete example of a module with a controller + twig view: https://github.com/ericski/Drupal-8-Module-Theming-Example

    To render a body field you can use `check_markup()` like so:

    ```php
    $html = check_markup($text, $format_id, $lang);
    ```

    `$format_id` can be `basic_html`, `full_html`, etc. The previous code is equivalente to:

    ```php
    $filter_types_to_skip = [...];
    $build = [
    '#type' => 'processed_text',
    '#text' => $text,
    '#format' => $format_id,
    '#filter_types_to_skip' => $filter_types_to_skip,
    '#langcode' => $langcode,
    ];
    return \Drupal::service('renderer')
    ->renderPlain($build);
    ```

    ## Caching

    If it is about clearing the cache after the user changes settings, you can clear the node_view cache tag with `Drupal::entityManager()->getViewBuilder('node')->resetCache()`. If you want to clear the cache of a specific tag, you can pass the node ID to that method or you can use `\Drupal\Core\Cache\Cache::invalidateTags($node->getCacheTags())`.
  11. @cesarmiquel cesarmiquel revised this gist Jul 15, 2022. 1 changed file with 7 additions and 1 deletion.
    8 changes: 7 additions & 1 deletion drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -408,11 +408,17 @@ For a full listing of Drupal's core services check [this link](https://api.drupa
    To use your config:

    ```php
    $config = \Drupal::service('config.factory')->get('your_module.settings');
    $config = \Drupal::service('config.factory')->get('mymodule.settings');
    $value = $config->get('key');
    ...
    ```

    or simpler

    ```php
    $config = \Drupal::config('mymodule.settings')->get('name_of_form_field');
    ```


    ## Custom entities

  12. @cesarmiquel cesarmiquel revised this gist Jul 15, 2022. 1 changed file with 14 additions and 0 deletions.
    14 changes: 14 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -400,6 +400,20 @@ It is good practice to pass along references to popular services instead of usin

    For a full listing of Drupal's core services check [this link](https://api.drupal.org/api/drupal/core%21core.services.yml/8.2.x)


    ## Config

    - [How to build a simple config form](https://www.drupal.org/docs/drupal-apis/form-api/configformbase-with-simple-configuration-api)

    To use your config:

    ```php
    $config = \Drupal::service('config.factory')->get('your_module.settings');
    $value = $config->get('key');
    ...
    ```


    ## Custom entities

    ### baseFieldDefinitions
  13. @cesarmiquel cesarmiquel revised this gist Jul 4, 2022. 1 changed file with 13 additions and 0 deletions.
    13 changes: 13 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -106,6 +106,19 @@ $item = [
    'date' => $node->field_supplement_date->value,
    ];

    // Body
    $body_text = $node->body->value;
    $body_text = $node->get('body')->value;
    $body_array = $node->body->getValue();
    $body_text example: '<p>Hello!</p>'
    $body_array example: array(
    0 => array(
    'value' => '<p>Hello!</p>',
    'summary' => '',
    'format' => 'basic_html',
    ) )
    $field_item_list = $

    // Other alternatives

    $node->get('field_slug')->getString();
  14. @cesarmiquel cesarmiquel revised this gist Jun 10, 2022. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -67,6 +67,7 @@ $mediaEntity->save();
    ### Drupal 8 -> Drupal 9 migration:

    - [file_save_data, file_copy and file_move are deprecated and replaced with a service](https://www.drupal.org/node/3223520) - file_save_data, file_copy and file_move are deprecated and replaced with a service that implements \Drupal\file\FileRepositoryInterface.
    - [all change records](https://www.drupal.org/list-changes/drupal) - all deprecations are listed here



  15. @cesarmiquel cesarmiquel revised this gist May 30, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -701,7 +701,7 @@ class MyEntityNormalizer extends SerializerAwareNormalizer implements Normalizer
    $normalizer['field_title'] = $entity->field_title->value;

    // Calling normalizer on referenced entities:
    $normalized['districts'] = array_map(function($district) use ($format, $context) {
    $normalized['field_xxxxxx'] = array_map(function($district) use ($format, $context) {
    return $this->serializer->normalize($district, $format, $context);
    }, $entity->field_xxxxxx->referencedEntities());

  16. @cesarmiquel cesarmiquel revised this gist May 30, 2022. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -699,6 +699,12 @@ class MyEntityNormalizer extends SerializerAwareNormalizer implements Normalizer
    public function normalize($entity, $format = NULL, array $context = []) {
    $normalizer['id'] = $entity->id();
    $normalizer['field_title'] = $entity->field_title->value;

    // Calling normalizer on referenced entities:
    $normalized['districts'] = array_map(function($district) use ($format, $context) {
    return $this->serializer->normalize($district, $format, $context);
    }, $entity->field_xxxxxx->referencedEntities());

    return $normalizer;
    }

  17. @cesarmiquel cesarmiquel revised this gist May 30, 2022. 1 changed file with 43 additions and 0 deletions.
    43 changes: 43 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -684,6 +684,49 @@ As the default formatted, all of them uses **text\_default**, for the widget
    Links:
    - [Serialization API overview](https://www.drupal.org/docs/8/api/serialization-api/serialization-api-overview)

    ### Creating your own Normalizer

    Create a class in `my_module/src/Normalizer/MyEntityNormalizer.php` with the normalizer code:

    ```php
    namespace Drupal\my_module\Normalizer;

    use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
    use Symfony\Component\Serializer\Normalizer\SerializerAwareNormalizer;

    class MyEntityNormalizer extends SerializerAwareNormalizer implements NormalizerInterface {

    public function normalize($entity, $format = NULL, array $context = []) {
    $normalizer['id'] = $entity->id();
    $normalizer['field_title'] = $entity->field_title->value;
    return $normalizer;
    }

    public function supportsNormalization($data, $format = NULL) {
    if (!is_object($data) || $format !== 'json') {
    return FALSE;
    }

    if ($data instanceof Entity) {
    return TRUE;
    }

    return FALSE;
    }
    }
    ```

    You must also add your Normalizer to `my_module.services.yml`:

    ```yml
    services:
    my_module.entity_name.normalizer:
    class: Drupal\my_module\Normalizer\MyEntityNormalizer
    tags:
    - { name: normalizer, priority: 10 }
    ```
    ### Using serializer
    ```php
    use Drupal\node\Entity\Node;

  18. @cesarmiquel cesarmiquel revised this gist May 30, 2022. 1 changed file with 13 additions and 4 deletions.
    17 changes: 13 additions & 4 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -439,6 +439,8 @@ With setDisplayOptions config, we can set options for the field widget (display

    For better understanding, see another example with a node entity:


    ```php
    $fields['article'] = BaseFieldDefinition::create('entity_reference')
    ->setLabel(t('Article'))
    ->setDescription(t('Article related to demo entity.'))
    @@ -466,7 +468,7 @@ For better understanding, see another example with a node entity:
    ])
    ->setDisplayConfigurable('view', TRUE)
    ->setDisplayConfigurable('form', TRUE);

    ```

    Note that we can set **target\_bundles** in **handler\_settings**.

    @@ -480,6 +482,8 @@ This field contains a plain string value. The default widget is **string\_textfi

    Also, we can create a **string\_long** field that can contain a long string value. The default widget is **string\_textarea**, the default formatter – **basic\_string**.


    ```php
    $fields['notes'] = BaseFieldDefinition::create('string_long')
    ->setLabel(t('Notes'))
    ->setDescription(t('Example of string_long field.'))
    @@ -497,12 +501,13 @@ Also, we can create a **string\_long** field that can contain a long string va
    ])
    ->setDisplayConfigurable('view', TRUE)
    ->setDisplayConfigurable('form', TRUE);

    ```

    ### boolean field

    If an entity field contains a boolean value, the default widget is **boolean\_checkbox**, the default formatter – **boolean**.

    ```php
    $fields['status'] = BaseFieldDefinition::create('boolean')
    ->setLabel(t('Publishing status'))
    ->setDescription(t('A boolean indicating whether the Demo entity is published.'))
    @@ -519,14 +524,15 @@ If an entity field contains a boolean value, the default widget is **boolean\_c
    ])
    ->setDisplayConfigurable('view', TRUE)
    ->setDisplayConfigurable('form', TRUE);

    ```

    ### list\_integer, list\_float, list\_string fields

    These fields come from the options module and basically similar, so it is enough to demonstrate the use of one of them.

    All these fields have **options\_select** as the default widget and **list\_default** as the default formatter. 

    ```php
    $fields['http_status'] = BaseFieldDefinition::create('list_integer')
    ->setLabel(t('HTTP status code'))
    ->setDescription(t('Hypertext Transfer Protocol (HTTP) response status codes.'))
    @@ -554,7 +560,7 @@ All these fields have **options\_select** as the default widget and **list\_defa
    ])
    ->setDisplayConfigurable('view', TRUE)
    ->setDisplayConfigurable('form', TRUE);
    ```

    ### text, text\_long, text\_with\_summary fields

    @@ -582,6 +588,7 @@ As the default formatted, all of them uses **text\_default**, for the widget

    ### datetime field

    ```php
    $fields['start_date'] = BaseFieldDefinition::create('datetime')
    ->setLabel(t('Only Date'))
    ->setDescription(t('Date field example.'))
    @@ -604,6 +611,8 @@ As the default formatted, all of them uses **text\_default**, for the widget
    ])
    ->setDisplayConfigurable('form', TRUE)
    ->setDisplayConfigurable('view', TRUE);
    ```

    ### Widgets

    ```
  19. @cesarmiquel cesarmiquel revised this gist May 30, 2022. 1 changed file with 261 additions and 0 deletions.
    261 changes: 261 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -386,6 +386,267 @@ It is good practice to pass along references to popular services instead of usin

    For a full listing of Drupal's core services check [this link](https://api.drupal.org/api/drupal/core%21core.services.yml/8.2.x)

    ## Custom entities

    ### baseFieldDefinitions

    Let's take a look at a method baseFieldDefinitions and its abilities today.

    Base fields are non-configurable fields that always exist on a given entity type, like the node title or created and changed dates. By definition, base fields are fields that exist for every bundle.

    Entity types define their base fields in a static method baseFieldDefinitions on the entity class. The definitions returned by this function can be overridden for all bundles by hook_entity_base_field_info_alter() or overridden on a per-bundle basis via base_field_override configuration entities.
    Drupal core has the following field types:

    - boolean
    - changed
    - created
    - decimal
    - email
    - entity_reference
    - float
    - integer
    - language
    - map
    - password
    - string
    - string_long
    - timestamp
    - uri
    - uuid
    - comment
    - datetime
    - file
    - image
    - link
    - list_float
    - list_integer
    - list_string
    - path
    - telephone
    - text
    - text_long
    - text_with_summary

    Below you can find examples with most of these types of fields.

    ### entity\_reference field

    $fields\['user\_id'\] is an example of **entity\_reference** field.

    The default widget – **entity\_reference\_autocomplete**, the default formatter – **entity\_reference\_label**. In settings, you can set the entity type for auto-complete. Also, you can set a handler (the examples of creating custom handlers you can find [here](https://fivejars.com/blog/change-entity-autocomplete-selection-rules-drupal-8)).

    With setDisplayOptions config, we can set options for the field widget (display context – form) and the field formatter (display context – view).

    For better understanding, see another example with a node entity:

    $fields['article'] = BaseFieldDefinition::create('entity_reference')
    ->setLabel(t('Article'))
    ->setDescription(t('Article related to demo entity.'))
    ->setSetting('target_type', 'node')
    ->setSetting('handler', 'default:node')
    ->setSetting('handler_settings', [
    'target_bundles' => ['article' => 'article'],
    'auto_create' => FALSE,
    ])
    ->setRequired(TRUE)
    ->setTranslatable(FALSE)
    ->setDisplayOptions('view', [
    'label' => 'visible',
    'type' => 'string',
    'weight' => 2,
    ])
    ->setDisplayOptions('form', [
    'type' => 'entity_reference_autocomplete',
    'weight' => 2,
    'settings' => [
    'match_operator' => 'CONTAINS',
    'size' => '60',
    'placeholder' => 'Enter here article title...',
    ],
    ])
    ->setDisplayConfigurable('view', TRUE)
    ->setDisplayConfigurable('form', TRUE);


    Note that we can set **target\_bundles** in **handler\_settings**.

    ### String field

    $fields\['name'\] – is an example of a string field.

    This field contains a plain string value. The default widget is **string\_textfield**, and the default formatter – **string**.

    ### string\_long field

    Also, we can create a **string\_long** field that can contain a long string value. The default widget is **string\_textarea**, the default formatter – **basic\_string**.

    $fields['notes'] = BaseFieldDefinition::create('string_long')
    ->setLabel(t('Notes'))
    ->setDescription(t('Example of string_long field.'))
    ->setDefaultValue('')
    ->setRequired(FALSE)
    ->setDisplayOptions('view', [
    'label' => 'visible',
    'type' => 'basic_string',
    'weight' => 5,
    ])
    ->setDisplayOptions('form', [
    'type' => 'string_textarea',
    'weight' => 5,
    'settings' => ['rows' => 4],
    ])
    ->setDisplayConfigurable('view', TRUE)
    ->setDisplayConfigurable('form', TRUE);


    ### boolean field

    If an entity field contains a boolean value, the default widget is **boolean\_checkbox**, the default formatter – **boolean**.

    $fields['status'] = BaseFieldDefinition::create('boolean')
    ->setLabel(t('Publishing status'))
    ->setDescription(t('A boolean indicating whether the Demo entity is published.'))
    ->setDefaultValue(TRUE)
    ->setSettings(['on_label' => 'Published', 'off_label' => 'Unpublished'])
    ->setDisplayOptions('view', [
    'label' => 'visible',
    'type' => 'boolean',
    'weight' => 2,
    ])
    ->setDisplayOptions('form', [
    'type' => 'boolean_checkbox',
    'weight' => 2,
    ])
    ->setDisplayConfigurable('view', TRUE)
    ->setDisplayConfigurable('form', TRUE);


    ### list\_integer, list\_float, list\_string fields

    These fields come from the options module and basically similar, so it is enough to demonstrate the use of one of them.

    All these fields have **options\_select** as the default widget and **list\_default** as the default formatter. 

    $fields['http_status'] = BaseFieldDefinition::create('list_integer')
    ->setLabel(t('HTTP status code'))
    ->setDescription(t('Hypertext Transfer Protocol (HTTP) response status codes.'))
    ->setDefaultValue(200)
    ->setSettings([
    'allowed_values' => [
    200 => 'OK',
    201 => 'Created',
    202 => 'Accepted',
    300 => 'Multiple Choices',
    301 => 'Moved Permanently',
    302 => 'Moved Temporarily',
    403 => 'Forbidden',
    404 => 'Not Found',
    ],
    ])
    ->setDisplayOptions('view', [
    'label' => 'visible',
    'type' => 'list_default',
    'weight' => 6,
    ])
    ->setDisplayOptions('form', [
    'type' => 'options_select',
    'weight' => 6,
    ])
    ->setDisplayConfigurable('view', TRUE)
    ->setDisplayConfigurable('form', TRUE);


    ### text, text\_long, text\_with\_summary fields

    These fields store a text with a text format.

    As the default formatted, all of them uses **text\_default**, for the widget – **text\_textfield**, **text\_textarea** and **text\_textarea\_with\_summary**.

    ```php
    $fields['text_long'] = BaseFieldDefinition::create('text_long')
    ->setLabel(t('Text (formatted, long)'))
    ->setDescription(t('Test formatted text.'))
    ->setDisplayOptions('view', [
    'label' => 'visible',
    'type' => 'text_default',
    'weight' => 6,
    ])
    ->setDisplayOptions('form', [
    'type' => 'text_textarea',
    'weight' => 6,
    'rows' => 6,
    ])
    ->setDisplayConfigurable('view', TRUE)
    ->setDisplayConfigurable('form', TRUE);
    ```

    ### datetime field

    $fields['start_date'] = BaseFieldDefinition::create('datetime')
    ->setLabel(t('Only Date'))
    ->setDescription(t('Date field example.'))
    ->setRevisionable(TRUE)
    ->setSettings([
    'datetime_type' => 'date',
    ])
    ->setDefaultValue('')
    ->setDisplayOptions('view', [
    'label' => 'above',
    'type' => 'datetime_default',
    'settings' => [
    'format_type' => 'medium',
    ],
    'weight' => -9,
    ])
    ->setDisplayOptions('form', [
    'type' => 'datetime_default',
    'weight' => -9,
    ])
    ->setDisplayConfigurable('form', TRUE)
    ->setDisplayConfigurable('view', TRUE);
    ### Widgets

    ```
    -------------------------------------------- ---------------------------------------------------------------------------------------
    Plugin ID Plugin class
    -------------------------------------------- ---------------------------------------------------------------------------------------
    boolean_checkbox Drupal\Core\Field\Plugin\Field\FieldWidget\BooleanCheckboxWidget
    datetime_datelist Drupal\datetime\Plugin\Field\FieldWidget\DateTimeDatelistWidget
    datetime_default Drupal\datetime\Plugin\Field\FieldWidget\DateTimeDefaultWidget
    datetime_timestamp Drupal\Core\Datetime\Plugin\Field\FieldWidget\TimestampDatetimeWidget
    email_default Drupal\Core\Field\Plugin\Field\FieldWidget\EmailDefaultWidget
    entity_reference_autocomplete Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget
    entity_reference_autocomplete_tags Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteTagsWidget
    field_example_3text Drupal\field_example\Plugin\Field\FieldWidget\Text3Widget
    field_example_colorpicker Drupal\field_example\Plugin\Field\FieldWidget\ColorPickerWidget
    field_example_text Drupal\field_example\Plugin\Field\FieldWidget\TextWidget
    field_permission_example_widget Drupal\field_permission_example\Plugin\Field\FieldWidget\TextWidget
    file_generic Drupal\file\Plugin\Field\FieldWidget\FileWidget
    image_image Drupal\image\Plugin\Field\FieldWidget\ImageWidget
    language_select Drupal\Core\Field\Plugin\Field\FieldWidget\LanguageSelectWidget
    link_default Drupal\link\Plugin\Field\FieldWidget\LinkWidget
    menu_item_extras_view_mode_selector_select Drupal\menu_item_extras\Plugin\Field\FieldWidget\MenuItemExtrasViewModeSelectorSelect
    moderation_state_default Drupal\content_moderation\Plugin\Field\FieldWidget\ModerationStateWidget
    number Drupal\Core\Field\Plugin\Field\FieldWidget\NumberWidget
    oembed_textfield Drupal\media\Plugin\Field\FieldWidget\OEmbedWidget
    options_buttons Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsButtonsWidget
    options_select Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget
    path Drupal\path\Plugin\Field\FieldWidget\PathWidget
    string_textarea Drupal\Core\Field\Plugin\Field\FieldWidget\StringTextareaWidget
    string_textfield Drupal\Core\Field\Plugin\Field\FieldWidget\StringTextfieldWidget
    text_textarea Drupal\text\Plugin\Field\FieldWidget\TextareaWidget
    text_textarea_with_summary Drupal\text\Plugin\Field\FieldWidget\TextareaWithSummaryWidget
    text_textfield Drupal\text\Plugin\Field\FieldWidget\TextfieldWidget
    uri Drupal\Core\Field\Plugin\Field\FieldWidget\UriWidget
    -------------------------------------------- ---------------------------------------------------------------------------------------
    ```
    ### References:
    - [ENTITY BASEFIELDDEFINITIONS FIELDS EXAMPLES IN DRUPAL 8](https://fivejars.com/blog/entity-basefielddefinitions-fields-examples-drupal-8)
    - [list of supported value in entity baseFieldDefinitions setDisplayOptions type(field widget)](https://drupal.stackexchange.com/questions/271298/list-of-supported-value-in-entity-basefielddefinitions-setdisplayoptions-typefi)
    ## Logging
    Para logear en reemplazo de `watchdog()` se usa el siguiente código:
  20. @cesarmiquel cesarmiquel revised this gist May 23, 2022. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -282,7 +282,9 @@ $tree = \Drupal::entityTypeManager()
    $query->condition('field_tags.entity.name', 'tag1');
    // or by parent tid
    $query->condition('field_supplement_type.entity.parent', $slug->tid);

    // Disable access control if we are anonynous for example
    $query->accessCheck(FALSE);

    $now = new DrupalDateTime('now');
    $now->setTimezone(new \DateTimeZone(DATETIME_STORAGE_TIMEZONE)); // set a desired timezone (instead of the one from the site)
    $query->condition('field_date', $now->format(DATETIME_DATETIME_STORAGE_FORMAT), '>=');
  21. @cesarmiquel cesarmiquel revised this gist May 20, 2022. 1 changed file with 11 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -373,6 +373,17 @@ class MyService {
    }
    ```

    ### Dependencies

    It is good practice to pass along references to popular services instead of using `\Drupal::service()`. For example: if you need an `entityTypeManager` it is preferred to inject it instead of using `\Drupal::entityTypeManager()`. It makes your code more easily testable. Some common services to inject into your Service might be:

    - `entity_type.manager` - `EntityTypeManager` object to perform entity queries on
    - `database` - `Connection` object to the Drupal database to perform queries on
    - `current_user` - `AccountProxy` to the current user
    - `date.formatter` - `DateFormatter` object which gives you access to the `DateFormat::format()` using Drupal date formats

    For a full listing of Drupal's core services check [this link](https://api.drupal.org/api/drupal/core%21core.services.yml/8.2.x)

    ## Logging

    Para logear en reemplazo de `watchdog()` se usa el siguiente código:
  22. @cesarmiquel cesarmiquel revised this gist May 2, 2022. 1 changed file with 53 additions and 50 deletions.
    103 changes: 53 additions & 50 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    # Drupal 8 Cheatsheet

    ## Files
    ## Files, Images and Media

    ```php
    // Load file object
    @@ -19,6 +19,58 @@ $relative_path = file_url_transform_relative(file_create_url($uri));
    $contents = file_get_contents($uri);
    ```

    Create a directory in `public://` if it doesn't exist.

    ```php
    $image_dest = 'public://article/images';
    if (!is_dir($image_dest)) {
    \Drupal::service('file_system')->mkdir($image_dest, NULL, TRUE);
    }
    ```

    Create a file using `FileRepository::writeData` ([docs](https://api.drupal.org/api/drupal/core%21modules%21file%21src%21FileRepository.php/function/FileRepository%3A%3AwriteData/9.3.x)) in Drupal from image data:

    ```php
    use Drupal\Core\File\FileSystemInterface;

    $image_url = "https://example.com/images/img.png";
    $image_content = file_get_contents($image_url);
    $image_filename = "img.png";

    if ($image_content) {
    // D9.x
    $imageFid = \Drupal::service('file.repository')
    ->writeData(
    $image_content,
    "$image_dest/$image_filename",
    FileSystemInterface::EXISTS_REPLACE
    );
    // D8.x
    file_save_data($image_content, "$image_dest/$image_filename", FileSystemInterface::EXISTS_REPLACE);
    }
    ```

    Once we have a `FileEntity` (returned by `writeData`) you can create a Media like so:

    ```php
    $data = [
    'bundle' => 'image',
    'name' => 'Title/ALT text form image',
    'field_media_image' => ['target_id' => $imageFid],
    ];

    $mediaEntity = \Drupal::entityManager()
    ->getStorage('media')
    ->create($data);
    $mediaEntity->save();
    ```
    ### Drupal 8 -> Drupal 9 migration:

    - [file_save_data, file_copy and file_move are deprecated and replaced with a service](https://www.drupal.org/node/3223520) - file_save_data, file_copy and file_move are deprecated and replaced with a service that implements \Drupal\file\FileRepositoryInterface.




    ## Nodes

    ```php
    @@ -208,55 +260,6 @@ $uri = $style->buildUri($image_uri);
    $url = $style->buildUrl($image_uri);
    ```


    ## Images and files

    Create a directory in `public://` if it doesn't exist.

    ```php
    $image_dest = 'public://article/images';
    if (!is_dir($image_dest)) {
    \Drupal::service('file_system')->mkdir($image_dest, NULL, TRUE);
    }
    ```

    Create a file using `FileRepository::writeData` ([docs](https://api.drupal.org/api/drupal/core%21modules%21file%21src%21FileRepository.php/function/FileRepository%3A%3AwriteData/9.3.x)) in Drupal from image data:

    ```php
    use Drupal\Core\File\FileSystemInterface;

    $image_url = "https://example.com/images/img.png";
    $image_content = file_get_contents($image_url);
    $image_filename = "img.png";

    if ($image_content) {
    // D9.x
    $imageFid = \Drupal::service('file.repository')
    ->writeData(
    $image_content,
    "$image_dest/$image_filename",
    FileSystemInterface::EXISTS_REPLACE
    );
    // D8.x
    file_save_data($image_content, "$image_dest/$image_filename", FileSystemInterface::EXISTS_REPLACE);
    }
    ```

    Once we have a `FileEntity` (returned by `writeData`) you can create a Media like so:

    ```php
    $data = [
    'bundle' => 'image',
    'name' => 'Title/ALT text form image',
    'field_media_image' => ['target_id' => $imageFid],
    ];

    $mediaEntity = \Drupal::entityManager()
    ->getStorage('media')
    ->create($data);
    $mediaEntity->save();
    ```

    ## Taxonomy

    ```php
  23. @cesarmiquel cesarmiquel revised this gist May 2, 2022. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -230,12 +230,15 @@ $image_content = file_get_contents($image_url);
    $image_filename = "img.png";

    if ($image_content) {
    // D9.x
    $imageFid = \Drupal::service('file.repository')
    ->writeData(
    $image_content,
    "$image_dest/$image_filename",
    FileSystemInterface::EXISTS_REPLACE
    );
    // D8.x
    file_save_data($image_content, "$image_dest/$image_filename", FileSystemInterface::EXISTS_REPLACE);
    }
    ```

  24. @cesarmiquel cesarmiquel revised this gist May 2, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -222,7 +222,7 @@ if (!is_dir($image_dest)) {

    Create a file using `FileRepository::writeData` ([docs](https://api.drupal.org/api/drupal/core%21modules%21file%21src%21FileRepository.php/function/FileRepository%3A%3AwriteData/9.3.x)) in Drupal from image data:

    ```
    ```php
    use Drupal\Core\File\FileSystemInterface;

    $image_url = "https://example.com/images/img.png";
  25. @cesarmiquel cesarmiquel revised this gist May 2, 2022. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -248,7 +248,9 @@ $data = [
    'field_media_image' => ['target_id' => $imageFid],
    ];

    $mediaEntity = $this->createEntity($data, 'media');
    $mediaEntity = \Drupal::entityManager()
    ->getStorage('media')
    ->create($data);
    $mediaEntity->save();
    ```

  26. @cesarmiquel cesarmiquel revised this gist May 2, 2022. 1 changed file with 44 additions and 0 deletions.
    44 changes: 44 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -208,6 +208,50 @@ $uri = $style->buildUri($image_uri);
    $url = $style->buildUrl($image_uri);
    ```


    ## Images and files

    Create a directory in `public://` if it doesn't exist.

    ```php
    $image_dest = 'public://article/images';
    if (!is_dir($image_dest)) {
    \Drupal::service('file_system')->mkdir($image_dest, NULL, TRUE);
    }
    ```

    Create a file using `FileRepository::writeData` ([docs](https://api.drupal.org/api/drupal/core%21modules%21file%21src%21FileRepository.php/function/FileRepository%3A%3AwriteData/9.3.x)) in Drupal from image data:

    ```
    use Drupal\Core\File\FileSystemInterface;
    $image_url = "https://example.com/images/img.png";
    $image_content = file_get_contents($image_url);
    $image_filename = "img.png";
    if ($image_content) {
    $imageFid = \Drupal::service('file.repository')
    ->writeData(
    $image_content,
    "$image_dest/$image_filename",
    FileSystemInterface::EXISTS_REPLACE
    );
    }
    ```

    Once we have a `FileEntity` (returned by `writeData`) you can create a Media like so:

    ```php
    $data = [
    'bundle' => 'image',
    'name' => 'Title/ALT text form image',
    'field_media_image' => ['target_id' => $imageFid],
    ];

    $mediaEntity = $this->createEntity($data, 'media');
    $mediaEntity->save();
    ```

    ## Taxonomy

    ```php
  27. @cesarmiquel cesarmiquel revised this gist Nov 12, 2021. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -179,6 +179,7 @@ foreach($authos as $author) {
    References
    - https://www.drupal.org/project/media_entity/issues/2813025
    - https://codimth.com/blog/web/drupal/how-create-nodes-programmatically-drupal-8
    - [Working with the Entity API | Entity API | Drupal Wiki guide on Drupal.org](https://www.drupal.org/docs/drupal-apis/entity-api/working-with-the-entity-api)

    ## Image styles

  28. @cesarmiquel cesarmiquel revised this gist Oct 16, 2021. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -174,7 +174,7 @@ foreach($authos as $author) {
    ]);
    $node->save();
    $new_nid = $node->id();
    ```
    ```

    References
    - https://www.drupal.org/project/media_entity/issues/2813025
    @@ -215,6 +215,7 @@ $tree = \Drupal::entityTypeManager()
    ->getStorage('taxonomy_term')
     ->loadTree(self::HOME_SUPPLEMENT_LIST_VID);
    ```

    ## Entity Queries

    ```php
    @@ -251,7 +252,7 @@ $tree = \Drupal::entityTypeManager()
    $tids = $query->execute();
    $terms = \Drupal\taxonomy\Entity\Term::loadMultiple($tids);

    ```
    ```
    - [Ver más sobre queries y fechas](https://www.webomelette.com/query-entities-using-dates-drupal-8)
    - Ver [QueryInterface documentation](https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21Query%21QueryInterface.php/interface/QueryInterface/8.2.x)

  29. @cesarmiquel cesarmiquel revised this gist Oct 4, 2021. 1 changed file with 45 additions and 0 deletions.
    45 changes: 45 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -362,6 +362,51 @@ class MyService {
    ->deserialize($serialized_content, \Drupal\node\Entity\Node::class, 'json');
    ```

    You can serialize more complex structures like so:

    ```php
    <?php
    use Drupal\node\Entity\Node;
    $list = [
    Node::load(44130),
    Node::load(44131),
    Node::load(44130),
    ];
    $object = [
    'total' => 3,
    'data' => $list
    ];
    print_r(
    \Drupal::service('serializer')->serialize($object, 'json')
    );
    ```

    will output:

    ```json
    {
    "data": [
    {
    "nid": "44130",
    "title": "Primer update de la nota"
    },
    {
    "nid": "44131",
    "title": "Un nuevo update a mi nodo"
    },
    {
    "nid": "44132",
    "title": "Tercer update de la nota"
    }
    ],
    "total": 3
    }
    ```

    ## Migrate

    Para ejecutar una migración via código:
  30. @cesarmiquel cesarmiquel revised this gist Oct 4, 2021. 1 changed file with 20 additions and 0 deletions.
    20 changes: 20 additions & 0 deletions drupal-8-cheatsheet.md
    Original file line number Diff line number Diff line change
    @@ -342,6 +342,26 @@ class MyService {

    - Para más información: https://www.drupal.org/node/2595985

    ## Normalizer and Serializer

    Links:
    - [Serialization API overview](https://www.drupal.org/docs/8/api/serialization-api/serialization-api-overview)

    ```php
    use Drupal\node\Entity\Node;
    // Serialize a node to JSON
    $node = Node::load($nid);
    $format = 'json';
    $serialized_content = \Drupal::service('serializer')
    ->serialize($node, $format)
    );
    // Deserialize from JSON -> Node
    $node = \Drupal::service('serializer')
    ->deserialize($serialized_content, \Drupal\node\Entity\Node::class, 'json');
    ```

    ## Migrate

    Para ejecutar una migración via código: