/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { // Remove the translated values. $this->entity->removeTranslation($this->language->id); $this->entity->save(); // Remove any existing path alias for the removed translation. // @todo This should be taken care of by the Path module. if (\Drupal::moduleHandler()->moduleExists('path')) { $path = $this->entity->getSystemPath(); $conditions = array('source' => $path, 'langcode' => $this->language->id); \Drupal::service('path.alias_storage')->delete($conditions); } $form_state->setRedirectUrl($this->getCancelUrl()); }
/** * Alters the field to render a link. * * @param \Drupal\Core\Entity\EntityInterface $entity * @param \Drupal\views\ResultRow $values * The current row of the views result. * * @return string * The acutal rendered text (without the link) of this field. */ protected function renderLink(EntityInterface $entity, ResultRow $values) { $text = !empty($this->options['text']) ? $this->options['text'] : t('View'); $this->options['alter']['make_link'] = TRUE; $this->options['alter']['path'] = $entity->getSystemPath(); return $text; }
/** * {@inheritdoc} */ protected function renderLink(EntityInterface $entity, ResultRow $values) { if ($entity && $entity->access('update')) { $this->options['alter']['make_link'] = TRUE; $text = !empty($this->options['text']) ? $this->options['text'] : t('Edit'); $this->options['alter']['path'] = $entity->getSystemPath('edit-form'); $this->options['alter']['query'] = drupal_get_destination(); return $text; } }
/** * Checks that workflows have the expected behaviors for the given user. * * @param \Drupal\user\UserInterface $user * The user to test the workflow behavior against. * @param array $expected_status * The an associative array with the operation name as key and the expected * status as value. */ protected function assertWorkflows(UserInterface $user, $expected_status) { $default_langcode = $this->langcodes[0]; $languages = $this->container->get('language_manager')->getLanguages(); $args = array('@user_label' => $user->getUsername()); $this->drupalLogin($user); // Check whether the user is allowed to access the entity form in edit mode. $edit_path = $this->entity->getSystemPath('edit-form'); $options = array('language' => $languages[$default_langcode]); $this->drupalGet($edit_path, $options); $this->assertResponse($expected_status['edit'], format_string('The @user_label has the expected edit access.', $args)); // Check whether the user is allowed to access the translation overview. $langcode = $this->langcodes[1]; $translations_path = $this->entity->getSystemPath('drupal:content-translation-overview'); $options = array('language' => $languages[$langcode]); $this->drupalGet($translations_path, $options); $this->assertResponse($expected_status['overview'], format_string('The @user_label has the expected translation overview access.', $args)); // Check whether the user is allowed to create a translation. $add_translation_path = $translations_path . "/add/{$default_langcode}/{$langcode}"; if ($expected_status['add_translation'] == 200) { $this->clickLink('Add'); $this->assertUrl($add_translation_path, $options, 'The translation overview points to the translation form when creating translations.'); // Check that the translation form does not contain shared elements for // translators. if ($expected_status['edit'] == 403) { $this->assertNoSharedElements(); } } else { $this->drupalGet($add_translation_path, $options); } $this->assertResponse($expected_status['add_translation'], format_string('The @user_label has the expected translation creation access.', $args)); // Check whether the user is allowed to edit a translation. $langcode = $this->langcodes[2]; $edit_translation_path = $translations_path . "/edit/{$langcode}"; $options = array('language' => $languages[$langcode]); if ($expected_status['edit_translation'] == 200) { $this->drupalGet($translations_path, $options); $editor = $expected_status['edit'] == 200; if ($editor) { $this->clickLink('Edit', 2); // An editor should be pointed to the entity form in multilingual mode. $this->assertUrl($edit_path, $options, 'The translation overview points to the edit form for editors when editing translations.'); } else { $this->clickLink('Edit'); // While a translator should be pointed to the translation form. $this->assertUrl($edit_translation_path, $options, 'The translation overview points to the translation form for translators when editing translations.'); // Check that the translation form does not contain shared elements. $this->assertNoSharedElements(); } } else { $this->drupalGet($edit_translation_path, $options); } $this->assertResponse($expected_status['edit_translation'], format_string('The @user_label has the expected translation creation access.', $args)); }
/** * Prepares the link to delete a node. * * @param \Drupal\Core\Entity\EntityInterface $node * The node entity this field belongs to. * @param \Drupal\views\ResultRow $values * The values retrieved from the view's result set. * * @return string * Returns a string for the link text. */ protected function renderLink($node, ResultRow $values) { // Ensure user has access to delete this node. if (!$node->access('delete')) { return; } $this->options['alter']['make_link'] = TRUE; $this->options['alter']['path'] = $node->getSystemPath('delete-form'); $this->options['alter']['query'] = drupal_get_destination(); $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Delete'); return $text; }
/** * {@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 ''; }
/** * 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); }
/** * 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); }