auto_entitylabel-8.x-3.x-dev/auto_entitylabel.module

auto_entitylabel.module
<?php

/**
 * @file
 * Allows hiding of entity label fields and automatic label creation.
 */

use Drupal\auto_entitylabel\AutoEntityLabelManager;
use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;

/**
 * Implements hook_help().
 */
function auto_entitylabel_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.auto_entitylabel':
      $output = '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('This is a small and efficient module that allows hiding of entity label fields. To prevent empty labels it can be configured to generate the label automatically by a given pattern. The module can be used for any entity type that has a label, including e.g. for node titles, comment subjects, taxonomy term names and profile2 labels.') . '</p>';
      $output .= '<p>' . t('Patterns for automatic labels are constructed with the help of tokens. Drupal core provides a basic set of <a href="@url_tokens" target="blank">tokens</a>. For a token selection widget install the token. Some entity types (e.g. profile2) provide tokens via the entity_token, which is part of the entity module.', ['@url_tokens' => 'https://www.drupal.org/project/token']) . '</p>';
      $output .= '<p>' . t('Watch the <a href="@url_daily_dose_of_drupal" target="blank">Daily Dose of Drupal</a> screencast by <a href="@url_shane_thomas" target="blank">Shane Thomas</a> for a short introduction and demonstration of the module and some of its features. Demonstration made in D7 but can help a lot.',
          [
            '@url_daily_dose_of_drupal' => 'http://codekarate.com/daily-dose-of-drupal/drupal-7-automatic-entity-label-module',
            '@url_shane_thomas' => 'https://www.drupal.org/user/506260',
          ]) . '</p>';
      $output .= '<h3>' . t('Usage') . '</h3>';
      $output .= '<p>' . t('The configuration can be accessed with the <i>Manage automatic entity labels</i> operation or the <i>Automatic label</i> tab when editing entity types. For example, when configuring a node type, visit <i>Administration</i> » <i>Structure</i> » <i>Content types</i> (/admin/structure/types). You can also configure automatic labels for other entity types such as <i>Media<i>, in which case you would visit <i>Administration</i> » <i>Structure</i> » <i>Media</i> (/admin/structure/media).') . '</p>';

      return $output;
  }
}

/**
 * Implements hook_entity_type_alter().
 *
 * Adds the Auto Label tab to the entity configuration page.
 */
function auto_entitylabel_entity_type_alter(array &$entity_types) {
  /** @var \Drupal\Core\Entity\EntityTypeInterface $entity_type */
  foreach ($entity_types as $entity_type) {
    if ($entity_type->getBundleOf() && $entity_type->hasLinkTemplate('edit-form')) {
      $entity_type->setLinkTemplate('auto-label', $entity_type->getLinkTemplate('edit-form') . "/auto-label");
    }
  }
}

/**
 * Implements hook_form_alter().
 */
function auto_entitylabel_form_alter(&$form, FormStateInterface $form_state) {
  /** @var \Drupal\Core\Entity\EntityFormInterface $formObject */
  $formObject = $form_state->getFormObject();
  if ($formObject instanceof EntityFormInterface) {
    $entity = $formObject->getEntity();
    if ($entity instanceof ContentEntityInterface) {
      auto_entitylabel_prepare_entityform($form, $entity);
    }
  }
}

/**
 * Implements hook_inline_entity_form_entity_form_alter().
 */
function auto_entitylabel_inline_entity_form_entity_form_alter(&$form, &$form_state) {
  $entity = $form['#entity'];
  auto_entitylabel_prepare_entityform($form, $entity);
}

/**
 * Implements hook_inline_entity_form_table_fields_alter().
 */
function auto_entitylabel_inline_entity_form_table_fields_alter(&$fields, $context) {
  // Replace label field behavior.
  if (isset($fields['label'])) {
    $fields['label']['type'] = 'callback';
    $fields['label']['callback'] = 'auto_entitylabel_inline_entity_label_callback';
  }
}

/**
 * A callback function to provide autoentitylabel for inline entity form.
 */
function auto_entitylabel_inline_entity_label_callback($entity, $variables) {
  $autolabel = $entity->label();
  if ($entity instanceof ContentEntityInterface) {
    $decorator = \Drupal::service('auto_entitylabel.entity_decorator');
    /** @var \Drupal\auto_entitylabel\AutoEntityLabelManager $decorated_entity */
    $decorated_entity = $decorator->decorate($entity);
    if ($decorated_entity->hasLabel() && $decorated_entity->autoLabelNeeded()) {
      $autolabel = $decorated_entity->setLabel();
    }

  }

  return $autolabel;
}

/**
 * Prepares the label replacement in the entity form.
 *
 * @param array $form
 *   Form array.
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 *   The entity which title will be replaced.
 */
function auto_entitylabel_prepare_entityform(array &$form, ContentEntityInterface $entity) {
  if (empty($form['#auto_entitylabel_processed'])) {
    $decorator = \Drupal::service('auto_entitylabel.entity_decorator');
    /** @var \Drupal\auto_entitylabel\AutoEntityLabelManager $entity */
    $entity = $decorator->decorate($entity);
    $label = $entity->getLabelName();
    $widget = &$form[$label]['widget'][0];

    switch ($entity->getStatus()) {
      case AutoEntityLabelManager::ENABLED:
        // Hide the label field. It will be automatically generated in
        // hook_entity_presave().
        $widget['value']['#type'] = 'hidden';
        $widget['value']['#required'] = FALSE;
        if (empty($widget['value']['#default_value'])) {
          $widget['value']['#default_value'] = '%AutoEntityLabel%';
        }
        break;

      case AutoEntityLabelManager::OPTIONAL:
        // Allow label field to be empty. It will be automatically generated
        // in hook_entity_presave().
        $widget['value']['#required'] = FALSE;
        break;

      case AutoEntityLabelManager::PREFILLED:
        if (empty($widget['value']['#default_value'])) {
          $widget['value']['#default_value'] = $entity->setLabel();
        }
        break;
    }

    $form['#auto_entitylabel_processed'] = TRUE;
  }
}

/**
 * Implements hook_entity_prepare_view().
 */
function auto_entitylabel_entity_prepare_view($entity_type_id, array $entities, array $displays, $view_mode) {
  foreach ($entities as $entity) {
    if (isset($entity->in_preview) && $entity->in_preview === TRUE && $entity instanceof ContentEntityInterface) {
      $decorator = \Drupal::service('auto_entitylabel.entity_decorator');
      /** @var \Drupal\auto_entitylabel\AutoEntityLabelManager $decorated_entity */
      $decorated_entity = $decorator->decorate($entity);

      if ($decorated_entity->hasLabel() && $decorated_entity->autoLabelNeeded()) {
        $decorated_entity->setLabel();
      }
    }
  }
}

/**
 * Implements hook_entity_presave().
 */
function auto_entitylabel_entity_presave(EntityInterface $entity) {
  if ($entity instanceof ContentEntityInterface) {
    $decorator = \Drupal::service('auto_entitylabel.entity_decorator');
    /** @var \Drupal\auto_entitylabel\AutoEntityLabelManager $decorated_entity */
    $decorated_entity = $decorator->decorate($entity);
    if ($decorated_entity->hasLabel() && $decorated_entity->autoLabelNeeded()) {

      // Need to generate a label for this entity.
      //
      // There's a few cases we need to handle.
      // I'm going to lay these out explicitly so that the logic is
      // clear. I expect we can optimize these at a later point.
      //
      // Two of the scenarios need the placeholder label, so
      // always generate it.
      // Make the placeholder unique for this entity. Handles the case
      // where both a paragraph on a node and a node have an auto label.
      $placeholder = strtr('%AutoEntityLabel: @entityId%', ['@entityId' => $entity->uuid()]);

      // Check to see if this is a new entity.
      if ($entity->isNew()) {
        // Handle the case where the automatic label is optional.
        // Check to see if isTitlePreserved is set. If the autolabel is
        // optional AND the user has filled this title in then the
        // the autolabel should not be set.
        if (!$decorated_entity->isTitlePreserved() || $entity->label() == '%AutoEntityLabel%') {
          // For a new entity check to see whether the automatic label
          // is configured to be generated before we've saved the node
          // to the database or after. While the entity is flagged as
          // new this presave is running before the entity has been saved
          // to the database.
          if ($decorated_entity->getNewContentBehavior() === AutoEntityLabelManager::BEFORE_SAVE) {
            // Generate the automatic label during this run of the presave
            // hook. Note that not all tokens are available during the
            // first presave hook run for new entities (most notably the
            // entity id token).
            $decorated_entity->setLabel();
          }
          else {
            // Generate the label after the first save, when the entity has
            // been written to the database and all tokens are available.
            // When the after first save option is selected code in the
            // autoentity_entity_insert function will trigger a resave of the
            // entity, which will in turn trigger another run of this presave
            // hook (but during the second run the entity will not be new).
            // To allow the entity to save we'll set a placeholder title,
            // one that will be replaced once the entity is resaved.
            // Using Drupal functions so as not to trigger two runs of
            // setLabel().
            $label_field = $entity->getEntityType()->getKey('label');
            $entity->set($label_field, $placeholder);
          }
        }
      }
      else {
        // This is an update of an existing entity.
        // Check to see whether the existing title needs to be
        // preserved.
        if ($decorated_entity->isTitlePreserved()) {
          // The existing title needs to be preserved.
          // Now check whether or not the title is the new entity
          // placeholder. Because if it is we want to ignore
          // the isTitlePreserved flag and update the label anyway
          // (the code assumes that the only way the entity will
          // have the placeholder title is if we've configured this entity
          // to set its auto label during the second run of the presave
          // hook and this is that second run).
          $oldLabel = $entity->label();
          if ($oldLabel == $placeholder) {
            $decorated_entity->setLabel();
          }
        }
        else {
          // Don't preserve the exiting title. Update the label.
          $decorated_entity->setLabel();
        }
      }
    }
  }
}

/**
 * Implements hook_entity_insert().
 */
function auto_entitylabel_entity_insert(EntityInterface $entity) {
  // AutoEntityLabel only supports content entities.
  if ($entity instanceof ContentEntityInterface) {
    // To support tokens that are only available after the entity has
    // been created (like id tokens) trigger a second save.
    // To do this without corrupting the entity run the
    // save operation at the end of the entity insert transaction.
    // To run code at the entity of the entity insert transaction
    // we need to register a transaction shutdown function.
    // Check the autolabel settings for the entity to see if we
    // need to register the shutdown function.
    $decorator = \Drupal::service('auto_entitylabel.entity_decorator');
    /** @var \Drupal\auto_entitylabel\AutoEntityLabelManager $decorated_entity */
    $decorated_entity = $decorator->decorate($entity);
    if ($decorated_entity->hasLabel()
      && $decorated_entity->autoLabelNeeded()
      && $decorated_entity->getNewContentBehavior() === AutoEntityLabelManager::AFTER_SAVE
    ) {
      // This new entity has an autolabel and it needs to be generated
      // after the entity has been saved in the database. Register the
      // shutdown function.
      drupal_register_shutdown_function('_auto_entitylabel_post_insert', $entity);

      // Set entity label in memory so messages and such can use what will be
      // saved during shutdown.
      $decorator = \Drupal::service('auto_entitylabel.entity_decorator');
      /** @var \Drupal\auto_entitylabel\AutoEntityLabelManager $decorated_entity */
      $decorated_entity = $decorator->decorate($entity);
      if ($decorated_entity->hasLabel() && $decorated_entity->autoLabelNeeded()) {
        $placeholder = strtr('%AutoEntityLabel: @entityId%', ['@entityId' => $entity->uuid()]);
        if (!$decorated_entity->isTitlePreserved() || $entity->label() == $placeholder) {
          if ($decorated_entity->getNewContentBehavior() === AutoEntityLabelManager::AFTER_SAVE) {
            // Update entity's label in memory for anything running after us.
            $label = $decorated_entity->setLabel();

            // Update messages that were using the placeholder label.
            $messenger = Drupal::messenger();
            $all_messages = $messenger->all();
            $messenger->deleteAll();
            foreach ($all_messages as $type => $messages) {
              foreach ($messages as $message) {
                if (strpos($message, $placeholder) >= 0) {
                  if ($message instanceof MarkupInterface) {
                    $message = Markup::create(str_replace($placeholder, $label, $message));
                  }
                  else {
                    $message = str_replace($placeholder, $label, $message);
                  }
                }
                $messenger->addMessage($message, $type);
              }
            }
          }
        }
      }
    }
  }
}

/**
 * Re-save the entity to trigger creation of the automatic label if necessary.
 */
function _auto_entitylabel_post_insert(EntityInterface $entityArg) {
  if ($entityArg instanceof ContentEntityInterface) {
    // Because of the way PHP shutdown functions work this operation may
    // be called during an entity delete operation (as demonstrated by
    // the Kernel test). Reload the entity from the database to check that
    // it hasn't been deleted.
    if ($entity = \Drupal::entityTypeManager()->getStorage($entityArg->getEntityTypeId())->loadUnchanged($entityArg->id())) {

      // The entity hasn't been deleted, continue processing.
      // Again because of the way shutdown functions work this
      // function may be called for entities that don't have an
      // autolabel or ones that do but don't need to be saved
      // again. Run the same checks that were run during the
      // insert hook to be sure that this entity really needs the
      // second save.
      $decorator = \Drupal::service('auto_entitylabel.entity_decorator');
      /** @var \Drupal\auto_entitylabel\AutoEntityLabelManager $decorated_entity */
      $decorated_entity = $decorator->decorate($entity);

      if ($decorated_entity->hasLabel()
      && $decorated_entity->autoLabelNeeded()
      && $decorated_entity->getNewContentBehavior() === AutoEntityLabelManager::AFTER_SAVE) {
        if ($entity->getEntityType()->isRevisionable()) {
          $entity->setNewRevision(FALSE);
        }
        $entity->save();
      }
    }
  }
}

/**
 * Implements hook_validation_constraint_alter().
 *
 * Override core NotNull constraint to allow entities that use Auto Entity
 * Labels to validate when their label is empty before being set automatically.
 */
function auto_entitylabel_validation_constraint_alter(array &$definitions) {
  $definitions['NotNull']['class'] = 'Drupal\auto_entitylabel\Plugin\Validation\EntityLabelNotNullConstraint';
}

/**
 * Implements hook_entity_operation().
 */
function auto_entitylabel_entity_operation(EntityInterface $entity) {
  $operations = [];
  $entity_type = $entity->getEntityType();
  $entity_type_id = $entity_type->id();
  $entity_id = $entity->id();
  if ($entity->hasLinkTemplate('auto-label') &&
    \Drupal::currentUser()
      ->hasPermission('administer ' . $entity_type_id . ' labels')) {

    $operations['auto-label'] = [
      'title' => t('Manage automatic entity labels'),
      'weight' => 100,
      'url' => Url::fromRoute("entity.{$entity_type_id}.auto_label", [$entity_type_id => $entity_id]),
    ];
  }

  return $operations;
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc