Chris@0: drupalCreateContentType(['type' => 'page', 'name' => 'Basic page']); Chris@0: $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); Chris@0: Chris@0: ConfigurableLanguage::createFromLangcode('it')->save(); Chris@0: $this->rebuildContainer(); Chris@0: Chris@0: $this->editorUser = $this->drupalCreateUser(['access content', 'access contextual links', 'edit any article content']); Chris@0: $this->authenticatedUser = $this->drupalCreateUser(['access content', 'access contextual links']); Chris@0: $this->anonymousUser = $this->drupalCreateUser(['access content']); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests contextual links with different permissions. Chris@0: * Chris@0: * Ensures that contextual link placeholders always exist, even if the user is Chris@0: * not allowed to use contextual links. Chris@0: */ Chris@0: public function testDifferentPermissions() { Chris@0: $this->drupalLogin($this->editorUser); Chris@0: Chris@0: // Create three nodes in the following order: Chris@0: // - An article, which should be user-editable. Chris@0: // - A page, which should not be user-editable. Chris@0: // - A second article, which should also be user-editable. Chris@0: $node1 = $this->drupalCreateNode(['type' => 'article', 'promote' => 1]); Chris@0: $node2 = $this->drupalCreateNode(['type' => 'page', 'promote' => 1]); Chris@0: $node3 = $this->drupalCreateNode(['type' => 'article', 'promote' => 1]); Chris@0: Chris@0: // Now, on the front page, all article nodes should have contextual links Chris@0: // placeholders, as should the view that contains them. Chris@0: $ids = [ Chris@0: 'node:node=' . $node1->id() . ':changed=' . $node1->getChangedTime() . '&langcode=en', Chris@0: 'node:node=' . $node2->id() . ':changed=' . $node2->getChangedTime() . '&langcode=en', Chris@0: 'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime() . '&langcode=en', Chris@0: 'entity.view.edit_form:view=frontpage:location=page&name=frontpage&display_id=page_1&langcode=en', Chris@0: ]; Chris@0: Chris@0: // Editor user: can access contextual links and can edit articles. Chris@0: $this->drupalGet('node'); Chris@0: for ($i = 0; $i < count($ids); $i++) { Chris@0: $this->assertContextualLinkPlaceHolder($ids[$i]); Chris@0: } Chris@0: $this->renderContextualLinks([], 'node'); Chris@0: $this->assertResponse(400); Chris@0: $this->assertRaw('No contextual ids specified.'); Chris@0: $response = $this->renderContextualLinks($ids, 'node'); Chris@0: $this->assertResponse(200); Chris@0: $json = Json::decode($response); Chris@0: $this->assertIdentical($json[$ids[0]], ''); Chris@0: $this->assertIdentical($json[$ids[1]], ''); Chris@0: $this->assertIdentical($json[$ids[2]], ''); Chris@0: $this->assertIdentical($json[$ids[3]], ''); Chris@0: Chris@0: // Verify that link language is properly handled. Chris@0: $node3->addTranslation('it')->set('title', $this->randomString())->save(); Chris@0: $id = 'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime() . '&langcode=it'; Chris@0: $this->drupalGet('node', ['language' => ConfigurableLanguage::createFromLangcode('it')]); Chris@0: $this->assertContextualLinkPlaceHolder($id); Chris@0: Chris@0: // Authenticated user: can access contextual links, cannot edit articles. Chris@0: $this->drupalLogin($this->authenticatedUser); Chris@0: $this->drupalGet('node'); Chris@0: for ($i = 0; $i < count($ids); $i++) { Chris@0: $this->assertContextualLinkPlaceHolder($ids[$i]); Chris@0: } Chris@0: $this->renderContextualLinks([], 'node'); Chris@0: $this->assertResponse(400); Chris@0: $this->assertRaw('No contextual ids specified.'); Chris@0: $response = $this->renderContextualLinks($ids, 'node'); Chris@0: $this->assertResponse(200); Chris@0: $json = Json::decode($response); Chris@0: $this->assertIdentical($json[$ids[0]], ''); Chris@0: $this->assertIdentical($json[$ids[1]], ''); Chris@0: $this->assertIdentical($json[$ids[2]], ''); Chris@0: $this->assertIdentical($json[$ids[3]], ''); Chris@0: Chris@0: // Anonymous user: cannot access contextual links. Chris@0: $this->drupalLogin($this->anonymousUser); Chris@0: $this->drupalGet('node'); Chris@0: for ($i = 0; $i < count($ids); $i++) { Chris@0: $this->assertNoContextualLinkPlaceHolder($ids[$i]); Chris@0: } Chris@0: $this->renderContextualLinks([], 'node'); Chris@0: $this->assertResponse(403); Chris@0: $this->renderContextualLinks($ids, 'node'); Chris@0: $this->assertResponse(403); Chris@0: Chris@0: // Get a page where contextual links are directly rendered. Chris@0: $this->drupalGet(Url::fromRoute('menu_test.contextual_test')); Chris@0: $this->assertEscaped(""); Chris@0: $this->assertRaw(''); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Asserts that a contextual link placeholder with the given id exists. Chris@0: * Chris@0: * @param string $id Chris@0: * A contextual link id. Chris@0: * Chris@0: * @return bool Chris@0: * The result of the assertion. Chris@0: */ Chris@0: protected function assertContextualLinkPlaceHolder($id) { Chris@0: return $this->assertRaw(' $id]) . '>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id])); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Asserts that a contextual link placeholder with the given id does not exist. Chris@0: * Chris@0: * @param string $id Chris@0: * A contextual link id. Chris@0: * Chris@0: * @return bool Chris@0: * The result of the assertion. Chris@0: */ Chris@0: protected function assertNoContextualLinkPlaceHolder($id) { Chris@0: return $this->assertNoRaw(' $id]) . '>', format_string('Contextual link placeholder with id @id does not exist.', ['@id' => $id])); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Get server-rendered contextual links for the given contextual link ids. Chris@0: * Chris@0: * @param array $ids Chris@0: * An array of contextual link ids. Chris@0: * @param string $current_path Chris@0: * The Drupal path for the page for which the contextual links are rendered. Chris@0: * Chris@0: * @return string Chris@0: * The response body. Chris@0: */ Chris@0: protected function renderContextualLinks($ids, $current_path) { Chris@0: $post = []; Chris@0: for ($i = 0; $i < count($ids); $i++) { Chris@0: $post['ids[' . $i . ']'] = $ids[$i]; Chris@0: } Chris@0: return $this->drupalPostWithFormat('contextual/render', 'json', $post, ['query' => ['destination' => $current_path]]); Chris@0: } Chris@0: Chris@0: }