protected function getRevisionDescription(ContentEntityInterface $revision, $is_current = FALSE) { /** @var \Drupal\Core\Entity\ContentEntityInterface|\Drupal\user\EntityOwnerInterface $revision */ if ($revision instanceof EntityOwnerInterface) { $username = ['#theme' => 'username', '#account' => $revision->getOwner()]; } else { $username = ''; } if ($revision instanceof ExpandedEntityRevisionInterface) { // Use revision link to link to revisions that are not active. $date = $this->dateFormatter()->format($revision->getRevisionCreationTime(), 'short'); if (!$is_current) { $link = $this->l($date, $revision->urlInfo('revision')); } else { $link = $revision->link($date); } } else { $link = $revision->link($revision->label(), 'revision'); } $markup = ''; if ($revision instanceof EntityRevisionLogInterface) { $markup = $revision->getRevisionLog(); } if ($username) { $template = '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}'; } else { $template = '{% trans %} {{ date }} {% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}'; } $column = ['data' => ['#type' => 'inline_template', '#template' => $template, '#context' => ['date' => $link, 'username' => $this->renderer()->renderPlain($username), 'message' => ['#markup' => $markup, '#allowed_tags' => Xss::getHtmlTagList()]]]]; return $column; }
/** * Check if an entity's default revision and/or state needs adjusting. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity to check. * @param bool $published_state * Whether the state being transitioned to is a published state or not. * * @return bool * TRUE when either the default revision or the state needs to be updated. */ protected function shouldModerate(ContentEntityInterface $entity, $published_state) { // @todo clarify the first condition. // First condition is needed so you can add a translation. // Second condition checks to see if the published status has changed. return $entity->isDefaultTranslation() || $entity->isPublished() !== $published_state; }
/** * Get the entity owner if applicable. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * * @return \Drupal\user\UserInterface|null */ protected function getEntityOwner(ContentEntityInterface $entity) { if ($entity instanceof EntityOwnerInterface) { return $entity->getOwner(); } return NULL; }
/** * 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; }
/** * Set the entity of this source. */ public function setEntity(ContentEntityInterface $entity) { $this->entity = $entity; if ($this->entity->hasTranslation($this->getLanguage())) { $this->entity = $this->entity->getTranslation($this->getLanguage()); } }
/** * {@inheritdoc} */ public function getCacheTags() { // @todo https://www.drupal.org/node/2779933 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; }
/** * {@inheritdoc} */ public function onPresave(ContentEntityInterface $entity, $default_revision, $published_state) { // This is *probably* not necessary if configuration is setup correctly, // but it can't hurt. $entity->setNewRevision(TRUE); // A newly-created revision is always the default revision, or else // it gets lost. $entity->isDefaultRevision($entity->isNew() || $default_revision); }
/** * {@inheritdoc} */ protected function doSaveFieldItems(ContentEntityInterface $entity, array $names = []) { // The anonymous user account is saved with the fixed user ID of 0. // Therefore we need to check for NULL explicitly. if ($entity->id() === NULL) { $entity->uid->value = $this->database->nextId($this->database->query('SELECT MAX(uid) FROM {users}')->fetchField()); $entity->enforceIsNew(); } return parent::doSaveFieldItems($entity, $names); }
protected function getAddLink(ContentEntityInterface $host) { $link = ''; if ($host->access('update', \Drupal::currentUser())) { $link = '<ul class="action-links action-links-field-collection-add"><li>'; $link .= \Drupal::l(t('Add'), Url::FromRoute('field_collection_item.add_page', ['field_collection' => $this->fieldDefinition->getName(), 'host_type' => $host->getEntityTypeId(), 'host_id' => $host->id()])); $link .= '</li></ul>'; } return $link; }
/** * {@inheritdoc} */ protected function save(ContentEntityInterface $entity, array $old_destination_id_values = array()) { // Do not overwrite the root account password. if ($entity->id() != 1) { // Set the pre_hashed password so that the PasswordItem field does not hash // already hashed passwords. If the md5_passwords configuration option is // set we need to rehash the password and prefix with a U. // @see \Drupal\Core\Field\Plugin\Field\FieldType\PasswordItem::preSave() $entity->pass->pre_hashed = TRUE; if (isset($this->configuration['md5_passwords'])) { $entity->pass->value = 'U' . $this->password->hash($entity->pass->value); } } return parent::save($entity, $old_destination_id_values); }
/** * Asserts that a context for the given property path can be derived. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity to test with. * @param $property_path * The property path to look for. * @param $expected_data_type * The expected data type. * * @return \Drupal\Core\Plugin\Context\ContextInterface * The context with a value. */ protected function assertPropertyPath(ContentEntityInterface $entity, $property_path, $expected_data_type) { $typed_data_entity = $entity->getTypedData(); $context_definition = new ContextDefinition($typed_data_entity->getDataDefinition()->getDataType()); $context_with_value = new Context($context_definition, $typed_data_entity); $context_without_value = new Context($context_definition); // Test the context without value. $property_context = $this->typedDataResolver->getContextFromProperty($property_path, $context_without_value); $this->assertEquals($expected_data_type, $property_context->getContextDefinition()->getDataType()); // Test the context with value. $property_context = $this->typedDataResolver->getContextFromProperty($property_path, $context_with_value); $this->assertEquals($expected_data_type, $property_context->getContextDefinition()->getDataType()); // Return the context with value so it can be asserted. return $property_context; }
/** * {@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')); }
/** * 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; }
/** * Creates a translated entity. */ protected function createTranslatableEntity() { $this->entity = EntityTest::create(); $this->entity->addTranslation('es', ['name' => 'name spanish']); $this->entity->addTranslation('fr', ['name' => 'name french']); $this->entity->save(); }
/** * {@inheritdoc} */ public function create(ContentEntityInterface $entity, $fields) { $query = $this->database->insert('comment_entity_statistics')->fields(array('entity_id', 'entity_type', 'field_name', 'cid', 'last_comment_timestamp', 'last_comment_name', 'last_comment_uid', 'comment_count')); foreach ($fields as $field_name => $detail) { // Skip fields that entity does not have. if (!$entity->hasField($field_name)) { continue; } // Get the user ID from the entity if it's set, or default to the // currently logged in user. $last_comment_uid = 0; if ($entity instanceof EntityOwnerInterface) { $last_comment_uid = $entity->getOwnerId(); } if (!isset($last_comment_uid)) { // Default to current user when entity does not implement // EntityOwnerInterface or author is not set. $last_comment_uid = $this->currentUser->id(); } // Default to REQUEST_TIME when entity does not have a changed property. $last_comment_timestamp = REQUEST_TIME; if ($entity instanceof EntityChangedInterface) { $last_comment_timestamp = $entity->getChangedTime(); } $query->values(array('entity_id' => $entity->id(), 'entity_type' => $entity->getEntityTypeId(), 'field_name' => $field_name, 'cid' => 0, 'last_comment_timestamp' => $last_comment_timestamp, 'last_comment_name' => NULL, 'last_comment_uid' => $last_comment_uid, 'comment_count' => 0)); } $query->execute(); }
/** * Populates target values with the source values. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity being translated. * @param \Drupal\Core\Language\LanguageInterface $source * The language to be used as source. * @param \Drupal\Core\Language\LanguageInterface $target * The language to be used as target. */ public function prepareTranslation(ContentEntityInterface $entity, LanguageInterface $source, LanguageInterface $target) { /* @var \Drupal\Core\Entity\ContentEntityInterface $source_translation */ $source_translation = $entity->getTranslation($source->getId()); $target_translation = $entity->addTranslation($target->getId(), $source_translation->toArray()); // Make sure we do not inherit the affected status from the source values. if ($entity->getEntityType()->isRevisionable()) { $target_translation->setRevisionTranslationAffected(NULL); } /** @var \Drupal\user\UserInterface $user */ $user = $this->entityManager()->getStorage('user')->load($this->currentUser()->id()); $metadata = $this->manager->getTranslationMetadata($target_translation); // Update the translation author to current user, as well the translation // creation time. $metadata->setAuthor($user); $metadata->setCreatedTime(REQUEST_TIME); }
/** * Transforms an entity into an array of strings. * * Parses an entity's fields and for every field it builds an array of string * to be compared. Basically this function transforms an entity into an array * of strings. * * @param ContentEntityInterface $entity * An entity containing fields. * * @return array * Array of strings resulted by parsing the entity. */ public function parseEntity(ContentEntityInterface $entity) { $result = array(); $langcode = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId(); // Load entity of current language, otherwise fields are always compared by // their default language. if ($entity->hasTranslation($langcode)) { $entity = $entity->getTranslation($langcode); } $entity_type_id = $entity->getEntityTypeId(); // Load all entity base fields. $entity_base_fields = $this->entityManager->getBaseFieldDefinitions($entity_type_id); // Loop through entity fields and transform every FieldItemList object // into an array of strings according to field type specific settings. foreach ($entity as $field_items) { $field_type = $field_items->getFieldDefinition()->getType(); $plugin_config = $this->pluginsConfig->get('field_types.' . $field_type); $plugin = NULL; if ($plugin_config && $plugin_config['type'] != 'hidden') { $plugin = $this->diffBuilderManager->createInstance($plugin_config['type'], $plugin_config['settings']); } if ($plugin) { // Configurable field. It is the responsibility of the class extending // this class to hide some configurable fields from comparison. This // class compares all configurable fields. if (!array_key_exists($field_items->getName(), $entity_base_fields)) { $build = $plugin->build($field_items); if (!empty($build)) { $result[$field_items->getName()] = $build; } } else { // Check if this field needs to be compared. $config_key = 'entity.' . $entity_type_id . '.' . $field_items->getName(); $enabled = $this->config->get($config_key); if ($enabled) { $build = $plugin->build($field_items); if (!empty($build)) { $result[$field_items->getName()] = $build; } } } } } return $result; }
/** * Will test the redirects. */ public function testRedirects() { // Test alias normalization. $this->config->set('normalize_aliases', TRUE)->save(); $this->assertRedirect('node/' . $this->node->id(), 'test-node'); $this->assertRedirect('Test-node', 'test-node'); $this->config->set('normalize_aliases', FALSE)->save(); $this->assertRedirect('node/' . $this->node->id(), NULL, 'HTTP/1.1 200 OK'); $this->assertRedirect('Test-node', NULL, 'HTTP/1.1 200 OK'); // Test deslashing. $this->config->set('deslash', TRUE)->save(); $this->assertRedirect('test-node/', 'test-node'); $this->config->set('deslash', FALSE)->save(); $this->assertRedirect('test-node/', NULL, 'HTTP/1.1 200 OK'); // Test front page redirects. $this->config->set('frontpage_redirect', TRUE)->save(); $this->config('system.site')->set('page.front', '/node')->save(); $this->assertRedirect('node', '<front>'); // Test front page redirects with an alias. \Drupal::service('path.alias_storage')->save('/node', '/node-alias'); $this->assertRedirect('node-alias', '<front>'); $this->config->set('frontpage_redirect', FALSE)->save(); $this->assertRedirect('node', NULL, 'HTTP/1.1 200 OK'); $this->assertRedirect('node-alias', NULL, 'HTTP/1.1 200 OK'); // Test post request. $this->config->set('normalize_aliases', TRUE)->save(); $this->drupalPost('Test-node', 'application/json', array()); // Does not do a redirect, stays in the same path. $this->assertEqual(basename($this->getUrl()), 'Test-node'); // Test the access checking. $this->config->set('normalize_aliases', TRUE)->save(); $this->config->set('access_check', TRUE)->save(); $this->assertRedirect('admin/config/system/site-information', NULL, 'HTTP/1.1 403 Forbidden'); $this->config->set('access_check', FALSE)->save(); // @todo - here it seems that the access check runs prior to our redirecting // check why so and enable the test. //$this->assertRedirect('admin/config/system/site-information', 'site-info'); // Login as user with admin privileges. $this->drupalLogin($this->adminUser); // Test ignoring admin paths. $this->config->set('ignore_admin_path', FALSE)->save(); $this->assertRedirect('admin/config/system/site-information', 'site-info'); $this->config->set('ignore_admin_path', TRUE)->save(); $this->assertRedirect('admin/config/system/site-information', NULL, 'HTTP/1.1 200 OK'); }
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 synchronizeFields(ContentEntityInterface $entity, $sync_langcode, $original_langcode = NULL) { $translations = $entity->getTranslationLanguages(); $field_type_manager = \Drupal::service('plugin.manager.field.field_type'); // If we have no information about what to sync to, if we are creating a new // entity, if we have no translations for the current entity and we are not // creating one, then there is nothing to synchronize. if (empty($sync_langcode) || $entity->isNew() || count($translations) < 2) { return; } // If the entity language is being changed there is nothing to synchronize. $entity_type = $entity->getEntityTypeId(); $entity_unchanged = isset($entity->original) ? $entity->original : $this->entityManager->getStorage($entity_type)->loadUnchanged($entity->id()); if ($entity->getUntranslated()->language()->getId() != $entity_unchanged->getUntranslated()->language()->getId()) { return; } /** @var \Drupal\Core\Field\FieldItemListInterface $items */ foreach ($entity as $field_name => $items) { $field_definition = $items->getFieldDefinition(); $field_type_definition = $field_type_manager->getDefinition($field_definition->getType()); $column_groups = $field_type_definition['column_groups']; // Sync if the field is translatable, not empty, and the synchronization // setting is enabled. if ($field_definition instanceof ThirdPartySettingsInterface && $field_definition->isTranslatable() && !$items->isEmpty() && ($translation_sync = $field_definition->getThirdPartySetting('content_translation', 'translation_sync'))) { // Retrieve all the untranslatable column groups and merge them into // single list. $groups = array_keys(array_diff($translation_sync, array_filter($translation_sync))); if (!empty($groups)) { $columns = array(); foreach ($groups as $group) { $info = $column_groups[$group]; // A missing 'columns' key indicates we have a single-column group. $columns = array_merge($columns, isset($info['columns']) ? $info['columns'] : array($group)); } if (!empty($columns)) { $values = array(); foreach ($translations as $langcode => $language) { $values[$langcode] = $entity->getTranslation($langcode)->get($field_name)->getValue(); } // If a translation is being created, the original values should be // used as the unchanged items. In fact there are no unchanged items // to check against. $langcode = $original_langcode ?: $sync_langcode; $unchanged_items = $entity_unchanged->getTranslation($langcode)->get($field_name)->getValue(); $this->synchronizeItems($values, $unchanged_items, $sync_langcode, array_keys($translations), $columns); foreach ($translations as $langcode => $language) { $entity->getTranslation($langcode)->get($field_name)->setValue($values[$langcode]); } } } } } }
/** * Checks whether field languages are correctly stored for the given entity. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity fields are attached to. * @param string $message * (optional) A message to display with the assertion. */ protected function assertFieldStorageLangcode(ContentEntityInterface $entity, $message = '') { $status = TRUE; $entity_type = $entity->getEntityTypeId(); $id = $entity->id(); $langcode = $entity->getUntranslated()->language()->id; $fields = array($this->field_name, $this->untranslatable_field_name); foreach ($fields as $field_name) { $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name); $tables = array(ContentEntityDatabaseStorage::_fieldTableName($field_storage), ContentEntityDatabaseStorage::_fieldRevisionTableName($field_storage)); foreach ($tables as $table) { $record = \Drupal::database()->select($table, 'f')->fields('f')->condition('f.entity_id', $id)->condition('f.revision_id', $id)->execute()->fetchObject(); if ($record->langcode != $langcode) { $status = FALSE; break; } } } return $this->assertTrue($status, $message); }
/** * {@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')); }
/** * Save the entity. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The content entity. * @param array $old_destination_id_values * An array of destination id values. * * @return array * An array containing the entity id. */ protected function save(ContentEntityInterface $entity, array $old_destination_id_values = array()) { $entity->save(); return array($entity->id()); }
/** * {@inheritdoc} */ protected function getRevisionDescription(ContentEntityInterface $revision, $is_default = FALSE) { /** @var \Drupal\Core\Entity\ContentEntityInterface|\Drupal\user\EntityOwnerInterface|\Drupal\Core\Entity\RevisionLogInterface $revision */ if ($revision instanceof RevisionLogInterface) { // Use revision link to link to revisions that are not active. $date = $this->dateFormatter->format($revision->getRevisionCreationTime(), 'short'); $link = $revision->toLink($date, 'revision'); // @todo: Simplify this when https://www.drupal.org/node/2334319 lands. $username = ['#theme' => 'username', '#account' => $revision->getRevisionUser()]; $username = $this->renderer->render($username); } else { $link = $revision->toLink($revision->label(), 'revision'); $username = ''; } $markup = ''; if ($revision instanceof RevisionLogInterface) { $markup = $revision->getRevisionLogMessage(); } if ($username) { $template = '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}'; } else { $template = '{% trans %} {{ date }} {% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}'; } $column = ['data' => ['#type' => 'inline_template', '#template' => $template, '#context' => ['date' => $link->toString(), 'username' => $username, 'message' => ['#markup' => $markup, '#allowed_tags' => Xss::getHtmlTagList()]]]]; return $column; }
/** * Builds the entity translation for the provided translation data. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity for which the translation should be returned. * @param array $data * The translation data for the fields. * @param string $target_langcode * The target language. * * @return \Drupal\Core\Entity\ContentEntityInterface $translation * Translation data. */ protected function makePreview(ContentEntityInterface $entity, array $data, $target_langcode) { // If the translation for this language does not exist yet, initialize it. if (!$entity->hasTranslation($target_langcode)) { $entity->addTranslation($target_langcode, $entity->toArray()); } $embeded_fields = $this->config('tmgmt_content.settings')->get('embedded_fields'); $translation = $entity->getTranslation($target_langcode); foreach ($data as $name => $field_data) { foreach (Element::children($field_data) as $delta) { $field_item = $field_data[$delta]; foreach (Element::children($field_item) as $property) { $property_data = $field_item[$property]; // If there is translation data for the field property, save it. if (isset($property_data['#translation']['#text']) && $property_data['#translate']) { $translation->get($name)->offsetGet($delta)->set($property, $property_data['#translation']['#text']); } elseif (isset($embeded_fields[$entity->getEntityTypeId()][$name])) { $this->makePreview($translation->get($name)->offsetGet($delta)->{$property}, $property_data, $target_langcode); } } } } return $translation; }
/** * The title getter. * * @return string * The title of the event. */ public function getTitle() { return $this->entity->label(); }
/** * Populates the affected flag for all the revision translations. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * An entity object being saved. */ protected function populateAffectedRevisionTranslations(ContentEntityInterface $entity) { if ($this->entityType->isTranslatable() && $this->entityType->isRevisionable()) { $languages = $entity->getTranslationLanguages(); foreach ($languages as $langcode => $language) { $translation = $entity->getTranslation($langcode); // Avoid populating the value if it was already manually set. $affected = $translation->isRevisionTranslationAffected(); if (!isset($affected) && $translation->hasTranslationChanges()) { $translation->setRevisionTranslationAffected(TRUE); } } } }
/** * {@inheritdoc} */ protected function purgeFieldItems(ContentEntityInterface $entity, FieldDefinitionInterface $field_definition) { $storage_definition = $field_definition->getFieldStorageDefinition(); $is_deleted = $this->storageDefinitionIsDeleted($storage_definition); $table_mapping = $this->getTableMapping(); $table_name = $table_mapping->getDedicatedDataTableName($storage_definition, $is_deleted); $revision_name = $table_mapping->getDedicatedRevisionTableName($storage_definition, $is_deleted); $revision_id = $this->entityType->isRevisionable() ? $entity->getRevisionId() : $entity->id(); $this->database->delete($table_name)->condition('revision_id', $revision_id)->execute(); if ($this->entityType->isRevisionable()) { $this->database->delete($revision_name)->condition('revision_id', $revision_id)->execute(); } }
/** * Returns a list of the metatag fields on an entity. */ protected function getFields(ContentEntityInterface $entity) { $field_list = array(); if ($entity instanceof ContentEntityInterface) { // Get a list of the metatag field types. $field_types = $this->fieldTypes(); // Get a list of the fields on this entity. $fields = $entity->getFields(); // Iterate through all the fields looking for ones in our list. foreach ($fields as $key => $field) { // Get the field definition which holds the type. $field_info = $field->getFieldDefinition(); // Get the field type, ie: metatag. $field_type = $field_info->getType(); // Check the field type against our list of fields. if (isset($field_type) && in_array($field_type, $field_types)) { // Get the machine name of the field. $field_name = $field->getName(); $field_list[$field_name] = $field_info; } } } return $field_list; }
/** * {@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; }