예제 #1
0
 /**
  * {@inheritdoc}
  */
 public function getCancelUrl()
 {
     if ($this->revision->getEntityType()->hasLinkTemplate('version-history')) {
         return $this->revision->toUrl('version-history');
     }
     return $this->revision->toUrl();
 }
예제 #2
0
 /**
  * {@inheritdoc}
  */
 public function getFormId()
 {
     $form_id = $this->entity->getEntityTypeId();
     if ($this->entity->getEntityType()->hasKey('bundle')) {
         $form_id = $this->entity->bundle() . '_' . $form_id;
     }
     if ($this->operation != 'default') {
         $form_id = $form_id . '_' . $this->operation;
     }
     return $form_id . '_form';
 }
예제 #3
0
 /**
  * {@inheritdoc}
  */
 public function isModeratedEntity(EntityInterface $entity)
 {
     if (!$entity instanceof ContentEntityInterface) {
         return FALSE;
     }
     return $this->shouldModerateEntitiesOfBundle($entity->getEntityType(), $entity->bundle());
 }
예제 #4
0
  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    if ($this->entity && $this->entityTypeDefinition->hasHandlerClass('entity_clone')) {
      $form['information'] = [
        '#markup' => $this->stringTranslationManager->translate('<p>Do you want clone the <em>@entity_type</em> entity named <em>@title</em>?</p>', [
          '@entity_type' => $this->entity->getEntityType()->getLabel(),
          '@title' => $this->entity->label(),
        ]),
      ];

      /** @var \Drupal\entity_clone\EntityClone\EntityCloneFormInterface $entity_clone_handler */
      if ($this->entityTypeManager->hasHandler($this->entityTypeDefinition->id(), 'entity_clone_form')) {
        $entity_clone_form_handler = $this->entityTypeManager->getHandler($this->entityTypeDefinition->id(), 'entity_clone_form');
        $form = array_merge($form, $entity_clone_form_handler->formElement($this->entity));
      }

      $form['clone'] = [
        '#type' => 'submit',
        '#value' => 'Clone',
      ];

      $form['abort'] = [
        '#type' => 'submit',
        '#value' => 'Abort',
        '#submit' => '::cancelForm',
      ];
    }

    return $form;
  }
 /**
  * {@inheritdoc}
  */
 public function getTranslationMetadata(EntityInterface $translation)
 {
     // We need a new instance of the metadata handler wrapping each translation.
     $entity_type = $translation->getEntityType();
     $class = $entity_type->get('content_translation_metadata');
     return new $class($translation, $this->getTranslationHandler($entity_type->id()));
 }
 /**
  * {@inheritdoc}
  */
 public function save(array $form, FormStateInterface $form_state)
 {
     // Save as a new revision if requested to do so.
     if (!$form_state->isValueEmpty('revision')) {
         $this->entity->setNewRevision();
     }
     $insert = $this->entity->isNew();
     $this->entity->save();
     $context = ['@type' => $this->entity->bundle(), '%info' => $this->entity->label()];
     $logger = $this->logger($this->entity->id());
     $bundle_entity = $this->getBundleEntity();
     $t_args = ['@type' => $bundle_entity ? $bundle_entity->label() : 'None', '%info' => $this->entity->label()];
     if ($insert) {
         $logger->notice('@type: added %info.', $context);
         drupal_set_message($this->t('@type %info has been created.', $t_args));
     } else {
         $logger->notice('@type: updated %info.', $context);
         drupal_set_message($this->t('@type %info has been updated.', $t_args));
     }
     if ($this->entity->id()) {
         $form_state->setValue('id', $this->entity->id());
         $form_state->set('id', $this->entity->id());
         if ($this->entity->getEntityType()->hasLinkTemplate('collection')) {
             $form_state->setRedirectUrl($this->entity->toUrl('collection'));
         } else {
             $form_state->setRedirectUrl($this->entity->toUrl('canonical'));
         }
     } else {
         // In the unlikely case something went wrong on save, the entity will be
         // rebuilt and entity form redisplayed.
         drupal_set_message($this->t('The entity could not be saved.'), 'error');
         $form_state->setRebuild();
     }
 }
 /**
  * Implements hook_entity_view_alter().
  */
 public function entityViewAlter(&$build, EntityInterface $entity, EntityViewDisplayInterface $display)
 {
     if ($entity->getEntityType()->isRevisionable() && !$this->moderationInfo->isLatestRevision($entity)) {
         // Hide quickedit, because its super confusing for the user to not edit the
         // live revision.
         unset($build['#attributes']['data-quickedit-entity-id']);
     }
 }
예제 #8
0
 /**
  * {@inheritdoc}
  */
 protected function alterBuild(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode)
 {
     $entity_type_id = $entity->getEntityTypeId();
     if ($entity instanceof ContentEntityInterface && $entity->isDefaultRevision() || !$entity->getEntityType()->isRevisionable()) {
         $build['#contextual_links'][$entity_type_id] = ['route_parameters' => [$entity_type_id => $entity->id()]];
     } else {
         $build['#contextual_links'][$entity_type_id . '_revision'] = ['route_parameters' => [$entity_type_id => $entity->id(), $entity_type_id . '_revision' => $entity->getRevisionId()]];
     }
 }
예제 #9
0
 /**
  * {@inheritdoc}
  */
 protected function checkAccess(EntityInterface $entity)
 {
     // Only check access if the current file access control handler explicitly
     // opts in by implementing FileAccessFormatterControlHandlerInterface.
     $access_handler_class = $entity->getEntityType()->getHandlerClass('access');
     if (is_subclass_of($access_handler_class, '\\Drupal\\file\\FileAccessFormatterControlHandlerInterface')) {
         return $entity->access('view', NULL, TRUE);
     } else {
         return AccessResult::allowed();
     }
 }
 /**
  * {@inheritdoc}
  */
 public function getTranslationAccess(EntityInterface $entity, $op)
 {
     // @todo Move this logic into a translation access controller checking also
     //   the translation language and the given account.
     $entity_type = $entity->getEntityType();
     $translate_permission = TRUE;
     // If no permission granularity is defined this entity type does not need an
     // explicit translate permission.
     $current_user = \Drupal::currentUser();
     if (!$current_user->hasPermission('translate any entity') && ($permission_granularity = $entity_type->getPermissionGranularity())) {
         $translate_permission = $current_user->hasPermission($permission_granularity == 'bundle' ? "translate {$entity->bundle()} {$entity->getEntityTypeId()}" : "translate {$entity->getEntityTypeId()}");
     }
     return $translate_permission && $current_user->hasPermission("{$op} content translations");
 }
예제 #11
0
 /**
  * Populate the fields on a given entity with sample values.
  *
  * @param $entity
  *  The entity to be enriched with sample field values.
  */
 public function populateFields(EntityInterface $entity)
 {
     $instances = entity_load_multiple_by_properties('field_instance_config', array('entity_type' => $entity->getEntityType()->id(), 'bundle' => $entity->bundle()));
     if ($skips = function_exists('drush_get_option') ? drush_get_option('skip-fields', '') : @$_REQUEST['skip-fields']) {
         foreach (explode(',', $skips) as $skip) {
             unset($instances[$skip]);
         }
     }
     foreach ($instances as $instance) {
         /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
         $field_storage = $instance->getFieldStorageDefinition();
         $max = $cardinality = $field_storage->getCardinality();
         if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
             // Just an arbitrary number for 'unlimited'
             $max = rand(1, 3);
         }
         $field_name = $field_storage->getName();
         $entity->{$field_name}->generateSampleItems($max);
     }
 }
 /**
  * Tests cache tags presence and invalidation of the entity when referenced.
  *
  * Tests the following cache tags:
  * - entity type view cache tag: "<entity type>_view"
  * - entity cache tag: "<entity type>:<entity ID>"
  * - entity type list cache tag: "<entity type>_list"
  * - referencing entity type view cache tag: "<referencing entity type>_view"
  * - referencing entity type cache tag: "<referencing entity type>:<referencing entity ID>"
  */
 public function testReferencedEntity()
 {
     $entity_type = $this->entity->getEntityTypeId();
     $referencing_entity_url = $this->referencing_entity->urlInfo('canonical');
     $non_referencing_entity_url = $this->non_referencing_entity->urlInfo('canonical');
     $listing_url = Url::fromRoute('entity.entity_test.collection_referencing_entities', ['entity_reference_field_name' => $entity_type . '_reference', 'referenced_entity_type' => $entity_type, 'referenced_entity_id' => $this->entity->id()]);
     $empty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_empty', ['entity_type_id' => $entity_type]);
     $nonempty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_labels_alphabetically', ['entity_type_id' => $entity_type]);
     // The default cache contexts for rendered entities.
     $entity_cache_contexts = ['theme', 'user.roles'];
     // Cache tags present on every rendered page.
     $page_cache_tags = Cache::mergeTags(['rendered'], \Drupal::moduleHandler()->moduleExists('block') ? ['config:block_list'] : []);
     $view_cache_tag = array();
     if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) {
         $view_cache_tag = \Drupal::entityManager()->getViewBuilder($entity_type)->getCacheTags();
     }
     // Generate the cache tags for the (non) referencing entities.
     $referencing_entity_cache_tags = Cache::mergeTags($this->referencing_entity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags(), $this->entity->getCacheTags(), $this->getAdditionalCacheTagsForEntity($this->entity), $view_cache_tag, ['rendered']);
     $non_referencing_entity_cache_tags = Cache::mergeTags($this->non_referencing_entity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags(), ['rendered']);
     // Generate the cache tags for all two possible entity listing paths.
     // 1. list cache tag only (listing query has no match)
     // 2. list cache tag plus entity cache tag (listing query has a match)
     $empty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $page_cache_tags);
     $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->entity->getCacheTags(), $this->getAdditionalCacheTagsForEntityListing($this->entity), $page_cache_tags);
     $this->pass("Test referencing entity.", 'Debug');
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($referencing_entity_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags));
     // Also verify the existence of an entity render cache entry.
     $cache_keys = ['entity_view', 'entity_test', $this->referencing_entity->id(), 'full'];
     $cid = $this->createCacheId($cache_keys, $entity_cache_contexts);
     $redirected_cid = $this->createRedirectedCacheId($cache_keys, $entity_cache_contexts);
     $this->verifyRenderCache($cid, $referencing_entity_cache_tags, $redirected_cid);
     $this->pass("Test non-referencing entity.", 'Debug');
     $this->verifyPageCache($non_referencing_entity_url, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($non_referencing_entity_url, 'HIT', Cache::mergeTags($non_referencing_entity_cache_tags, $page_cache_tags));
     // Also verify the existence of an entity render cache entry.
     $cache_keys = ['entity_view', 'entity_test', $this->non_referencing_entity->id(), 'full'];
     $cid = $this->createCacheId($cache_keys, $entity_cache_contexts);
     $this->verifyRenderCache($cid, $non_referencing_entity_cache_tags);
     $this->pass("Test listing of referencing entities.", 'Debug');
     // Prime the page cache for the listing of referencing entities.
     $this->verifyPageCache($listing_url, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($listing_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags));
     $this->pass("Test empty listing.", 'Debug');
     // Prime the page cache for the empty listing.
     $this->verifyPageCache($empty_entity_listing_url, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags);
     // Verify the entity type's list cache contexts are present.
     $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts');
     $this->assertEqual($this->getAdditionalCacheContextsForEntityListing(), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header));
     $this->pass("Test listing containing referenced entity.", 'Debug');
     // Prime the page cache for the listing containing the referenced entity.
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS', $nonempty_entity_listing_cache_tags);
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', $nonempty_entity_listing_cache_tags);
     // Verify the entity type's list cache contexts are present.
     $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts');
     $this->assertEqual($this->getAdditionalCacheContextsForEntityListing(), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header));
     // Verify that after modifying the referenced entity, there is a cache miss
     // for every route except the one for the non-referencing entity.
     $this->pass("Test modification of referenced entity.", 'Debug');
     $this->entity->save();
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     $this->verifyPageCache($listing_url, 'MISS');
     $this->verifyPageCache($empty_entity_listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     // Verify that after modifying the referencing entity, there is a cache miss
     // for every route except the ones for the non-referencing entity and the
     // empty entity listing.
     $this->pass("Test modification of referencing entity.", 'Debug');
     $this->referencing_entity->save();
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     $this->verifyPageCache($listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     // Verify that after modifying the non-referencing entity, there is a cache
     // miss only for the non-referencing entity route.
     $this->pass("Test modification of non-referencing entity.", 'Debug');
     $this->non_referencing_entity->save();
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     $this->verifyPageCache($non_referencing_entity_url, 'MISS');
     // Verify cache hits.
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) {
         // Verify that after modifying the entity's display, there is a cache miss
         // for both the referencing entity, and the listing of referencing
         // entities, but not for any other routes.
         $referenced_entity_view_mode = $this->selectViewMode($this->entity->getEntityTypeId());
         $this->pass("Test modification of referenced entity's '{$referenced_entity_view_mode}' display.", 'Debug');
         $entity_display = entity_get_display($entity_type, $this->entity->bundle(), $referenced_entity_view_mode);
         $entity_display->save();
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         $this->verifyPageCache($empty_entity_listing_url, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
     }
     $bundle_entity_type = $this->entity->getEntityType()->getBundleEntityType();
     if ($bundle_entity_type !== 'bundle') {
         // Verify that after modifying the corresponding bundle entity, there is a
         // cache miss for both the referencing entity, and the listing of
         // referencing entities, but not for any other routes.
         $this->pass("Test modification of referenced entity's bundle entity.", 'Debug');
         $bundle_entity = entity_load($bundle_entity_type, $this->entity->bundle());
         $bundle_entity->save();
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         // Special case: entity types may choose to use their bundle entity type
         // cache tags, to avoid having excessively granular invalidation.
         $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getEntityType()->getListCacheTags() == $this->entity->getEntityType()->getListCacheTags();
         if ($is_special_case) {
             $this->verifyPageCache($empty_entity_listing_url, 'MISS');
             $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
         } else {
             $this->verifyPageCache($empty_entity_listing_url, 'HIT');
             $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         }
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
         if ($is_special_case) {
             $this->verifyPageCache($empty_entity_listing_url, 'HIT');
             $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         }
     }
     if ($this->entity->getEntityType()->get('field_ui_base_route')) {
         // Verify that after modifying a configurable field on the entity, there
         // is a cache miss.
         $this->pass("Test modification of referenced entity's configurable field.", 'Debug');
         $field_storage_name = $this->entity->getEntityTypeId() . '.configurable_field';
         $field_storage = FieldStorageConfig::load($field_storage_name);
         $field_storage->save();
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($empty_entity_listing_url, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
         // Verify that after modifying a configurable field on the entity, there
         // is a cache miss.
         $this->pass("Test modification of referenced entity's configurable field.", 'Debug');
         $field_name = $this->entity->getEntityTypeId() . '.' . $this->entity->bundle() . '.configurable_field';
         $field = FieldConfig::load($field_name);
         $field->save();
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($empty_entity_listing_url, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
     }
     // Verify that after invalidating the entity's cache tag directly, there is
     // a cache miss for every route except the ones for the non-referencing
     // entity and the empty entity listing.
     $this->pass("Test invalidation of referenced entity's cache tag.", 'Debug');
     Cache::invalidateTags($this->entity->getCacheTags());
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     $this->verifyPageCache($listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     // Verify that after invalidating the entity's list cache tag directly,
     // there is a cache miss for both the empty entity listing and the non-empty
     // entity listing routes, but not for other routes.
     $this->pass("Test invalidation of referenced entity's list cache tag.", 'Debug');
     Cache::invalidateTags($this->entity->getEntityType()->getListCacheTags());
     $this->verifyPageCache($empty_entity_listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     if (!empty($view_cache_tag)) {
         // Verify that after invalidating the generic entity type's view cache tag
         // directly, there is a cache miss for both the referencing entity, and the
         // listing of referencing entities, but not for other routes.
         $this->pass("Test invalidation of referenced entity's 'view' cache tag.", 'Debug');
         Cache::invalidateTags($view_cache_tag);
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         $this->verifyPageCache($empty_entity_listing_url, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
     }
     // Verify that after deleting the entity, there is a cache miss for every
     // route except for the non-referencing entity one.
     $this->pass('Test deletion of referenced entity.', 'Debug');
     $this->entity->delete();
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     $this->verifyPageCache($listing_url, 'MISS');
     $this->verifyPageCache($empty_entity_listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     // Verify cache hits.
     $referencing_entity_cache_tags = Cache::mergeTags($this->referencing_entity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags(), ['rendered']);
     $this->verifyPageCache($referencing_entity_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags));
     $this->verifyPageCache($listing_url, 'HIT', $page_cache_tags);
     $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags);
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing(), $page_cache_tags));
 }
 /**
  * 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);
     }
 }
 /**
  * Tests cache tags presence and invalidation of the entity when referenced.
  *
  * Tests the following cache tags:
  * - "<entity type>_view:1"
  * - "<entity type>:<entity ID>"
  * - "<referencing entity type>_view:1"
  * * - "<referencing entity type>:<referencing entity ID>"
  */
 public function testReferencedEntity()
 {
     $entity_type = $this->entity->getEntityTypeId();
     $referencing_entity_path = $this->referencing_entity->getSystemPath();
     $non_referencing_entity_path = $this->non_referencing_entity->getSystemPath();
     $listing_path = 'entity_test/list/' . $entity_type . '_reference/' . $entity_type . '/' . $this->entity->id();
     $render_cache_tags = array('rendered:1');
     $theme_cache_tags = array('theme:stark', 'theme_global_settings:1');
     $view_cache_tag = array();
     if ($this->entity->getEntityType()->hasControllerClass('view_builder')) {
         $view_cache_tag = \Drupal::entityManager()->getViewBuilder($entity_type)->getCacheTag();
     }
     // Generate the cache tags for the (non) referencing entities.
     $referencing_entity_cache_tags = NestedArray::mergeDeep($this->referencing_entity->getCacheTag(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTag(), $this->entity->getCacheTag(), $view_cache_tag);
     $referencing_entity_cache_tags = explode(' ', HtmlViewSubscriber::convertCacheTagsToHeader($referencing_entity_cache_tags));
     $referencing_entity_cache_tags = array_merge($referencing_entity_cache_tags, $this->getAdditionalCacheTagsForEntity($this->entity));
     $non_referencing_entity_cache_tags = NestedArray::mergeDeep($this->non_referencing_entity->getCacheTag(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTag());
     $non_referencing_entity_cache_tags = explode(' ', HtmlViewSubscriber::convertCacheTagsToHeader($non_referencing_entity_cache_tags));
     $this->pass("Test referencing entity.", 'Debug');
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $tags = array_merge($render_cache_tags, $theme_cache_tags, $referencing_entity_cache_tags);
     $this->verifyPageCache($referencing_entity_path, 'HIT', $tags);
     // Also verify the existence of an entity render cache entry.
     $cid = 'entity_view:entity_test:' . $this->referencing_entity->id() . ':full:stark:r.anonymous:' . date_default_timezone_get();
     $tags = array_merge($render_cache_tags, $referencing_entity_cache_tags);
     $this->verifyRenderCache($cid, $tags);
     $this->pass("Test non-referencing entity.", 'Debug');
     $this->verifyPageCache($non_referencing_entity_path, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $tags = array_merge($render_cache_tags, $theme_cache_tags, $non_referencing_entity_cache_tags);
     $this->verifyPageCache($non_referencing_entity_path, 'HIT', $tags);
     // Also verify the existence of an entity render cache entry.
     $cid = 'entity_view:entity_test:' . $this->non_referencing_entity->id() . ':full:stark:r.anonymous:' . date_default_timezone_get();
     $tags = array_merge($render_cache_tags, $non_referencing_entity_cache_tags);
     $this->verifyRenderCache($cid, $tags);
     $this->pass("Test listing of referencing entities.", 'Debug');
     // Prime the page cache for the listing of referencing entities.
     $this->verifyPageCache($listing_path, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $tags = array_merge($render_cache_tags, $theme_cache_tags, $referencing_entity_cache_tags);
     $this->verifyPageCache($listing_path, 'HIT', $tags);
     // Verify that after modifying the referenced entity, there is a cache miss
     // for both the referencing entity, and the listing of referencing entities,
     // but not for the non-referencing entity.
     $this->pass("Test modification of referenced entity.", 'Debug');
     $this->entity->save();
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     $this->verifyPageCache($listing_path, 'MISS');
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_path, 'HIT');
     $this->verifyPageCache($listing_path, 'HIT');
     // Verify that after modifying the referencing entity, there is a cache miss
     // for both the referencing entity, and the listing of referencing entities,
     // but not for the non-referencing entity.
     $this->pass("Test modification of referencing entity.", 'Debug');
     $this->referencing_entity->save();
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     $this->verifyPageCache($listing_path, 'MISS');
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_path, 'HIT');
     $this->verifyPageCache($listing_path, 'HIT');
     // Verify that after modifying the non-referencing entity, there is a cache
     // miss for only the non-referencing entity, not for the referencing entity,
     // nor for the listing of referencing entities.
     $this->pass("Test modification of non-referencing entity.", 'Debug');
     $this->non_referencing_entity->save();
     $this->verifyPageCache($referencing_entity_path, 'HIT');
     $this->verifyPageCache($listing_path, 'HIT');
     $this->verifyPageCache($non_referencing_entity_path, 'MISS');
     // Verify cache hits.
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     if ($this->entity->getEntityType()->hasControllerClass('view_builder')) {
         // Verify that after modifying the entity's display, there is a cache miss
         // for both the referencing entity, and the listing of referencing
         // entities, but not for the non-referencing entity.
         $referenced_entity_view_mode = $this->selectViewMode($this->entity->getEntityTypeId());
         $this->pass("Test modification of referenced entity's '{$referenced_entity_view_mode}' display.", 'Debug');
         $entity_display = entity_get_display($entity_type, $this->entity->bundle(), $referenced_entity_view_mode);
         $entity_display->save();
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
     }
     $bundle_entity_type = $this->entity->getEntityType()->getBundleEntityType();
     if ($bundle_entity_type !== 'bundle') {
         // Verify that after modifying the corresponding bundle entity, there is a
         // cache miss for both the referencing entity, and the listing of
         // referencing entities, but not for the non-referencing entity.
         $this->pass("Test modification of referenced entity's bundle entity.", 'Debug');
         $bundle_entity = entity_load($bundle_entity_type, $this->entity->bundle());
         $bundle_entity->save();
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
     }
     if ($this->entity->getEntityType()->isFieldable()) {
         // Verify that after modifying a configurable field on the entity, there
         // is a cache miss.
         $this->pass("Test modification of referenced entity's configurable field.", 'Debug');
         $field_name = $this->entity->getEntityTypeId() . '.configurable_field';
         $field_storage = entity_load('field_storage_config', $field_name);
         $field_storage->save();
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
         // Verify that after modifying a configurable field instance on the
         // entity, there is a cache miss.
         $this->pass("Test modification of referenced entity's configurable field instance.", 'Debug');
         $field_instance_name = $this->entity->getEntityTypeId() . '.' . $this->entity->bundle() . '.configurable_field';
         $field_instance = entity_load('field_instance_config', $field_instance_name);
         $field_instance->save();
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
     }
     // Verify that after invalidating the entity's cache tag directly,  there is
     // a cache miss for both the referencing entity, and the listing of
     // referencing entities, but not for the non-referencing entity.
     $this->pass("Test invalidation of referenced entity's cache tag.", 'Debug');
     Cache::invalidateTags($this->entity->getCacheTag());
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     $this->verifyPageCache($listing_path, 'MISS');
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_path, 'HIT');
     $this->verifyPageCache($listing_path, 'HIT');
     if (!empty($view_cache_tag)) {
         // Verify that after invalidating the generic entity type's view cache tag
         // directly, there is a cache miss for both the referencing entity, and the
         // listing of referencing entities, but not for the non-referencing entity.
         $this->pass("Test invalidation of referenced entity's 'view' cache tag.", 'Debug');
         Cache::invalidateTags($view_cache_tag);
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
     }
     // Verify that after deleting the entity, there is a cache miss for both the
     // referencing entity, and the listing of referencing entities, but not for
     // the non-referencing entity.
     $this->pass('Test deletion of referenced entity.', 'Debug');
     $this->entity->delete();
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     $this->verifyPageCache($listing_path, 'MISS');
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     // Verify cache hits.
     $referencing_entity_cache_tags = NestedArray::mergeDeep($this->referencing_entity->getCacheTag(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTag());
     $referencing_entity_cache_tags = explode(' ', HtmlViewSubscriber::convertCacheTagsToHeader($referencing_entity_cache_tags));
     $tags = array_merge($render_cache_tags, $theme_cache_tags, $referencing_entity_cache_tags);
     $this->verifyPageCache($referencing_entity_path, 'HIT', $tags);
     $tags = array_merge($render_cache_tags, $theme_cache_tags);
     $this->verifyPageCache($listing_path, 'HIT', $tags);
 }
예제 #15
0
 /**
  * Returns a list of mapped properties for the passed content entity.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   A content entity.
  *
  * @return array
  *    An array of mappings between predicates and field properties. All
  *    fields, and properties of the entity and the fields, that are available
  *    will be returned.
  */
 public function getEntityTypeMappedProperties(EntityInterface $entity)
 {
     $bundle = $entity->bundle();
     $properties = [];
     // Collect impacted fields.
     $definitions = $this->entityManager->getFieldDefinitions($entity->getEntityTypeId(), $bundle);
     $base_field_definitions = $this->entityManager->getBaseFieldDefinitions($entity->getEntityTypeId());
     $rdf_bundle_entity = $this->entityManager->getStorage($entity->getEntityType()->getBundleEntityType())->load($bundle);
     /** @var \Drupal\Core\Field\BaseFieldDefinition $field_definition */
     foreach ($definitions as $field_name => $field_definition) {
         /** @var \Drupal\field\Entity\FieldStorageConfig $storage_definition */
         $storage_definition = $field_definition->getFieldStorageDefinition();
         if (!$storage_definition instanceof FieldStorageConfig) {
             continue;
         }
         foreach ($storage_definition->getColumns() as $column => $column_info) {
             if ($property = $storage_definition->getThirdPartySetting('rdf_entity', 'mapping_' . $column, FALSE)) {
                 $properties['by_field'][$field_name][$column] = $property;
                 $properties['flat'][$property] = $property;
             }
         }
     }
     foreach ($base_field_definitions as $field_name => $base_field_definition) {
         $field_data = $rdf_bundle_entity->getThirdPartySetting('rdf_entity', 'mapping_' . $field_name, FALSE);
         if (!$field_data) {
             continue;
         }
         foreach ($field_data as $column => $predicate) {
             if (empty($predicate)) {
                 continue;
             }
             $properties['by_field'][$field_name][$column] = $predicate;
             $properties['flat'][$predicate] = $predicate;
         }
     }
     return $properties;
 }
예제 #16
0
 /**
  * Adds an operation on bundles that should have a Moderation form.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The entity on which to define an operation.
  *
  * @return array
  *   An array of operation definitions.
  *
  * @see hook_entity_operation()
  */
 public function entityOperation(EntityInterface $entity)
 {
     $operations = [];
     $type = $entity->getEntityType();
     $bundle_of = $type->getBundleOf();
     if ($this->currentUser->hasPermission('administer moderation states') && $bundle_of && $this->moderationInfo->canModerateEntitiesOfEntityType($this->entityTypeManager->getDefinition($bundle_of))) {
         $operations['manage-moderation'] = ['title' => t('Manage moderation'), 'weight' => 27, 'url' => Url::fromRoute("entity.{$type->id()}.moderation", [$entity->getEntityTypeId() => $entity->id()])];
     }
     return $operations;
 }
예제 #17
0
  /**
   * Builds the group string used in the match array.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The matched entity.
   *
   * @return string
   *   The match group for this entity.
   */
  protected function buildGroup($entity) {
    $group = $entity->getEntityType()->getLabel();

    // If the entities by this entity should be grouped by bundle, get the
    // name and append it to the group.
    if ($this->configuration['group_by_bundle']) {
      $bundles = $this->entityManager->getBundleInfo($entity->getEntityTypeId());
      $bundle_label = $bundles[$entity->bundle()]['label'];
      $group .= ' - ' . $bundle_label;
    }

    return $group;
  }
예제 #18
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);
     }
 }
예제 #19
0
 /**
  * Updates the changed time of the entity.
  *
  * Applies only if the entity implements the EntityChangedInterface.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The entity updated with the submitted values.
  */
 public function updateChangedTime(EntityInterface $entity)
 {
     if ($entity->getEntityType()->isSubclassOf(EntityChangedInterface::class)) {
         $entity->setChangedTime(REQUEST_TIME);
     }
 }
예제 #20
0
 /**
  * Tests cache tags presence and invalidation of the entity when referenced.
  *
  * Tests the following cache tags:
  * - entity type view cache tag: "<entity type>_view"
  * - entity cache tag: "<entity type>:<entity ID>"
  * - entity type list cache tag: "<entity type>_list"
  * - referencing entity type view cache tag: "<referencing entity type>_view"
  * - referencing entity type cache tag: "<referencing entity type>:<referencing entity ID>"
  */
 public function testReferencedEntity()
 {
     $entity_type = $this->entity->getEntityTypeId();
     $referencing_entity_url = $this->referencingEntity->urlInfo('canonical');
     $non_referencing_entity_url = $this->nonReferencingEntity->urlInfo('canonical');
     $listing_url = Url::fromRoute('entity.entity_test.collection_referencing_entities', ['entity_reference_field_name' => $entity_type . '_reference', 'referenced_entity_type' => $entity_type, 'referenced_entity_id' => $this->entity->id()]);
     $empty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_empty', ['entity_type_id' => $entity_type]);
     $nonempty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_labels_alphabetically', ['entity_type_id' => $entity_type]);
     // The default cache contexts for rendered entities.
     $default_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'];
     $entity_cache_contexts = $default_cache_contexts;
     $page_cache_contexts = Cache::mergeContexts($default_cache_contexts, ['url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT]);
     // Cache tags present on every rendered page.
     // 'user.permissions' is a required cache context, and responses that vary
     // by this cache context when requested by anonymous users automatically
     // also get this cache tag, to ensure correct invalidation.
     $page_cache_tags = Cache::mergeTags(['rendered'], ['config:user.role.anonymous']);
     // If the block module is used, the Block page display variant is used,
     // which adds the block config entity type's list cache tags.
     $page_cache_tags = Cache::mergeTags($page_cache_tags, \Drupal::moduleHandler()->moduleExists('block') ? ['config:block_list'] : []);
     $page_cache_tags_referencing_entity = in_array('user.permissions', $this->getAccessCacheContextsForEntity($this->referencingEntity)) ? ['config:user.role.anonymous'] : [];
     $view_cache_tag = array();
     if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) {
         $view_cache_tag = \Drupal::entityManager()->getViewBuilder($entity_type)->getCacheTags();
     }
     $context_metadata = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($entity_cache_contexts);
     $cache_context_tags = $context_metadata->getCacheTags();
     // Generate the cache tags for the (non) referencing entities.
     $referencing_entity_cache_tags = Cache::mergeTags($this->referencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags());
     // Includes the main entity's cache tags, since this entity references it.
     $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $this->entity->getCacheTags());
     $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $this->getAdditionalCacheTagsForEntity($this->entity));
     $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $view_cache_tag);
     $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $cache_context_tags);
     $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, ['rendered']);
     $non_referencing_entity_cache_tags = Cache::mergeTags($this->nonReferencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags());
     $non_referencing_entity_cache_tags = Cache::mergeTags($non_referencing_entity_cache_tags, ['rendered']);
     // Generate the cache tags for all two possible entity listing paths.
     // 1. list cache tag only (listing query has no match)
     // 2. list cache tag plus entity cache tag (listing query has a match)
     $empty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $page_cache_tags);
     $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->entity->getCacheTags());
     $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $this->getAdditionalCacheTagsForEntityListing($this->entity));
     $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $page_cache_tags);
     $this->pass("Test referencing entity.", 'Debug');
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $expected_tags = Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags);
     $expected_tags = Cache::mergeTags($expected_tags, $page_cache_tags_referencing_entity);
     $this->verifyPageCache($referencing_entity_url, 'HIT', $expected_tags);
     // Also verify the existence of an entity render cache entry.
     $cache_keys = ['entity_view', 'entity_test', $this->referencingEntity->id(), 'full'];
     $cid = $this->createCacheId($cache_keys, $entity_cache_contexts);
     $access_cache_contexts = $this->getAccessCacheContextsForEntity($this->entity);
     $additional_cache_contexts = $this->getAdditionalCacheContextsForEntity($this->referencingEntity);
     $redirected_cid = NULL;
     if (count($access_cache_contexts) || count($additional_cache_contexts)) {
         $cache_contexts = Cache::mergeContexts($entity_cache_contexts, $additional_cache_contexts);
         $cache_contexts = Cache::mergeContexts($cache_contexts, $access_cache_contexts);
         $redirected_cid = $this->createCacheId($cache_keys, $cache_contexts);
         $context_metadata = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($cache_contexts);
         $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $context_metadata->getCacheTags());
     }
     $this->verifyRenderCache($cid, $referencing_entity_cache_tags, $redirected_cid);
     $this->pass("Test non-referencing entity.", 'Debug');
     $this->verifyPageCache($non_referencing_entity_url, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($non_referencing_entity_url, 'HIT', Cache::mergeTags($non_referencing_entity_cache_tags, $page_cache_tags));
     // Also verify the existence of an entity render cache entry.
     $cache_keys = ['entity_view', 'entity_test', $this->nonReferencingEntity->id(), 'full'];
     $cid = $this->createCacheId($cache_keys, $entity_cache_contexts);
     $this->verifyRenderCache($cid, $non_referencing_entity_cache_tags);
     $this->pass("Test listing of referencing entities.", 'Debug');
     // Prime the page cache for the listing of referencing entities.
     $this->verifyPageCache($listing_url, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $expected_tags = Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags);
     $expected_tags = Cache::mergeTags($expected_tags, $page_cache_tags_referencing_entity);
     $this->verifyPageCache($listing_url, 'HIT', $expected_tags);
     $this->pass("Test empty listing.", 'Debug');
     // Prime the page cache for the empty listing.
     $this->verifyPageCache($empty_entity_listing_url, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags);
     // Verify the entity type's list cache contexts are present.
     $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts');
     $this->assertEqual(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header));
     $this->pass("Test listing containing referenced entity.", 'Debug');
     // Prime the page cache for the listing containing the referenced entity.
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS', $nonempty_entity_listing_cache_tags);
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', $nonempty_entity_listing_cache_tags);
     // Verify the entity type's list cache contexts are present.
     $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts');
     $this->assertEqual(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header));
     // Verify that after modifying the referenced entity, there is a cache miss
     // for every route except the one for the non-referencing entity.
     $this->pass("Test modification of referenced entity.", 'Debug');
     $this->entity->save();
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     $this->verifyPageCache($listing_url, 'MISS');
     $this->verifyPageCache($empty_entity_listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     // Verify that after modifying the referencing entity, there is a cache miss
     // for every route except the ones for the non-referencing entity and the
     // empty entity listing.
     $this->pass("Test modification of referencing entity.", 'Debug');
     $this->referencingEntity->save();
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     $this->verifyPageCache($listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     // Verify that after modifying the non-referencing entity, there is a cache
     // miss only for the non-referencing entity route.
     $this->pass("Test modification of non-referencing entity.", 'Debug');
     $this->nonReferencingEntity->save();
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     $this->verifyPageCache($non_referencing_entity_url, 'MISS');
     // Verify cache hits.
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) {
         // Verify that after modifying the entity's display, there is a cache miss
         // for both the referencing entity, and the listing of referencing
         // entities, but not for any other routes.
         $referenced_entity_view_mode = $this->selectViewMode($this->entity->getEntityTypeId());
         $this->pass("Test modification of referenced entity's '{$referenced_entity_view_mode}' display.", 'Debug');
         $entity_display = entity_get_display($entity_type, $this->entity->bundle(), $referenced_entity_view_mode);
         $entity_display->save();
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         $this->verifyPageCache($empty_entity_listing_url, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
     }
     if ($bundle_entity_type_id = $this->entity->getEntityType()->getBundleEntityType()) {
         // Verify that after modifying the corresponding bundle entity, there is a
         // cache miss for both the referencing entity, and the listing of
         // referencing entities, but not for any other routes.
         $this->pass("Test modification of referenced entity's bundle entity.", 'Debug');
         $bundle_entity = entity_load($bundle_entity_type_id, $this->entity->bundle());
         $bundle_entity->save();
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         // Special case: entity types may choose to use their bundle entity type
         // cache tags, to avoid having excessively granular invalidation.
         $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getEntityType()->getListCacheTags() == $this->entity->getEntityType()->getListCacheTags();
         if ($is_special_case) {
             $this->verifyPageCache($empty_entity_listing_url, 'MISS');
             $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
         } else {
             $this->verifyPageCache($empty_entity_listing_url, 'HIT');
             $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         }
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
         if ($is_special_case) {
             $this->verifyPageCache($empty_entity_listing_url, 'HIT');
             $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         }
     }
     if ($this->entity->getEntityType()->get('field_ui_base_route')) {
         // Verify that after modifying a configurable field on the entity, there
         // is a cache miss.
         $this->pass("Test modification of referenced entity's configurable field.", 'Debug');
         $field_storage_name = $this->entity->getEntityTypeId() . '.configurable_field';
         $field_storage = FieldStorageConfig::load($field_storage_name);
         $field_storage->save();
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($empty_entity_listing_url, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
         // Verify that after modifying a configurable field on the entity, there
         // is a cache miss.
         $this->pass("Test modification of referenced entity's configurable field.", 'Debug');
         $field_name = $this->entity->getEntityTypeId() . '.' . $this->entity->bundle() . '.configurable_field';
         $field = FieldConfig::load($field_name);
         $field->save();
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($empty_entity_listing_url, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
     }
     // Verify that after invalidating the entity's cache tag directly, there is
     // a cache miss for every route except the ones for the non-referencing
     // entity and the empty entity listing.
     $this->pass("Test invalidation of referenced entity's cache tag.", 'Debug');
     Cache::invalidateTags($this->entity->getCacheTagsToInvalidate());
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     $this->verifyPageCache($listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     // Verify that after invalidating the entity's list cache tag directly,
     // there is a cache miss for both the empty entity listing and the non-empty
     // entity listing routes, but not for other routes.
     $this->pass("Test invalidation of referenced entity's list cache tag.", 'Debug');
     Cache::invalidateTags($this->entity->getEntityType()->getListCacheTags());
     $this->verifyPageCache($empty_entity_listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
     $this->verifyPageCache($referencing_entity_url, 'HIT');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     $this->verifyPageCache($listing_url, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($empty_entity_listing_url, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
     if (!empty($view_cache_tag)) {
         // Verify that after invalidating the generic entity type's view cache tag
         // directly, there is a cache miss for both the referencing entity, and the
         // listing of referencing entities, but not for other routes.
         $this->pass("Test invalidation of referenced entity's 'view' cache tag.", 'Debug');
         Cache::invalidateTags($view_cache_tag);
         $this->verifyPageCache($referencing_entity_url, 'MISS');
         $this->verifyPageCache($listing_url, 'MISS');
         $this->verifyPageCache($non_referencing_entity_url, 'HIT');
         $this->verifyPageCache($empty_entity_listing_url, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_url, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_url, 'HIT');
         $this->verifyPageCache($listing_url, 'HIT');
     }
     // Verify that after deleting the entity, there is a cache miss for every
     // route except for the non-referencing entity one.
     $this->pass('Test deletion of referenced entity.', 'Debug');
     $this->entity->delete();
     $this->verifyPageCache($referencing_entity_url, 'MISS');
     $this->verifyPageCache($listing_url, 'MISS');
     $this->verifyPageCache($empty_entity_listing_url, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_url, 'MISS');
     $this->verifyPageCache($non_referencing_entity_url, 'HIT');
     // Verify cache hits.
     $referencing_entity_cache_tags = Cache::mergeTags($this->referencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags());
     $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, ['rendered']);
     $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing());
     $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $page_cache_tags);
     $this->verifyPageCache($referencing_entity_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags));
     $this->verifyPageCache($listing_url, 'HIT', $page_cache_tags);
     $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags);
     $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', $nonempty_entity_listing_cache_tags);
 }
예제 #21
0
 /**
  * Tests cache tags presence and invalidation of the entity when referenced.
  *
  * Tests the following cache tags:
  * - entity type view cache tag: "<entity type>_view"
  * - entity cache tag: "<entity type>:<entity ID>"
  * - entity type list cache tag: "<entity type>_list"
  * - referencing entity type view cache tag: "<referencing entity type>_view"
  * - referencing entity type cache tag: "<referencing entity type>:<referencing entity ID>"
  */
 public function testReferencedEntity()
 {
     $entity_type = $this->entity->getEntityTypeId();
     $referencing_entity_path = $this->referencing_entity->getSystemPath();
     $non_referencing_entity_path = $this->non_referencing_entity->getSystemPath();
     $listing_path = 'entity_test/list/' . $entity_type . '_reference/' . $entity_type . '/' . $this->entity->id();
     $empty_entity_listing_path = 'entity_test/list_empty/' . $entity_type;
     $nonempty_entity_listing_path = 'entity_test/list_labels_alphabetically/' . $entity_type;
     $render_cache_tags = array('rendered');
     $theme_cache_tags = array('theme:stark', 'theme_global_settings');
     $view_cache_tag = array();
     if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) {
         $view_cache_tag = \Drupal::entityManager()->getViewBuilder($entity_type)->getCacheTags();
     }
     // Generate the cache tags for the (non) referencing entities.
     $referencing_entity_cache_tags = Cache::mergeTags($this->referencing_entity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags(), $this->entity->getCacheTags(), $this->getAdditionalCacheTagsForEntity($this->entity), $view_cache_tag);
     $non_referencing_entity_cache_tags = Cache::mergeTags($this->non_referencing_entity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags());
     // Generate the cache tags for all two possible entity listing paths.
     // 1. list cache tag only (listing query has no match)
     // 2. list cache tag plus entity cache tag (listing query has a match)
     $empty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $theme_cache_tags, $render_cache_tags);
     $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->entity->getCacheTags(), $this->getAdditionalCacheTagsForEntityListing($this->entity), $theme_cache_tags, $render_cache_tags);
     $this->pass("Test referencing entity.", 'Debug');
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $referencing_entity_cache_tags);
     $this->verifyPageCache($referencing_entity_path, 'HIT', $tags);
     // Also verify the existence of an entity render cache entry.
     $cid = 'entity_view:entity_test:' . $this->referencing_entity->id() . ':full:stark:r.anonymous:' . date_default_timezone_get();
     $tags = Cache::mergeTags($render_cache_tags, $referencing_entity_cache_tags);
     $this->verifyRenderCache($cid, $tags);
     $this->pass("Test non-referencing entity.", 'Debug');
     $this->verifyPageCache($non_referencing_entity_path, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $non_referencing_entity_cache_tags);
     $this->verifyPageCache($non_referencing_entity_path, 'HIT', $tags);
     // Also verify the existence of an entity render cache entry.
     $cid = 'entity_view:entity_test:' . $this->non_referencing_entity->id() . ':full:stark:r.anonymous:' . date_default_timezone_get();
     $tags = Cache::mergeTags($render_cache_tags, $non_referencing_entity_cache_tags);
     $this->verifyRenderCache($cid, $tags);
     $this->pass("Test listing of referencing entities.", 'Debug');
     // Prime the page cache for the listing of referencing entities.
     $this->verifyPageCache($listing_path, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $referencing_entity_cache_tags);
     $this->verifyPageCache($listing_path, 'HIT', $tags);
     $this->pass("Test empty listing.", 'Debug');
     // Prime the page cache for the empty listing.
     $this->verifyPageCache($empty_entity_listing_path, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($empty_entity_listing_path, 'HIT', $empty_entity_listing_cache_tags);
     $this->pass("Test listing containing referenced entity.", 'Debug');
     // Prime the page cache for the listing containing the referenced entity.
     $this->verifyPageCache($nonempty_entity_listing_path, 'MISS');
     // Verify a cache hit, but also the presence of the correct cache tags.
     $this->verifyPageCache($nonempty_entity_listing_path, 'HIT', $nonempty_entity_listing_cache_tags);
     // Verify that after modifying the referenced entity, there is a cache miss
     // for every route except the one for the non-referencing entity.
     $this->pass("Test modification of referenced entity.", 'Debug');
     $this->entity->save();
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     $this->verifyPageCache($listing_path, 'MISS');
     $this->verifyPageCache($empty_entity_listing_path, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_path, 'MISS');
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_path, 'HIT');
     $this->verifyPageCache($listing_path, 'HIT');
     $this->verifyPageCache($empty_entity_listing_path, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
     // Verify that after modifying the referencing entity, there is a cache miss
     // for every route except the ones for the non-referencing entity and the
     // empty entity listing.
     $this->pass("Test modification of referencing entity.", 'Debug');
     $this->referencing_entity->save();
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     $this->verifyPageCache($listing_path, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     $this->verifyPageCache($empty_entity_listing_path, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_path, 'HIT');
     $this->verifyPageCache($listing_path, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
     // Verify that after modifying the non-referencing entity, there is a cache
     // miss only for the non-referencing entity route.
     $this->pass("Test modification of non-referencing entity.", 'Debug');
     $this->non_referencing_entity->save();
     $this->verifyPageCache($referencing_entity_path, 'HIT');
     $this->verifyPageCache($listing_path, 'HIT');
     $this->verifyPageCache($empty_entity_listing_path, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
     $this->verifyPageCache($non_referencing_entity_path, 'MISS');
     // Verify cache hits.
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) {
         // Verify that after modifying the entity's display, there is a cache miss
         // for both the referencing entity, and the listing of referencing
         // entities, but not for any other routes.
         $referenced_entity_view_mode = $this->selectViewMode($this->entity->getEntityTypeId());
         $this->pass("Test modification of referenced entity's '{$referenced_entity_view_mode}' display.", 'Debug');
         $entity_display = entity_get_display($entity_type, $this->entity->bundle(), $referenced_entity_view_mode);
         $entity_display->save();
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         $this->verifyPageCache($empty_entity_listing_path, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
     }
     $bundle_entity_type = $this->entity->getEntityType()->getBundleEntityType();
     if ($bundle_entity_type !== 'bundle') {
         // Verify that after modifying the corresponding bundle entity, there is a
         // cache miss for both the referencing entity, and the listing of
         // referencing entities, but not for any other routes.
         $this->pass("Test modification of referenced entity's bundle entity.", 'Debug');
         $bundle_entity = entity_load($bundle_entity_type, $this->entity->bundle());
         $bundle_entity->save();
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         // Special case: entity types may choose to use their bundle entity type
         // cache tags, to avoid having excessively granular invalidation.
         $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getEntityType()->getListCacheTags() == $this->entity->getEntityType()->getListCacheTags();
         if ($is_special_case) {
             $this->verifyPageCache($empty_entity_listing_path, 'MISS');
             $this->verifyPageCache($nonempty_entity_listing_path, 'MISS');
         } else {
             $this->verifyPageCache($empty_entity_listing_path, 'HIT');
             $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
         }
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
         if ($is_special_case) {
             $this->verifyPageCache($empty_entity_listing_path, 'HIT');
             $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
         }
     }
     if ($this->entity->getEntityType()->get('field_ui_base_route')) {
         // Verify that after modifying a configurable field on the entity, there
         // is a cache miss.
         $this->pass("Test modification of referenced entity's configurable field.", 'Debug');
         $field_storage_name = $this->entity->getEntityTypeId() . '.configurable_field';
         $field_storage = entity_load('field_storage_config', $field_storage_name);
         $field_storage->save();
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($empty_entity_listing_path, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
         // Verify that after modifying a configurable field on the entity, there
         // is a cache miss.
         $this->pass("Test modification of referenced entity's configurable field.", 'Debug');
         $field_name = $this->entity->getEntityTypeId() . '.' . $this->entity->bundle() . '.configurable_field';
         $field = entity_load('field_config', $field_name);
         $field->save();
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($empty_entity_listing_path, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
     }
     // Verify that after invalidating the entity's cache tag directly, there is
     // a cache miss for every route except the ones for the non-referencing
     // entity and the empty entity listing.
     $this->pass("Test invalidation of referenced entity's cache tag.", 'Debug');
     Cache::invalidateTags($this->entity->getCacheTags());
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     $this->verifyPageCache($listing_path, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_path, 'MISS');
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     $this->verifyPageCache($empty_entity_listing_path, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($referencing_entity_path, 'HIT');
     $this->verifyPageCache($listing_path, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
     // Verify that after invalidating the entity's list cache tag directly,
     // there is a cache miss for both the empty entity listing and the non-empty
     // entity listing routes, but not for other routes.
     $this->pass("Test invalidation of referenced entity's list cache tag.", 'Debug');
     Cache::invalidateTags($this->entity->getEntityType()->getListCacheTags());
     $this->verifyPageCache($empty_entity_listing_path, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_path, 'MISS');
     $this->verifyPageCache($referencing_entity_path, 'HIT');
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     $this->verifyPageCache($listing_path, 'HIT');
     // Verify cache hits.
     $this->verifyPageCache($empty_entity_listing_path, 'HIT');
     $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
     if (!empty($view_cache_tag)) {
         // Verify that after invalidating the generic entity type's view cache tag
         // directly, there is a cache miss for both the referencing entity, and the
         // listing of referencing entities, but not for other routes.
         $this->pass("Test invalidation of referenced entity's 'view' cache tag.", 'Debug');
         Cache::invalidateTags($view_cache_tag);
         $this->verifyPageCache($referencing_entity_path, 'MISS');
         $this->verifyPageCache($listing_path, 'MISS');
         $this->verifyPageCache($non_referencing_entity_path, 'HIT');
         $this->verifyPageCache($empty_entity_listing_path, 'HIT');
         $this->verifyPageCache($nonempty_entity_listing_path, 'HIT');
         // Verify cache hits.
         $this->verifyPageCache($referencing_entity_path, 'HIT');
         $this->verifyPageCache($listing_path, 'HIT');
     }
     // Verify that after deleting the entity, there is a cache miss for every
     // route except for the the non-referencing entity one.
     $this->pass('Test deletion of referenced entity.', 'Debug');
     $this->entity->delete();
     $this->verifyPageCache($referencing_entity_path, 'MISS');
     $this->verifyPageCache($listing_path, 'MISS');
     $this->verifyPageCache($empty_entity_listing_path, 'MISS');
     $this->verifyPageCache($nonempty_entity_listing_path, 'MISS');
     $this->verifyPageCache($non_referencing_entity_path, 'HIT');
     // Verify cache hits.
     $referencing_entity_cache_tags = Cache::mergeTags($this->referencing_entity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags());
     $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $referencing_entity_cache_tags);
     $this->verifyPageCache($referencing_entity_path, 'HIT', $tags);
     $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags);
     $this->verifyPageCache($listing_path, 'HIT', $tags);
     $tags = Cache::mergeTags($render_cache_tags, $theme_cache_tags, $this->entity->getEntityType()->getListCacheTags());
     $this->verifyPageCache($empty_entity_listing_path, 'HIT', $tags);
     $tags = Cache::mergeTags($tags, $this->getAdditionalCacheTagsForEntityListing());
     $this->verifyPageCache($nonempty_entity_listing_path, 'HIT', $tags);
 }
 /**
  * {@inheritdoc}
  */
 public function isBundleForModeratableEntity(EntityInterface $entity)
 {
     $type = $entity->getEntityType();
     return $type instanceof ConfigEntityTypeInterface && ($bundle_of = $type->get('bundle_of')) && $this->entityTypeManager->getDefinition($bundle_of)->isRevisionable() && $this->currentUser->hasPermission('administer moderation states');
 }
예제 #23
0
 /**
  * Creates or updates the moderation state of an entity.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The entity to update or create a moderation state for.
  */
 protected function updateOrCreateFromEntity(EntityInterface $entity)
 {
     $moderation_state = $entity->moderation_state->target_id;
     /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
     if (!$moderation_state) {
         $moderation_state = $this->moderationInfo->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle())->getThirdPartySetting('content_moderation', 'default_moderation_state');
     }
     // @todo what if $entity->moderation_state->target_id is null at this point?
     $entity_type_id = $entity->getEntityTypeId();
     $entity_id = $entity->id();
     $entity_revision_id = $entity->getRevisionId();
     $entity_langcode = $entity->language()->getId();
     $storage = $this->entityTypeManager->getStorage('content_moderation_state');
     $entities = $storage->loadByProperties(['content_entity_type_id' => $entity_type_id, 'content_entity_id' => $entity_id]);
     /** @var \Drupal\content_moderation\ContentModerationStateInterface $content_moderation_state */
     $content_moderation_state = reset($entities);
     if (!$content_moderation_state instanceof ContentModerationStateInterface) {
         $content_moderation_state = $storage->create(['content_entity_type_id' => $entity_type_id, 'content_entity_id' => $entity_id]);
     } else {
         // Create a new revision.
         $content_moderation_state->setNewRevision(TRUE);
     }
     // Sync translations.
     if (!$content_moderation_state->hasTranslation($entity_langcode)) {
         $content_moderation_state->addTranslation($entity_langcode);
     }
     if ($content_moderation_state->language()->getId() !== $entity_langcode) {
         $content_moderation_state = $content_moderation_state->getTranslation($entity_langcode);
     }
     // Create the ContentModerationState entity for the inserted entity.
     $content_moderation_state->set('content_entity_revision_id', $entity_revision_id);
     $content_moderation_state->set('moderation_state', $moderation_state);
     ContentModerationState::updateOrCreateFromEntity($content_moderation_state);
 }
 /**
  * Initializes the translation form state.
  *
  * @param \Drupal\Core\Form\FormStateInterface $form_state
  * @param \Drupal\Core\Entity\EntityInterface $host
  */
 protected function initIsTranslating(FormStateInterface $form_state, EntityInterface $host)
 {
     if ($this->isTranslating != NULL) {
         return;
     }
     $this->isTranslating = FALSE;
     if (!$host->isTranslatable()) {
         return;
     }
     if (!$host->getEntityType()->hasKey('default_langcode')) {
         return;
     }
     $default_langcode_key = $host->getEntityType()->getKey('default_langcode');
     if (!$host->hasField($default_langcode_key)) {
         return;
     }
     if (!empty($form_state->get('content_translation'))) {
         // Adding a language through the ContentTranslationController.
         $this->isTranslating = TRUE;
     }
     if ($host->hasTranslation($form_state->get('langcode')) && $host->getTranslation($form_state->get('langcode'))->get($default_langcode_key)->value == 0) {
         // Editing a translation.
         $this->isTranslating = TRUE;
     }
 }
 /**
  * Adds an operation on bundles that should have a Moderation form.
  *
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The entity on which to define an operation.
  *
  * @return array
  *   An array of operation definitions.
  *
  * @see hook_entity_operation().
  */
 public function entityOperation(EntityInterface $entity)
 {
     $operations = [];
     $type = $entity->getEntityType();
     if ($this->moderationInfo->isBundleForModeratableEntity($entity)) {
         $operations['manage-moderation'] = ['title' => t('Manage moderation'), 'weight' => 27, 'url' => Url::fromRoute("entity.{$type->id()}.moderation", [$entity->getEntityTypeId() => $entity->id()])];
     }
     return $operations;
 }