/**
  * {@inheritdoc}
  */
 public function submitForm(array &$form, FormStateInterface $form_state)
 {
     $this->entityManager->getStorage($this->entityRevision->getEntityTypeId())->deleteRevision($this->entityRevision->getRevisionId());
     $this->logger('content')->notice('@type: deleted %title revision %revision.', ['@type' => $this->entityRevision->bundle(), '%title' => $this->entityRevision->label(), '%revision' => $this->entityRevision->getRevisionId()]);
     drupal_set_message(t('@type %title has been deleted', ['@type' => $this->entityRevision->{$this->entityRevision->getEntityType()->getKey('bundle')}->entity->label(), '%title' => $this->entityRevision->label()]));
     $form_state->setRedirectUrl($this->entityRevision->urlInfo('version-history'));
 }
 protected function checkAccess(ContentEntityInterface $entity, AccountInterface $account, $operation = 'view')
 {
     $entity_type = $entity->getEntityType();
     $entity_type_id = $entity->getEntityTypeId();
     $entity_access = $this->entityTypeManager->getAccessControlHandler($entity_type_id);
     /** @var \Drupal\Core\Entity\EntityStorageInterface $entity_storage */
     $entity_storage = $this->entityTypeManager->getStorage($entity_type_id);
     $map = ['view' => "view all {$entity_type_id} revisions", 'list' => "view all {$entity_type_id} revisions", 'update' => "revert all {$entity_type_id} revisions", 'delete' => "delete all {$entity_type_id} revisions"];
     $bundle = $entity->bundle();
     $type_map = ['view' => "view {$entity_type_id} {$bundle} revisions", 'list' => "view {$entity_type_id} {$bundle} revisions", 'update' => "revert {$entity_type_id} {$bundle} revisions", 'delete' => "delete {$entity_type_id} {$bundle} revisions"];
     if (!$entity || !isset($map[$operation]) || !isset($type_map[$operation])) {
         // If there was no node to check against, or the $op was not one of the
         // supported ones, we return access denied.
         return FALSE;
     }
     // Statically cache access by revision ID, language code, user account ID,
     // and operation.
     $langcode = $entity->language()->getId();
     $cid = $entity->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $operation;
     if (!isset($this->accessCache[$cid])) {
         // Perform basic permission checks first.
         if (!$account->hasPermission($map[$operation]) && !$account->hasPermission($type_map[$operation]) && !$account->hasPermission('administer nodes')) {
             $this->accessCache[$cid] = FALSE;
             return FALSE;
         }
         if (($admin_permission = $entity_type->getAdminPermission()) && $account->hasPermission($admin_permission)) {
             $this->accessCache[$cid] = TRUE;
         } else {
             // First check the access to the default revision and finally, if the
             // node passed in is not the default revision then access to that, too.
             $this->accessCache[$cid] = $entity_access->access($entity_storage->load($entity->id()), $operation, $account) && ($entity->isDefaultRevision() || $entity_access->access($entity, $operation, $account));
         }
     }
     return $this->accessCache[$cid];
 }
 /**
  * Returns the entity_form_display object used to build an entity form.
  *
  * Depending on the configuration of the form mode for the entity bundle, this
  * can be either the display object associated to the form mode, or the
  * 'default' display.
  *
  * This method should only be used internally when rendering an entity form.
  * When assigning suggested display options for a component in a given form
  * mode, entity_get_form_display() should be used instead, in order to avoid
  * inadvertently modifying the output of other form modes that might happen to
  * use the 'default' display too. Those options will then be effectively
  * applied only if the form mode is configured to use them.
  *
  * hook_entity_form_display_alter() is invoked on each display, allowing 3rd
  * party code to alter the display options held in the display before they are
  * used to generate render arrays.
  *
  * @param \Drupal\Core\Entity\ContentEntityInterface $entity
  *   The entity for which the form is being built.
  * @param string $form_mode
  *   The form mode.
  *
  * @return \Drupal\Core\Entity\Display\EntityFormDisplayInterface
  *   The display object that should be used to build the entity form.
  *
  * @see entity_get_form_display()
  * @see hook_entity_form_display_alter()
  */
 public static function collectRenderDisplay(ContentEntityInterface $entity, $form_mode)
 {
     $entity_type = $entity->getEntityTypeId();
     $bundle = $entity->bundle();
     // Check the existence and status of:
     // - the display for the form mode,
     // - the 'default' display.
     if ($form_mode != 'default') {
         $candidate_ids[] = $entity_type . '.' . $bundle . '.' . $form_mode;
     }
     $candidate_ids[] = $entity_type . '.' . $bundle . '.default';
     $results = \Drupal::entityQuery('entity_form_display')->condition('id', $candidate_ids)->condition('status', TRUE)->execute();
     // Load the first valid candidate display, if any.
     $storage = \Drupal::entityManager()->getStorage('entity_form_display');
     foreach ($candidate_ids as $candidate_id) {
         if (isset($results[$candidate_id])) {
             $display = $storage->load($candidate_id);
             break;
         }
     }
     // Else create a fresh runtime object.
     if (empty($display)) {
         $display = $storage->create(array('targetEntityType' => $entity_type, 'bundle' => $bundle, 'mode' => $form_mode, 'status' => TRUE));
     }
     // Let the display know which form mode was originally requested.
     $display->originalMode = $form_mode;
     // Let modules alter the display.
     $display_context = array('entity_type' => $entity_type, 'bundle' => $bundle, 'form_mode' => $form_mode);
     \Drupal::moduleHandler()->alter('entity_form_display', $display, $display_context);
     return $display;
 }
 /**
  * {@inheritdoc}
  */
 public function getCacheTags()
 {
     // @todo write a test for this.
     $tags = parent::getCacheTags();
     // Tab changes if node or node-type is modified.
     $tags = array_merge($tags, $this->entity->getCacheTags());
     $tags[] = $this->entity->getEntityType()->getBundleEntityType() . ':' . $this->entity->bundle();
     return $tags;
 }
 protected function checkAccess(ContentEntityInterface $entity, AccountInterface $account, $operation = 'view')
 {
     $entity_type_id = $entity->getEntityTypeId();
     $entity_access = $this->entityManager->getAccessControlHandler($entity_type_id);
     /** @var \Drupal\content_entity_base\Entity\Storage\RevisionableStorageInterface|\Drupal\Core\Entity\EntityStorageInterface $entity_storage */
     $entity_storage = $this->entityManager->getStorage($entity_type_id);
     if (!$entity_storage instanceof RevisionableStorageInterface) {
         throw new \InvalidArgumentException('The entity storage has to implement \\Drupal\\content_entity_base\\Entity\\Storage\\RevisionableStorageInterface');
     }
     $map = ['view' => "view all {$entity_type_id} revisions", 'update' => "revert all {$entity_type_id} revisions", 'delete' => "delete all {$entity_type_id} revisions"];
     $bundle = $entity->bundle();
     $type_map = ['view' => "view {$entity_type_id} {$bundle} revisions", 'update' => "revert {$entity_type_id} {$bundle} revisions", 'delete' => "delete {$entity_type_id} {$bundle} revisions"];
     if (!$entity || !isset($map[$operation]) || !isset($type_map[$operation])) {
         // If there was no node to check against, or the $op was not one of the
         // supported ones, we return access denied.
         return FALSE;
     }
     // Statically cache access by revision ID, language code, user account ID,
     // and operation.
     $langcode = $entity->language()->getId();
     $cid = $entity->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $operation;
     if (!isset($this->access[$cid])) {
         // Perform basic permission checks first.
         if (!$account->hasPermission($map[$operation]) && !$account->hasPermission($type_map[$operation]) && !$account->hasPermission('administer nodes')) {
             $this->access[$cid] = FALSE;
             return FALSE;
         }
         // There should be at least two revisions. If the vid of the given node
         // and the vid of the default revision differ, then we already have two
         // different revisions so there is no need for a separate database check.
         // Also, if you try to revert to or delete the default revision, that's
         // not good.
         if ($entity->isDefaultRevision() && ($entity_storage->countDefaultLanguageRevisions($entity) == 1 || $operation == 'update' || $operation == 'delete')) {
             $this->access[$cid] = FALSE;
         } elseif ($account->hasPermission('administer ' . $entity_type_id)) {
             $this->access[$cid] = TRUE;
         } else {
             // First check the access to the default revision and finally, if the
             // node passed in is not the default revision then access to that, too.
             $this->access[$cid] = $entity_access->access($entity_storage->load($entity->id()), $operation, $account) && ($entity->isDefaultRevision() || $entity_access->access($entity, $operation, $account));
         }
     }
     return $this->access[$cid];
 }
 /**
  * {@inheritdoc}
  */
 public function submitForm(array &$form, FormStateInterface $form_state)
 {
     // The revision timestamp will be updated when the revision is saved. Keep
     // the original one for the confirmation message.
     $this->entityRevision->setNewRevision();
     $this->entityRevision->isDefaultRevision(TRUE);
     if ($this->entityRevision instanceof EntityRevisionLogInterface) {
         if ($this->entityRevision instanceof TimestampedRevisionInterface) {
             $original_revision_timestamp = $this->entityRevision->getRevisionCreationTime();
             $this->entityRevision->revision_log = t('Copy of the revision from %date.', ['%date' => $this->dateFormatter->format($original_revision_timestamp)]);
         } else {
             $this->entityRevision->revision_log = t('Copy of the revision');
         }
     }
     $this->entityRevision->save();
     $this->logger('content')->notice('@type: reverted %title revision %revision.', ['@type' => $this->entityRevision->bundle(), '%title' => $this->entityRevision->label(), '%revision' => $this->entityRevision->getRevisionId()]);
     drupal_set_message(t('@type %title has been reverted to the revision', ['@type' => $this->entityRevision->{$this->entityRevision->getEntityType()->getKey('bundle')}->entity->label(), '%title' => $this->entityRevision->label()]));
     $form_state->setRedirectUrl($this->entityRevision->urlInfo('version-history'));
 }
 /**
  * Deletes values of fields in dedicated tables for all revisions.
  *
  * @param \Drupal\Core\Entity\ContentEntityInterface $entity
  *   The entity. It must have a revision ID.
  */
 protected function deleteRevisionFromDedicatedTables(ContentEntityInterface $entity)
 {
     $vid = $entity->getRevisionId();
     if (isset($vid)) {
         $table_mapping = $this->getTableMapping();
         foreach ($this->entityManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()) as $field_definition) {
             $storage_definition = $field_definition->getFieldStorageDefinition();
             if (!$table_mapping->requiresDedicatedTableStorage($storage_definition)) {
                 continue;
             }
             $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition);
             $this->database->delete($revision_name)->condition('entity_id', $entity->id())->condition('revision_id', $vid)->execute();
         }
     }
 }
 public function getBundle() {
   return $this->entity->bundle();
 }
 /**
  * {@inheritdoc}
  */
 public function getValidTransitions(ContentEntityInterface $entity, AccountInterface $user)
 {
     $bundle = $this->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle());
     /** @var \Drupal\content_moderation\Entity\ModerationState $current_state */
     $current_state = $entity->moderation_state->entity;
     $current_state_id = $current_state ? $current_state->id() : $bundle->getThirdPartySetting('content_moderation', 'default_moderation_state');
     // Determine the states that are legal on this bundle.
     $legal_bundle_states = $bundle->getThirdPartySetting('content_moderation', 'allowed_moderation_states', []);
     // Legal transitions include those that are possible from the current state,
     // filtered by those whose target is legal on this bundle and that the
     // user has access to execute.
     $transitions = array_filter($this->getTransitionsFrom($current_state_id), function (ModerationStateTransition $transition) use($legal_bundle_states, $user) {
         return in_array($transition->getToState(), $legal_bundle_states, TRUE) && $user->hasPermission('use ' . $transition->id() . ' transition');
     });
     return $transitions;
 }
 /**
  * Inject the relevant css for the template.
  *
  * You can specify CSS files to be included per entity type and bundle in your
  * themes css file. This code uses your current theme which is likely to be the
  * front end theme.
  *
  * Examples:
  *
  * entity_print:
  *   all: 'yourtheme/all-pdfs',
  *   commerce_order:
  *     all: 'yourtheme/orders'
  *   node:
  *     article: 'yourtheme/article-pdf'
  *
  * @param array $render
  *   The renderable array.
  * @param \Drupal\Core\Entity\ContentEntityInterface $entity
  *   The entity info from entity_get_info().
  *
  * @return array
  *   An array of stylesheets to be used for this template.
  */
 protected function addCss($render, ContentEntityInterface $entity)
 {
     $theme = $this->themeHandler->getDefault();
     $theme_path = $this->getThemePath($theme);
     /** @var \Drupal\Core\Extension\InfoParser $parser */
     $theme_info = $this->infoParser->parse("{$theme_path}/{$theme}.info.yml");
     // Parse out the CSS from the theme info.
     if (isset($theme_info['entity_print'])) {
         // See if we have the special "all" key which is added to every PDF.
         if (isset($theme_info['entity_print']['all'])) {
             $render['#attached']['library'][] = $theme_info['entity_print']['all'];
             unset($theme_info['entity_print']['all']);
         }
         foreach ($theme_info['entity_print'] as $key => $value) {
             // If the entity type doesn't match just skip.
             if ($key !== $entity->getEntityTypeId()) {
                 continue;
             }
             // Parse our css files per entity type and bundle.
             foreach ($value as $css_bundle => $css) {
                 // If it's magic key "all" add it otherwise check the bundle.
                 if ($css_bundle === 'all' || $entity->bundle() === $css_bundle) {
                     $render['#attached']['library'][] = $css;
                 }
             }
         }
     }
     return $render;
 }
Example #11
0
 /**
  * Determines the default moderation state on load for an entity.
  *
  * This method is only applicable when an entity is loaded that has
  * no moderation state on it, but should. In those cases, failing to set
  * one may result in NULL references elsewhere when other code tries to check
  * the moderation state of the entity.
  *
  * The amount of indirection here makes performance a concern, but
  * given how Entity API works I don't know how else to do it.
  * This reliably gets us *A* valid state. However, that state may be
  * not the ideal one. Suggestions on how to better select the default
  * state here are welcome.
  *
  * @param \Drupal\Core\Entity\ContentEntityInterface $entity
  *   The entity for which we want a default state.
  *
  * @return string
  *   The default state for the given entity.
  */
 protected function getDefaultLoadStateId(ContentEntityInterface $entity)
 {
     return $this->moderationInfo->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle())->getThirdPartySetting('content_moderation', 'default_moderation_state');
 }
 /**
  * Retrieves all indexes that are configured to index the given entity.
  *
  * @param \Drupal\Core\Entity\ContentEntityInterface $entity
  *   The entity for which to check.
  *
  * @return \Drupal\search_api\IndexInterface[]
  *   All indexes that are configured to index the given entity (using this
  *   datasource class).
  */
 public static function getIndexesForEntity(ContentEntityInterface $entity)
 {
     $entity_type = $entity->getEntityTypeId();
     $datasource_id = 'entity:' . $entity_type;
     $entity_bundle = $entity->bundle();
     $index_names = \Drupal::entityQuery('search_api_index')->condition('datasources.*', $datasource_id)->execute();
     if (!$index_names) {
         return array();
     }
     // Needed for PhpStorm. See https://youtrack.jetbrains.com/issue/WI-23395.
     /** @var \Drupal\search_api\IndexInterface[] $indexes */
     $indexes = Index::loadMultiple($index_names);
     // If the datasource's entity type supports bundles, we have to filter the
     // indexes for whether they also include the specific bundle of the given
     // entity. Otherwise, we are done.
     if ($entity_type !== $entity_bundle) {
         foreach ($indexes as $index_id => $index) {
             try {
                 $config = $index->getDatasource($datasource_id)->getConfiguration();
                 $default = !empty($config['default']);
                 $bundle_set = !empty($config['bundles'][$entity_bundle]);
                 if ($default == $bundle_set) {
                     unset($indexes[$index_id]);
                 }
             } catch (SearchApiException $e) {
                 unset($indexes[$index_id]);
             }
         }
     }
     return $indexes;
 }
 /**
  * Gets a list of states a user may transition an entity to.
  *
  * @param \Drupal\Core\Entity\ContentEntityInterface $entity
  *   The entity to be transitioned.
  * @param \Drupal\Core\Session\AccountInterface $user
  *   The account that wants to perform a transition.
  *
  * @return ModerationState[]
  *   Returns an array of States to which the specified user may transition the
  *   entity.
  */
 public function getValidTransitionTargets(ContentEntityInterface $entity, AccountInterface $user)
 {
     $bundle = $this->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle());
     $states_for_bundle = $bundle->getThirdPartySetting('workbench_moderation', 'allowed_moderation_states', []);
     /** @var ModerationState $state */
     $state = $entity->moderation_state->entity;
     $current_state_id = $state->id();
     $all_transitions = $this->getPossibleTransitions();
     $destinations = $all_transitions[$current_state_id];
     $destinations = array_intersect($states_for_bundle, $destinations);
     $permitted_destinations = array_filter($destinations, function ($state_name) use($current_state_id, $user) {
         return $this->userMayTransition($current_state_id, $state_name, $user);
     });
     return $this->entityTypeManager->getStorage('moderation_state')->loadMultiple($permitted_destinations);
 }
Example #14
0
  /**
   * Get whether a new revision should be created by default for this entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity_to_update
   *
   * @return bool
   */
  public function getRevisionDefault(ContentEntityInterface $entity_to_update) {
    $bundle_type_id = $entity_to_update->getEntityType()->getBundleEntityType();
    $bundle = $this->entityTypeManager->getStorage($bundle_type_id)->load($entity_to_update->bundle());

    // This should exist because of previous check in supportsRevisionBundleDefault but just in case.
    if ($bundle instanceof NodeTypeInterface) {
      return $bundle->isNewRevision();
    }
    return FALSE;
  }
 /**
  * Returns the display object used to render an entity.
  *
  * See the collectRenderDisplays() method for details.
  *
  * @param \Drupal\Core\Entity\ContentEntityInterface $entity
  *   The entity being rendered.
  * @param string $view_mode
  *   The view mode.
  *
  * @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface
  *   The display object that should be used to render the entity.
  *
  * @see \Drupal\entity\Entity\EntityDisplay::collectRenderDisplays()
  */
 public static function collectRenderDisplay(ContentEntityInterface $entity, $view_mode)
 {
     $displays = static::collectRenderDisplays(array($entity), $view_mode);
     return $displays[$entity->bundle()];
 }
 /**
  * Builds a table row for overview form.
  *
  * @param array ContentEntityInterface $entity
  *   Data needed to build the list row.
  * @param array $bundles
  *   The array of bundles.
  *
  * @return array
  */
 public function overviewRow(ContentEntityInterface $entity, array $bundles)
 {
     $label = $entity->label() ?: $this->t('@type: @id', array('@type' => $entity->getEntityTypeId(), '@id' => $entity->id()));
     // Get existing translations and current job items for the entity
     // to determine translation statuses
     $translations = $entity->getTranslationLanguages();
     $source_lang = $entity->language()->getId();
     $current_job_items = tmgmt_job_item_load_latest('content', $entity->getEntityTypeId(), $entity->id(), $source_lang);
     $row = array('id' => $entity->id(), 'title' => $entity->hasLinkTemplate('canonical') ? $entity->toLink($label, 'canonical')->toString() : ($entity->label() ?: $entity->id()));
     if (count($bundles) > 1) {
         $row['bundle'] = isset($bundles[$entity->bundle()]) ? $bundles[$entity->bundle()] : t('Unknown');
     }
     // Load entity translation specific data.
     $manager = \Drupal::service('content_translation.manager');
     foreach (\Drupal::languageManager()->getLanguages() as $langcode => $language) {
         $translation_status = 'current';
         if ($langcode == $source_lang) {
             $translation_status = 'original';
         } elseif (!isset($translations[$langcode])) {
             $translation_status = 'missing';
         } elseif ($translation = $entity->getTranslation($langcode)) {
             $metadata = $manager->getTranslationMetadata($translation);
             if ($metadata->isOutdated()) {
                 $translation_status = 'outofdate';
             }
         }
         $build = $this->buildTranslationStatus($translation_status, isset($current_job_items[$langcode]) ? $current_job_items[$langcode] : NULL);
         $row['langcode-' . $langcode] = ['data' => \Drupal::service('renderer')->render($build), 'class' => array('langstatus-' . $langcode)];
     }
     return $row;
 }