/**
  * Renders the Metatag defaults lable plus its configuration.
  *
  * @param EntityInterface $entity
  *   The Metatag defaults entity.
  * @return
  *   Render array for a table cell.
  */
 public function getLabelAndConfig(EntityInterface $entity)
 {
     $output = '<div>';
     $prefix = '';
     $inherits = '';
     if ($entity->id() != 'global') {
         $prefix = '<div class="indentation"></div>';
         $inherits .= 'Global';
     }
     if (strpos($entity->id(), '__') !== FALSE) {
         $prefix .= '<div class="indentation"></div>';
         list($entity_label, $bundle_label) = explode(': ', $entity->get('label'));
         $inherits .= ', ' . $entity_label;
     }
     $output .= '<div>
               <p>Inherits meta tags from: ' . $inherits . '</p>
             </div>';
     $tags = $entity->get('tags');
     if (count($tags)) {
         $output .= '<table>
                 <tbody>';
         foreach ($tags as $tag_id => $tag_value) {
             $output .= '<tr><td>' . $tag_id . ':</td><td>' . $tag_value . '</td></tr>';
         }
         $output .= '</tbody></table>';
     }
     $output .= '</div></div>';
     return array('data' => array('#type' => 'details', '#prefix' => $prefix, '#title' => $this->getLabel($entity), 'config' => array('#markup' => $output)));
 }
예제 #2
0
 /**
  * {@inheritdoc}
  */
 public function buildRow(EntityInterface $entity)
 {
     $row = array();
     $row['date']['data'] = $entity->get('activity_date')->view(array('label' => 'hidden'));
     $row['title']['data'] = array('#type' => 'link', '#title' => SafeMarkup::checkPlain($entity->label()), '#url' => $entity->urlInfo());
     $row['type'] = $entity->get('type')->entity->label();
     return $row + parent::buildRow($entity);
 }
 /**
  * Builds a row for an entity in the entity listing.
  *
  * @param EntityInterface $entity
  *   The entity for which to build the row.
  *
  * @return array
  *   A render array of the table row for displaying the entity.
  *
  * @see Drupal\Core\Entity\EntityListController::render()
  */
 public function buildRow(EntityInterface $entity)
 {
     $row['label'] = $entity->label();
     $row['machine_name'] = $entity->id();
     $row['description'] = $entity->get('description');
     $row['source_type'] = $entity->get('source_type');
     return $row + parent::buildRow($entity);
 }
 /**
  * {@inheritdoc}
  */
 public function buildRow(EntityInterface $medium_editor)
 {
     $row['label'] = $medium_editor->label();
     $row['description'] = String::checkPlain($medium_editor->get('description'));
     $row['toolbar'] = String::checkPlain(implode(', ', $medium_editor->getToolbar()));
     $row['delay'] = String::checkPlain($medium_editor->get('delay'));
     return $row + parent::buildRow($medium_editor);
 }
예제 #5
0
 /**
  * {@inheritdoc}
  */
 public function buildRow(EntityInterface $entity)
 {
     $row = array();
     $row['label']['data'] = array('#type' => 'link', '#title' => SafeMarkup::checkPlain($entity->label()), '#url' => $entity->urlInfo());
     $row['type'] = SafeMarkup::checkPlain($entity->get('type')->entity->label());
     $row['changed'] = $this->dateFormatter->format($entity->get('changed')->value, 'short');
     return $row + parent::buildRow($entity);
 }
예제 #6
0
 /**
  * {@inheritdoc}
  */
 public function buildRow(EntityInterface $entity)
 {
     $row = array();
     if (!empty($this->weightKey)) {
         // Override default values to markup elements.
         $row['#attributes']['class'][] = 'draggable';
         $row['#weight'] = $entity->get($this->weightKey);
         // Add weight column.
         $row['weight'] = array('#type' => 'weight', '#title' => t('Weight for @title', array('@title' => $entity->label())), '#title_display' => 'invisible', '#default_value' => $entity->get($this->weightKey), '#attributes' => array('class' => array('weight')));
     }
     return $row + parent::buildRow($entity);
 }
예제 #7
0
 /**
  * {@inheritdoc}
  */
 public function get($property_name)
 {
     if (!isset($this->entity)) {
         throw new MissingDataException("Unable to get property {$property_name} as no entity has been provided.");
     }
     if (!$this->entity instanceof FieldableEntityInterface) {
         // @todo: Add support for config entities in
         // https://www.drupal.org/node/1818574.
         throw new \InvalidArgumentException("Unable to get unknown property {$property_name}.");
     }
     // This will throw an exception for unknown fields.
     return $this->entity->get($property_name);
 }
 /**
  * {@inheritdoc}
  */
 public function buildRow(EntityInterface $entity)
 {
     /* @var $entity \Drupal\simple_oauth\Entity\AccessToken */
     $type = $entity->get('resource')->target_id == 'authentication' ? t('Refresh Token') : t('Access Token');
     $row['type'] = $type;
     $user = $entity->get('auth_user_id')->entity;
     $row['user'] = $this->l($user->label(), new Url('entity.user.canonical', array('user' => $user->id())));
     $owner = $entity->get('user_id')->entity;
     $row['owner'] = $this->l($owner->label(), new Url('entity.user.canonical', array('user' => $owner->id())));
     $row['id'] = $entity->id();
     $row['name'] = $this->l($entity->label(), new Url('entity.access_token.edit_form', array('access_token' => $entity->id())));
     $row['resource'] = $entity->get('resource')->entity->label();
     return $row + parent::buildRow($entity);
 }
 /**
  * {@inheritdoc}
  */
 public function buildRow(EntityInterface $entity)
 {
     $theme = $entity->get('theme');
     $plugin_definition = $entity->getPlugin()->getPluginDefinition();
     $row['label'] = array('data' => $this->getLabel($entity), 'class' => 'table-filter-text-source');
     $row['theme'] = array('data' => String::checkPlain($this->themes[$theme]->info['name']), 'class' => 'table-filter-text-source');
     $row['category'] = array('data' => String::checkPlain($plugin_definition['category']), 'class' => 'table-filter-text-source');
     $row['operations']['data'] = $this->buildOperations($entity);
     return $row;
 }
예제 #10
0
 /**
  * {@inheritdoc}
  */
 public function buildRow(EntityInterface $entity)
 {
     $row['label'] = $entity->label();
     $row['id'] = $entity->id();
     $row['type'] = $entity->get('type');
     if ($info = $entity->getPluginDefinition()) {
         $row['type'] = $info['title'];
     }
     return $row + parent::buildRow($entity);
 }
 /**
  * Assign a player to a team.
  *
  * Incoming entity will be a registration node with a reference
  * to a team. When that's updated, load the team node and make
  * sure the player is assigned/removed from the team node.
  *
  * TODO: This does not update the previous revision, so manual
  * clean up is needed if the player is switched to a different
  * team.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  */
 public function assignPlayerToTeam(\Drupal\Core\Entity\EntityInterface $entity)
 {
     $team_nid = $entity->get('field_registration_teams')->getValue();
     if (isset($team_nid[0]['target_id'])) {
         $team_node = \Drupal\node\Entity\Node::load($team_nid[0]['target_id']);
         $player_nids = array_merge($team_node->get('field_players')->getValue(), array(array('target_id' => $entity->getOwnerId())));
         $player_nids = array_map("unserialize", array_unique(array_map("serialize", $player_nids)));
         $team_node->get('field_players')->setValue($player_nids);
         $team_node->save();
     }
 }
예제 #12
0
 /**
  * {@inheritdoc}
  */
 public function examples(EntityInterface $entity)
 {
     $examples = array();
     foreach ($this->nameExamples() as $index => $example_name) {
         $formatted = SafeMarkup::checkPlain(NameFormatParser::parse($example_name, $entity->get('pattern')));
         if (empty($formatted)) {
             $formatted = '<em>&lt;&lt;empty&gt;&gt;</em>';
         }
         $examples[] = $formatted . " <sup>{$index}</sup>";
     }
     return $examples;
 }
 /**
  * {@inheritdoc}
  */
 public function buildRow(EntityInterface $entity)
 {
     /* @var $entity \Drupal\checkstyle\Entity\CheckstyleIssue */
     $row['id'] = $this->l($entity->id(), new Url('entity.checkstyle_issue.edit_form', array('checkstyle_issue' => $entity->id())));
     /** @var EntityReferenceFieldItemList $ref_field */
     $ref_field = $entity->get('issue_type');
     /** @var Node $ref_entity */
     $ref_entity = Node::load($ref_field->get(0)->getValue()['target_id']);
     #krumo($ref_entity->get('issue_type')->getValue()[0]['value']);
     #krumo( $ref_entity->get('title'));
     # @todo find decent way of displaying this stuff
     $row['issue_type'] = $ref_entity->get('issue_type')->getValue()[0]['value'];
     return $row + parent::buildRow($entity);
 }
 /**
  * {@inheritdoc}
  */
 protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account)
 {
     // Permissions only apply to own entities.
     if ($account->id() != $entity->get('auth_user_id')->target_id) {
         return AccessResult::forbidden();
     }
     switch ($operation) {
         case 'view':
             return AccessResult::allowedIfHasPermission($account, 'view own access token entities');
         case 'update':
             return AccessResult::allowedIfHasPermission($account, 'edit own access token entities');
         case 'delete':
             return AccessResult::allowedIfHasPermission($account, 'delete own access token entities');
     }
     return AccessResult::allowed();
 }
예제 #15
0
 /**
  * Tests that the prepareView() formatter method still fires for empty values.
  */
 function testFieldEmpty()
 {
     // Uses \Drupal\field_test\Plugin\Field\FieldFormatter\TestFieldEmptyFormatter.
     $display = array('label' => 'hidden', 'type' => 'field_empty_test', 'settings' => array('test_empty_string' => '**EMPTY FIELD**' . $this->randomName()));
     // $this->entity is set by the setUp() method and by default contains 4
     // numeric values.  We only want to test the display of this one field.
     $this->render($this->entity->get($this->field_name)->view($display));
     // The test field by default contains values, so should not display the
     // default "empty" text.
     $this->assertNoText($display['settings']['test_empty_string']);
     // Now remove the values from the test field and retest.
     $this->entity->{$this->field_name} = array();
     $this->entity->save();
     $this->render($this->entity->get($this->field_name)->view($display));
     // This time, as the field values have been removed, we *should* show the
     // default "empty" text.
     $this->assertText($display['settings']['test_empty_string']);
 }
예제 #16
0
 /**
  * Updates a (possible nested) entity property with a value.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The config entity.
  * @param array $parents
  *   The array of parents.
  * @param string|object $value
  *   The value to update to.
  */
 protected function updateEntityProperty(EntityInterface $entity, array $parents, $value)
 {
     $top_key = array_shift($parents);
     $entity_value = $entity->get($top_key);
     if (is_array($entity_value)) {
         NestedArray::setValue($entity_value, $parents, $value);
     } else {
         $entity_value = $value;
     }
     $entity->set($top_key, $entity_value);
 }
예제 #17
0
 /**
  * Gets the creation sid for a given $entity and $field_name.
  *
  * Is a helper function for:
  * - workflow_node_current_state()
  * - workflow_node_previous_state()
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  * @param string $field_name
  *
  * @return string $sid
  *   The ID of the creation State for the Workflow of the field.
  */
 private static function getCreationStateId($entity, $field_name)
 {
     $sid = '';
     $field_config = $entity->get($field_name)->getFieldDefinition();
     $field_storage = $field_config->getFieldStorageDefinition();
     $wid = $field_storage->getSetting('workflow_type');
     $workflow = Workflow::load($wid);
     if ($workflow) {
         $sid = $workflow->getCreationSid();
     } else {
         drupal_set_message(t('Workflow !wid cannot be loaded. Contact your system administrator.', array('!wid' => $wid)), 'error');
     }
     return $sid;
 }
 /**
  * Responds to entity PATCH requests.
  *
  * @param \Drupal\Core\Entity\EntityInterface $original_entity
  *   The original entity object.
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The entity.
  *
  * @return \Drupal\rest\ResourceResponse
  *   The HTTP response object.
  *
  * @throws \Symfony\Component\HttpKernel\Exception\HttpException
  */
 public function patch(EntityInterface $original_entity, EntityInterface $entity = NULL)
 {
     if ($entity == NULL) {
         throw new BadRequestHttpException('No entity content received.');
     }
     $definition = $this->getPluginDefinition();
     if ($entity->getEntityTypeId() != $definition['entity_type']) {
         throw new BadRequestHttpException('Invalid entity type');
     }
     if (!$original_entity->access('update')) {
         throw new AccessDeniedHttpException();
     }
     // Overwrite the received properties.
     $langcode_key = $entity->getEntityType()->getKey('langcode');
     foreach ($entity->_restSubmittedFields as $field_name) {
         $field = $entity->get($field_name);
         // It is not possible to set the language to NULL as it is automatically
         // re-initialized. As it must not be empty, skip it if it is.
         if ($field_name == $langcode_key && $field->isEmpty()) {
             continue;
         }
         if (!$original_entity->get($field_name)->access('edit')) {
             throw new AccessDeniedHttpException(SafeMarkup::format('Access denied on updating field @field.', array('@field' => $field_name)));
         }
         $original_entity->set($field_name, $field->getValue());
     }
     // Validate the received data before saving.
     $this->validate($original_entity);
     try {
         $original_entity->save();
         $this->logger->notice('Updated entity %type with ID %id.', array('%type' => $entity->getEntityTypeId(), '%id' => $entity->id()));
         // Update responses have an empty body.
         return new ResourceResponse(NULL, 204);
     } catch (EntityStorageException $e) {
         throw new HttpException(500, 'Internal Server Error', $e);
     }
 }
 /**
  * {@inheritdoc}
  */
 public function getChangedTime()
 {
     return $this->translation->hasField('content_translation_changed') ? $this->translation->get('content_translation_changed')->value : $this->translation->getChangedTime();
 }
 /**
  * {@inheritdoc}
  */
 public function accessEditEntityField(EntityInterface $entity, $field_name)
 {
     return $entity->access('update') && $entity->get($field_name)->access('edit');
 }
 /**
  * {@inheritdoc}
  */
 public function forbiddenMessage(EntityInterface $entity, $field_name)
 {
     if (!isset($this->authenticatedCanPostComments)) {
         // We only output a link if we are certain that users will get the
         // permission to post comments by logging in.
         $this->authenticatedCanPostComments = $this->entityManager->getStorage('user_role')->load(DRUPAL_AUTHENTICATED_RID)->hasPermission('post comments');
     }
     if ($this->authenticatedCanPostComments) {
         // We cannot use drupal_get_destination() because these links
         // sometimes appear on /node and taxonomy listing pages.
         if ($entity->get($field_name)->getFieldDefinition()->getSetting('form_location') == CommentItemInterface::FORM_SEPARATE_PAGE) {
             $destination = array('destination' => 'comment/reply/' . $entity->getEntityTypeId() . '/' . $entity->id() . '/' . $field_name . '#comment-form');
         } else {
             $destination = array('destination' => $entity->getSystemPath() . '#comment-form');
         }
         if ($this->userConfig->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) {
             // Users can register themselves.
             return $this->t('<a href="@login">Log in</a> or <a href="@register">register</a> to post comments', array('@login' => $this->urlGenerator->generateFromRoute('user.login', array(), array('query' => $destination)), '@register' => $this->urlGenerator->generateFromRoute('user.register', array(), array('query' => $destination))));
         } else {
             // Only admins can add new users, no public registration.
             return $this->t('<a href="@login">Log in</a> to post comments', array('@login' => $this->urlGenerator->generateFromRoute('user.login', array(), array('query' => $destination))));
         }
     }
     return '';
 }
예제 #22
0
 /**
  * Gets the new entity ID from the location header and tries to read it from
  * the database.
  *
  * @param string $entity_type
  *   Entity type we need to load the entity from DB.
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The entity we want to check that was inserted correctly.
  * @param array $entity_values
  *   The values of $entity.
  */
 public function assertReadEntityIdFromHeaderAndDb($entity_type, EntityInterface $entity, array $entity_values = array())
 {
     // Get the location from the HTTP response header.
     $location_url = $this->drupalGetHeader('location');
     $url_parts = explode('/', $location_url);
     $id = end($url_parts);
     // Get the entity using the ID found.
     $loaded_entity = \Drupal::entityManager()->getStorage($entity_type)->load($id);
     $this->assertNotIdentical(FALSE, $loaded_entity, 'The new ' . $entity_type . ' was found in the database.');
     $this->assertEqual($entity->uuid(), $loaded_entity->uuid(), 'UUID of created entity is correct.');
     // Verify that the field values sent and received from DB are the same.
     foreach ($entity_values as $property => $value) {
         $actual_value = $loaded_entity->get($property)->value;
         $send_value = $entity->get($property)->value;
         $this->assertEqual($send_value, $actual_value, 'Created property ' . $property . ' expected: ' . $send_value . ', actual: ' . $actual_value);
     }
     // Delete the entity loaded from DB.
     $loaded_entity->delete();
 }
예제 #23
0
 /**
  * Responds to entity PATCH requests.
  *
  * @param \Drupal\Core\Entity\EntityInterface $original_entity
  *   The original entity object.
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The entity.
  *
  * @return \Drupal\rest\ModifiedResourceResponse
  *   The HTTP response object.
  *
  * @throws \Symfony\Component\HttpKernel\Exception\HttpException
  */
 public function patch(EntityInterface $original_entity, EntityInterface $entity = NULL)
 {
     if ($entity == NULL) {
         throw new BadRequestHttpException('No entity content received.');
     }
     $definition = $this->getPluginDefinition();
     if ($entity->getEntityTypeId() != $definition['entity_type']) {
         throw new BadRequestHttpException('Invalid entity type');
     }
     if (!$original_entity->access('update')) {
         throw new AccessDeniedHttpException();
     }
     // Overwrite the received properties.
     $entity_keys = $entity->getEntityType()->getKeys();
     foreach ($entity->_restSubmittedFields as $field_name) {
         $field = $entity->get($field_name);
         // Entity key fields need special treatment: together they uniquely
         // identify the entity. Therefore it does not make sense to modify any of
         // them. However, rather than throwing an error, we just ignore them as
         // long as their specified values match their current values.
         if (in_array($field_name, $entity_keys, TRUE)) {
             // Unchanged values for entity keys don't need access checking.
             if ($original_entity->get($field_name)->getValue() === $entity->get($field_name)->getValue()) {
                 continue;
             } elseif (isset($entity_keys['langcode']) && $field_name === $entity_keys['langcode'] && $field->isEmpty()) {
                 continue;
             }
         }
         if (!$original_entity->get($field_name)->access('edit')) {
             throw new AccessDeniedHttpException("Access denied on updating field '{$field_name}'.");
         }
         $original_entity->set($field_name, $field->getValue());
     }
     // Validate the received data before saving.
     $this->validate($original_entity);
     try {
         $original_entity->save();
         $this->logger->notice('Updated entity %type with ID %id.', array('%type' => $original_entity->getEntityTypeId(), '%id' => $original_entity->id()));
         // Return the updated entity in the response body.
         return new ModifiedResourceResponse($original_entity, 200);
     } catch (EntityStorageException $e) {
         throw new HttpException(500, 'Internal Server Error', $e);
     }
 }
 /**
  * Verifies that a length violation exists for the given field.
  *
  * @param \Drupal\core\Entity\EntityInterface $entity
  *   The entity object to validate.
  * @param string $field_name
  *   The field that violates the maximum length.
  * @param int $length
  *   Number of characters that was exceeded.
  * @param int $count
  *   (optional) The number of expected violations. Defaults to 1.
  * @param int $expected_index
  *   (optional) The index at which to expect the violation. Defaults to 0.
  */
 protected function assertLengthViolation(EntityInterface $entity, $field_name, $length, $count = 1, $expected_index = 0)
 {
     $violations = $entity->validate();
     $this->assertEqual(count($violations), $count, "Violation found when {$field_name} is too long.");
     $this->assertEqual($violations[$expected_index]->getPropertyPath(), "{$field_name}.0.value");
     $field_label = $entity->get($field_name)->getFieldDefinition()->getLabel();
     $this->assertEqual($violations[$expected_index]->getMessage(), t('%name: may not be longer than @max characters.', array('%name' => $field_label, '@max' => $length)));
 }
 /**
  * Overrides Drupal\Core\Entity\EntityListController::buildRow();
  */
 public function buildRow(EntityInterface $endpoint)
 {
     return array('data' => array('name' => $endpoint->get('label'), 'description' => $endpoint->get('description'), 'path' => $endpoint->get('path'), 'operations' => array('data' => $this->buildOperations($endpoint))), 'title' => t('Machine name: ') . $endpoint->id());
 }
 /**
  * Returns the value for the specified property in the given language.
  *
  * @param \Drupal\Core\Entity\EntityInterface $translation
  *   The translation object the property value should be retrieved from.
  * @param string $property
  *   The property name.
  * @param string $langcode
  *   The property value.
  *
  * @return
  *   The property value.
  */
 protected function getValue(EntityInterface $translation, $property, $langcode)
 {
     $key = $property == 'user_id' ? 'target_id' : 'value';
     return $translation->get($property)->{$key};
 }
 /**
  * Build the default links (reply, edit, delete …) for a comment.
  *
  * @param \Drupal\comment\CommentInterface $entity
  *   The comment object.
  * @param \Drupal\Core\Entity\EntityInterface $commented_entity
  *   The entity to which the comment is attached.
  *
  * @return array
  *   An array that can be processed by drupal_pre_render_links().
  */
 protected function buildLinks(CommentInterface $entity, EntityInterface $commented_entity)
 {
     $links = array();
     $status = $commented_entity->get($entity->getFieldName())->status;
     if ($status == CommentItemInterface::OPEN) {
         if ($entity->access('delete')) {
             $links['comment-delete'] = array('title' => t('Delete'), 'url' => $entity->urlInfo('delete-form'));
         }
         if ($entity->access('update')) {
             $links['comment-edit'] = array('title' => t('Edit'), 'url' => $entity->urlInfo('edit-form'));
         }
         if ($entity->access('create')) {
             $links['comment-reply'] = array('title' => t('Reply'), 'url' => Url::fromRoute('comment.reply', ['entity_type' => $entity->getCommentedEntityTypeId(), 'entity' => $entity->getCommentedEntityId(), 'field_name' => $entity->getFieldName(), 'pid' => $entity->id()]));
         }
         if (!$entity->isPublished() && $entity->access('approve')) {
             $links['comment-approve'] = array('title' => t('Approve'), 'url' => Url::fromRoute('comment.approve', ['comment' => $entity->id()]));
         }
         if (empty($links) && $this->currentUser->isAnonymous()) {
             $links['comment-forbidden']['title'] = $this->commentManager->forbiddenMessage($commented_entity, $entity->getFieldName());
         }
     }
     // Add translations link for translation-enabled comment bundles.
     if ($this->moduleHandler->moduleExists('content_translation') && $this->access($entity)->isAllowed()) {
         $links['comment-translations'] = array('title' => t('Translate'), 'url' => $entity->urlInfo('drupal:content-translation-overview'));
     }
     return array('#theme' => 'links__comment__comment', '#links' => $links, '#attributes' => array('class' => array('links', 'inline')));
 }
예제 #28
0
 /**
  * Gets a list of displays included in the view.
  *
  * @param \Drupal\Core\Entity\EntityInterface $view
  *   The view entity instance to get a list of displays for.
  *
  * @return array
  *   An array of display types that this view includes.
  */
 protected function getDisplaysList(EntityInterface $view)
 {
     $displays = array();
     foreach ($view->get('display') as $display) {
         $definition = $this->displayManager->getDefinition($display['display_plugin']);
         if (!empty($definition['admin'])) {
             // Cast the admin label to a string since it is an object.
             // @see \Drupal\Core\StringTranslation\TranslatableMarkup
             $displays[] = (string) $definition['admin'];
         }
     }
     sort($displays);
     return $displays;
 }
예제 #29
0
 /**
  * Format date.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  * @param string $field_name
  * @param string $format
  */
 protected function formatDate(EntityInterface $entity, $field_name, $format)
 {
     $timestamp = $entity->get($field_name)->value;
     return $this->dateFormatter->format($timestamp, $format);
 }
예제 #30
0
 /**
  * Implements Drupal\Core\Entity\EntityStorageInterface::save().
  *
  * @throws EntityMalformedException
  *   When attempting to save a configuration entity that has no ID.
  */
 public function save(EntityInterface $entity)
 {
     // Configuration entity IDs are strings, and '0' is a valid ID.
     $id = $entity->id();
     if ($id === NULL || $id === '') {
         throw new EntityMalformedException('The entity does not have an ID.');
     }
     // Check the configuration entity ID length.
     // @see \Drupal\Core\Config\Entity\ConfigEntityStorage::MAX_ID_LENGTH
     // @todo Consider moving this to a protected method on the parent class, and
     //   abstracting it for all entity types.
     if (strlen($entity->get($this->idKey)) > self::MAX_ID_LENGTH) {
         throw new ConfigEntityIdLengthException(SafeMarkup::format('Configuration entity ID @id exceeds maximum allowed length of @length characters.', array('@id' => $entity->get($this->idKey), '@length' => self::MAX_ID_LENGTH)));
     }
     return parent::save($entity);
 }