Merge remote-tracking branch 'upstream/8.x' into kernel

8.0.x
Larry Garfield 2012-05-10 00:14:31 -05:00
commit 270dcd2e88
96 changed files with 934 additions and 730 deletions

View File

@ -598,7 +598,7 @@ function drupal_settings_initialize() {
global $base_url, $base_path, $base_root, $script_path;
// Export the following settings.php variables to the global namespace
global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directory_name, $config_signature_key;
global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directory_name;
$conf = array();
if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) {

View File

@ -71,7 +71,7 @@ function config_install_default_config($module) {
* @return
* An array of file names under a branch.
*/
function config_get_signed_file_storage_names_with_prefix($prefix = '') {
function config_get_files_with_prefix($prefix = '') {
$files = glob(config_get_config_directory() . '/' . $prefix . '*.xml');
$clean_name = function ($value) {
return basename($value, '.xml');
@ -79,23 +79,6 @@ function config_get_signed_file_storage_names_with_prefix($prefix = '') {
return array_map($clean_name, $files);
}
/**
* Generates a hash of a config file's contents using our encryption key.
*
* @param $data
* The contents of a configuration file.
*
* @return
* A hash of the data.
*/
function config_sign_data($data) {
// The configuration key is loaded from settings.php and imported into the global namespace
global $config_signature_key;
// SHA-512 is both secure and very fast on 64 bit CPUs.
return hash_hmac('sha512', $data, $config_signature_key);
}
/**
* @todo
*

View File

@ -3213,6 +3213,56 @@ function form_process_actions($element, &$form_state) {
return $element;
}
/**
* #process callback for #pattern form element property.
*
* @param $element
* An associative array containing the properties and children of the
* generic input element.
* @param $form_state
* The $form_state array for the form this element belongs to.
*
* @return
* The processed element.
*
* @see form_validate_pattern()
*/
function form_process_pattern($element, &$form_state) {
if (isset($element['#pattern']) && !isset($element['#attributes']['pattern'])) {
$element['#attributes']['pattern'] = $element['#pattern'];
$element['#element_validate'][] = 'form_validate_pattern';
}
return $element;
}
/**
* #element_validate callback for #pattern form element property.
*
* @param $element
* An associative array containing the properties and children of the
* generic form element.
* @param $form_state
* The $form_state array for the form this element belongs to.
*
* @see form_process_pattern()
*/
function form_validate_pattern($element, &$form_state) {
if ($element['#value'] !== '') {
// The pattern must match the entire string and should have the same
// behavior as the RegExp object in ECMA 262.
// - Use bracket-style delimiters to avoid introducing a special delimiter
// character like '/' that would have to be escaped.
// - Put in brackets so that the pattern can't interfere with what's
// prepended and appended.
$pattern = '{^(?:' . $element['#pattern'] . ')$}';
if (!preg_match($pattern, $element['#value'])) {
form_error($element, t('%name field is not in the right format.', array('%name' => $element['#title'])));
}
}
}
/**
* Processes a container element.
*
@ -3951,8 +4001,8 @@ function theme_tel($variables) {
* @param $variables
* An associative array containing:
* - element: An associative array containing the properties of the element.
* Properties used: #title, #value, #description, #size, #min, #max,
* #placeholder, #required, #attributes, #step.
* Properties used: #title, #value, #description, #min, #max, #placeholder,
* #required, #attributes, #step.
*
* @ingroup themeable
*/
@ -3960,7 +4010,7 @@ function theme_number($variables) {
$element = $variables['element'];
$element['#attributes']['type'] = 'number';
element_set_attributes($element, array('id', 'name', 'value', 'size', 'step', 'min', 'max', 'maxlength', 'placeholder'));
element_set_attributes($element, array('id', 'name', 'value', 'step', 'min', 'max', 'placeholder'));
_form_set_class($element, array('form-number'));
$output = '<input' . drupal_attributes($element['#attributes']) . ' />';
@ -3974,8 +4024,8 @@ function theme_number($variables) {
* @param $variables
* An associative array containing:
* - element: An associative array containing the properties of the element.
* Properties used: #title, #value, #description, #size, #min, #max,
* #required, #attributes, #step.
* Properties used: #title, #value, #description, #min, #max, #attributes,
* #step.
*
* @ingroup themeable
*/
@ -4031,6 +4081,36 @@ function form_validate_number(&$element, &$form_state) {
}
}
/**
* Determines the value for a range element.
*
* Make sure range elements always have a value. The 'required' attribute is not
* allowed for range elements.
*
* @param $element
* The form element whose value is being populated.
* @param $input
* The incoming input to populate the form element. If this is FALSE, the
* element's default value should be returned.
*
* @return
* The data that will appear in the $form_state['values'] collection for
* this element. Return nothing to use the default.
*/
function form_type_range_value($element, $input = FALSE) {
if ($input === '') {
$offset = ($element['#max'] - $element['#min']) / 2;
// Round to the step.
if (strtolower($element['#step']) != 'any') {
$steps = round($offset / $element['#step']);
$offset = $element['#step'] * $steps;
}
return $element['#min'] + $offset;
}
}
/**
* Returns HTML for a url form element.
*

View File

@ -1022,11 +1022,6 @@ function install_settings_form_submit($form, &$form_state) {
'required' => TRUE,
);
$settings['config_signature_key'] = array(
'value' => drupal_hash_base64(drupal_random_bytes(55)),
'required' => TRUE,
);
// This duplicates drupal_get_token() because that function can't work yet.
// Wondering if it makes sense to move this later in the process, but its
// nice having all the settings stuff here.
@ -1036,7 +1031,7 @@ function install_settings_form_submit($form, &$form_state) {
// already has the db stuff in it, and right now in that case your
// config directory never gets created. So this needs to be moved elsewhere.
$settings['config_directory_name'] = array(
'value' => 'config_' . drupal_hmac_base64('', session_id() . $settings['config_signature_key']['value'] . $settings['drupal_hash_salt']['value']),
'value' => 'config_' . drupal_hmac_base64('', session_id() . $settings['drupal_hash_salt']['value']),
'required' => TRUE,
);

View File

@ -1,7 +1,7 @@
<?php
use Drupal\Core\Database\Database;
use Drupal\Core\Config\SignedFileStorage;
use Drupal\Core\Config\FileStorage;
/**
* Indicates that a module has not been installed yet.
@ -403,9 +403,9 @@ function drupal_uninstall_modules($module_list = array(), $uninstall_dependents
$parts = explode('/', $file);
$file = array_pop($parts);
$config_name = str_replace('.xml', '', $file);
$signed_storage = new SignedFileStorage($config_name);
$file_storage = new FileStorage($config_name);
// Delete the configuration from storage.
$signed_storage->delete();
$file_storage->delete();
}
}

View File

@ -1,10 +0,0 @@
<?php
namespace Drupal\Core\Config;
use Drupal\Core\Config\ConfigFileStorageException;
/**
* @todo
*/
class ConfigFileStorageSignatureException extends ConfigFileStorageException {}

View File

@ -3,7 +3,7 @@
namespace Drupal\Core\Config;
use Drupal\Core\Config\DrupalConfigVerifiedStorageInterface;
use Drupal\Core\Config\SignedFileStorage;
use Drupal\Core\Config\FileStorage;
/**
* @todo
@ -13,11 +13,11 @@ abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorag
protected $name;
/**
* The local signed file object to read from and write to.
* The local file object to read from and write to.
*
* @var SignedFileStorage
* @var Drupal\Core\Config\FileStorage
*/
protected $signedFile;
protected $fileStorage;
/**
* Implements DrupalConfigVerifiedStorageInterface::__construct().
@ -27,16 +27,16 @@ abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorag
}
/**
* Instantiates a new signed file object or returns the existing one.
* Instantiates a new file storage object or returns the existing one.
*
* @return SignedFileStorage
* The signed file object for this configuration object.
* @return Drupal\Core\Config\FileStorage
* The file object for this configuration object.
*/
protected function signedFileStorage() {
if (!isset($this->signedFile)) {
$this->signedFile = new SignedFileStorage($this->name);
protected function fileStorage() {
if (!isset($this->fileStorage)) {
$this->fileStorage = new FileStorage($this->name);
}
return $this->signedFile;
return $this->fileStorage;
}
/**
@ -50,7 +50,7 @@ abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorag
* Implements DrupalConfigVerifiedStorageInterface::deleteFile().
*/
public function deleteFile() {
return $this->signedFileStorage()->delete();
return $this->fileStorage()->delete();
}
/**
@ -67,7 +67,7 @@ abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorag
* @todo
*/
public function readFromFile() {
return $this->signedFileStorage()->read($this->name);
return $this->fileStorage()->read($this->name);
}
/**
@ -89,7 +89,7 @@ abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorag
* Implements DrupalConfigVerifiedStorageInterface::writeToFile().
*/
public function writeToFile($data) {
return $this->signedFileStorage()->write($data);
return $this->fileStorage()->write($data);
}
/**

View File

@ -6,7 +6,7 @@ namespace Drupal\Core\Config;
* Defines an interface for verified storage manipulation.
*
* This class allows reading and writing configuration data from/to the
* verified storage and copying to/from the signed file storing the same data.
* verified storage and copying to/from the file storing the same data.
*/
interface DrupalConfigVerifiedStorageInterface {

View File

@ -0,0 +1,96 @@
<?php
namespace Drupal\Core\Config;
/**
* Represents the file storage interface.
*
* Classes implementing this interface allow reading and writing configuration
* data to and from disk.
*/
class FileStorage {
/**
* Constructs a FileStorage object.
*
* @param string $name
* The name for the configuration data. Should be lowercase.
*/
public function __construct($name) {
$this->name = $name;
}
/**
* Reads and returns a file.
*
* @return
* The data of the file.
*
* @throws
* Exception
*/
protected function readData() {
$data = file_get_contents($this->getFilePath());
if ($data === FALSE) {
throw new \Exception('Read file is invalid.');
}
return $data;
}
/**
* Checks whether the XML configuration file already exists on disk.
*
* @return
* @todo
*/
protected function exists() {
return file_exists($this->getFilePath());
}
/**
* Returns the path to the XML configuration file.
*
* @return
* @todo
*/
public function getFilePath() {
return config_get_config_directory() . '/' . $this->name . '.xml';
}
/**
* Writes the contents of the configuration file to disk.
*
* @param $data
* The data to be written to the file.
*
* @throws
* Exception
*/
public function write($data) {
if (!file_put_contents($this->getFilePath(), $data)) {
throw new \Exception('Failed to write configuration file: ' . $this->getFilePath());
}
}
/**
* Returns the contents of the configuration file.
*
* @return
* @todo
*/
public function read() {
if ($this->exists()) {
$data = $this->readData();
return $data;
}
return FALSE;
}
/**
* Deletes a configuration file.
*/
public function delete() {
// Needs error handling and etc.
@drupal_unlink($this->getFilePath());
}
}

View File

@ -1,143 +0,0 @@
<?php
namespace Drupal\Core\Config;
/**
* Represents the signed file storage interface.
*
* Classes implementing this interface allow reading and writing configuration
* data to and from disk, while automatically managing and verifying
* cryptographic signatures.
*/
class SignedFileStorage {
/**
* Constructs a SignedFileStorage object.
*
* @param string $name
* The name for the configuration data. Should be lowercase.
*/
public function __construct($name) {
$this->name = $name;
}
/**
* Reads and returns a signed file and its signature.
*
* @return
* An array with "signature" and "data" keys.
*
* @throws
* Exception
*/
protected function readWithSignature() {
$content = file_get_contents($this->getFilePath());
if ($content === FALSE) {
throw new \Exception('Read file is invalid.');
}
$signature = file_get_contents($this->getFilePath() . '.sig');
if ($signature === FALSE) {
throw new \Exception('Signature file is invalid.');
}
return array('data' => $content, 'signature' => $signature);
}
/**
* Checks whether the XML configuration file already exists on disk.
*
* @return
* @todo
*/
protected function exists() {
return file_exists($this->getFilePath());
}
/**
* Returns the path to the XML configuration file.
*
* @return
* @todo
*/
public function getFilePath() {
return config_get_config_directory() . '/' . $this->name . '.xml';
}
/**
* Recreates the signature for the file.
*/
public function resign() {
if ($this->exists()) {
$parts = $this->readWithSignature();
$this->write($parts['data']);
}
}
/**
* Cryptographically verifies the integrity of the configuration file.
*
* @param $contentOnSuccess
* Whether or not to return the contents of the verified configuration file.
*
* @return mixed
* If $contentOnSuccess was TRUE, returns the contents of the verified
* configuration file; otherwise returns TRUE on success. Always returns
* FALSE if the configuration file was not successfully verified.
*/
public function verify($contentOnSuccess = FALSE) {
if ($this->exists()) {
$split = $this->readWithSignature();
$expected_signature = config_sign_data($split['data']);
if ($expected_signature === $split['signature']) {
if ($contentOnSuccess) {
return $split['data'];
}
return TRUE;
}
}
return FALSE;
}
/**
* Writes the contents of the configuration file to disk.
*
* @param $data
* The data to be written to the file.
*
* @throws
* Exception
*/
public function write($data) {
$signature = config_sign_data($data);
if (!file_put_contents($this->getFilePath(), $data)) {
throw new \Exception('Failed to write configuration file: ' . $this->getFilePath());
}
if (!file_put_contents($this->getFilePath() . '.sig', $signature)) {
throw new \Exception('Failed to write signature file: ' . $this->getFilePath());
}
}
/**
* Returns the contents of the configuration file.
*
* @return
* @todo
*/
public function read() {
if ($this->exists()) {
$verification = $this->verify(TRUE);
if ($verification === FALSE) {
throw new \Exception('Invalid signature in file header.');
}
return $verification;
}
}
/**
* Deletes a configuration file.
*/
public function delete() {
// Needs error handling and etc.
@drupal_unlink($this->getFilePath());
@drupal_unlink($this->getFilePath() . '.sig');
}
}

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Provides Ajax page updating via jQuery $.ajax (Asynchronous JavaScript and XML).
*

View File

@ -1,4 +1,3 @@
/**
* @file
* Conditionally hide or show the appropriate settings and saved defaults
@ -7,6 +6,8 @@
(function ($) {
"use strict";
Drupal.behaviors.authorizeFileTransferForm = {
attach: function(context) {
$('#edit-connection-settings-authorize-filetransfer-default').change(function() {

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Attaches the autocomplete behavior to all required fields.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Attaches the batch behavior to progress bars.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Toggle the visibility of a fieldset using smooth animations.
*/

View File

@ -5,6 +5,8 @@ jQuery.noConflict();
(function ($) {
"use strict";
/**
* Attach all registered behaviors to a page element.
*

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Retrieves the summary for the first element.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Attach the machine-readable name form element behavior.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* A progressbar object. Initialized with the given id. Must be inserted into
* the DOM afterwards through progressBar.element.

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* The base States namespace.
*

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Drag and drop table rows with field manipulation.
*

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Attaches sticky table headers.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
Drupal.behaviors.tableSelect = {
attach: function (context, settings) {
// Select the inner-most table in case of nested tables.

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Set the client's system time zone as default values of form fields.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* This script transforms a set of fieldsets into a stack of vertical
* tabs. Another tab pane can be selected by clicking on the respective

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Provide the summary information for the block settings vertical tabs.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
Drupal.behaviors.bookFieldsetSummaries = {
attach: function (context) {
$(context).find('fieldset.book-outline-form').drupalSetSummary(function (context) {

View File

@ -102,7 +102,7 @@ function book_node_view_link(Node $node, $view_mode) {
if ((user_access('add content to books') || user_access('administer book outlines')) && node_access('create', $child_type) && $node->status == 1 && $node->book['depth'] < MENU_MAX_DEPTH) {
$links['book_add_child'] = array(
'title' => t('Add child page'),
'href' => 'node/add/' . str_replace('_', '-', $child_type),
'href' => 'node/add/' . $child_type,
'query' => array('parent' => $node->book['mlid']),
);
}

View File

@ -5,6 +5,8 @@
(function ($) {
"use strict";
Drupal.behaviors.color = {
attach: function (context, settings) {
var i, j, colors, field_name;

View File

@ -4,6 +4,9 @@
*/
(function ($) {
"use strict";
Drupal.color = {
callback: function(context, settings, form, farb, height, width) {
// Solid background.

View File

@ -5,6 +5,8 @@
(function ($) {
"use strict";
Drupal.behaviors.commentFieldsetSummaries = {
attach: function (context) {
var $context = $(context);

View File

@ -135,7 +135,7 @@ function comment_entity_info() {
// See comment_node_type_load() and comment_menu_alter().
'path' => 'admin/structure/types/manage/%comment_node_type/comment',
'bundle argument' => 4,
'real path' => 'admin/structure/types/manage/' . str_replace('_', '-', $type) . '/comment',
'real path' => 'admin/structure/types/manage/' . $type . '/comment',
'access arguments' => array('administer content types'),
),
);
@ -150,9 +150,7 @@ function comment_entity_info() {
* This function is used as a menu loader callback in comment_menu().
*
* @param $name
* The URL-formatted machine name of the node type whose comment fields are
* to be edited. 'URL-formatted' means that underscores are replaced by
* hyphens.
* The machine name of the node type whose comment fields are to be edited.
*
* @return
* The comment bundle name corresponding to the node type.
@ -160,7 +158,7 @@ function comment_entity_info() {
* @see comment_menu_alter()
*/
function comment_node_type_load($name) {
if ($type = node_type_get_type(strtr($name, array('-' => '_')))) {
if ($type = node_type_load($name)) {
return 'comment_node_' . $type->type;
}
}

View File

@ -5,14 +5,12 @@
* Tests for the Configuration module.
*/
use Drupal\Core\Config\SignedFileStorage;
use Drupal\Core\Config\FileStorage;
/**
* Tests the secure file writer.
*/
class ConfigFileSecurityTestCase extends DrupalWebTestCase {
protected $profile = 'testing';
protected $filename = 'foo.bar';
protected $testContent = 'Good morning, Denver!';
@ -25,27 +23,11 @@ class ConfigFileSecurityTestCase extends DrupalWebTestCase {
);
}
/**
* Tests that a file written by this system has a valid signature.
*/
function testFileVerify() {
$file = new SignedFileStorage($this->filename);
$file->write($this->testContent);
$this->assertTrue($file->verify(), 'A file verifies after being written.');
unset($file);
// Load the file again, so that there is no stale data from the old object.
$file = new SignedFileStorage($this->filename);
$this->assertTrue($file->verify(), 'A file verifies after being written and reloaded.');
}
/**
* Tests that a file written by this system can be successfully read back.
*/
function testFilePersist() {
$file = new SignedFileStorage($this->filename);
$file = new FileStorage($this->filename);
$file->write($this->testContent);
unset($file);
@ -54,7 +36,7 @@ class ConfigFileSecurityTestCase extends DrupalWebTestCase {
// Note that if any other exception is thrown, we let the test system
// handle catching and reporting it.
try {
$file = new SignedFileStorage($this->filename);
$file = new FileStorage($this->filename);
$saved_content = $file->read();
$this->assertEqual($saved_content, $this->testContent, 'A file can be read back successfully.');
@ -63,35 +45,12 @@ class ConfigFileSecurityTestCase extends DrupalWebTestCase {
$this->fail('File failed verification when being read.');
}
}
/**
* Tests that a file fails validation if it's been monkeyed with.
*/
function testFileNotVerify() {
$file = new SignedFileStorage($this->filename);
$file->write($this->testContent);
// Manually overwrite the body of the secure file. Note that we skip the
// first line, which is reserved for the signature and such, to overwrite
// just the payload.
$raw_file = new SplFileObject($file->getFilePath(), 'a+');
$raw_file->fwrite('Good morning, Detroit!');
$raw_file->fflush();
unset($raw_file);
unset($file);
$file = new SignedFileStorage($this->filename);
$this->assertFalse($file->verify(), 'Corrupted file does not verify.');
}
}
/**
* Tests reading and writing file contents.
*/
class ConfigFileContentTestCase extends DrupalWebTestCase {
protected $profile = 'testing';
protected $fileExtension = 'xml';
public static function getInfo() {
@ -238,22 +197,22 @@ class ConfigFileContentTestCase extends DrupalWebTestCase {
// Get file listing for all files starting with 'foo'. Should return
// two elements.
$files = config_get_signed_file_storage_names_with_prefix('foo');
$files = config_get_files_with_prefix('foo');
$this->assertEqual(count($files), 2, 'Two files listed with the prefix \'foo\'.');
// Get file listing for all files starting with 'biff'. Should return
// one element.
$files = config_get_signed_file_storage_names_with_prefix('biff');
$files = config_get_files_with_prefix('biff');
$this->assertEqual(count($files), 1, 'One file listed with the prefix \'biff\'.');
// Get file listing for all files starting with 'foo.bar'. Should return
// one element.
$files = config_get_signed_file_storage_names_with_prefix('foo.bar');
$files = config_get_files_with_prefix('foo.bar');
$this->assertEqual(count($files), 1, 'One file listed with the prefix \'foo.bar\'.');
// Get file listing for all files starting with 'bar'. Should return
// an empty array.
$files = config_get_signed_file_storage_names_with_prefix('bar');
$files = config_get_files_with_prefix('bar');
$this->assertEqual($files, array(), 'No files listed with the prefix \'bar\'.');
// Delete the configuration.

View File

@ -5,6 +5,8 @@
(function ($) {
"use strict";
Drupal.contextualLinks = Drupal.contextualLinks || {};
/**

View File

@ -5,6 +5,8 @@
(function ($) {
"use strict";
/**
* Implements Drupal.behaviors for the Dashboard module.
*/

View File

@ -186,7 +186,7 @@ function hook_entity_info() {
'label' => $name,
'admin' => array(
'path' => 'admin/structure/types/manage/%node_type',
'real path' => 'admin/structure/types/manage/' . str_replace('_', '-', $type),
'real path' => 'admin/structure/types/manage/' . $type,
'bundle argument' => 4,
'access arguments' => array('administer content types'),
),

View File

@ -222,8 +222,6 @@ class ListFieldUITestCase extends FieldTestCase {
$type_name = 'test_' . strtolower($this->randomName());
$type = $this->drupalCreateContentType(array('name' => $type_name, 'type' => $type_name));
$this->type = $type->type;
// Store a valid URL name, with hyphens instead of underscores.
$this->hyphen_type = str_replace('_', '-', $this->type);
}
/**
@ -429,7 +427,7 @@ class ListFieldUITestCase extends FieldTestCase {
);
field_create_instance($instance);
$this->admin_path = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields/' . $this->field_name;
$this->admin_path = 'admin/structure/types/manage/' . $this->type . '/fields/' . $this->field_name;
}
/**

View File

@ -324,11 +324,6 @@ function number_field_widget_form(&$form, &$form_state, $field, $instance, $lang
$element += array(
'#type' => 'number',
'#default_value' => $value,
// Allow a slightly larger size that the field length to allow for some
// configurations where all characters won't fit in input field.
'#size' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] + 4 : 12,
// Allow two extra characters for signed values and decimal separator.
'#maxlength' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] + 2 : 10,
);
// Set the step for floating point and decimal numbers.

View File

@ -56,7 +56,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
field_create_instance($this->instance);
// Display creation form.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$langcode = LANGUAGE_NOT_SPECIFIED;
$this->assertFieldByName("{$this->field['field_name']}[$langcode][0][value]", '', t('Widget is displayed'));
@ -81,7 +81,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
);
foreach ($wrong_entries as $wrong_entry) {
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$edit = array(
"{$this->field['field_name']}[$langcode][0][value]" => $wrong_entry,
);
@ -99,7 +99,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
);
foreach ($wrong_entries as $wrong_entry) {
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$edit = array(
"{$this->field['field_name']}[$langcode][0][value]" => $wrong_entry,
);

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Auto-hide summary textarea if empty and show hide and unhide links.
*/

View File

@ -225,7 +225,6 @@ function text_field_formatter_settings_form($field, $instance, $view_mode, $form
$element['trim_length'] = array(
'#title' => t('Trim length'),
'#type' => 'number',
'#size' => 10,
'#default_value' => $settings['trim_length'],
'#min' => 1,
'#required' => TRUE,

View File

@ -111,7 +111,7 @@ class TextFieldTestCase extends DrupalWebTestCase {
$langcode = LANGUAGE_NOT_SPECIFIED;
// Display creation form.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed'));
$this->assertNoFieldByName("{$this->field_name}[$langcode][0][format]", '1', t('Format selector is not displayed'));
@ -180,7 +180,7 @@ class TextFieldTestCase extends DrupalWebTestCase {
// Display the creation form. Since the user only has access to one format,
// no format selector will be displayed.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed'));
$this->assertNoFieldByName("{$this->field_name}[$langcode][0][format]", '', t('Format selector is not displayed'));

View File

@ -1326,7 +1326,7 @@ class FieldFormTestCase extends FieldTestCase {
$langcode = LANGUAGE_NOT_SPECIFIED;
// Display creation form.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', 'Widget is displayed');
$this->assertNoField("{$this->field_name}[$langcode][1][value]", 'No extraneous widget is displayed');
// TODO : check that the widget is populated with default value ?
@ -1381,7 +1381,7 @@ class FieldFormTestCase extends FieldTestCase {
// Submit with missing required value.
$edit = array();
$this->drupalPost('test-entity/add/test-bundle', $edit, t('Save'));
$this->drupalPost('test-entity/add/test_bundle', $edit, t('Save'));
$this->assertRaw(t('!name field is required.', array('!name' => $this->instance['label'])), 'Required field with no value fails validation');
// Create an entity
@ -1418,7 +1418,7 @@ class FieldFormTestCase extends FieldTestCase {
$langcode = LANGUAGE_NOT_SPECIFIED;
// Display creation form -> 1 widget.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', 'Widget 1 is displayed');
$this->assertNoField("{$this->field_name}[$langcode][1][value]", 'No extraneous widget is displayed');
@ -1516,7 +1516,7 @@ class FieldFormTestCase extends FieldTestCase {
));
// Display creation form.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
// Press the 'Add more' button.
$this->drupalPost(NULL, array(), t('Add another item'));
@ -1539,7 +1539,7 @@ class FieldFormTestCase extends FieldTestCase {
$langcode = LANGUAGE_NOT_SPECIFIED;
// Display creation form -> 1 widget.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
// Press 'add more' button a couple times -> 3 widgets.
// drupalPostAJAX() will not work iteratively, so we add those through
@ -1599,7 +1599,7 @@ class FieldFormTestCase extends FieldTestCase {
$langcode = LANGUAGE_NOT_SPECIFIED;
// Display creation form.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertFieldByName("{$this->field_name}[$langcode]", '', t('Widget is displayed.'));
// Create entity with three values.
@ -1666,7 +1666,7 @@ class FieldFormTestCase extends FieldTestCase {
$this->assertFalse($form[$field_name_no_access]['#access'], 'Field #access is FALSE for the field without edit access.');
// Display creation form.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertNoFieldByName("{$field_name_no_access}[$langcode][0][value]", '', t('Widget is not displayed if field access is denied.'));
// Create entity.

View File

@ -42,8 +42,7 @@ function field_test_menu() {
$bundles = field_info_bundles('test_entity');
foreach ($bundles as $bundle_name => $bundle_info) {
$bundle_url_str = str_replace('_', '-', $bundle_name);
$items['test-entity/add/' . $bundle_url_str] = array(
$items['test-entity/add/' . $bundle_name] = array(
'title' => t('Add %bundle test_entity', array('%bundle' => $bundle_info['label'])),
'page callback' => 'field_test_entity_add',
'page arguments' => array(2),

View File

@ -158,7 +158,6 @@ function hook_field_formatter_settings_form($field, $instance, $view_mode, $form
$element['trim_length'] = array(
'#title' => t('Length'),
'#type' => 'number',
'#size' => 20,
'#default_value' => $settings['trim_length'],
'#min' => 1,
'#required' => TRUE,

View File

@ -5,6 +5,8 @@
(function($) {
"use strict";
Drupal.behaviors.fieldUIFieldOverview = {
attach: function (context, settings) {
$(context).find('table#field-overview').once('field-overview', function () {

View File

@ -34,8 +34,6 @@ class FieldUITestCase extends DrupalWebTestCase {
$type_name = strtolower($this->randomName(8)) . '_test';
$type = $this->drupalCreateContentType(array('name' => $type_name, 'type' => $type_name));
$this->type = $type->type;
// Store a valid URL name, with hyphens instead of underscores.
$this->hyphen_type = str_replace('_', '-', $this->type);
}
/**
@ -199,7 +197,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
* Tests the manage fields page.
*/
function manageFieldsPage() {
$this->drupalGet('admin/structure/types/manage/' . $this->hyphen_type . '/fields');
$this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields');
// Check all table columns.
$table_headers = array(
t('Label'),
@ -232,7 +230,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
'fields[_add_new_field][label]' => $this->field_label,
'fields[_add_new_field][field_name]' => $this->field_name_input,
);
$this->fieldUIAddNewField('admin/structure/types/manage/' . $this->hyphen_type, $edit);
$this->fieldUIAddNewField('admin/structure/types/manage/' . $this->type, $edit);
// Assert the field appears in the "add existing field" section for
// different entity types; e.g. if a field was added in a node entity, it
@ -247,7 +245,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
*/
function updateField() {
// Go to the field edit page.
$this->drupalGet('admin/structure/types/manage/' . $this->hyphen_type . '/fields/' . $this->field_name);
$this->drupalGet('admin/structure/types/manage/' . $this->type . '/fields/' . $this->field_name);
// Populate the field settings with new settings.
$string = 'updated dummy test string';
@ -330,7 +328,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
field_create_instance($instance);
$langcode = LANGUAGE_NOT_SPECIFIED;
$admin_path = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields/' . $field_name;
$admin_path = 'admin/structure/types/manage/' . $this->type . '/fields/' . $field_name;
$element_id = "edit-$field_name-$langcode-0-value";
$element_name = "{$field_name}[$langcode][0][value]";
$this->drupalGet($admin_path);
@ -366,7 +364,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
*/
function testDeleteField() {
// Create a new field.
$bundle_path1 = 'admin/structure/types/manage/' . $this->hyphen_type;
$bundle_path1 = 'admin/structure/types/manage/' . $this->type;
$edit1 = array(
'fields[_add_new_field][label]' => $this->field_label,
'fields[_add_new_field][field_name]' => $this->field_name_input,
@ -377,10 +375,9 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
$type_name2 = strtolower($this->randomName(8)) . '_test';
$type2 = $this->drupalCreateContentType(array('name' => $type_name2, 'type' => $type_name2));
$type_name2 = $type2->type;
$hyphen_type2 = str_replace('_', '-', $type_name2);
// Add an instance to the second node type.
$bundle_path2 = 'admin/structure/types/manage/' . $hyphen_type2;
$bundle_path2 = 'admin/structure/types/manage/' . $type_name2;
$edit2 = array(
'fields[_add_existing_field][label]' => $this->field_label,
'fields[_add_existing_field][field_name]' => $this->field_name,
@ -412,7 +409,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
* Tests that Field UI respects the 'no_ui' option in hook_field_info().
*/
function testHiddenFields() {
$bundle_path = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields/';
$bundle_path = 'admin/structure/types/manage/' . $this->type . '/fields/';
// Check that the field type is not available in the 'add new field' row.
$this->drupalGet($bundle_path);
@ -447,15 +444,14 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
* Tests renaming a bundle.
*/
function testRenameBundle() {
$type2 = strtolower($this->randomName(8)) . '_' .'test';
$hyphen_type2 = str_replace('_', '-', $type2);
$type2 = strtolower($this->randomName(8)) . '_test';
$options = array(
'type' => $type2,
);
$this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type, $options, t('Save content type'));
$this->drupalPost('admin/structure/types/manage/' . $this->type, $options, t('Save content type'));
$this->drupalGet('admin/structure/types/manage/' . $hyphen_type2 . '/fields');
$this->drupalGet('admin/structure/types/manage/' . $type2 . '/fields');
}
/**
@ -470,7 +466,7 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase {
'fields[_add_new_field][type]' => 'taxonomy_term_reference',
'fields[_add_new_field][widget_type]' => 'options_select',
);
$url = 'admin/structure/types/manage/' . $this->hyphen_type . '/fields';
$url = 'admin/structure/types/manage/' . $this->type . '/fields';
$this->drupalPost($url, $edit, t('Save'));
$this->assertText(t('The machine-readable name is already in use. It must be unique.'));
@ -498,7 +494,7 @@ class FieldUIManageDisplayTestCase extends FieldUITestCase {
* Tests formatter settings.
*/
function testFormatterUI() {
$manage_fields = 'admin/structure/types/manage/' . $this->hyphen_type;
$manage_fields = 'admin/structure/types/manage/' . $this->type;
$manage_display = $manage_fields . '/display';
// Create a field, and a node with some data for the field.
@ -551,7 +547,7 @@ class FieldUIManageDisplayTestCase extends FieldUITestCase {
'fields[_add_new_field][label]' => 'Test field',
'fields[_add_new_field][field_name]' => 'test',
);
$this->fieldUIAddNewField('admin/structure/types/manage/' . $this->hyphen_type, $edit);
$this->fieldUIAddNewField('admin/structure/types/manage/' . $this->type, $edit);
// For this test, use a formatter setting value that is an integer unlikely
// to appear in a rendered node other than as part of the field being tested
// (for example, unlikely to be part of the "Submitted by ... on ..." line).
@ -579,14 +575,14 @@ class FieldUIManageDisplayTestCase extends FieldUITestCase {
$edit = array(
'fields[field_test][type]' => 'field_test_with_prepare_view',
);
$this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display', $edit, t('Save'));
$this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
$this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], t("The field is displayed as expected in view modes that use 'default' settings."));
// Specialize the 'rss' mode, check that the field is displayed the same.
$edit = array(
"view_modes_custom[rss]" => TRUE,
);
$this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display', $edit, t('Save'));
$this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
$this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], t("The field is displayed as expected in newly specialized 'rss' mode."));
// Set the field to 'hidden' in the view mode, check that the field is
@ -594,7 +590,7 @@ class FieldUIManageDisplayTestCase extends FieldUITestCase {
$edit = array(
'fields[field_test][type]' => 'hidden',
);
$this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display/rss', $edit, t('Save'));
$this->drupalPost('admin/structure/types/manage/' . $this->type . '/display/rss', $edit, t('Save'));
$this->assertNodeViewNoText($node, 'rss', $value, t("The field is hidden in 'rss' mode."));
// Set the view mode back to 'default', check that the field is displayed
@ -602,14 +598,14 @@ class FieldUIManageDisplayTestCase extends FieldUITestCase {
$edit = array(
"view_modes_custom[rss]" => FALSE,
);
$this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display', $edit, t('Save'));
$this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
$this->assertNodeViewText($node, 'rss', $output['field_test_with_prepare_view'], t("The field is displayed as expected when 'rss' mode is set back to 'default' settings."));
// Specialize the view mode again.
$edit = array(
"view_modes_custom[rss]" => TRUE,
);
$this->drupalPost('admin/structure/types/manage/' . $this->hyphen_type . '/display', $edit, t('Save'));
$this->drupalPost('admin/structure/types/manage/' . $this->type . '/display', $edit, t('Save'));
// Check that the previous settings for the view mode have been kept.
$this->assertNodeViewNoText($node, 'rss', $value, t("The previous settings are kept when 'rss' mode is specialized again."));
}

View File

@ -9,6 +9,8 @@
(function ($) {
"use strict";
/**
* Attach behaviors to managed file element upload fields.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
Drupal.behaviors.filterStatus = {
attach: function (context, settings) {
var $context = $(context);

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Automatically display the guidelines of the selected text format.
*/

View File

@ -1363,8 +1363,6 @@ function _filter_url_settings($form, &$form_state, $filter, $format, $defaults)
'#type' => 'number',
'#title' => t('Maximum link text length'),
'#default_value' => $filter->settings['filter_url_length'],
'#size' => 5,
'#maxlength' => 4,
'#min' => 1,
'#field_suffix' => t('characters'),
'#description' => t('URLs longer than this number of characters will be truncated to prevent long strings that break formatting. The link itself will be retained; just the text portion of the link will be truncated.'),

View File

@ -180,7 +180,7 @@ function forum_menu_local_tasks_alter(&$data, $router_item, $root_path) {
'#theme' => 'menu_local_action',
'#link' => array(
'title' => t('Add new @node_type', array('@node_type' => node_type_get_name($type))),
'href' => 'node/add/' . str_replace('_', '-', $type) . '/' . $forum_term->tid,
'href' => 'node/add/' . $type . '/' . $forum_term->tid,
),
);
}
@ -547,32 +547,43 @@ function forum_field_storage_pre_insert($entity_type, $entity, &$skip_fields) {
function forum_field_storage_pre_update($entity_type, $entity, &$skip_fields) {
$first_call = &drupal_static(__FUNCTION__, array());
if ($entity_type == 'node' && $entity->status && _forum_node_check_node_type($entity)) {
// We don't maintain data for old revisions, so clear all previous values
// from the table. Since this hook runs once per field, per object, make
// sure we only wipe values once.
if (!isset($first_call[$entity->nid])) {
$first_call[$entity->nid] = FALSE;
if ($entity_type == 'node' && _forum_node_check_node_type($entity)) {
// If the node is published, update the forum index.
if ($entity->status) {
// We don't maintain data for old revisions, so clear all previous values
// from the table. Since this hook runs once per field, per object, make
// sure we only wipe values once.
if (!isset($first_call[$entity->nid])) {
$first_call[$entity->nid] = FALSE;
db_delete('forum_index')->condition('nid', $entity->nid)->execute();
}
$query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp'));
foreach ($entity->taxonomy_forums as $language) {
foreach ($language as $item) {
$query->values(array(
'nid' => $entity->nid,
'title' => $entity->title,
'tid' => $item['tid'],
'sticky' => $entity->sticky,
'created' => $entity->created,
'comment_count' => 0,
'last_comment_timestamp' => $entity->created,
));
}
}
$query->execute();
// The logic for determining last_comment_count is fairly complex, so
// call _forum_update_forum_index() too.
_forum_update_forum_index($entity->nid);
}
// When a forum node is unpublished, remove it from the forum_index table.
else {
db_delete('forum_index')->condition('nid', $entity->nid)->execute();
}
$query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp'));
foreach ($entity->taxonomy_forums as $language) {
foreach ($language as $item) {
$query->values(array(
'nid' => $entity->nid,
'title' => $entity->title,
'tid' => $item['tid'],
'sticky' => $entity->sticky,
'created' => $entity->created,
'comment_count' => 0,
'last_comment_timestamp' => $entity->created,
));
}
}
$query->execute();
// The logic for determining last_comment_count is fairly complex, so
// call _forum_update_forum_index() too.
_forum_update_forum_index($entity->nid);
}
}
@ -710,8 +721,8 @@ function forum_block_view_pre_render($elements) {
/**
* Implements hook_form().
*/
function forum_form($node, $form_state) {
$type = node_type_get_type($node);
function forum_form(Node $node, &$form_state) {
$type = node_type_load($node->type);
$form['title'] = array(
'#type' => 'textfield',
'#title' => check_plain($type->title_label),

View File

@ -590,3 +590,65 @@ class ForumTestCase extends DrupalWebTestCase {
}
}
}
/**
* Tests the forum index listing.
*/
class ForumIndexTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Forum index',
'description' => 'Tests the forum index listing.',
'group' => 'Forum',
);
}
function setUp() {
parent::setUp('taxonomy', 'comment', 'forum');
// Create a test user.
$web_user = $this->drupalCreateUser(array('create forum content', 'edit own forum content', 'edit any forum content', 'administer nodes'));
$this->drupalLogin($web_user);
}
/**
* Tests the forum index for published and unpublished nodes.
*/
function testForumIndexStatus() {
$langcode = LANGUAGE_NOT_SPECIFIED;
// The forum ID to use.
$tid = 1;
// Create a test node.
$title = $this->randomName(20);
$edit = array(
"title" => $title,
"body[$langcode][0][value]" => $this->randomName(200),
);
// Create the forum topic, preselecting the forum ID via a URL parameter.
$this->drupalPost('node/add/forum/' . $tid, $edit, t('Save'));
// Check that the node exists in the database.
$node = $this->drupalGetNodeByTitle($title);
$this->assertTrue(!empty($node), 'New forum node found in database.');
// Verify that the node appears on the index.
$this->drupalGet('forum/' . $tid);
$this->assertText($title, 'Published forum topic appears on index.');
// Unpublish the node.
$edit = array(
'status' => FALSE,
);
$this->drupalPost("node/{$node->nid}/edit", $edit, t('Save'));
$this->assertText(t('Access denied'), 'Unpublished node is no longer accessible.');
// Verify that the node no longer appears on the index.
$this->drupalGet('forum/' . $tid);
$this->assertNoText($title, 'Unpublished forum topic no longer appears on index.');
}
}

View File

@ -450,7 +450,6 @@ function image_resize_form($data) {
'#default_value' => isset($data['width']) ? $data['width'] : '',
'#field_suffix' => ' ' . t('pixels'),
'#required' => TRUE,
'#size' => 10,
'#min' => 1,
);
$form['height'] = array(
@ -459,7 +458,6 @@ function image_resize_form($data) {
'#default_value' => isset($data['height']) ? $data['height'] : '',
'#field_suffix' => ' ' . t('pixels'),
'#required' => TRUE,
'#size' => 10,
'#min' => 1,
);
return $form;
@ -547,8 +545,6 @@ function image_rotate_form($data) {
'#description' => t('The number of degrees the image should be rotated. Positive numbers are clockwise, negative are counter-clockwise.'),
'#field_suffix' => '&deg;',
'#required' => TRUE,
'#size' => 6,
'#maxlength' => 4,
);
$form['bgcolor'] = array(
'#type' => 'textfield',

View File

@ -91,8 +91,6 @@ function image_field_instance_settings_form($field, $instance) {
'#title' => t('Maximum width'),
'#title_display' => 'invisible',
'#default_value' => $max_resolution[0],
'#size' => 5,
'#maxlength' => 5,
'#min' => 1,
'#field_suffix' => ' x ',
);
@ -101,8 +99,6 @@ function image_field_instance_settings_form($field, $instance) {
'#title' => t('Maximum height'),
'#title_display' => 'invisible',
'#default_value' => $max_resolution[1],
'#size' => 5,
'#maxlength' => 5,
'#min' => 1,
'#field_suffix' => ' ' . t('pixels'),
);
@ -122,8 +118,6 @@ function image_field_instance_settings_form($field, $instance) {
'#title' => t('Minimum width'),
'#title_display' => 'invisible',
'#default_value' => $min_resolution[0],
'#size' => 5,
'#maxlength' => 5,
'#min' => 1,
'#field_suffix' => ' x ',
);
@ -132,8 +126,6 @@ function image_field_instance_settings_form($field, $instance) {
'#title' => t('Minimum height'),
'#title_display' => 'invisible',
'#default_value' => $min_resolution[1],
'#size' => 5,
'#maxlength' => 5,
'#min' => 1,
'#field_suffix' => ' ' . t('pixels'),
);

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
$.datepicker.regional['drupal-locale'] = {
closeText: Drupal.t('Done'),
prevText: Drupal.t('Prev'),

View File

@ -1890,175 +1890,6 @@ class LocaleBrowserDetectionTest extends DrupalUnitTestCase {
}
}
/**
* Functional tests for a user's ability to change their default language.
*/
class LocaleUserLanguageFunctionalTest extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'User language settings',
'description' => "Tests user's ability to change their default language.",
'group' => 'Locale',
);
}
function setUp() {
parent::setUp('locale');
}
/**
* Test if user can change their default language.
*/
function testUserLanguageConfiguration() {
global $base_url;
// User to add and remove language.
$admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages'));
// User to change their default language.
$web_user = $this->drupalCreateUser();
// Add custom language.
$this->drupalLogin($admin_user);
// Code for the language.
$langcode = 'xx';
// The English name for the language.
$name = $this->randomName(16);
$edit = array(
'predefined_langcode' => 'custom',
'langcode' => $langcode,
'name' => $name,
'direction' => '0',
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->drupalLogout();
// Login as normal user and edit account settings.
$this->drupalLogin($web_user);
$path = 'user/' . $web_user->uid . '/edit';
$this->drupalGet($path);
// Ensure language settings fieldset is available.
$this->assertText(t('Language'), t('Language selector available.'));
// Ensure custom language is present.
$this->assertText($name, t('Language present on form.'));
// Switch to our custom language.
$edit = array(
'preferred_langcode' => $langcode,
);
$this->drupalPost($path, $edit, t('Save'));
// Ensure form was submitted successfully.
$this->assertText(t('The changes have been saved.'), t('Changes were saved.'));
// Check if language was changed.
$elements = $this->xpath('//input[@id=:id]', array(':id' => 'edit-preferred-langcode-' . $langcode));
$this->assertTrue(isset($elements[0]) && !empty($elements[0]['checked']), t('Default language successfully updated.'));
$this->drupalLogout();
}
}
/**
* Functional test for language handling during user creation.
*/
class LocaleUserCreationTest extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'User creation',
'description' => 'Tests whether proper language is stored for new users and access to language selector.',
'group' => 'Locale',
);
}
function setUp() {
parent::setUp('locale');
variable_set('user_register', USER_REGISTER_VISITORS);
}
/**
* Functional test for language handling during user creation.
*/
function testLocalUserCreation() {
// User to add and remove language and create new users.
$admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages', 'administer users'));
$this->drupalLogin($admin_user);
// Add predefined language.
$langcode = 'fr';
$edit = array(
'predefined_langcode' => 'fr',
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
$this->assertText('French', t('Language added successfully.'));
$this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), t('Correct page redirection.'));
// Set language negotiation.
$edit = array(
'language_interface[enabled][language-url]' => TRUE,
);
$this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings'));
$this->assertText(t('Language negotiation configuration saved.'), t('Set language negotiation.'));
// Check if the language selector is available on admin/people/create and
// set to the currently active language.
$this->drupalGet($langcode . '/admin/people/create');
$this->assertFieldChecked("edit-preferred-langcode-$langcode", t('Global language set in the language selector.'));
// Create a user with the admin/people/create form and check if the correct
// language is set.
$username = $this->randomName(10);
$edit = array(
'name' => $username,
'mail' => $this->randomName(4) . '@example.com',
'pass[pass1]' => $username,
'pass[pass2]' => $username,
);
$this->drupalPost($langcode . '/admin/people/create', $edit, t('Create new account'));
$user = user_load_by_name($username);
$this->assertEqual($user->preferred_langcode, $langcode, t('New user has correct preferred language set.'));
$this->assertEqual($user->langcode, $langcode, t('New user has correct profile language set.'));
// Register a new user and check if the language selector is hidden.
$this->drupalLogout();
$this->drupalGet($langcode . '/user/register');
$this->assertNoFieldByName('language[fr]', t('Language selector is not accessible.'));
$username = $this->randomName(10);
$edit = array(
'name' => $username,
'mail' => $this->randomName(4) . '@example.com',
);
$this->drupalPost($langcode . '/user/register', $edit, t('Create new account'));
$user = user_load_by_name($username);
$this->assertEqual($user->preferred_langcode, $langcode, t('New user has correct preferred language set.'));
$this->assertEqual($user->langcode, $langcode, t('New user has correct profile language set.'));
// Test if the admin can use the language selector and if the
// correct language is was saved.
$user_edit = $langcode . '/user/' . $user->uid . '/edit';
$this->drupalLogin($admin_user);
$this->drupalGet($user_edit);
$this->assertFieldChecked("edit-preferred-langcode-$langcode", t('Language selector is accessible and correct language is selected.'));
// Set pass_raw so we can login the new user.
$user->pass_raw = $this->randomName(10);
$edit = array(
'pass[pass1]' => $user->pass_raw,
'pass[pass2]' => $user->pass_raw,
);
$this->drupalPost($user_edit, $edit, t('Save'));
$this->drupalLogin($user);
$this->drupalGet($user_edit);
$this->assertFieldChecked("edit-preferred-langcode-$langcode", t('Language selector is accessible and correct language is selected.'));
}
}
/**
* Functional tests for configuring a different path alias per language.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
Drupal.behaviors.menuChangeParentItems = {
attach: function (context, settings) {
$('fieldset#edit-menu input').each(function () {

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
Drupal.behaviors.menuFieldsetSummaries = {
attach: function (context) {
$(context).find('fieldset.menu-link-form').drupalSetSummary(function (context) {

View File

@ -20,22 +20,21 @@ function node_overview_types() {
foreach ($names as $key => $name) {
$type = $types[$key];
if (node_hook($type->type, 'form')) {
$type_url_str = str_replace('_', '-', $type->type);
$row = array(theme('node_admin_overview', array('name' => $name, 'type' => $type)));
// Set the edit column.
$row[] = array('data' => l(t('edit'), 'admin/structure/types/manage/' . $type_url_str));
$row[] = array('data' => l(t('edit'), 'admin/structure/types/manage/' . $type->type));
if ($field_ui) {
// Manage fields.
$row[] = array('data' => l(t('manage fields'), 'admin/structure/types/manage/' . $type_url_str . '/fields'));
$row[] = array('data' => l(t('manage fields'), 'admin/structure/types/manage/' . $type->type . '/fields'));
// Display fields.
$row[] = array('data' => l(t('manage display'), 'admin/structure/types/manage/' . $type_url_str . '/display'));
$row[] = array('data' => l(t('manage display'), 'admin/structure/types/manage/' . $type->type . '/display'));
}
// Set the delete column.
if ($type->custom) {
$row[] = array('data' => l(t('delete'), 'admin/structure/types/manage/' . $type_url_str . '/delete'));
$row[] = array('data' => l(t('delete'), 'admin/structure/types/manage/' . $type->type . '/delete'));
}
else {
$row[] = array('data' => '');
@ -319,7 +318,7 @@ function node_type_form_submit($form, &$form_state) {
}
if ($op == t('Delete content type')) {
$form_state['redirect'] = 'admin/structure/types/manage/' . str_replace('_', '-', $type->old_type) . '/delete';
$form_state['redirect'] = 'admin/structure/types/manage/' . $type->old_type . '/delete';
return;
}

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
Drupal.behaviors.contentTypes = {
attach: function (context) {
var $context = $(context);

View File

@ -605,7 +605,8 @@ function hook_node_load($nodes, $types) {
function hook_node_access($node, $op, $account) {
$type = is_string($node) ? $node : $node->type;
if (in_array($type, node_permissions_get_configured_types())) {
$configured_types = node_permissions_get_configured_types();
if (isset($configured_types[$type])) {
if ($op == 'create' && user_access('create ' . $type . ' content', $account)) {
return NODE_ACCESS_ALLOW;
}
@ -1096,7 +1097,7 @@ function hook_prepare(Drupal\node\Node $node) {
* @ingroup node_api_hooks
*/
function hook_form(Drupal\node\Node $node, &$form_state) {
$type = node_type_get_type($node);
$type = node_type_load($node->type);
$form['title'] = array(
'#type' => 'textfield',

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
Drupal.behaviors.nodeFieldsetSummaries = {
attach: function (context) {
var $context = $(context);

View File

@ -135,12 +135,12 @@ function node_help($path, $arg) {
case 'node/%/edit':
$node = node_load($arg[1]);
$type = node_type_get_type($node);
$type = node_type_load($node->type);
return (!empty($type->help) ? '<p>' . filter_xss_admin($type->help) . '</p>' : '');
}
if ($arg[0] == 'node' && $arg[1] == 'add' && $arg[2]) {
$type = node_type_get_type(str_replace('-', '_', $arg[2]));
$type = node_type_load($arg[2]);
return (!empty($type->help) ? '<p>' . filter_xss_admin($type->help) . '</p>' : '');
}
}
@ -249,7 +249,7 @@ function node_entity_info() {
'label' => $name,
'admin' => array(
'path' => 'admin/structure/types/manage/%node_type',
'real path' => 'admin/structure/types/manage/' . str_replace('_', '-', $type),
'real path' => 'admin/structure/types/manage/' . $type,
'bundle argument' => 4,
'access arguments' => array('administer content types'),
),
@ -410,31 +410,12 @@ function _node_extract_type($node) {
* @return
* An array of node types, as objects, keyed by the type.
*
* @see node_type_get_type()
* @see node_type_load()
*/
function node_type_get_types() {
return _node_types_build()->types;
}
/**
* Returns the node type of the passed node or node type string.
*
* @param Drupal\node\Node|string $node
* A node entity or string that indicates the node type to return.
*
* @return
* A single node type, as an object, or FALSE if the node type is not found.
* The node type is an object containing fields from hook_node_info() return
* values, as well as the field 'type' (the machine-readable type) and other
* fields used internally and defined in _node_types_build(),
* hook_node_info(), and node_type_set_defaults().
*/
function node_type_get_type($node) {
$type = _node_extract_type($node);
$types = _node_types_build()->types;
return isset($types[$type]) ? $types[$type] : FALSE;
}
/**
* Returns the node type base of the passed node or node type string.
*
@ -500,14 +481,14 @@ function node_types_rebuild() {
* Menu argument loader: Loads a node type by string.
*
* @param $name
* The machine-readable name of a node type to load, where '_' is replaced
* with '-'.
* The machine name of a node type to load.
*
* @return
* A node type object or FALSE if $name does not exist.
*/
function node_type_load($name) {
return node_type_get_type(strtr($name, array('-' => '_')));
$types = _node_types_build()->types;
return isset($types[$name]) ? $types[$name] : FALSE;
}
/**
@ -650,16 +631,16 @@ function node_field_extra_fields() {
/**
* Deletes a node type from the database.
*
* @param $type
* The machine-readable name of the node type to be deleted.
* @param $name
* The machine name of the node type to delete.
*/
function node_type_delete($type) {
$info = node_type_get_type($type);
function node_type_delete($name) {
$type = node_type_load($name);
db_delete('node_type')
->condition('type', $type)
->condition('type', $name)
->execute();
field_attach_delete_bundle('node', $type);
module_invoke_all('node_type_delete', $info);
field_attach_delete_bundle('node', $name);
module_invoke_all('node_type_delete', $type);
// Clear the node type cache.
node_type_cache_reset();
@ -1011,8 +992,8 @@ function node_object_prepare(Node $node) {
*
* @see node_form_validate()
*/
function node_validate($node, $form, &$form_state) {
$type = node_type_get_type($node);
function node_validate(Node $node, $form, &$form_state) {
$type = node_type_load($node->type);
if (isset($node->nid) && (node_last_changed($node->nid) > $node->changed)) {
form_set_error('changed', t('The content on this page has either been modified by another user, or you have already submitted modifications using this form. As a result, your changes cannot be saved.'));
@ -1441,7 +1422,7 @@ function node_permission() {
);
// Generate standard node permissions for all applicable node types.
foreach (node_permissions_get_configured_types() as $type) {
foreach (node_permissions_get_configured_types() as $name => $type) {
$perms += node_list_permissions($type);
}
@ -1900,8 +1881,7 @@ function node_menu() {
);
// @todo Remove this loop when we have a 'description callback' property.
foreach (node_type_get_types() as $type) {
$type_url_str = str_replace('_', '-', $type->type);
$items['node/add/' . $type_url_str] = array(
$items['node/add/' . $type->type] = array(
'title' => $type->name,
'title callback' => 'check_plain',
'page callback' => 'node_add',
@ -2925,7 +2905,8 @@ function node_access($op, $node, $account = NULL) {
function node_node_access($node, $op, $account) {
$type = is_string($node) ? $node : $node->type;
if (in_array($type, node_permissions_get_configured_types())) {
$configured_types = node_permissions_get_configured_types();
if (isset($configured_types[$type])) {
if ($op == 'create' && user_access('create ' . $type . ' content', $account)) {
return NODE_ACCESS_ALLOW;
}
@ -2949,34 +2930,31 @@ function node_node_access($node, $op, $account) {
/**
* Helper function to generate standard node permission list for a given type.
*
* @param $type
* The machine-readable name of the node type.
* @param $name
* The machine name of the node type.
*
* @return array
* An array of permission names and descriptions.
*/
function node_list_permissions($type) {
$info = node_type_get_type($type);
// Build standard list of node permissions for this type.
$perms = array(
"create $type content" => array(
'title' => t('%type_name: Create new content', array('%type_name' => $info->name)),
"create $type->type content" => array(
'title' => t('%type_name: Create new content', array('%type_name' => $type->name)),
),
"edit own $type content" => array(
'title' => t('%type_name: Edit own content', array('%type_name' => $info->name)),
"edit own $type->type content" => array(
'title' => t('%type_name: Edit own content', array('%type_name' => $type->name)),
),
"edit any $type content" => array(
'title' => t('%type_name: Edit any content', array('%type_name' => $info->name)),
"edit any $type->type content" => array(
'title' => t('%type_name: Edit any content', array('%type_name' => $type->name)),
),
"delete own $type content" => array(
'title' => t('%type_name: Delete own content', array('%type_name' => $info->name)),
"delete own $type->type content" => array(
'title' => t('%type_name: Delete own content', array('%type_name' => $type->name)),
),
"delete any $type content" => array(
'title' => t('%type_name: Delete any content', array('%type_name' => $info->name)),
"delete any $type->type content" => array(
'title' => t('%type_name: Delete any content', array('%type_name' => $type->name)),
),
);
return $perms;
}
@ -2995,15 +2973,12 @@ function node_list_permissions($type) {
* An array of node types managed by this module.
*/
function node_permissions_get_configured_types() {
$configured_types = array();
foreach (node_type_get_types() as $type => $info) {
if (variable_get('node_permissions_' . $type, 1)) {
$configured_types[] = $type;
foreach (node_type_get_types() as $name => $type) {
if (variable_get('node_permissions_' . $name, 1)) {
$configured_types[$name] = $type;
}
}
return $configured_types;
}
@ -3534,10 +3509,10 @@ function _node_access_rebuild_batch_finished($success, $results, $operations) {
* Implements hook_form().
*/
function node_content_form(Node $node, $form_state) {
// It is impossible to define a content type without implementing hook_form()
// @todo: remove this requirement.
// @todo It is impossible to define a content type without implementing
// hook_form(). Remove this requirement.
$form = array();
$type = node_type_get_type($node);
$type = node_type_load($node->type);
if ($type->has_title) {
$form['title'] = array(

View File

@ -1317,7 +1317,7 @@ class NodeTypeTestCase extends NodeWebTestCase {
$this->assertEqual($node_types['article']->name, $node_names['article'], t('Correct node type base has been returned.'));
$this->assertEqual($node_types['article'], node_type_get_type('article'), t('Correct node type has been returned.'));
$this->assertEqual($node_types['article'], node_type_load('article'), t('Correct node type has been returned.'));
$this->assertEqual($node_types['article']->name, node_type_get_name('article'), t('Correct node type name has been returned.'));
$this->assertEqual($node_types['page']->base, node_type_get_base('page'), t('Correct node type base has been returned.'));
}
@ -1336,7 +1336,7 @@ class NodeTypeTestCase extends NodeWebTestCase {
$web_user = $this->drupalCreateUser(array('create ' . $type->name . ' content'));
$this->drupalLogin($web_user);
$this->drupalGet('node/add/' . str_replace('_', '-', $type->name));
$this->drupalGet('node/add/' . $type->type);
$this->assertResponse(200, 'The new content type can be accessed at node/add.');
// Create a content type via the user interface.

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
Drupal.behaviors.openid = {
attach: function (context) {
var $context = $(context);

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Attach the child dialog behavior to new content.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Open the overlay, or load content into it, when an admin link is clicked.
*/

View File

@ -42,8 +42,13 @@ function path_admin_overview($keys = NULL) {
$destination = drupal_get_destination();
foreach ($result as $data) {
$row = array();
$row['data']['alias'] = l($data->alias, $data->source);
$row['data']['source'] = l($data->source, $data->source, array('alias' => TRUE));
$row['data']['alias'] = l(truncate_utf8($data->alias, 50, FALSE, TRUE), $data->source, array(
'attributes' => array('title' => $data->alias),
));
$row['data']['source'] = l(truncate_utf8($data->source, 50, FALSE, TRUE), $data->source, array(
'alias' => TRUE,
'attributes' => array('title' => $data->source),
));
if ($multilanguage) {
$row['data']['language_name'] = language_name($data->langcode);
}

View File

@ -4,6 +4,8 @@
*/
(function ($) {
"use strict";
Drupal.behaviors.pathFieldsetSummaries = {
attach: function (context) {
$(context).find('fieldset.path-form').drupalSetSummary(function (context) {

View File

@ -128,6 +128,18 @@ class PathAliasTestCase extends PathTestCase {
$this->drupalGet($edit['alias']);
$this->assertNoText($node1->title, 'Alias was successfully deleted.');
$this->assertResponse(404);
// Create a really long alias.
$edit = array();
$edit['source'] = 'node/' . $node1->nid;
$alias = $this->randomName(128);
$edit['alias'] = $alias;
// The alias is shortened to 50 characters counting the elipsis.
$truncated_alias = substr($alias, 0, 47);
$this->drupalPost('admin/config/search/path/add', $edit, t('Save'));
$this->assertNoText($alias, 'The untruncated alias was not found.');
// The 'truncated' alias will always be found.
$this->assertText($truncated_alias, 'The truncated alias was found.');
}
/**

View File

@ -218,12 +218,12 @@ function poll_field_extra_fields() {
/**
* Implements hook_form().
*/
function poll_form($node, &$form_state) {
function poll_form(Node $node, &$form_state) {
global $user;
$admin = user_access('bypass node access') || user_access('edit any poll content') || (user_access('edit own poll content') && $user->uid == $node->uid);
$type = node_type_get_type($node);
$type = node_type_load($node->type);
// The submit handlers to add more poll choices require that this form is
// cached, regardless of whether Ajax is used.
@ -389,8 +389,6 @@ function _poll_choice_form($key, $chid = NULL, $value = '', $votes = 0, $weight
'#title' => $value !== '' ? t('Vote count for choice @label', array('@label' => $value)) : t('Vote count for new choice'),
'#title_display' => 'invisible',
'#default_value' => $votes,
'#size' => 5,
'#maxlength' => 7,
'#min' => 0,
'#parents' => array('choice', $key, 'chvotes'),
'#access' => user_access('administer nodes'),

View File

@ -93,9 +93,8 @@ function search_admin_settings($form) {
'#type' => 'number',
'#title' => t('Minimum word length to index'),
'#default_value' => variable_get('minimum_word_size', 3),
'#size' => 5,
'#maxlength' => 3,
'#min' => 1,
'#max' => 1000,
'#description' => t('The number of characters a word has to be to be indexed. A lower setting means better search result ranking, but also a larger database. Each search query must contain at least one keyword that is this size (or longer).')
);
$form['indexing_settings']['overlap_cjk'] = array(

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Handle the concept of a fixed number of slots.
*

View File

@ -986,7 +986,7 @@ class DrupalWebTestCase extends DrupalTestCase {
// Find a non-existent random type name.
do {
$name = strtolower($this->randomName(8));
} while (node_type_get_type($name));
} while (node_type_load($name));
// Populate defaults array.
$defaults = array(
@ -1344,7 +1344,6 @@ class DrupalWebTestCase extends DrupalTestCase {
$this->originalLanguage = $language_interface;
$this->originalLanguageDefault = variable_get('language_default');
$this->originalConfigDirectory = $GLOBALS['config_directory_name'];
$this->originalConfigSignatureKey = $GLOBALS['config_signature_key'];
$this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files');
$this->originalProfile = drupal_get_profile();
$this->originalUser = $user;
@ -1377,7 +1376,6 @@ class DrupalWebTestCase extends DrupalTestCase {
$GLOBALS['config_directory_name'] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config';
$this->configFileDirectory = $this->originalFileDirectory . '/' . $GLOBALS['config_directory_name'];
file_prepare_directory($this->configFileDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
$GLOBALS['config_signature_key'] = drupal_hash_base64(drupal_random_bytes(55));
// Log fatal errors.
ini_set('log_errors', 1);
@ -1600,10 +1598,15 @@ class DrupalWebTestCase extends DrupalTestCase {
// Delete temporary files directory.
file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10));
// Remove all prefixed tables (all the tables in the schema).
$schema = drupal_get_schema(NULL, TRUE);
foreach ($schema as $name => $table) {
db_drop_table($name);
// Remove all prefixed tables.
$tables = db_find_tables($this->databasePrefix . '%');
foreach ($tables as $table) {
if (db_drop_table(substr($table, strlen($this->databasePrefix)))) {
unset($tables[$table]);
}
}
if (!empty($tables)) {
$this->fail('Failed to drop all prefixed tables.');
}
// Get back to the original connection.
@ -1637,9 +1640,11 @@ class DrupalWebTestCase extends DrupalTestCase {
// Rebuild caches.
$this->refreshVariables();
// Reset public files directory.
$GLOBALS['conf']['file_public_path'] = $this->originalFileDirectory;
// Reset configuration globals.
$GLOBALS['config_directory_name'] = $this->originalConfigDirectory;
$GLOBALS['config_signature_key'] = $this->originalConfigSignatureKey;
// Reset language.
$language_interface = $this->originalLanguage;

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Add the cool table collapsing on the testing overview page.
*/

View File

@ -1,4 +1,7 @@
(function ($) {
"use strict";
$(document).ready(function() {
var nid = Drupal.settings.statistics.nid;
var basePath = Drupal.settings.basePath

View File

@ -23,8 +23,6 @@ function image_gd_settings() {
'#type' => 'number',
'#title' => t('JPEG quality'),
'#description' => t('Define the image quality for JPEG manipulations. Ranges from 0 to 100. Higher values mean better image quality but bigger files.'),
'#size' => 10,
'#maxlength' => 3,
'#min' => 0,
'#max' => 100,
'#default_value' => variable_get('image_jpeg_quality', 75),

View File

@ -1398,8 +1398,8 @@ function hook_forms($form_id, $args) {
* used to set up global parameters that are needed later in the request.
*
* Only use this hook if your code must run even for cached page views. This
* hook is called before modules or most include files are loaded into memory.
* It happens while Drupal is still in bootstrap mode.
* hook is called before the theme, modules, or most include files are loaded
* into memory. It happens while Drupal is still in bootstrap mode.
*
* @see hook_init()
*/
@ -1414,7 +1414,8 @@ function hook_boot() {
*
* This hook is run at the beginning of the page request. It is typically
* used to set up global parameters that are needed later in the request.
* When this hook is called, all modules are already loaded in memory.
* When this hook is called, the theme and all modules are already loaded in
* memory.
*
* This hook is not run on cached pages.
*

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Checks to see if the cron should be automatically run.
*/

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Show/hide the 'Email site administrator when updates are available' checkbox
* on the install page.

View File

@ -363,7 +363,7 @@ function system_element_info() {
'#size' => 60,
'#maxlength' => 128,
'#autocomplete_path' => FALSE,
'#process' => array('form_process_autocomplete', 'ajax_process_form'),
'#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
'#theme' => 'textfield',
'#theme_wrappers' => array('form_element'),
);
@ -372,7 +372,7 @@ function system_element_info() {
'#size' => 30,
'#maxlength' => 128,
'#autocomplete_path' => FALSE,
'#process' => array('form_process_autocomplete', 'ajax_process_form'),
'#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
'#theme' => 'tel',
'#theme_wrappers' => array('form_element'),
);
@ -381,7 +381,7 @@ function system_element_info() {
'#size' => 60,
'#maxlength' => EMAIL_MAX_LENGTH,
'#autocomplete_path' => FALSE,
'#process' => array('form_process_autocomplete', 'ajax_process_form'),
'#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
'#element_validate' => array('form_validate_email'),
'#theme' => 'email',
'#theme_wrappers' => array('form_element'),
@ -391,7 +391,7 @@ function system_element_info() {
'#size' => 60,
'#maxlength' => 255,
'#autocomplete_path' => FALSE,
'#process' => array('form_process_autocomplete', 'ajax_process_form'),
'#process' => array('form_process_autocomplete', 'ajax_process_form', 'form_process_pattern'),
'#element_validate' => array('form_validate_url'),
'#theme' => 'url',
'#theme_wrappers' => array('form_element'),
@ -407,9 +407,7 @@ function system_element_info() {
);
$types['number'] = array(
'#input' => TRUE,
'#size' => 30,
'#step' => 1,
'#maxlength' => 128,
'#process' => array('ajax_process_form'),
'#element_validate' => array('form_validate_number'),
'#theme' => 'number',
@ -417,11 +415,9 @@ function system_element_info() {
);
$types['range'] = array(
'#input' => TRUE,
'#size' => 30,
'#step' => 1,
'#min' => 0,
'#max' => 100,
'#maxlength' => 128,
'#process' => array('ajax_process_form'),
'#element_validate' => array('form_validate_number'),
'#theme' => 'range',
@ -443,7 +439,7 @@ function system_element_info() {
'#input' => TRUE,
'#size' => 60,
'#maxlength' => 128,
'#process' => array('ajax_process_form'),
'#process' => array('ajax_process_form', 'form_process_pattern'),
'#theme' => 'password',
'#theme_wrappers' => array('form_element'),
);
@ -1127,6 +1123,7 @@ function system_menu() {
*/
function system_cron_page() {
drupal_page_is_cacheable(FALSE);
drupal_cron_run();
// HTTP 204 is "No content", meaning "I did what you asked and we're done."

View File

@ -365,6 +365,20 @@ class FormsTestCase extends DrupalWebTestCase {
}
}
/**
* Tests default value handling of #type 'range' elements.
*/
function testRange() {
$values = json_decode($this->drupalPost('form-test/range', array(), 'Submit'));
$this->assertEqual($values->with_default_value, 18);
$this->assertEqual($values->float, 10.5);
$this->assertEqual($values->integer, 6);
$this->assertEqual($values->offset, 6.9);
$this->drupalPost('form-test/range/invalid', array(), 'Submit');
$this->assertFieldByXPath('//input[@type="range" and contains(@class, "error")]', NULL, 'Range element has the error class.');
}
/**
* Test handling of disabled elements.
*
@ -770,6 +784,65 @@ class FormValidationTestCase extends DrupalWebTestCase {
$this->assertText(t('!name field is required.', array('!name' => 'Title')));
$this->assertText('Test element is invalid');
}
/**
* Tests #pattern validation.
*/
function testPatternValidation() {
$textfield_error = t('%name field is not in the right format.', array('%name' => 'One digit followed by lowercase letters'));
$tel_error = t('%name field is not in the right format.', array('%name' => 'Everything except numbers'));
$password_error = t('%name field is not in the right format.', array('%name' => 'Password'));
// Invalid textfield, valid tel.
$edit = array(
'textfield' => 'invalid',
'tel' => 'valid',
);
$this->drupalPost('form-test/pattern', $edit, 'Submit');
$this->assertRaw($textfield_error);
$this->assertNoRaw($tel_error);
$this->assertNoRaw($password_error);
// Valid textfield, invalid tel, valid password.
$edit = array(
'textfield' => '7seven',
'tel' => '818937',
'password' => '0100110',
);
$this->drupalPost('form-test/pattern', $edit, 'Submit');
$this->assertNoRaw($textfield_error);
$this->assertRaw($tel_error);
$this->assertNoRaw($password_error);
// Non required fields are not validated if empty.
$edit = array(
'textfield' => '',
'tel' => '',
);
$this->drupalPost('form-test/pattern', $edit, 'Submit');
$this->assertNoRaw($textfield_error);
$this->assertNoRaw($tel_error);
$this->assertNoRaw($password_error);
// Invalid password.
$edit = array(
'password' => $this->randomName(),
);
$this->drupalPost('form-test/pattern', $edit, 'Submit');
$this->assertNoRaw($textfield_error);
$this->assertNoRaw($tel_error);
$this->assertRaw($password_error);
// The pattern attribute overrides #pattern and is not validated on the
// server side.
$edit = array(
'textfield' => '',
'tel' => '',
'url' => 'http://www.example.com/',
);
$this->drupalPost('form-test/pattern', $edit, 'Submit');
$this->assertNoRaw(t('%name field is not in the right format.', array('%name' => 'Client side validation')));
}
}
/**

View File

@ -37,6 +37,12 @@ function form_test_menu() {
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
$items['form-test/pattern'] = array(
'title' => 'Pattern validation',
'page callback' => 'drupal_get_form',
'page arguments' => array('form_test_pattern_form'),
'access callback' => TRUE,
);
$items['form_test/tableselect/multiple-true'] = array(
'title' => 'Tableselect checkboxes test',
@ -145,6 +151,18 @@ function form_test_menu() {
'page arguments' => array('form_test_number', 'range'),
'access callback' => TRUE,
);
$items['form-test/range']= array(
'title' => 'Range',
'page callback' => 'drupal_get_form',
'page arguments' => array('form_test_range'),
'access callback' => TRUE,
);
$items['form-test/range/invalid'] = array(
'title' => 'Invalid range',
'page callback' => 'drupal_get_form',
'page arguments' => array('form_test_range_invalid'),
'access callback' => TRUE,
);
$items['form-test/checkboxes-radios'] = array(
'title' => t('Checkboxes, Radios'),
'page callback' => 'drupal_get_form',
@ -519,6 +537,41 @@ function form_test_limit_validation_errors_form_partial_submit($form, $form_stat
}
}
/**
* Builds a simple form using the FAPI #pattern proterty.
*/
function form_test_pattern_form($form, &$form_state) {
$form['textfield'] = array(
'#type' => 'textfield',
'#title' => 'One digit followed by lowercase letters',
'#pattern' => '[0-9][a-z]+',
);
$form['tel'] = array(
'#type' => 'tel',
'#title' => 'Everything except numbers',
'#pattern' => '[^\d]*',
);
$form['password'] = array(
'#type' => 'password',
'#title' => 'Password',
'#pattern' => '[01]+',
);
$form['url'] = array(
'#type' => 'url',
'#title' => 'Client side validation',
'#decription' => 'Just client side validation, using the #pattern attribute.',
'#attributes' => array(
'pattern' => '.*foo.*',
),
'#pattern' => 'ignored',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
return $form;
}
/**
* Create a header and options array. Helper function for callbacks.
*/
@ -1276,6 +1329,80 @@ function form_test_number($form, &$form_state, $element = 'number') {
return $form;
}
/**
* Form constructor for testing #type 'range' elements.
*
* @see form_test_range_submit()
* @ingroup forms
*/
function form_test_range($form, &$form_state) {
$form['with_default_value'] = array(
'#type' => 'range',
'#title' => 'Range with default value',
'#min' => 10,
'#max' => 20,
'#step' => 2,
'#default_value' => 18,
'#description' => 'The default value is 18.',
);
$form['float'] = array(
'#type' => 'range',
'#title' => 'Float',
'#min' => 10,
'#max' => 11,
'#step' => 'any',
'#description' => 'Floating point number between 10 and 11.',
);
$form['integer'] = array(
'#type' => 'range',
'#title' => 'Integer',
'#min' => 2,
'#max' => 8,
'#step' => 2,
'#description' => 'Even integer between 2 and 8.',
);
$form['offset'] = array(
'#type' => 'range',
'#title' => 'Offset',
'#min' => 2.9,
'#max' => 10.9,
'#description' => 'Value between 2.9 and 10.9.',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
return $form;
}
/**
* Form submission handler for form_test_range().
*/
function form_test_range_submit($form, &$form_state) {
drupal_json_output($form_state['values']);
exit;
}
/**
* Form constructor for testing invalid #type 'range' elements.
*
* @ingroup forms
*/
function form_test_range_invalid($form, &$form_state) {
$form['minmax'] = array(
'#type' => 'range',
'#min' => 10,
'#max' => 5,
'#title' => 'Invalid range',
'#description' => 'Minimum greater than maximum.',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
return $form;
}
/**
* Builds a form to test the placeholder attribute.
*/

View File

@ -62,7 +62,11 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase {
}
/**
* Overrides DrupalWebTestCase::setUp() specialized for upgrade testing.
* Overrides DrupalWebTestCase::setUp() for upgrade testing.
*
* @see DrupalWebTestCase::prepareDatabasePrefix()
* @see DrupalWebTestCase::changeDatabasePrefix()
* @see DrupalWebTestCase::prepareEnvironment()
*/
protected function setUp() {
global $user, $language_interface, $conf;
@ -76,54 +80,27 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase {
$this->loadedModules = module_list();
// Generate a temporary prefixed database to ensure that tests have a clean starting point.
$this->databasePrefix = 'simpletest' . mt_rand(1000, 1000000);
db_update('simpletest_test_id')
->fields(array('last_prefix' => $this->databasePrefix))
->condition('test_id', $this->testId)
->execute();
// Create the database prefix for this test.
$this->prepareDatabasePrefix();
// Clone the current connection and replace the current prefix.
$connection_info = Database::getConnectionInfo('default');
Database::renameConnection('default', 'simpletest_original_default');
foreach ($connection_info as $target => $value) {
$connection_info[$target]['prefix'] = array(
'default' => $value['prefix']['default'] . $this->databasePrefix,
);
}
Database::addConnectionInfo('default', 'default', $connection_info['default']);
// Prepare the environment for running tests.
$this->prepareEnvironment();
// Store necessary current values before switching to prefixed database.
$this->originalLanguage = $language_interface;
$this->originalLanguageDefault = variable_get('language_default');
$this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files');
$this->originalProfile = drupal_get_profile();
// Reset all statics and variables to perform tests in a clean environment.
$conf = array();
drupal_static_reset();
// Change the database prefix.
// All static variables need to be reset before the database prefix is
// changed, since Drupal\Core\Utility\CacheArray implementations attempt to
// write back to persistent caches when they are destructed.
$this->changeDatabasePrefix();
// Unregister the registry.
// This is required to make sure that the database layer works properly.
spl_autoload_unregister('drupal_autoload_class');
spl_autoload_unregister('drupal_autoload_interface');
// Create test directories ahead of installation so fatal errors and debug
// information can be logged during installation process.
// Use mock files directories with the same prefix as the database.
$public_files_directory = $this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10);
$private_files_directory = $public_files_directory . '/private';
$temp_files_directory = $private_files_directory . '/temp';
// Create the directories.
file_prepare_directory($public_files_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
file_prepare_directory($private_files_directory, FILE_CREATE_DIRECTORY);
file_prepare_directory($temp_files_directory, FILE_CREATE_DIRECTORY);
$this->generatedTestFiles = FALSE;
// Log fatal errors.
ini_set('log_errors', 1);
ini_set('error_log', $public_files_directory . '/error.log');
// Reset all statics and variables to perform tests in a clean environment.
$conf = array();
// Load the database from the portable PHP dump.
// The files may be gzipped.
foreach ($this->databaseDumpFiles as $file) {
@ -134,15 +111,16 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase {
}
// Set path variables.
$this->variable_set('file_public_path', $public_files_directory);
$this->variable_set('file_private_path', $private_files_directory);
$this->variable_set('file_temporary_path', $temp_files_directory);
$this->variable_set('file_public_path', $this->public_files_directory);
$this->variable_set('file_private_path', $this->private_files_directory);
$this->variable_set('file_temporary_path', $this->temp_files_directory);
$this->pass('Finished loading the dump.');
// Load user 1.
$this->originalUser = $user;
// Ensure that the session is not written to the new environment and replace
// the global $user session with uid 1 from the new test site.
drupal_save_session(FALSE);
// Login as uid 1.
$user = db_query('SELECT * FROM {users} WHERE uid = :uid', array(':uid' => 1))->fetchObject();
// Generate and set a D8-compatible session cookie.
@ -155,58 +133,6 @@ abstract class UpgradePathTestCase extends DrupalWebTestCase {
$this->setup = TRUE;
}
/**
* Override of DrupalWebTestCase::tearDown() specialized for upgrade testing.
*/
protected function tearDown() {
global $user, $language_interface;
// In case a fatal error occurred that was not in the test process read the
// log to pick up any fatal errors.
simpletest_log_read($this->testId, $this->databasePrefix, get_class($this), TRUE);
// Delete temporary files directory.
file_unmanaged_delete_recursive($this->originalFileDirectory . '/simpletest/' . substr($this->databasePrefix, 10));
// Get back to the original connection.
Database::removeConnection('default');
Database::renameConnection('simpletest_original_default', 'default');
// Remove all prefixed tables.
$tables = db_find_tables($this->databasePrefix . '%');
foreach ($tables as $table) {
db_drop_table($table);
}
// Return the user to the original one.
$user = $this->originalUser;
drupal_save_session(TRUE);
// Ensure that internal logged in variable and cURL options are reset.
$this->loggedInUser = FALSE;
$this->additionalCurlOptions = array();
// Reload module list and implementations to ensure that test module hooks
// aren't called after tests.
module_list(TRUE);
module_implements_reset();
// Reset the Field API.
field_cache_clear();
// Rebuild caches.
parent::refreshVariables();
// Reset language.
$language_interface = $this->originalLanguage;
if ($this->originalLanguageDefault) {
$GLOBALS['conf']['language_default'] = $this->originalLanguageDefault;
}
// Close the CURL handler.
$this->curlClose();
}
/**
* Specialized variable_set() that works even if the child site is not upgraded.
*

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Move a block in the blocks table from one region to another via select list.
*

View File

@ -1535,7 +1535,7 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
// Display creation form.
$langcode = LANGUAGE_NOT_SPECIFIED;
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertFieldByName("{$this->field_name}[$langcode]", '', 'Widget is displayed.');
// Submit with some value.
@ -1557,7 +1557,7 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
// Delete the vocabulary and verify that the widget is gone.
taxonomy_vocabulary_delete($this->vocabulary->vid);
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertNoFieldByName("{$this->field_name}[$langcode]", '', 'Widget is not displayed');
}
@ -1668,7 +1668,7 @@ class TaxonomyTermFieldMultipleVocabularyTestCase extends TaxonomyWebTestCase {
// Submit an entity with both terms.
$langcode = LANGUAGE_NOT_SPECIFIED;
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertFieldByName("{$this->field_name}[$langcode][]", '', 'Widget is displayed');
$edit = array(
"{$this->field_name}[$langcode][]" => array($term1->tid, $term2->tid),
@ -1707,7 +1707,7 @@ class TaxonomyTermFieldMultipleVocabularyTestCase extends TaxonomyWebTestCase {
$this->assertEqual(sizeof($field_info['settings']['allowed_values']), 1, 'Only one vocabulary is allowed for the field.');
// The widget should still be displayed.
$this->drupalGet('test-entity/add/test-bundle');
$this->drupalGet('test-entity/add/test_bundle');
$this->assertFieldByName("{$this->field_name}[$langcode][]", '', 'Widget is still displayed');
// Term 1 should still pass validation.

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
Drupal.toolbar = Drupal.toolbar || {};
/**

View File

@ -62,7 +62,7 @@ function translation_node_overview(Node $node) {
$title = t('n/a');
if (node_access('create', $node)) {
$text = t('add translation');
$path = 'node/add/' . str_replace('_', '-', $node->type);
$path = 'node/add/' . $node->type;
$links = language_negotiation_get_switch_links($type, $path);
$query = array('query' => array('translation' => $node->nid, 'target' => $langcode));
$options[] = empty($links->links[$langcode]['href']) ? l($text, $path, $query) : l($text, $links->links[$langcode]['href'], array_merge_recursive($links->links[$langcode], $query));

View File

@ -75,7 +75,7 @@ class TranslationTestCase extends DrupalWebTestCase {
$languages = language_list();
$prefixes = language_negotiation_url_prefixes();
$this->drupalGet('node/' . $node->nid . '/translate');
$this->assertLinkByHref($prefixes['es'] . '/node/add/' . str_replace('_', '-', $node->type), 0, t('The "add translation" link for %language points to the localized path of the target language.', array('%language' => $languages['es']->name)));
$this->assertLinkByHref($prefixes['es'] . '/node/add/' . $node->type, 0, t('The "add translation" link for %language points to the localized path of the target language.', array('%language' => $languages['es']->name)));
// Submit translation in Spanish.
$node_translation_title = $this->randomName();

View File

@ -404,8 +404,6 @@ function user_admin_settings() {
'#type' => 'number',
'#title' => t('Picture upload file size'),
'#default_value' => variable_get('user_picture_file_size', '30'),
'#size' => 10,
'#maxlength' => 10,
'#min' => 0,
'#field_suffix' => ' ' . t('KB'),
'#description' => t('Maximum allowed file size for uploaded pictures. Upload size is normally limited only by the PHP maximum post and file upload settings, and images are automatically scaled down to the dimensions specified above.'),

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Attach handlers to evaluate the strength of any password fields and to check
* that its confirmation is correct.
@ -157,6 +159,7 @@ Drupal.evaluatePasswordStrength = function (password, translate) {
strength = 5;
}
var indicatorText;
// Based on the strength, work out what text should be shown by the password strength meter.
if (strength < 60) {
indicatorText = translate.weak;

View File

@ -1,5 +1,7 @@
(function ($) {
"use strict";
/**
* Shows checked and disabled checkboxes for inherited permissions.
*/

View File

@ -2416,3 +2416,172 @@ class UserEntityCallbacksTestCase extends DrupalWebTestCase {
$this->assertEqual('user/' . $this->account->uid, $uri['path'], t('Correct user URI.'));
}
}
/**
* Functional tests for a user's ability to change their default language.
*/
class UserLanguageFunctionalTest extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'User language settings',
'description' => "Tests user's ability to change their default language.",
'group' => 'User',
);
}
function setUp() {
parent::setUp(array('user', 'language'));
}
/**
* Test if user can change their default language.
*/
function testUserLanguageConfiguration() {
global $base_url;
// User to add and remove language.
$admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages'));
// User to change their default language.
$web_user = $this->drupalCreateUser();
// Add custom language.
$this->drupalLogin($admin_user);
// Code for the language.
$langcode = 'xx';
// The English name for the language.
$name = $this->randomName(16);
$edit = array(
'predefined_langcode' => 'custom',
'langcode' => $langcode,
'name' => $name,
'direction' => '0',
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->drupalLogout();
// Login as normal user and edit account settings.
$this->drupalLogin($web_user);
$path = 'user/' . $web_user->uid . '/edit';
$this->drupalGet($path);
// Ensure language settings fieldset is available.
$this->assertText(t('Language'), t('Language selector available.'));
// Ensure custom language is present.
$this->assertText($name, t('Language present on form.'));
// Switch to our custom language.
$edit = array(
'preferred_langcode' => $langcode,
);
$this->drupalPost($path, $edit, t('Save'));
// Ensure form was submitted successfully.
$this->assertText(t('The changes have been saved.'), t('Changes were saved.'));
// Check if language was changed.
$elements = $this->xpath('//input[@id=:id]', array(':id' => 'edit-preferred-langcode-' . $langcode));
$this->assertTrue(isset($elements[0]) && !empty($elements[0]['checked']), t('Default language successfully updated.'));
$this->drupalLogout();
}
}
/**
* Functional test for language handling during user creation.
*/
class UserLanguageCreationTest extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'User language creation',
'description' => 'Tests whether proper language is stored for new users and access to language selector.',
'group' => 'User',
);
}
function setUp() {
parent::setUp(array('user', 'language'));
variable_set('user_register', USER_REGISTER_VISITORS);
}
/**
* Functional test for language handling during user creation.
*/
function testLocalUserCreation() {
// User to add and remove language and create new users.
$admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages', 'administer users'));
$this->drupalLogin($admin_user);
// Add predefined language.
$langcode = 'fr';
$edit = array(
'predefined_langcode' => 'fr',
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
$this->assertText('French', t('Language added successfully.'));
$this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), t('Correct page redirection.'));
// Set language negotiation.
$edit = array(
'language_interface[enabled][language-url]' => TRUE,
);
$this->drupalPost('admin/config/regional/language/detection', $edit, t('Save settings'));
$this->assertText(t('Language negotiation configuration saved.'), t('Set language negotiation.'));
// Check if the language selector is available on admin/people/create and
// set to the currently active language.
$this->drupalGet($langcode . '/admin/people/create');
$this->assertFieldChecked("edit-preferred-langcode-$langcode", t('Global language set in the language selector.'));
// Create a user with the admin/people/create form and check if the correct
// language is set.
$username = $this->randomName(10);
$edit = array(
'name' => $username,
'mail' => $this->randomName(4) . '@example.com',
'pass[pass1]' => $username,
'pass[pass2]' => $username,
);
$this->drupalPost($langcode . '/admin/people/create', $edit, t('Create new account'));
$user = user_load_by_name($username);
$this->assertEqual($user->preferred_langcode, $langcode, t('New user has correct preferred language set.'));
$this->assertEqual($user->langcode, $langcode, t('New user has correct profile language set.'));
// Register a new user and check if the language selector is hidden.
$this->drupalLogout();
$this->drupalGet($langcode . '/user/register');
$this->assertNoFieldByName('language[fr]', t('Language selector is not accessible.'));
$username = $this->randomName(10);
$edit = array(
'name' => $username,
'mail' => $this->randomName(4) . '@example.com',
);
$this->drupalPost($langcode . '/user/register', $edit, t('Create new account'));
$user = user_load_by_name($username);
$this->assertEqual($user->preferred_langcode, $langcode, t('New user has correct preferred language set.'));
$this->assertEqual($user->langcode, $langcode, t('New user has correct profile language set.'));
// Test if the admin can use the language selector and if the
// correct language is was saved.
$user_edit = $langcode . '/user/' . $user->uid . '/edit';
$this->drupalLogin($admin_user);
$this->drupalGet($user_edit);
$this->assertFieldChecked("edit-preferred-langcode-$langcode", t('Language selector is accessible and correct language is selected.'));
// Set pass_raw so we can login the new user.
$user->pass_raw = $this->randomName(10);
$edit = array(
'pass[pass1]' => $user->pass_raw,
'pass[pass2]' => $user->pass_raw,
);
$this->drupalPost($user_edit, $edit, t('Save'));
$this->drupalLogin($user);
$this->drupalGet($user_edit);
$this->assertFieldChecked("edit-preferred-langcode-$langcode", t('Language selector is accessible and correct language is selected.'));
}
}

View File

@ -2,8 +2,10 @@
* @file
* Preview for the Bartik theme.
*/
(function ($) {
"use strict";
Drupal.color = {
logoChanged: false,
callback: function(context, settings, form, farb, height, width) {

View File

@ -251,13 +251,6 @@ $drupal_hash_salt = '';
*/
$config_directory_name = '';
/**
* Configuration signature key.
*
* Drupal configuration files are signed using this key.
*/
$config_signature_key = '';
/**
* Base URL (optional).
*