entities – Entity where member variable is different type than when serialized

Not entirely sure how to phrase this.

I’ve got a config entity that needs to store a block id. In my config I have the mapping set to a string for the id.
When I load the entity, I’d think it would be more convenient to load the id and have the variable be a block.

This would mean I would need to :

  • On load, set $this->block = loadblock($id)
  • On save, set config->block = $block->id()

I’m finding the saving of entities to be quite ‘magic’ and thus hard for me to figure out.

Schema:

myent.myent.*:
  type: config_entity
  mapping:
    display_block:
      type: string
      label: Display block

entity:

/**
 * @ConfigEntityType(
 *   id = "myent",
 *   ...
 *   config_export = {
 *     ...
 *     "display_block",
 *   },
 * )
 */
class MyEnt extends ConfigEntityBase {

  // This should be loaded as an entity, not a string.
  protected $display_block;

}

For the loading, I could just override __construct and use the loaded string to load up the entity but that feels very hacky. Plus then IDK how to save it properly when saving.

There is also the option of having a getBlockRaw and getBlock as two seperate options. Have a variable for the string and a non exported one for the loaded entity.

entities – Confused about Entity bundles

I’m trying to convert a Drupal 7 site to Drupal 9 before D7 reaches EOL, and I had a custom module that had a lot of custom tables defined in Hook Schema, that would be joined together in different ways to handle a multi-step form made with the ctools form wizard. This site was originally created in Drupal 6, and updated to Drupal 7 while doing the minimum changes to the custom modules, so it predates the concept of Entities. The database structure of those tables is normalized, in 3rd normal form, because if you flattened it, would your end with millions of rows with mostly redundant information. The problem was that those tables existed in their own microcosm, not accessible to the rest of the site.

I’ve decided to rebuild everything from the ground up when doing the site upgrade, and I’ve also decided to drupalize this so the contents of these tables can be accessed by regular views, avoiding content duplication. This means that every old table will have to have it’s own entity type. Fields will be basefields for performance, since I will need 50-100 fields in total, and every fiend added through the UI requires a join as far as I understand. If I need to add fields in the future, I will do it through a module update, not by adding them through the UI, so I don’t need the entities to be fieldable.

After giving you this context, my actual question is, if I will only ever need 1 type of every entity bundle, do I really need entity bundles? What would entity bundles do for me?

entities – The “yourtypeentity” entity type does not exist. dans DrupalCoreEntityEntityTypeManager->getDefinition()

i have followed this tuto “https://www.droptica.com/blog/how-create-custom-entity-drupal-8/” on the web , but i am facing this error “DrupalComponentPluginExceptionPluginNotFoundException : The “dictionary_term” entity type does not exist. dans DrupalCoreEntityEntityTypeManager->getDefinition() (ligne 150 de /var/www/html/core/lib/Drupal/Core/Entity/EntityTypeManager.php).”

can anyone help me please i am new on drupal 8

<?php
/**
 * @file
 * Contains Drupalcontent_entity_exampleEntityContentEntityExample.
 */

namespace DrupaldictionaryEntity;

use DrupalCoreEntityEntityStorageInterface;
use DrupalCoreFieldBaseFieldDefinition;
use DrupalCoreEntityContentEntityBase;
use DrupalCoreEntityEntityTypeInterface;
use DrupaluserUserInterface;
use DrupalCoreEntityEntityChangedTrait;

/**
 * Defines the ContentEntityExample entity.
 *
 * @ingroup dictionary
 *
 *
 * @ContentEntityType(
 * id = "dictionary_term",
 * label = @Translation("Dictionary Term entity"),
 * handlers = {
 * "view_builder" = "DrupalCoreEntityEntityViewBuilder",
 * "list_builder" = "DrupaldictionaryEntityControllerTermListBuilder",
 * "form" = {
 * "add" = "DrupaldictionaryFormTermForm",
 * "edit" = "DrupaldictionaryFormTermForm",
 * "delete" = "DrupaldictionaryFormTermDeleteForm",
 * },
 * "access" = "DrupaldictionaryTermAccessControlHandler",
 * },
 * list_cache_contexts = { "user" },
 * base_table = "dictionary_term",
 * admin_permission = "administer dictionary_term entity",
 * entity_keys = {
 * "id" = "id",
 * "uuid" = "uuid",
 * "user_id" = "user_id",
 * "created" = "created",
 * "changed" = "changed",
 * "pl" = "pl",
 * "en" = "en",
 * },
 * links = {
 * "canonical" = "/dictionary_term/{dictionary_term}",
 * "edit-form" = "/dictionary_term/{dictionary_term}/edit",
 * "delete-form" = "/dictionary_term/{dictionary_term}/delete",
 * "collection" = "/dictionary_term/list"
 * },
 * field_ui_base_route = "entity.dictionary.term_settings",
 * )
 */
class Term extends ContentEntityBase {

  use EntityChangedTrait;

  /**
   * {@inheritdoc}
   *
   * When a new entity instance is added, set the user_id entity reference to
   * the current user as the creator of the instance.
   */
  public static function preCreate(EntityStorageInterface $storage_controller, array &$values) {
    parent::preCreate($storage_controller, $values);
// Default author to current user.
    $values += array(
      'user_id' => Drupal::currentUser()->id(),
    );
  }

  /**
   * {@inheritdoc}
   *
   * Define the field properties here.
   *
   * Field name, type and size determine the table structure.
   *
   * In addition, we can define how the field and its content can be manipulated
   * in the GUI. The behaviour of the widgets used can be determined here.
   */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {

// Standard field, used as unique if primary index.
    $fields('id') = BaseFieldDefinition::create('integer')
      ->setLabel(t('ID'))
      ->setDescription(t('The ID of the Term entity.'))
      ->setReadOnly(TRUE);

// Standard field, unique outside of the scope of the current project.
    $fields('uuid') = BaseFieldDefinition::create('uuid')
      ->setLabel(t('UUID'))
      ->setDescription(t('The UUID of the Contact entity.'))
      ->setReadOnly(TRUE);

// Name field for the contact.
// We set display options for the view as well as the form.
// Users with correct privileges can change the view and edit configuration.
    $fields('pl') = BaseFieldDefinition::create('string')
      ->setLabel(t('Polish'))
      ->setDescription(t('Polish version.'))
      ->setSettings(array(
        'default_value' => '',
        'max_length' => 255,
        'text_processing' => 0,
      ))
      ->setDisplayOptions('view', array(
        'label' => 'above',
        'type' => 'string',
        'weight' => -6,
      ))
      ->setDisplayOptions('form', array(
        'type' => 'string_textfield',
        'weight' => -6,
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields('en') = BaseFieldDefinition::create('string')
      ->setLabel(t('English'))
      ->setDescription(t('English version.'))
      ->setSettings(array(
        'default_value' => '',
        'max_length' => 255,
        'text_processing' => 0,
      ))
      ->setDisplayOptions('view', array(
        'label' => 'above',
        'type' => 'string',
        'weight' => -4,
      ))
      ->setDisplayOptions('form', array(
        'type' => 'string_textfield',
        'weight' => -4,
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

// Owner field of the contact.
// Entity reference field, holds the reference to the user object.
// The view shows the user name field of the user.
// The form presents a auto complete field for the user name.
    $fields('user_id') = BaseFieldDefinition::create('entity_reference')
      ->setLabel(t('User Name'))
      ->setDescription(t('The Name of the associated user.'))
      ->setSetting('target_type', 'user')
      ->setSetting('handler', 'default')
      ->setDisplayOptions('view', array(
        'label' => 'above',
        'type' => 'author',
        'weight' => -3,
      ))
      ->setDisplayOptions('form', array(
        'type' => 'entity_reference_autocomplete',
        'settings' => array(
          'match_operator' => 'CONTAINS',
          'size' => 60,
          'placeholder' => '',
        ),
        'weight' => -3,
      ))
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);

    $fields('created') = BaseFieldDefinition::create('created')
      ->setLabel(t('Created'))
      ->setDescription(t('The time that the entity was created.'));

    $fields('changed') = BaseFieldDefinition::create('changed')
      ->setLabel(t('Changed'))
      ->setDescription(t('The time that the entity was last edited.'));

    return $fields;
  }

}

8 – Own permissions for paragraphs and ECK entities

I have come quite far in my Drupal 8 development without needing to write much custom php code. However, I am using paragraphs and eck entities as referenced entities in content types. For users to be able to edit their own content, I need edit and delete permissions in paragraph and eck to apply to only own content. I looked up some hooks and wrote the below code in my theme file. It doesn’t work. Will appreciate any help in taking this to finish line.

  function THEME_entity_info_alter(&$entity_info) {
    $entity_info('contact_information_fields')('access callback') = 'THEME_ENTITYNAME_access';
  }
    
  function THEME_ENTITYNAME_access(DrupalCoreEntityEntityInterface $entity, $op, DrupalCoreSessionAccountInterface $account) {
    $user = DrupaluserEntityUser::load(Drupal::currentUser()->id());
    switch ($op) {
      case 'update':
      case 'delete':
        if ($entity->uid == $user->get('uid')) {
          return TRUE;
        }
        break;
    }
    
    return eck__entity_access($entity, $op, $account);
  }

Can I put domain services inside domain entities?

Say I have a domain entity User:

class User {
  constructor (username, email, password) {
    this.username = username
    this.email = email
    this.password = password
  }
}

Now, all users need a way to validate their username and email

There are two ways I can think of doing so:

  1. Inside the domain entity (domain/entities/User.js)
class User {
  constructor (username, email, password) {
    this.username = username
    this.email = email
    this.password = password
  }
  
  validate () {
    // validation logic
    // ...

    if (!this.username.isValid || !this.email.isValid) {
      return false
    } else {
      return true
    }
  }
}
  1. In a domain service (/domain/services/validateUser.js)
function validateUser (userToValidate) {
  // validation logic
  // ..
  
  if (userIsValid) {
    return true
  } else {
    return false 
  }
}

Either way, the use case/application service calls the validation logic

function createUserUseCase (username, email, password) {
  const user = new User(username, email, password)
  const isValid = user.validate()

  // ...
  // or... calling a service

  const user = new User(username, email, password)
  const isValid = validateUser(user)

}

So, should entities also carry logic or only hold data? Can I put validation logic inside an Entity, or do I have to create a service that receives a user and validates the user?

Thanks.

entities – Define fields created through the UI as non-revisionable on a revisionable entity

Let’s say, I have a revisionable entity. Whether base fields should be revisionable or not can be set in the code. So far, so good.

But how about those fields that get added through the user interface? Is there a way to set all the fields as either revisionable or non-revisionable? Or is there a way to set this for each field individually in the UI?

entities – Combine fields from many nodes within a custom controller (Drupal 8 or 9)

I’m going this route as I can’t get a view to behave as needed.

In simple terms I have

content type 1 containing custom field 1 with a custom formatter

content type 2 containing custom field 2 with a custom formatter

content type 3 containing custom field 3 with a custom formatter

Each node will display correctly using the formatter if the node is viewed directly so I’m happy with that, however for some of the pages I need to display I need to use all (or partial) content from these content types as a single “entity”. What I’m trying to do is generate a response that in effect wrap the output of all 3 sets of fields into a single output that can then be pushed back into Drupal’s normal page processing so that other modules can work on the aggregated output before the HTML rendering phase. Additionally, if possible I’d like to be able to use different formatters other than the field default for the fields depending on the use context so a web page used the default formatter, a rest feed used formatter 2, an XML feed used formatter 3

I’m using Drupal 8.9 but will soon be going 9

entities – How do I create configurations which describe a list of changes to make to an entity, varying by type and bundle?

I have several kind of content (different Entity Types, possibly different bundles). I have a kind of editorial workflow in which I want to make several changes to a piece of content (an instance implementing ContentEntityinterface). What actual changes I’ll make (which fields, which values) and how (“edit and replace”https://drupal.stackexchange.com/”create revision”https://drupal.stackexchange.com/”clone to new entity”) will depend on.

  • The entity type of provided content (and ideally bundle, although I could cope with a switch)
  • The “kind” of operation in a business perspective (publish / unpublish / revert / clone as draft / etc)
  • Ideally, the “operating mode” (replace/revision/clone), but if that would bring asinine complexity I can circumvent by making different operations for each variation.

Because that configuration may ultimately be managed by non-technical users, and the new values will be “relative to context”, if I follow through with the idea of describing changes, values will have to be “human keywords” that will translate in code to a specific method (ex “publication_date: tomorrow”, “publication_author: site_author)

Finally, while there are specificities to each kind, there are also some “common fields” that will be changed the same way in all kind of entities. Sadly, for reasons, they don’t have the same name.

*For the sake of easing exchanges, let’s say I have the following “entitytype:bundle” available: ‘node:doc’, ‘node:news’, ‘media:image’. I have an operation “publish” which in all entities, affects the following metadata: “publication_date”, “author”, “version number” (business counter unrelated to technical ids), “editorial_state” (unrelated to the Drupal ‘status’).

My very first attempt at structuring configuration made it clear I couldn’t manage with just Simple configuration API.

publication__related_fields:
  - processus_management:
      - node: 'field_moderations_content'
      - media: 'moderation_media'
  - publication_date:
      - node:  'field_begin'
      - media: 'field_begin'
  - publication_author:
      - node:  'uid'
      - media: 'uid'

# Placeholder because later we may actually make some "replace" operations or "new revision" ones.
# For now "copy" translates to "create duplicate of Entity" (yeah, I know... :/)
publication__mode: 'copy'

data_changes_on_publication:
  publication_date: 'today'
  publication_author: 'current_user'

It quickly became obvious to me that I could need to “traverse” configuration either “from operation” or “from entity type” at least. So describing every use-case in a single file would cause headaches one moment or another.

Seems to me it’s a perfect use-case for configuration entities, but while I get the theory of things, I have much trouble wrapping my head around it.

Questions

Could I have configuration entities that would be structured like
mymodule.OPERATION.ENTITY_TYPE.BUNDLE.yml (or maybe ENTITY_TYPE.BUNDLE.OPERATION if you feel it’s more logical)?

How can I then tell to Drupal it has to use this scheming name for the files?
And how can I immediately throw an error and gracefully stop process if provided entity does not have an adequate configuration entity in base?

entities – D8: how to create configurations which describe a list of changes to make to an entity, varying by type and bundle?

Thanks in advance for your advices.

So, context.
I have several kind of contents (different Entity Types, possibly different bundles).

I have a kind of editorial workflow in which I want to make several changes to a piece of content (an instance implementing ContentEntityinterface). What actual changes I’ll make (which fields, which values) and how (“edit and replace”https://drupal.stackexchange.com/”create revision”https://drupal.stackexchange.com/”clone to new entity”) will depend on…

  • The entity type of provided content (and ideally bundle, although I could cope with a switch)
  • The “kind” of operation in a business perspective (publish / unpublish / revert / clone as draft / etc)
  • Ideally, the “operating mode” (replace/revision/clone), but if that would bring asinine complexity I can circumvent by making different operations for each variation.

Because that configuration may ultimately be managed by non-technical users, and the new values will be “relative to context”, if I follow through with the idea of describing changes, values will have to be “human keywords” that will translate in code to a specific method (ex “publication_date: tomorrow”, “publication_author: site_author)

Finally, while there are specificities to each kind, there are also some “common fields” that will be changed the same way in all kind of entities. Sadly, for reasons, they don’t have the same name.

*For the sake of easing exchanges, let’s say I have the following “entitytype:bundle” available: ‘node:doc’, ‘node:news’, ‘media:image’. I have an operation “publish” which in all entities, affects the following metadata: “publication_date”, “author”, “version number” (business counter unrelated to technical ids), “editorial_state” (unrelated to the Drupal ‘status’).

My current state of thoughts.

My very first attempt at structuring configuration made it clear I couldn’t manage with just Simple configuration API.

publication__related_fields:
  - processus_management:
      - node: 'field_moderations_content'
      - media: 'moderation_media'
  - publication_date:
      - node:  'field_begin'
      - media: 'field_begin'
  - publication_author:
      - node:  'uid'
      - media: 'uid'

# Placeholder because later we may actually make some "replace" operations or "new revision" ones.
# For now "copy" translates to "create duplicate of Entity" (yeah, I know... :/)
publication__mode: 'copy'

data_changes_on_publication:
  publication_date: 'today'
  publication_author: 'current_user'

It quickly became obvious to me that I could need to “traverse” configuration either “from operation” or “from entity type” at least. So describing every use-case in a single file would cause headaches one moment or another.

Seems to me it’s a perfect use-case for configuration entities, but while I get the theory of things, I have much trouble wrapping my head around it.

Questions

Could I have configuration entities that would be structured like…
mymodule.OPERATION.ENTITY_TYPE.BUNDLE.yml (or maybe ENTITY_TYPE.BUNDLE.OPERATION if you feel it’s more logical) ?

How can I then tell to Drupal it has to use this scheming name for the files?
And how can I immediately throw an error and gracefully stop process if provided entity does not have an adequate configuration entity in base?

I hope that’s not too broad of a question. Configuration schema is still blurry to me, and Config Entity new. I already checked official doc and some tutorials, and I’ll continue to do so, but every explanation or link to another tutorial/example will be greatly appreciated. Thanks in advance!

c# – Create a Generic Controller that has all entities in OData Web API

I have a Master table in database with list of other tables whose details I want to fetch through the API.
Steps to be incorporated –
1. Create a Generic OData Controller to fetch Master table details.
2. Because does not want to create controller for each entity in Master table, so want each entity in Master table to get registered automatically so that it can be accessed through API without building each of their controller.

I am pretty new to building Web APIs using OData. So require some help as to how go forward with this requirement