Issue #2503755 by Wim Leers, bobrov1989, webchick, dcrocks, andypost, emma.maria, catch, dawehner, Bojhan, tstoeckler, alexpott, yoroy: Switch from user login block to login menu link and search block in standard profile

8.0.x
webchick 2015-10-04 23:48:45 -07:00
parent d82d595840
commit 1cdbe865bc
13 changed files with 205 additions and 42 deletions

View File

@ -206,15 +206,14 @@ class DefaultMenuLinkTreeManipulators {
$access_result = AccessResult::allowed();
}
else {
// Use the definition here since that's a lot faster than creating a Url
// object that we don't need.
$definition = $instance->getPluginDefinition();
// 'url' should only be populated for external links.
if (!empty($definition['url']) && empty($definition['route_name'])) {
$url = $instance->getUrlObject();
// When no route name is specified, this must be an external link.
if (!$url->isRouted()) {
$access_result = AccessResult::allowed();
}
else {
$access_result = $this->accessManager->checkNamedRoute($definition['route_name'], $definition['route_parameters'], $this->account, TRUE);
$access_result = $this->accessManager->checkNamedRoute($url->getRouteName(), $url->getRouteParameters(), $this->account, TRUE);
}
}
return $access_result->cachePerPermissions();

View File

@ -130,7 +130,7 @@ abstract class MenuLinkBase extends PluginBase implements MenuLinkInterface {
$options['attributes']['title'] = $description;
}
if (empty($this->pluginDefinition['url'])) {
return new Url($this->pluginDefinition['route_name'], $this->pluginDefinition['route_parameters'], $options);
return new Url($this->getRouteName(), $this->getRouteParameters(), $options);
}
else {
return Url::fromUri($this->pluginDefinition['url'], $options);

View File

@ -358,6 +358,11 @@ class MenuForm extends EntityForm {
if (!$link->isEnabled()) {
$form[$id]['title']['#suffix'] = ' (' . $this->t('disabled') . ')';
}
// @todo Remove this in https://www.drupal.org/node/2568785.
elseif ($id === 'menu_plugin_id:user.logout') {
$form[$id]['title']['#suffix'] = ' (' . $this->t('<q>Log in</q> for anonymous users') . ')';
}
// @todo Remove this in https://www.drupal.org/node/2568785.
elseif (($url = $link->getUrlObject()) && $url->isRouted() && $url->getRouteName() == 'user.page') {
$form[$id]['title']['#suffix'] = ' (' . $this->t('logged in users only') . ')';
}

View File

@ -893,8 +893,7 @@ class MenuTest extends MenuWebTestBase {
// the front page.
/** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
$menu_link_manager = \Drupal::service('plugin.manager.menu.link');
$result = $menu_link_manager->loadLinksByRoute('user.logout');
$instance = reset($result);
$instance = $menu_link_manager->getInstance(['id' => 'user.logout']);
$this->assertTrue((bool) $instance, 'Standard menu link was loaded');
return $instance;

View File

@ -89,7 +89,6 @@ class PageCacheTagsIntegrationTest extends WebTestBase {
'config:block.block.bartik_breadcrumbs',
'config:block.block.bartik_content',
'config:block.block.bartik_tools',
'config:block.block.bartik_login',
'config:block.block.bartik_footer',
'config:block.block.bartik_help',
'config:block.block.bartik_search',
@ -106,6 +105,7 @@ class PageCacheTagsIntegrationTest extends WebTestBase {
'user:0',
'user:' . $author_1->id(),
'config:filter.format.basic_html',
'config:search.settings',
'config:system.menu.account',
'config:system.menu.tools',
'config:system.menu.footer',
@ -128,7 +128,6 @@ class PageCacheTagsIntegrationTest extends WebTestBase {
'config:block.block.bartik_breadcrumbs',
'config:block.block.bartik_content',
'config:block.block.bartik_tools',
'config:block.block.bartik_login',
'config:block.block.bartik_help',
'config:block.block.bartik_search',
'config:block.block.' . $block->id(),
@ -144,6 +143,7 @@ class PageCacheTagsIntegrationTest extends WebTestBase {
'node:' . $node_2->id(),
'user:' . $author_2->id(),
'config:filter.format.full_html',
'config:search.settings',
'config:system.menu.account',
'config:system.menu.tools',
'config:system.menu.footer',

View File

@ -0,0 +1,91 @@
<?php
/**
* @file
* Contains \Drupal\user\Plugin\Menu\MyAccountMenuLink.
*/
namespace Drupal\user\Plugin\Menu;
use Drupal\Core\Menu\MenuLinkDefault;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* A menu link that shows "Log in" or "Log out" as appropriate.
*/
class LoginLogoutMenuLink extends MenuLinkDefault {
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Constructs a new LoginLogoutMenuLink.
*
* @param array $configuration
* A configuration array containing information about the plugin instance.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Menu\StaticMenuLinkOverridesInterface $static_override
* The static override storage.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, StaticMenuLinkOverridesInterface $static_override, AccountInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $static_override);
$this->currentUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('menu_link.static.overrides'),
$container->get('current_user')
);
}
/**
* {@inheritdoc}
*/
public function getTitle() {
if ($this->currentUser->isAuthenticated()) {
return $this->t('Log out');
}
else {
return $this->t('Log in');
}
}
/**
* {@inheritdoc}
*/
public function getRouteName() {
if ($this->currentUser->isAuthenticated()) {
return 'user.logout';
}
else {
return 'user.login';
}
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
return ['user.roles:authenticated'];
}
}

View File

@ -65,11 +65,13 @@ class UserAccountLinksTest extends WebTestBase {
$this->drupalLogout();
$this->drupalGet('<front>');
// For a logged-out user, expect no secondary links.
$menu = $this->xpath('//ul[@class=:menu_class]', array(
// For a logged-out user, expect the secondary menu to have a "Log in" link.
$link = $this->xpath('//ul[@class=:menu_class]/li/a[contains(@href, :href) and text()=:text]', array(
':menu_class' => 'menu',
':href' => 'user/login',
':text' => 'Log in',
));
$this->assertEqual(count($menu), 0, 'The secondary links menu is not rendered, because none of its menu links are accessible for the anonymous user.');
$this->assertEqual(count($link), 1, 'Log in link is in secondary menu.');
}
/**

View File

@ -4,10 +4,9 @@ user.page:
route_name: user.page
menu_name: account
user.logout:
title: 'Log out'
route_name: user.logout
weight: 10
menu_name: account
class: Drupal\user\Plugin\Menu\LoginLogoutMenuLink
entity.user.collection:
title: People
route_name: entity.user.collection

View File

@ -1,19 +0,0 @@
langcode: en
status: true
dependencies:
module:
- user
theme:
- bartik
id: bartik_login
theme: bartik
region: sidebar_first
weight: 0
provider: null
plugin: user_login_block
settings:
id: user_login_block
label: 'User login'
provider: user
label_display: visible
visibility: { }

View File

@ -60,6 +60,10 @@ function standard_install() {
));
$shortcut->save();
// Allow all users to use search.
user_role_grant_permissions(RoleInterface::ANONYMOUS_ID, array('search content'));
user_role_grant_permissions(RoleInterface::AUTHENTICATED_ID, array('search content'));
// Enable the admin theme.
\Drupal::configFactory()->getEditable('node.settings')->set('use_admin_theme', TRUE)->save(TRUE);
}

View File

@ -73,6 +73,8 @@ class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
$this->accessManager = $this->getMock('\Drupal\Core\Access\AccessManagerInterface');
$this->currentUser = $this->getMock('Drupal\Core\Session\AccountInterface');
$this->currentUser->method('isAuthenticated')
->willReturn(TRUE);
$this->queryFactory = $this->getMockBuilder('Drupal\Core\Entity\Query\QueryFactory')
->disableOriginalConstructor()
->getMock();
@ -97,6 +99,7 @@ class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
* - 7
* - 6
* - 8
* - 9
*
* With link 6 being the only external link.
*/
@ -110,6 +113,7 @@ class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
6 => MenuLinkMock::create(array('id' => 'test.example6', 'route_name' => '', 'url' => 'https://www.drupal.org/', 'title' => 'barbar', 'parent' => '')),
7 => MenuLinkMock::create(array('id' => 'test.example7', 'route_name' => 'example7', 'title' => 'bazbaz', 'parent' => '')),
8 => MenuLinkMock::create(array('id' => 'test.example8', 'route_name' => 'example8', 'title' => 'quxqux', 'parent' => '')),
9 => DynamicMenuLinkMock::create(array('id' => 'test.example9', 'parent' => ''))->setCurrentUser($this->currentUser),
);
$this->originalTree = array();
$this->originalTree[1] = new MenuLinkTreeElement($this->links[1], FALSE, 1, FALSE, array());
@ -123,6 +127,7 @@ class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
));
$this->originalTree[6] = new MenuLinkTreeElement($this->links[6], FALSE, 1, FALSE, array());
$this->originalTree[8] = new MenuLinkTreeElement($this->links[8], FALSE, 1, FALSE, array());
$this->originalTree[9] = new MenuLinkTreeElement($this->links[9], FALSE, 1, FALSE, array());
}
/**
@ -156,16 +161,17 @@ class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
*/
public function testCheckAccess() {
// Those menu links that are non-external will have their access checks
// performed. 8 routes, but 1 is external, 2 already have their 'access'
// property set, and 1 is a child if an inaccessible menu link, so only 4
// performed. 9 routes, but 1 is external, 2 already have their 'access'
// property set, and 1 is a child if an inaccessible menu link, so only 5
// calls will be made.
$this->accessManager->expects($this->exactly(4))
$this->accessManager->expects($this->exactly(5))
->method('checkNamedRoute')
->will($this->returnValueMap(array(
array('example1', array(), $this->currentUser, TRUE, AccessResult::forbidden()),
array('example2', array('foo' => 'bar'), $this->currentUser, TRUE, AccessResult::allowed()->cachePerPermissions()),
array('example3', array('baz' => 'qux'), $this->currentUser, TRUE, AccessResult::neutral()),
array('example5', array(), $this->currentUser, TRUE, AccessResult::allowed()),
array('user.logout', array(), $this->currentUser, TRUE, AccessResult::allowed()),
)));
$this->mockTree();
@ -227,7 +233,7 @@ class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
*/
public function testCheckAccessWithLinkToAnyPagePermission() {
$this->mockTree();
$this->currentUser->expects($this->exactly(8))
$this->currentUser->expects($this->exactly(9))
->method('hasPermission')
->with('link to any page')
->willReturn(TRUE);
@ -243,6 +249,7 @@ class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
$this->assertEquals($expected_access_result, $this->originalTree[5]->subtree[7]->access);
$this->assertEquals($expected_access_result, $this->originalTree[6]->access);
$this->assertEquals($expected_access_result, $this->originalTree[8]->access);
$this->assertEquals($expected_access_result, $this->originalTree[9]->access);
}
/**
@ -253,8 +260,8 @@ class DefaultMenuLinkTreeManipulatorsTest extends UnitTestCase {
public function testFlatten() {
$this->mockTree();
$tree = $this->defaultMenuTreeManipulators->flatten($this->originalTree);
$this->assertEquals(array(1, 2, 5, 6, 8), array_keys($this->originalTree));
$this->assertEquals(array(1, 2, 5, 6, 8, 3, 4, 7), array_keys($tree));
$this->assertEquals(array(1, 2, 5, 6, 8, 9), array_keys($this->originalTree));
$this->assertEquals(array(1, 2, 5, 6, 8, 9, 3, 4, 7), array_keys($tree));
}
/**

View File

@ -0,0 +1,75 @@
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Menu\DynamicMenuLinkMock.
*/
namespace Drupal\Tests\Core\Menu;
use Drupal\Core\Session\AccountInterface;
/**
* Defines a mock implementation of a dynamic menu link used in tests only.
*
* Has a dynamic route and title. This is rather contrived, but there are valid
* use cases.
*
* @see \Drupal\user\Plugin\Menu\LoginLogoutMenuLink
*/
class DynamicMenuLinkMock extends MenuLinkMock {
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* Sets the current user.
*
* Allows the menu link to return the right title and route.
*
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
*
* @return $this
*/
public function setCurrentUser(AccountInterface $current_user) {
$this->currentUser = $current_user;
return $this;
}
/**
* {@inheritdoc}
*/
public function getTitle() {
if ($this->currentUser->isAuthenticated()) {
return 'Log out';
}
else {
return 'Log in';
}
}
/**
* {@inheritdoc}
*/
public function getRouteName() {
if ($this->currentUser->isAuthenticated()) {
return 'user.logout';
}
else {
return 'user.login';
}
}
/**
* {@inheritdoc}
*/
public function getCacheContexts() {
return ['user.roles:authenticated'];
}
}

View File

@ -50,7 +50,8 @@ a:active,
.site-branding,
.site-branding__text a,
.site-branding a,
.region-secondary-menu .menu-item a {
.region-secondary-menu .menu-item a,
.region-secondary-menu .menu-item a.is-active {
color: #fffeff;
}