Commit 7e504e93 authored by Dries's avatar Dries
Browse files

Merge branch '8.x' of git.drupal.org:project/drupal into 8.x

parents 958d9ad0 7e976297
......@@ -78,6 +78,7 @@ Drupal 8.0, xxxx-xx-xx (development version)
* Removed textgroups support from interface translation in favor of
native configuration language support.
* Reworked Gettext PO support to use pluggable read/write handlers.
- Added E-mail field type to core.
Drupal 7.0, 2011-01-05
----------------------
......
......@@ -42,7 +42,7 @@ Configuration system
- Daniel F. Kudwien 'sun' http://drupal.org/user/54136
- Alex Pott 'alexpott' http://drupal.org/user/157725
Configurable entity system
Configuration entity system
- Daniel F. Kudwien 'sun' http://drupal.org/user/54136
- Tim Plunkett 'tim.plunkett' http://drupal.org/user/241634
......
......@@ -18,7 +18,7 @@ function authorize_filetransfer_form($form, &$form_state) {
global $base_url, $is_https;
$form = array();
// If possible, we want to post this form securely via https.
// If possible, we want to post this form securely via HTTPS.
$form['#https'] = TRUE;
// Get all the available ways to transfer files.
......
......@@ -433,7 +433,7 @@ function conf_path($require_settings = TRUE, $reset = FALSE) {
* The hostname and optional port number, e.g. "www.example.com" or
* "www.example.com:8080".
* @param $script_name
* The part of the url following the hostname, including the leading slash.
* The part of the URL following the hostname, including the leading slash.
* @param $require_settings
* Defaults to TRUE. If TRUE, then only match directories with a
* 'settings.php' file. Otherwise match any directory.
......@@ -768,7 +768,7 @@ function drupal_settings_initialize() {
}
else {
// Otherwise use $base_url as session name, without the protocol
// to use the same session identifiers across http and https.
// to use the same session identifiers across HTTP and HTTPS.
list( , $session_name) = explode('://', $base_url, 2);
// HTTP_HOST can be modified by a visitor, but we already sanitized it
// in drupal_settings_initialize().
......@@ -1771,18 +1771,29 @@ function drupal_set_message($message = NULL, $type = 'status', $repeat = TRUE) {
}
/**
* Returns all messages that have been set.
* Returns all messages that have been set with drupal_set_message().
*
* @param $type
* (optional) Only return messages of this type.
* @param $clear_queue
* (optional) Set to FALSE if you do not want to clear the messages queue
* @param string $type
* (optional) Limit the messages returned by type. Defaults to NULL, meaning
* all types. These values are supported:
* - NULL
* - 'status'
* - 'warning'
* - 'error'
* @param bool $clear_queue
* (optional) If this is TRUE, the queue will be cleared of messages of the
* type specified in the $type parameter. Otherwise the queue will be left
* intact. Defaults to TRUE.
*
* @return
* An associative array, the key is the message type, the value an array
* of messages. If the $type parameter is passed, you get only that type,
* or an empty array if there are no such messages. If $type is not passed,
* all message types are returned, or an empty array if none exist.
* @return array
* A multidimensional array with keys corresponding to the set message types.
* The indexed array values of each contain the set messages for that type.
* The messages returned are limited to the type specified in the $type
* parameter. If there are no messages of the specified type, an empty array
* is returned.
*
* @see drupal_set_message()
* @see theme_status_messages()
*/
function drupal_get_messages($type = NULL, $clear_queue = TRUE) {
if ($messages = drupal_set_message()) {
......@@ -2245,6 +2256,9 @@ function _drupal_bootstrap_configuration() {
// Initialize the configuration, including variables from settings.php.
drupal_settings_initialize();
// Make sure we are using the test database prefix in child Drupal sites.
_drupal_initialize_db_test_prefix();
// Activate the class loader.
drupal_classloader();
......@@ -2310,17 +2324,9 @@ function _drupal_bootstrap_page_cache() {
}
/**
* Initializes the database system and registers autoload functions.
* In a test environment, get the test db prefix and set it in $databases.
*/
function _drupal_bootstrap_database() {
// Redirect the user to the installation script if Drupal has not been
// installed yet (i.e., if no $databases array has been defined in the
// settings.php file) and we are not already installing.
if (empty($GLOBALS['databases']) && !drupal_installation_attempted()) {
include_once DRUPAL_ROOT . '/core/includes/install.inc';
install_goto('core/install.php');
}
function _drupal_initialize_db_test_prefix() {
// The user agent header is used to pass a database prefix in the request when
// running tests. However, for security reasons, it is imperative that we
// validate we ourselves made the request.
......@@ -2348,6 +2354,20 @@ function _drupal_bootstrap_database() {
);
}
}
}
/**
* Initializes the database system by loading database.inc.
*/
function _drupal_bootstrap_database() {
// Redirect the user to the installation script if Drupal has not been
// installed yet (i.e., if no $databases array has been defined in the
// settings.php file) and we are not already installing.
if (empty($GLOBALS['databases']) && !drupal_installation_attempted()) {
include_once DRUPAL_ROOT . '/core/includes/install.inc';
install_goto('core/install.php');
}
// Initialize the database system. Note that the connection
// won't be initialized until it is actually requested.
......@@ -2404,47 +2424,62 @@ function drupal_get_bootstrap_phase() {
*
* @see Drupal\Core\DrupalKernel
*
* @param $reset
* A new container instance to reset the Drupal container to.
* @param Symfony\Component\DependencyInjection\Container $new_container
* A new container instance to replace the current.
* @param bool $rebuild
* (optional) Internal use only. Whether to enforce a rebuild of the container.
* Used by the testing framework to inject a fresh container for unit tests.
*
* @return Symfony\Component\DependencyInjection\Container
* The instance of the Container used to set up and maintain object
* instances.
*/
function drupal_container(Container $reset = NULL) {
function drupal_container(Container $new_container = NULL, $rebuild = FALSE) {
// We do not use drupal_static() here because we do not have a mechanism by
// which to reinitialize the stored objects, so a drupal_static_reset() call
// would leave Drupal in a nonfunctional state.
static $container = NULL;
if (isset($reset)) {
$container = $reset;
if ($rebuild) {
$container = NULL;
}
if (isset($new_container)) {
$container = $new_container;
}
elseif (!isset($container)) {
if (!isset($container)) {
// Return a ContainerBuilder instance with the bare essentials needed for any
// full bootstrap regardless of whether there will be a DrupalKernel involved.
// This will get merged with the full Kernel-built Container on normal page
// requests.
$container = new ContainerBuilder();
// Register configuration storage class and options.
// @todo The active store and its options need to be configurable.
// Use either global $conf (recursion warning) or global $config, or a
// bootstrap configuration *file* to allow to set/override this very
// lowest of low level configuration.
$container->setParameter('config.storage.options', array(
'connection' => 'default',
'target' => 'default',
));
$container->register('config.storage', 'Drupal\Core\Config\DatabaseStorage')
->addArgument('%config.storage.options%');
// Register active configuration storage.
$container
->register('config.cachedstorage.storage', 'Drupal\Core\Config\FileStorage')
->addArgument(config_get_config_directory(CONFIG_ACTIVE_DIRECTORY));
// @todo Replace this with a cache.factory service plus 'config' argument.
$container
->register('cache.config')
->setFactoryClass('Drupal\Core\Cache\CacheFactory')
->setFactoryMethod('get')
->addArgument('config');
$container
->register('config.storage', 'Drupal\Core\Config\CachedStorage')
->addArgument(new Reference('config.cachedstorage.storage'))
->addArgument(new Reference('cache.config'));
// Register configuration object factory.
$container->register('config.subscriber.globalconf', 'Drupal\Core\EventSubscriber\ConfigGlobalOverrideSubscriber');
$container->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher')
->addMethodCall('addSubscriber', array(new Reference('config.subscriber.globalconf')));
// Register configuration object factory.
$container->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
->addArgument(new Reference('config.storage'))
->addArgument(new Reference('dispatcher'));
// Register staging configuration storage.
$container
->register('config.storage.staging', 'Drupal\Core\Config\FileStorage')
->addArgument(config_get_config_directory(CONFIG_STAGING_DIRECTORY));
}
return $container;
}
......
......@@ -5,6 +5,8 @@
* Functions and interfaces for cache handling.
*/
use Drupal\Core\Cache\CacheFactory;
/**
* Instantiates and statically caches the correct class for a cache bin.
*
......@@ -32,9 +34,7 @@ function cache($bin = 'cache') {
// storage of a cache bin mid-request.
static $cache_objects;
if (!isset($cache_objects[$bin])) {
$cache_backends = cache_get_backends();
$class = isset($cache_backends[$bin]) ? $cache_backends[$bin] : $cache_backends['cache'];
$cache_objects[$bin] = new $class($bin);
$cache_objects[$bin] = CacheFactory::get($bin);
}
return $cache_objects[$bin];
}
......@@ -53,17 +53,7 @@ function cache($bin = 'cache') {
* The list of tags to invalidate cache items for.
*/
function cache_invalidate(array $tags) {
foreach (cache_get_backends() as $bin => $class) {
foreach (CacheFactory::getBackends() as $bin => $class) {
cache($bin)->invalidateTags($tags);
}
}
/**
* Returns a list of cache backends for this site.
*
* @return
* An associative array with cache bins as keys, and backend classes as value.
*/
function cache_get_backends() {
return variable_get('cache_classes', array('cache' => 'Drupal\Core\Cache\DatabaseBackend'));
}
......@@ -448,7 +448,7 @@ function drupal_get_query_parameters(array $query = NULL, array $exclude = array
* The query string to split.
*
* @return
* An array of url decoded couples $param_name => $value.
* An array of URL decoded couples $param_name => $value.
*/
function drupal_get_query_array($query) {
$result = array();
......@@ -1246,8 +1246,9 @@ function flood_is_allowed($name, $threshold, $window = 3600, $identifier = NULL)
* to being output to an HTML attribute value. It is often called as part of
* check_url() or filter_xss(), but those functions return an HTML-encoded
* string, so this function can be called independently when the output needs to
* be a plain-text string for passing to t(), l(), drupal_attributes(), or
* another function that will call check_plain() separately.
* be a plain-text string for passing to t(), l(),
* Drupal\Core\Template\Attribute, or another function that will call
* check_plain() separately.
*
* @param $uri
* A plain-text URI that might contain dangerous protocols.
......@@ -1300,10 +1301,11 @@ function drupal_strip_dangerous_protocols($uri) {
* @return
* A URI stripped of dangerous protocols and encoded for output to an HTML
* attribute value. Because it is already encoded, it should not be set as a
* value within a $attributes array passed to drupal_attributes(), because
* drupal_attributes() expects those values to be plain-text strings. To pass
* a filtered URI to drupal_attributes(), call
* drupal_strip_dangerous_protocols() instead.
* value within a $attributes array passed to Drupal\Core\Template\Attribute,
* because Drupal\Core\Template\Attribute expects those values to be
* plain-text strings. To pass a filtered URI to
* Drupal\Core\Template\Attribute, call drupal_strip_dangerous_protocols()
* instead.
*
* @see drupal_strip_dangerous_protocols()
*/
......@@ -1661,7 +1663,7 @@ function format_xml_elements($array) {
if ($value['key']) {
$output .= ' <' . $value['key'];
if (isset($value['attributes']) && is_array($value['attributes'])) {
$output .= drupal_attributes($value['attributes']);
$output .= new Attribute($value['attributes']);
}
if (isset($value['value']) && $value['value'] != '') {
......@@ -2086,7 +2088,7 @@ function _format_date_callback(array $matches = NULL, $new_langcode = NULL) {
* for the URL. If $options['language'] is omitted, the language will be
* obtained from language(LANGUAGE_TYPE_URL).
* - 'https': Whether this URL should point to a secure location. If not
* defined, the current scheme is used, so the user stays on http or https
* defined, the current scheme is used, so the user stays on HTTP or HTTPS
* respectively. TRUE enforces HTTPS and FALSE enforces HTTP, but HTTPS can
* only be enforced when the variable 'https' is set to TRUE.
* - 'base_url': Only used internally, to modify the base URL when a language
......@@ -2242,46 +2244,6 @@ function drupal_http_header_attributes(array $attributes = array()) {
return $attributes ? ' ' . implode('; ', $attributes) : '';
}
/**
* Converts an associative array to an XML/HTML tag attribute string.
*
* Each array key and its value will be formatted into an attribute string.
* If a value is itself an array, then its elements are concatenated to a single
* space-delimited string (for example, a class attribute with multiple values).
*
* Attribute values are sanitized by running them through check_plain().
* Attribute names are not automatically sanitized. When using user-supplied
* attribute names, it is strongly recommended to allow only white-listed names,
* since certain attributes carry security risks and can be abused.
*
* Examples of security aspects when using drupal_attributes:
* @code
* // By running the value in the following statement through check_plain,
* // the malicious script is neutralized.
* drupal_attributes(array('title' => t('<script>steal_cookie();</script>')));
*
* // The statement below demonstrates dangerous use of drupal_attributes, and
* // will return an onmouseout attribute with JavaScript code that, when used
* // as attribute in a tag, will cause users to be redirected to another site.
* //
* // In this case, the 'onmouseout' attribute should not be whitelisted --
* // you don't want users to have the ability to add this attribute or others
* // that take JavaScript commands.
* drupal_attributes(array('onmouseout' => 'window.location="http://malicious.com/";')));
* @endcode
*
* @param $attributes
* An associative array of key-value pairs to be converted to attributes.
*
* @return
* A string ready for insertion in a tag (starts with a space).
*
* @ingroup sanitization
*/
function drupal_attributes(array $attributes = array()) {
return new Attribute($attributes);
}
/**
* Formats an internal or external URL link as an HTML anchor tag.
*
......@@ -2303,7 +2265,8 @@ function drupal_attributes(array $attributes = array()) {
* - 'attributes': An associative array of HTML attributes to apply to the
* anchor tag. If element 'class' is included, it must be an array; 'title'
* must be a string; other elements are more flexible, as they just need
* to work in a call to drupal_attributes($options['attributes']).
* to work as an argument for the constructor of the class
* Drupal\Core\Template\Attribute($options['attributes']).
* - 'html' (default FALSE): Whether $text is HTML or just plain-text. For
* example, to make an image tag into a link, this must be set to TRUE, or
* you will see the escaped HTML image tag. $text is not sanitized if
......@@ -2370,7 +2333,7 @@ function l($text, $path, array $options = array()) {
}
// The result of url() is a plain-text URL. Because we are using it here
// in an HTML argument context, we need to encode it properly.
return '<a href="' . check_plain(url($path, $options)) . '"' . drupal_attributes($options['attributes']) . '>' . ($options['html'] ? $text : check_plain($text)) . '</a>';
return '<a href="' . check_plain(url($path, $options)) . '"' . new Attribute($options['attributes']) . '>' . ($options['html'] ? $text : check_plain($text)) . '</a>';
}
/**
......@@ -5182,7 +5145,7 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1)
// distribution we need to include the profile of the parent site (in which
// test runs are triggered).
if (drupal_valid_test_ua()) {
$testing_profile = variable_get('simpletest_parent_profile', FALSE);
$testing_profile = config('simpletest.settings')->get('parent_profile');
if ($testing_profile && $testing_profile != $profile) {
$searchdir[] = drupal_get_path('profile', $testing_profile) . '/' . $directory;
}
......
......@@ -17,14 +17,11 @@
* The extension type; e.g., 'module' or 'theme'.
* @param string $name
* The name of the module or theme to install default configuration for.
*
* @todo Make this acknowledge other storage engines rather than having
* SQL be hardcoded.
*/
function config_install_default_config($type, $name) {
$config_dir = drupal_get_path($type, $name) . '/config';
if (is_dir($config_dir)) {
$source_storage = new FileStorage(array('directory' => $config_dir));
$source_storage = new FileStorage($config_dir);
$target_storage = drupal_container()->get('config.storage');
$null_storage = new NullStorage();
......@@ -43,7 +40,9 @@ function config_install_default_config($type, $name) {
}
/**
* @todo Modules need a way to access the active store, whatever it is.
* Gets configuration object names starting with a given prefix.
*
* @see Drupal\Core\Config\StorageInterface::listAll()
*/
function config_get_storage_names_with_prefix($prefix = '') {
return drupal_container()->get('config.storage')->listAll($prefix);
......@@ -137,7 +136,7 @@ function config_sync_changes(array $config_changes, StorageInterface $source_sto
*/
function config_import() {
// Retrieve a list of differences between staging and the active store.
$source_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY)));
$source_storage = drupal_container()->get('config.storage.staging');
$target_storage = drupal_container()->get('config.storage');
$config_changes = config_sync_get_changes($source_storage, $target_storage);
......@@ -219,7 +218,7 @@ function config_import_invoke_owner(array $config_changes, StorageInterface $sou
function config_export() {
// Retrieve a list of differences between the active store and staging.
$source_storage = drupal_container()->get('config.storage');
$target_storage = new FileStorage(array('directory' => config_get_config_directory(CONFIG_STAGING_DIRECTORY)));
$target_storage = drupal_container()->get('config.storage.staging');
$config_changes = config_sync_get_changes($source_storage, $target_storage);
if (empty($config_changes)) {
......
......@@ -464,8 +464,8 @@ function file_create_url($uri) {
}
}
elseif ($scheme == 'http' || $scheme == 'https') {
// Check for http so that we don't have to implement getExternalUrl() for
// the http wrapper.
// Check for HTTP so that we don't have to implement getExternalUrl() for
// the HTTP wrapper.
return $uri;
}
else {
......
......@@ -6,6 +6,7 @@
*/
use Drupal\Core\Utility\Color;
use Drupal\Core\Template\Attribute;
/**
* @defgroup forms Form builder functions
......@@ -2670,7 +2671,7 @@ function theme_select($variables) {
element_set_attributes($element, array('id', 'name', 'size'));
_form_set_class($element, array('form-select'));
return '<select' . drupal_attributes($element['#attributes']) . '>' . form_select_options($element) . '</select>';
return '<select' . new Attribute($element['#attributes']) . '>' . form_select_options($element) . '</select>';
}
/**
......@@ -2784,7 +2785,7 @@ function theme_fieldset($variables) {
element_set_attributes($element, array('id'));
_form_set_class($element, array('form-wrapper'));
$output = '<fieldset' . drupal_attributes($element['#attributes']) . '>';
$output = '<fieldset' . new Attribute($element['#attributes']) . '>';
if (!empty($element['#title'])) {
// Always wrap fieldset legends in a SPAN for CSS positioning.
$output .= '<legend><span class="fieldset-legend">' . $element['#title'] . '</span></legend>';
......@@ -2806,7 +2807,8 @@ function theme_fieldset($variables) {
* Returns HTML for a radio button form element.
*
* Note: The input "name" attribute needs to be sanitized before output, which
* is currently done by passing all attributes to drupal_attributes().
* is currently done by initializing Drupal\Core\Template\Attribute with
* all the attributes.
*
* @param $variables
* An associative array containing:
......@@ -2826,7 +2828,7 @@ function theme_radio($variables) {
}
_form_set_class($element, array('form-radio'));
return '<input' . drupal_attributes($element['#attributes']) . ' />';
return '<input' . new Attribute($element['#attributes']) . ' />';
}
/**
......@@ -2853,7 +2855,7 @@ function theme_radios($variables) {
if (isset($element['#attributes']['title'])) {
$attributes['title'] = $element['#attributes']['title'];
}
return '<div' . drupal_attributes($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>';
return '<div' . new Attribute($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>';
}
/**
......@@ -2932,7 +2934,7 @@ function theme_date($variables) {
}
$attributes['class'][] = 'container-inline';
return '<div' . drupal_attributes($attributes) . '>' . drupal_render_children($element) . '</div>';
return '<div' . new Attribute($attributes) . '>' . drupal_render_children($element) . '</div>';
}
/**
......@@ -3054,8 +3056,8 @@ function form_process_radios($element) {
$element[$key] += array(
'#type' => 'radio',
'#title' => $choice,
// The key is sanitized in drupal_attributes() during output from the
// theme function.
// The key is sanitized in Drupal\Core\Template\Attribute during output
// from the theme function.
'#return_value' => $key,
// Use default or FALSE. A value of FALSE means that the radio button is
// not 'checked'.
......@@ -3094,7 +3096,7 @@ function theme_checkbox($variables) {
}
_form_set_class($element, array('form-checkbox'));
return '<input' . drupal_attributes($element['#attributes']) . ' />';
return '<input' . new Attribute($element['#attributes']) . ' />';
}
/**
......@@ -3120,7 +3122,7 @@ function theme_checkboxes($variables) {
if (isset($element['#attributes']['title'])) {
$attributes['title'] = $element['#attributes']['title'];
}
return '<div' . drupal_attributes($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>';
return '<div' . new Attribute($attributes) . '>' . (!empty($element['#children']) ? $element['#children'] : '') . '</div>';
}
/**
......@@ -3338,7 +3340,7 @@ function theme_container($variables) {
$element['#attributes']['class'][] = 'form-wrapper';
}
return '<div' . drupal_attributes($element['#attributes']) . '>' . $element['#children'] . '</div>';
return '<div' . new Attribute($element['#attributes']) . '>' . $element['#children'] . '</div>';
}
/**
......@@ -3914,7 +3916,7 @@ function theme_button($variables) {
$element['#attributes']['class'][] = 'form-button-disabled';
}
return '<input' . drupal_attributes($element['#attributes']) . ' />';
return '<input' . new Attribute($element['#attributes']) . ' />';
}
/**
......@@ -3943,7 +3945,7 @@ function theme_image_button($variables) {
$element['#attributes']['class'][] = 'form-button-disabled';
}
return '<input' . drupal_attributes($element['#attributes']) . ' />';
return '<input' . new Attribute($element['#attributes']) . ' />';
}
/**
......@@ -3960,7 +3962,7 @@ function theme_hidden($variables) {
$element = $variables['element'];
$element['#attributes']['type'] = 'hidden';
element_set_attributes($element, array('name', 'value'));
return '<input' . drupal_attributes($element['#attributes']) . " />\n";
return '<input' . new Attribute($element['#attributes']) . " />\n";
}
/**
......@@ -3980,7 +3982,7 @@ function theme_textfield($variables) {
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder'));
_form_set_class($element, array('form-text'));
return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element);
return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element);
}
/**
......@@ -4000,7 +4002,7 @@ function theme_email($variables) {
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder'));
_form_set_class($element, array('form-email'));
return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element);
return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element);
}
/**
......@@ -4034,7 +4036,7 @@ function theme_tel($variables) {
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder'));
_form_set_class($element, array('form-tel'));
return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element);
return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element);
}
/**
......@@ -4055,7 +4057,7 @@ function theme_number($variables) {
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']) . ' />';
$output = '<input' . new Attribute($element['#attributes']) . ' />';
return $output;
}
......@@ -4078,7 +4080,7 @@ function theme_range($variables) {
element_set_attributes($element, array('id', 'name', 'value', 'step', 'min', 'max'));
_form_set_class($element, array('form-range'));
$output = '<input' . drupal_attributes($element['#attributes']) . ' />';
$output = '<input' . new Attribute($element['#attributes']) . ' />';
return $output;
}
......@@ -4154,7 +4156,7 @@ function form_type_range_value($element, $input = FALSE) {
}
/**
* Returns HTML for a url form element.
* Returns HTML for a URL form element.
*
* @param $variables
* An associative array containing:
......@@ -4170,7 +4172,7 @@ function theme_url($variables) {
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder'));
_form_set_class($element, array('form-url'));
return '<input' . drupal_attributes($element['#attributes']) . ' />' . drupal_render_children($element);
return '<input' . new Attribute($element['#attributes']) . ' />' . drupal_render_children($element);
}
/**
......@@ -4190,7 +4192,7 @@ function theme_search($variables) {
element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength', 'placeholder'));