Revert "Issue #2002162 by klausi, eugene.ilyin: Convert form validation of users to entity validation."
This reverts commit 5b41b6f82f
.
8.0.x
parent
7742cc3563
commit
b00eeb7df8
|
@ -190,8 +190,7 @@ abstract class EntityStorageControllerBase implements EntityStorageControllerInt
|
|||
// of making LegacyConfigFieldItem implement PrepareCacheInterface.
|
||||
// @todo Remove once all core field types have been converted (see
|
||||
// http://drupal.org/node/2014671).
|
||||
|| (is_subclass_of($type_definition['class'], '\Drupal\field\Plugin\field\field_type\LegacyConfigFieldItem')
|
||||
&& isset($type_definition['provider']) && function_exists($type_definition['provider'] . '_field_load'))) {
|
||||
|| (is_subclass_of($type_definition['class'], '\Drupal\field\Plugin\field\field_type\LegacyConfigFieldItem') && function_exists($type_definition['provider'] . '_field_load'))) {
|
||||
|
||||
// Call the prepareCache() method directly on each item
|
||||
// individually.
|
||||
|
|
|
@ -70,7 +70,7 @@ class LocalActionManager extends DefaultPluginManager {
|
|||
$this->controllerResolver = $controller_resolver;
|
||||
$this->request = $request;
|
||||
$this->alterInfo($module_handler, 'menu_local_actions');
|
||||
$this->setCacheBackend($cache_backend, $language_manager, 'local_action');
|
||||
$this->setCacheBackend($cache_backend, $language_manager, 'local_action_plugins');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,22 +121,12 @@ class LocalActionManager extends DefaultPluginManager {
|
|||
public function getActionsForRoute($route_name) {
|
||||
if (!isset($this->instances[$route_name])) {
|
||||
$this->instances[$route_name] = array();
|
||||
if ($cache = $this->cacheBackend->get($this->cacheKey . ':' . $route_name)) {
|
||||
$route_actions = $cache->data;
|
||||
}
|
||||
else {
|
||||
// Iterate over all plugin definitions to find those that appear on the
|
||||
// current route, then cache the list.
|
||||
$route_actions = array();
|
||||
foreach ($this->getDefinitions() as $plugin_id => $action_info) {
|
||||
if (in_array($route_name, $action_info['appears_on'])) {
|
||||
$route_actions[] = $plugin_id;
|
||||
}
|
||||
// @todo - optimize this lookup by compiling or caching.
|
||||
foreach ($this->getDefinitions() as $plugin_id => $action_info) {
|
||||
if (in_array($route_name, $action_info['appears_on'])) {
|
||||
$plugin = $this->createInstance($plugin_id);
|
||||
$this->instances[$route_name][$plugin_id] = $plugin;
|
||||
}
|
||||
$this->cacheBackend->set($this->cacheKey . ':' . $route_name, $route_actions, CacheBackendInterface::CACHE_PERMANENT, array('local_action'));
|
||||
}
|
||||
foreach ($route_actions as $plugin_id) {
|
||||
$this->instances[$route_name][$plugin_id] = $this->createInstance($plugin_id);
|
||||
}
|
||||
}
|
||||
return $this->instances[$route_name];
|
||||
|
|
|
@ -446,59 +446,37 @@ class User extends EntityNG implements UserInterface {
|
|||
'description' => t('The name of this user'),
|
||||
'type' => 'string_field',
|
||||
'settings' => array('default_value' => ''),
|
||||
'property_constraints' => array(
|
||||
// No Length contraint here because the UserName constraint also covers
|
||||
// that.
|
||||
'value' => array(
|
||||
'UserName' => array(),
|
||||
'UserNameUnique' => array(),
|
||||
),
|
||||
),
|
||||
);
|
||||
$properties['pass'] = array(
|
||||
'label' => t('Password'),
|
||||
'label' => t('Name'),
|
||||
'description' => t('The password of this user (hashed)'),
|
||||
'type' => 'string_field',
|
||||
);
|
||||
$properties['mail'] = array(
|
||||
'label' => t('E-mail'),
|
||||
'label' => t('Name'),
|
||||
'description' => t('The e-mail of this user'),
|
||||
'type' => 'email_field',
|
||||
'type' => 'string_field',
|
||||
'settings' => array('default_value' => ''),
|
||||
'property_constraints' => array(
|
||||
'value' => array('UserMailUnique' => array()),
|
||||
),
|
||||
);
|
||||
$properties['signature'] = array(
|
||||
'label' => t('Signature'),
|
||||
'label' => t('Name'),
|
||||
'description' => t('The signature of this user'),
|
||||
'type' => 'string_field',
|
||||
'property_constraints' => array(
|
||||
'value' => array('Length' => array('max' => 255)),
|
||||
),
|
||||
);
|
||||
$properties['signature_format'] = array(
|
||||
'label' => t('Signature format'),
|
||||
'label' => t('Name'),
|
||||
'description' => t('The signature format of this user'),
|
||||
// @todo Convert the type to filter_format once
|
||||
// https://drupal.org/node/1758622 is comitted
|
||||
'type' => 'string_field',
|
||||
);
|
||||
$properties['theme'] = array(
|
||||
'label' => t('Theme'),
|
||||
'description' => t('The default theme of this user'),
|
||||
'type' => 'string_field',
|
||||
'property_constraints' => array(
|
||||
'value' => array('Length' => array('max' => DRUPAL_EXTENSION_NAME_MAX_LENGTH)),
|
||||
),
|
||||
);
|
||||
$properties['timezone'] = array(
|
||||
'label' => t('Timezone'),
|
||||
'description' => t('The timezone of this user'),
|
||||
'type' => 'string_field',
|
||||
'property_constraints' => array(
|
||||
'value' => array('Length' => array('max' => 32)),
|
||||
),
|
||||
);
|
||||
$properties['status'] = array(
|
||||
'label' => t('User status'),
|
||||
|
@ -526,14 +504,12 @@ class User extends EntityNG implements UserInterface {
|
|||
$properties['init'] = array(
|
||||
'label' => t('Init'),
|
||||
'description' => t('The email address used for initial account creation.'),
|
||||
'type' => 'email_field',
|
||||
'type' => 'string_field',
|
||||
'settings' => array('default_value' => ''),
|
||||
);
|
||||
$properties['roles'] = array(
|
||||
'label' => t('Roles'),
|
||||
'description' => t('The roles the user has.'),
|
||||
// @todo Convert this to entity_reference_field, see
|
||||
// https://drupal.org/node/2044859
|
||||
'type' => 'string_field',
|
||||
);
|
||||
return $properties;
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\user\Plugin\Validation\Constraint\UserMailUnique.
|
||||
*/
|
||||
|
||||
namespace Drupal\user\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a user's e-mail address is unique on the site.
|
||||
*
|
||||
* @Plugin(
|
||||
* id = "UserMailUnique",
|
||||
* label = @Translation("User e-mail unique", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class UserMailUnique extends Constraint {
|
||||
|
||||
public $message = 'The e-mail address %value is already taken.';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validatedBy() {
|
||||
return '\Drupal\user\Plugin\Validation\Constraint\UserUniqueValidator';
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\user\Plugin\Validation\Constraint\UserNameConstraint.
|
||||
*/
|
||||
|
||||
namespace Drupal\user\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a value is a valid user name.
|
||||
*
|
||||
* @Plugin(
|
||||
* id = "UserName",
|
||||
* label = @Translation("User name", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class UserNameConstraint extends Constraint {
|
||||
|
||||
public $emptyMessage = 'You must enter a username.';
|
||||
public $spaceBeginMessage = 'The username cannot begin with a space.';
|
||||
public $spaceEndMessage = 'The username cannot end with a space.';
|
||||
public $multipleSpacesMessage = 'The username cannot contain multiple spaces in a row.';
|
||||
public $illegalMessage = 'The username contains an illegal character.';
|
||||
public $tooLongMessage = 'The username %name is too long: it must be %max characters or less.';
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\user\Plugin\Validation\Constraint\UserNameConstraintValidator.
|
||||
*/
|
||||
|
||||
namespace Drupal\user\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
/**
|
||||
* Validates the UserName constraint.
|
||||
*/
|
||||
class UserNameConstraintValidator extends ConstraintValidator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate($name, Constraint $constraint) {
|
||||
if (!$name) {
|
||||
$this->context->addViolation($constraint->emptyMessage);
|
||||
return;
|
||||
}
|
||||
if (substr($name, 0, 1) == ' ') {
|
||||
$this->context->addViolation($constraint->spaceBeginMessage);
|
||||
}
|
||||
if (substr($name, -1) == ' ') {
|
||||
$this->context->addViolation($constraint->spaceEndMessage);
|
||||
}
|
||||
if (strpos($name, ' ') !== FALSE) {
|
||||
$this->context->addViolation($constraint->multipleSpacesMessage);
|
||||
}
|
||||
if (preg_match('/[^\x{80}-\x{F7} a-z0-9@_.\'-]/i', $name)
|
||||
|| preg_match(
|
||||
'/[\x{80}-\x{A0}' . // Non-printable ISO-8859-1 + NBSP
|
||||
'\x{AD}' . // Soft-hyphen
|
||||
'\x{2000}-\x{200F}' . // Various space characters
|
||||
'\x{2028}-\x{202F}' . // Bidirectional text overrides
|
||||
'\x{205F}-\x{206F}' . // Various text hinting characters
|
||||
'\x{FEFF}' . // Byte order mark
|
||||
'\x{FF01}-\x{FF60}' . // Full-width latin
|
||||
'\x{FFF9}-\x{FFFD}' . // Replacement characters
|
||||
'\x{0}-\x{1F}]/u', // NULL byte and control characters
|
||||
$name)
|
||||
) {
|
||||
$this->context->addViolation($constraint->illegalMessage);
|
||||
}
|
||||
if (drupal_strlen($name) > USERNAME_MAX_LENGTH) {
|
||||
$this->context->addViolation($constraint->tooLongMessage, array('%name' => $name, '%max' => USERNAME_MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\user\Plugin\Validation\Constraint\UserNameUnique.
|
||||
*/
|
||||
|
||||
namespace Drupal\user\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Drupal\Component\Annotation\Plugin;
|
||||
use Drupal\Core\Annotation\Translation;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a user name is unique on the site.
|
||||
*
|
||||
* @Plugin(
|
||||
* id = "UserNameUnique",
|
||||
* label = @Translation("User name unique", context = "Validation")
|
||||
* )
|
||||
*/
|
||||
class UserNameUnique extends Constraint {
|
||||
|
||||
public $message = 'The name %value is already taken.';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validatedBy() {
|
||||
return '\Drupal\user\Plugin\Validation\Constraint\UserUniqueValidator';
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\user\Plugin\Validation\Constraint\UserUniqueValidator.
|
||||
*/
|
||||
|
||||
namespace Drupal\user\Plugin\Validation\Constraint;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
/**
|
||||
* Validates the unique user property constraint, such as name and e-mail.
|
||||
*/
|
||||
class UserUniqueValidator extends ConstraintValidator {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate($value, Constraint $constraint) {
|
||||
$field = $this->context->getMetadata()->getTypedData()->getParent();
|
||||
$uid = $field->getParent()->id();
|
||||
|
||||
$value_taken = (bool) db_select('users')
|
||||
->fields('users', array('uid'))
|
||||
// The UID could be NULL, so we cast it to 0 in that case.
|
||||
->condition('uid', (int) $uid, '<>')
|
||||
->condition($field->getName(), db_like($value), 'LIKE')
|
||||
->range(0, 1)
|
||||
->execute()
|
||||
->fetchField();
|
||||
|
||||
if ($value_taken) {
|
||||
$this->context->addViolation($constraint->message, array("%value" => $value));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,41 +7,18 @@
|
|||
|
||||
namespace Drupal\user\Tests;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\simpletest\DrupalUnitTestBase;
|
||||
|
||||
/**
|
||||
* Performs validation tests on user fields.
|
||||
*/
|
||||
class UserValidationTest extends DrupalUnitTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('field', 'user', 'system');
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class UserValidationTest extends WebTestBase {
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'User validation',
|
||||
'description' => 'Verify that user validity checks behave as designed.',
|
||||
'name' => 'Username/e-mail validation',
|
||||
'description' => 'Verify that username/email validity checks behave as designed.',
|
||||
'group' => 'User'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('user', array('users'));
|
||||
$this->installSchema('system', array('sequences'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests user name validation.
|
||||
*/
|
||||
// Username validation.
|
||||
function testUsernames() {
|
||||
$test_cases = array( // '<username>' => array('<description>', 'assert<testName>'),
|
||||
'foo' => array('Valid username', 'assertNull'),
|
||||
|
@ -67,96 +44,4 @@ class UserValidationTest extends DrupalUnitTestBase {
|
|||
$this->$test($result, $description . ' (' . $name . ')');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs entity validation checks.
|
||||
*/
|
||||
function testValidation() {
|
||||
$user = entity_create('user', array('name' => 'test'));
|
||||
$violations = $user->validate();
|
||||
$this->assertEqual(count($violations), 0, 'No violations when validating a default user.');
|
||||
|
||||
// Only test one example invalid name here, the rest is already covered in
|
||||
// the testUsernames() method in this class.
|
||||
$name = $this->randomName(61);
|
||||
$user->set('name', $name);
|
||||
$violations = $user->validate();
|
||||
$this->assertEqual(count($violations), 1, 'Violation found when name is too long.');
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), 'name.0.value');
|
||||
$this->assertEqual($violations[0]->getMessage(), t('The username %name is too long: it must be %max characters or less.', array('%name' => $name, '%max' => 60)));
|
||||
|
||||
// Create a second test user to provoke a name collision.
|
||||
$user2 = entity_create('user', array(
|
||||
'name' => 'existing',
|
||||
'mail' => 'existing@exmaple.com',
|
||||
));
|
||||
$user2->save();
|
||||
$user->set('name', 'existing');
|
||||
$violations = $user->validate();
|
||||
$this->assertEqual(count($violations), 1, 'Violation found on name collision.');
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), 'name.0.value');
|
||||
$this->assertEqual($violations[0]->getMessage(), t('The name %name is already taken.', array('%name' => 'existing')));
|
||||
|
||||
// Make the name valid.
|
||||
$user->set('name', $this->randomName());
|
||||
|
||||
$user->set('mail', 'invalid');
|
||||
$violations = $user->validate();
|
||||
$this->assertEqual(count($violations), 1, 'Violation found when email is invalid');
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), 'mail.0.value');
|
||||
$this->assertEqual($violations[0]->getMessage(), t('This value is not a valid email address.'));
|
||||
|
||||
$mail = $this->randomName(EMAIL_MAX_LENGTH - 11) . '@example.com';
|
||||
$user->set('mail', $mail);
|
||||
$violations = $user->validate();
|
||||
$this->assertEqual(count($violations), 1, 'Violation found when email is too long');
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), 'mail.0.value');
|
||||
$this->assertEqual($violations[0]->getMessage(), t('This value is not a valid email address.'));
|
||||
|
||||
// Provoke a e-mail collision with an exsiting user.
|
||||
$user->set('mail', 'existing@exmaple.com');
|
||||
$violations = $user->validate();
|
||||
$this->assertEqual(count($violations), 1, 'Violation found when e-mail already exists.');
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), 'mail.0.value');
|
||||
$this->assertEqual($violations[0]->getMessage(), t('The e-mail address %mail is already taken.', array('%mail' => 'existing@exmaple.com')));
|
||||
$user->set('mail', NULL);
|
||||
|
||||
$user->set('signature', $this->randomString(256));
|
||||
$this->assertLengthViolation($user, 'signature', 255);
|
||||
$user->set('signature', NULL);
|
||||
|
||||
$user->set('theme', $this->randomString(DRUPAL_EXTENSION_NAME_MAX_LENGTH + 1));
|
||||
$this->assertLengthViolation($user, 'theme', DRUPAL_EXTENSION_NAME_MAX_LENGTH);
|
||||
$user->set('theme', NULL);
|
||||
|
||||
$user->set('timezone', $this->randomString(33));
|
||||
$this->assertLengthViolation($user, 'timezone', 32);
|
||||
$user->set('timezone', NULL);
|
||||
|
||||
$user->set('init', 'invalid');
|
||||
$violations = $user->validate();
|
||||
$this->assertEqual(count($violations), 1, 'Violation found when init email is invalid');
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), 'init.0.value');
|
||||
$this->assertEqual($violations[0]->getMessage(), t('This value is not a valid email address.'));
|
||||
|
||||
// @todo Test user role validation once https://drupal.org/node/2015701 got
|
||||
// committed.
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a length violation exists for the given field.
|
||||
*
|
||||
* @param \Drupal\core\Entity\EntityInterface $entity
|
||||
* The entity object to validate.
|
||||
* @param string $field_name
|
||||
* The field that violates the maximum length.
|
||||
* @param int $length
|
||||
* Number of characters that was exceeded.
|
||||
*/
|
||||
protected function assertLengthViolation(EntityInterface $entity, $field_name, $length) {
|
||||
$violations = $entity->validate();
|
||||
$this->assertEqual(count($violations), 1, "Violation found when $field_name is too long.");
|
||||
$this->assertEqual($violations[0]->getPropertyPath(), "$field_name.0.value");
|
||||
$this->assertEqual($violations[0]->getMessage(), t('This value is too long. It should have %limit characters or less.', array('%limit' => $length)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ const USERNAME_MAX_LENGTH = 60;
|
|||
/**
|
||||
* Maximum length of user e-mail text field.
|
||||
*/
|
||||
const EMAIL_MAX_LENGTH = 255;
|
||||
const EMAIL_MAX_LENGTH = 254;
|
||||
|
||||
/**
|
||||
* Only administrators can create user accounts.
|
||||
|
@ -321,24 +321,37 @@ function user_load_by_name($name) {
|
|||
|
||||
/**
|
||||
* Verify the syntax of the given name.
|
||||
*
|
||||
* @param string $name
|
||||
* The user name to validate.
|
||||
*
|
||||
* @return string|null
|
||||
* A translated violation message if the name is invalid or NULL if the name
|
||||
* is valid.
|
||||
*
|
||||
*/
|
||||
function user_validate_name($name) {
|
||||
$data = \Drupal::typedData()->create(array(
|
||||
'type' => 'string',
|
||||
'constraints' => array('UserName' => array()),
|
||||
));
|
||||
$data->setValue($name);
|
||||
$violations = $data->validate();
|
||||
if (count($violations) > 0) {
|
||||
return $violations[0]->getMessage();
|
||||
if (!$name) {
|
||||
return t('You must enter a username.');
|
||||
}
|
||||
if (substr($name, 0, 1) == ' ') {
|
||||
return t('The username cannot begin with a space.');
|
||||
}
|
||||
if (substr($name, -1) == ' ') {
|
||||
return t('The username cannot end with a space.');
|
||||
}
|
||||
if (strpos($name, ' ') !== FALSE) {
|
||||
return t('The username cannot contain multiple spaces in a row.');
|
||||
}
|
||||
if (preg_match('/[^\x{80}-\x{F7} a-z0-9@_.\'-]/i', $name)) {
|
||||
return t('The username contains an illegal character.');
|
||||
}
|
||||
if (preg_match('/[\x{80}-\x{A0}' . // Non-printable ISO-8859-1 + NBSP
|
||||
'\x{AD}' . // Soft-hyphen
|
||||
'\x{2000}-\x{200F}' . // Various space characters
|
||||
'\x{2028}-\x{202F}' . // Bidirectional text overrides
|
||||
'\x{205F}-\x{206F}' . // Various text hinting characters
|
||||
'\x{FEFF}' . // Byte order mark
|
||||
'\x{FF01}-\x{FF60}' . // Full-width latin
|
||||
'\x{FFF9}-\x{FFFD}' . // Replacement characters
|
||||
'\x{0}-\x{1F}]/u', // NULL byte and control characters
|
||||
$name)) {
|
||||
return t('The username contains an illegal character.');
|
||||
}
|
||||
if (drupal_strlen($name) > USERNAME_MAX_LENGTH) {
|
||||
return t('The username %name is too long: it must be %max characters or less.', array('%name' => $name, '%max' => USERNAME_MAX_LENGTH));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,328 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Menu\LocalActionManagerTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Menu;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Menu\LocalActionInterface;
|
||||
use Drupal\Core\Menu\LocalActionManager;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Tests the local action manager.
|
||||
*
|
||||
* @see \Drupal\Core\Menu\LocalActionManager
|
||||
*/
|
||||
class LocalActionManagerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested manager.
|
||||
*
|
||||
* @var \Drupal\Core\Menu\LocalActionManager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* The mocked controller resolver.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteProviderInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $controllerResolver;
|
||||
|
||||
/**
|
||||
* The test request.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* The mocked route provider.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteProviderInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $routeProvider;
|
||||
|
||||
/**
|
||||
* The mocked plugin discovery.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteProviderInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $pluginDiscovery;
|
||||
|
||||
/**
|
||||
* The plugin factory used in the test.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteProviderInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* The cache backend used in the test.
|
||||
*
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $cacheBackend;
|
||||
|
||||
/**
|
||||
* The plugin IDs for route 'test_route'.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pluginsTestRoute = array(
|
||||
'test_plugin_1',
|
||||
'test_plugin_2',
|
||||
'test_plugin_3',
|
||||
);
|
||||
|
||||
/**
|
||||
* The plugin IDs for route 'test_route_2'.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pluginsTestRoute2 = array(
|
||||
'test_plugin_3',
|
||||
'test_plugin_4',
|
||||
);
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Local actions manager.',
|
||||
'description' => 'Tests local actions manager.',
|
||||
'group' => 'Menu',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->controllerResolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface');
|
||||
$this->request = new Request();
|
||||
$this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
|
||||
$this->pluginDiscovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
|
||||
$this->factory = $this->getMock('Drupal\Component\Plugin\Factory\FactoryInterface');
|
||||
$this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getActionsForRoute method without an empty cache.
|
||||
*/
|
||||
public function testGetActionsForRouteEmptyCache() {
|
||||
$this->cacheBackend->expects($this->at(0))
|
||||
->method('get')
|
||||
->with('local_action:en:test_route')
|
||||
->will($this->returnValue(FALSE));
|
||||
|
||||
$this->cacheBackend->expects($this->at(1))
|
||||
->method('get')
|
||||
->with('local_action:en')
|
||||
->will($this->returnValue(FALSE));
|
||||
|
||||
$definitions = $this->getTestPluginDefinitions();
|
||||
$this->cacheBackend->expects($this->at(2))
|
||||
->method('set')
|
||||
->with('local_action:en', $definitions);
|
||||
|
||||
$this->cacheBackend->expects($this->at(3))
|
||||
->method('set')
|
||||
->with('local_action:en:test_route', $this->pluginsTestRoute);
|
||||
|
||||
$mock_plugin = $this->getMock('Drupal\Core\Menu\LocalActionInterface');
|
||||
$this->setupPluginFactory($mock_plugin);
|
||||
$this->setupPluginDiscovery();
|
||||
$this->setupLocalActionManager();
|
||||
|
||||
$expected_actions = array();
|
||||
foreach ($this->pluginsTestRoute as $plugin_id) {
|
||||
$expected_actions[$plugin_id] = $mock_plugin;
|
||||
}
|
||||
|
||||
$this->assertEquals($expected_actions, $this->manager->getActionsForRoute('test_route'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getActionsForRoute method with a filled cache.
|
||||
*/
|
||||
public function testGetActionsForRouteFilledCache() {
|
||||
$definitions = $this->getTestPluginDefinitions();
|
||||
|
||||
// Ensures that a call with a setup cache does not result in a full
|
||||
// rescan of all the plugins.
|
||||
$this->cacheBackend->expects($this->at(0))
|
||||
->method('get')
|
||||
->with('local_action:en:test_route')
|
||||
->will($this->returnValue((object) array('data' => $this->pluginsTestRoute)));
|
||||
|
||||
$this->pluginDiscovery->expects($this->never())
|
||||
->method('getDefinitions')
|
||||
->will($this->returnValue($definitions));
|
||||
|
||||
$this->cacheBackend->expects($this->never())
|
||||
->method('set');
|
||||
|
||||
$mock_plugin = $this->getMock('Drupal\Core\Menu\LocalActionInterface');
|
||||
$this->setupPluginFactory($mock_plugin);
|
||||
$this->setupLocalActionManager();
|
||||
|
||||
$expected_actions = array();
|
||||
foreach ($this->pluginsTestRoute as $plugin_id) {
|
||||
$expected_actions[$plugin_id] = $mock_plugin;
|
||||
}
|
||||
|
||||
$this->assertEquals($expected_actions, $this->manager->getActionsForRoute('test_route'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getActionsForRoute method with a filled cache for both routes.
|
||||
*/
|
||||
public function testGetActionsForFullFilledRouteCache() {
|
||||
$definitions = $this->getTestPluginDefinitions();
|
||||
|
||||
// Ensures that a call with a setup cache does not result in a full
|
||||
// rescan of all the plugins.
|
||||
$this->cacheBackend->expects($this->at(0))
|
||||
->method('get')
|
||||
->with('local_action:en:test_route')
|
||||
->will($this->returnValue((object) array('data' => $this->pluginsTestRoute)));
|
||||
$this->cacheBackend->expects($this->at(1))
|
||||
->method('get')
|
||||
->with('local_action:en:test_route_2')
|
||||
->will($this->returnValue((object) array('data' => $this->pluginsTestRoute2)));
|
||||
|
||||
$this->cacheBackend->expects($this->exactly(2))
|
||||
->method('get');
|
||||
|
||||
$this->pluginDiscovery->expects($this->never())
|
||||
->method('getDefinitions')
|
||||
->will($this->returnValue($definitions));
|
||||
|
||||
$this->cacheBackend->expects($this->never())
|
||||
->method('set');
|
||||
|
||||
$mock_plugin = $this->getMock('Drupal\Core\Menu\LocalActionInterface');
|
||||
$this->setupPluginFactory($mock_plugin);
|
||||
$this->setupLocalActionManager();
|
||||
|
||||
$expected_actions = array();
|
||||
foreach ($this->pluginsTestRoute as $plugin_id) {
|
||||
$expected_actions[$plugin_id] = $mock_plugin;
|
||||
}
|
||||
$expected_actions_2 = array();
|
||||
foreach ($this->pluginsTestRoute2 as $plugin_id) {
|
||||
$expected_actions_2[$plugin_id] = $mock_plugin;
|
||||
}
|
||||
|
||||
$this->assertEquals($expected_actions, $this->manager->getActionsForRoute('test_route'));
|
||||
$this->assertEquals($expected_actions_2, $this->manager->getActionsForRoute('test_route_2'));
|
||||
$this->assertEquals($expected_actions, $this->manager->getActionsForRoute('test_route'));
|
||||
$this->assertEquals($expected_actions_2, $this->manager->getActionsForRoute('test_route_2'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the local actions manager.
|
||||
*/
|
||||
protected function setupLocalActionManager() {
|
||||
$this->manager = $this
|
||||
->getMockBuilder('Drupal\Core\Menu\LocalActionManager')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(NULL)
|
||||
->getMock();
|
||||
|
||||
$property = new \ReflectionProperty('Drupal\Core\Menu\LocalActionManager', 'controllerResolver');
|
||||
$property->setAccessible(TRUE);
|
||||
$property->setValue($this->manager, $this->controllerResolver);
|
||||
|
||||
$property = new \ReflectionProperty('Drupal\Core\Menu\LocalActionManager', 'request');
|
||||
$property->setAccessible(TRUE);
|
||||
$property->setValue($this->manager, $this->request);
|
||||
|
||||
$property = new \ReflectionProperty('Drupal\Core\Menu\LocalActionManager', 'discovery');
|
||||
$property->setAccessible(TRUE);
|
||||
$property->setValue($this->manager, $this->pluginDiscovery);
|
||||
|
||||
$property = new \ReflectionProperty('Drupal\Core\Menu\LocalActionManager', 'factory');
|
||||
$property->setAccessible(TRUE);
|
||||
$property->setValue($this->manager, $this->factory);
|
||||
|
||||
$language_manager = $this->getMockBuilder('Drupal\Core\Language\LanguageManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$language_manager->expects($this->any())
|
||||
->method('getLanguage')
|
||||
->will($this->returnValue(new Language(array('id' => 'en'))));
|
||||
|
||||
$this->manager->setCacheBackend($this->cacheBackend, $language_manager, 'local_action');
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the plugin discovery.
|
||||
*/
|
||||
protected function setupPluginDiscovery() {
|
||||
$definitions = $this->getTestPluginDefinitions();
|
||||
|
||||
$this->pluginDiscovery->expects($this->any())
|
||||
->method('getDefinitions')
|
||||
->will($this->returnValue($definitions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the plugin factory.
|
||||
*
|
||||
* @param \Drupal\Core\Menu\LocalActionInterface $mock_plugin
|
||||
* A mocked plugin instance.
|
||||
*/
|
||||
protected function setupPluginFactory(LocalActionInterface $mock_plugin) {
|
||||
$map = array(
|
||||
array('test_plugin_1', array(), $mock_plugin),
|
||||
array('test_plugin_2', array(), $mock_plugin),
|
||||
array('test_plugin_3', array(), $mock_plugin),
|
||||
array('test_plugin_4', array(), $mock_plugin),
|
||||
);
|
||||
$this->factory->expects($this->any())
|
||||
->method('createInstance')
|
||||
->will($this->returnValueMap($map));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns plugin definitions for the test.
|
||||
*
|
||||
* @return array
|
||||
* An array of local action plugin definition.
|
||||
*/
|
||||
protected function getTestPluginDefinitions() {
|
||||
$definitions = array();
|
||||
$definitions['test_plugin_1'] = array(
|
||||
'id' => 'test_plugin_1',
|
||||
'title' => 'Test plugin 1',
|
||||
'route_name' => 'test_route_1',
|
||||
'appears_on' => array('test_route'),
|
||||
);
|
||||
$definitions['test_plugin_2'] = array(
|
||||
'id' => 'test_plugin_2',
|
||||
'title' => 'Test plugin 2',
|
||||
'route_name' => 'test_route_2',
|
||||
'appears_on' => array('test_route'),
|
||||
);
|
||||
$definitions['test_plugin_3'] = array(
|
||||
'id' => 'test_plugin_3',
|
||||
'title' => 'Test plugin 3',
|
||||
'route_name' => 'test_route_3',
|
||||
'appears_on' => array('test_route', 'test_route_2'),
|
||||
);
|
||||
$definitions['test_plugin_4'] = array(
|
||||
'id' => 'test_plugin_4',
|
||||
'title' => 'Test plugin 4',
|
||||
'route_name' => 'test_route_4',
|
||||
'appears_on' => array('test_route_2'),
|
||||
);
|
||||
return $definitions;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue