System entity seeks to provide configuration and export on individual entities, dubbed "system entities", that should not be created by content managers and have unique functionality/appearance per entity. The module is based on a machine name field that provides a semantic unique identifier per entity. This opens the door for special purpose entities that do not have common configuration or content layout with other entities as provided with Drupal's entity type/bundle scheme.

This document will provide developer guidelines for integrating your entities with the system entity module.

In this document:

Overview

System entity is an api package that wraps around existing entities. An entity is considered a system entity when it has a machine name value defined inside a machine name field and its entity type and bundle were defined in the appropriate hook (see Basic Setup). Machine names must be unique within the bundle level and are validated during entity save. Machine name fields can be reused between entity types and bundles without a problem.

Once a system entity is defined, it will be exportable using Features (see Export), and will be exposed to the system entity api using its type/bundle/machine name combo as an identifier (see API).

Translated system entities are grouped together under the same machine name, meaning that translations must contain the same machine name as the source translation, if applicable. Any additional translation properties (eg. tnid, i18n_tsid, etc) will have to be handled by your module. This is already provided for nodes and taxonomy by systementity_node and systementity_taxonomy respectively which are included with the systementity module. When loading a system entity, language is an optional parameter, and if omitted then the current language is assumed.

Basic Setup

System entity types are declared with the hook_systementity_type_info() hook, which require a entity type, bundle, and a machine name field.

/**
 * Implements hook_systementity_type_info().
 */
function MYMODULE_systementity_type_info() {
  $types['node']['my_system_item'] = array(
    'machine name field' => 'field_msi_machine_name',
  );

  return $types;
}

The above example has the bare minimum configuration for setting up a system entity type. 'node' being the entity type, 'my_system_item' being the entity bundle, and 'field_msi_machine_name' is the machine_name field name which holds the machine name of the entity.

This setup alone will provide entity export with Features and open the various api's to work with your entity.

API

After the system entity is defined, several hooks and functions are available for this entity.

With addition to hook_systementity_type_info(), you can define settings on a per entity basis with hook_systementity_settings().

/**
 * Implements hook_systementity_settings().
 */
function MYMODULE_systementity_settings() {
  $system_entities = array();

  $system_entities['node']['my_system_item']['item_1'] = array(
    'export' => array(
      'fields' => array('body'),
    ),
  );

  return $system_entities;
}

The above example provides export settings for the system entity. 'node' being the entity type, 'my_system_item' being the entity bundle, and 'item_1' is the machine name. This specific example will make the body field to be included in export and import (see Export).

A hook is available for adding/editing content of a rendered entity, hook_systementity__ENTITY_TYPE__BUNDLE__view().


/**
 * Implements hook_systementity__ENTITY_TYPE__BUNDLE__view().
 */
function MYMODULE_systementity__node__my_system_item__view($machine_name, $entity, &$content, $view_mode) {
  switch ($machine_name) {
    case 'item_1':
      if ($view_mode == 'full') {
        $content['my_content'] = array(
          '#markup' => t('This is added content'),
        );
      }
      break;
  }
}

The above example will add the text 'This is added content' to the body of the system entity in 'full' view mode. 'node' (in the function name) being the entity type, 'my_system_item' (in the function name) being the entity bundle, and 'item_1' is the machine name. A class is added to all system entities with the machine name. This example will have 'machine-name--item_1' class. With these two features provided it is possible to create entities with unique appearance and layout.

There are hooks for extending import/export behaviors, please see systementity.api.php for examples and documentation (see Export):

  • hook_systementity_export_alter() - hook for altering the export array
  • hook_systementity_import_alter() - hook for altering entity object before import
  • hook_systementity_import() - post entity save hook, for saving entity properties that are not part of the entity object/table, such as aliases.
  • hook_systementity_import_finished() - post import hook, generally used for saving references to other system entities after they have been created.

There are api functions for handling system entities:

  1. function systementity_load_entity($entity_type, $bundle, $machine_name, $langcode = NULL, $reset = FALSE) - Load a system entity. if langcode is omitted, current language is assumed.
  2. function systementity_type_load($entity_type = NULL, $bundle = NULL, $reset = FALSE) - load system entity type configuration, provided by hook_systementity_type_info() hooks.
  3. systementity_load_settings($entity_type = NULL, $bundle = NULL, $machine_name = NULL, $reset = FALSE) - load system entity settings, provided by hook_systementity_settings() hooks.
  4. systementity_machine_name($entity_type, $system_entity, $field_langcode = LANGUAGE_NONE, $field_delta = 0) - Get the machine name, given entity type and entity object.
  5. systementity_machine_name_list($entity_type, $bundle, $reset = FALSE) - Get list of system entity machine names of a given entity type and bundle. Returns all machine name with their labels in all available languages.

Export

System entities can be exported and imported using features. By default only entity label, language, alias, and machine name are exported. Additional fields and properties will be exported only if defined in the systementity_type_info or systementity_settings hooks.

Fields and properties can be partially imported, meaning they are exported but are never overriden, aka 'initial values' . They are imported only once where future feature reverts or rebuilds will not affect the entity. This allows importing entities while letting content managers edit the entities without affecting the state of the feature. The default label and alias export is of this type.

Naturally, export is a very complicated process, and problematic when importing reference values on a single component level. Entityreference and file fields will simply not export well and may lead in unwanted results as references may differ between environments. Avoiding exporting fields with references is recommended, unless there is a module that handles them by extending systementity. System node and system taxonomy modules handle these cases for tnid and parent properties.

Some properties of the entity are not stored on the entity but in separate tables managed by other modules, aliases are an example of that. Your module will have to handle these properties if there are any. Aliases are supported out of the box.

/**
 * Implements hook_systementity_type_info().
 */
function MYMODULE_systementity_type_info() {
  $types['node']['my_system_item'] = array(
    'machine name field' => 'field_msi_machine_name',
    'export' => array(
      'fields' => array('body', 'promote'),
      'alias' => TRUE,
      'initial value fields' => array('field_name', 'field_address'),
    ),
  );

The above example will define body and promote fields as hard exports (editing these fields will make the feature overridden), and field_name and field_address as initial value exports (editing these fields will NOT make the feature overridden).

The above configuration can be assigned to a specific system entity alone:

/**
 * Implements hook_systementity_settings().
 */
function MYMODULE_systementity_settings() {
  $system_entities = array();

  $system_entities['node']['my_system_item']['item_1'] = array(
    'export' => array(
      'fields' => array('body', 'promote'),
      'alias' => TRUE,
      'initial value fields' => array('field_name', 'field_address'),
    ),
  );

  return $system_entities;
}

The configuration from hook_systementity_type_info and hook_systementity_settings are additive, where hard exports will override initial value exports.