Commit cf7cc519 authored by webchick's avatar webchick

Issue #1356170 by ohnobinki, tim.plunkett: Remove all uses of...

Issue #1356170 by ohnobinki, tim.plunkett: Remove all uses of array_merge_recursive(), or document why they are being used instead of NestedArray::mergeDeep().
parent 97ccf0f5
......@@ -5,6 +5,8 @@
* Functions for use with Drupal's Ajax framework.
*/
use Drupal\Component\Utility\NestedArray;
/**
* @defgroup ajax Ajax framework
* @{
......@@ -290,7 +292,7 @@ function ajax_render($commands = array()) {
$scripts = drupal_add_js();
if (!empty($scripts['settings'])) {
$settings = $scripts['settings'];
array_unshift($commands, ajax_command_settings(call_user_func_array('array_merge_recursive', $settings['data']), TRUE));
array_unshift($commands, ajax_command_settings(NestedArray::mergeDeepArray($settings['data']), TRUE));
}
// Allow modules to alter any Ajax response.
......
......@@ -1347,19 +1347,11 @@ function file_download() {
$uri = $scheme . '://' . $target;
if (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) {
// Let other modules provide headers and controls access to the file.
// module_invoke_all() uses array_merge_recursive() which merges header
// values into a new array. To avoid that and allow modules to override
// headers instead, use array_merge() to merge the returned arrays.
$headers = array();
foreach (module_implements('file_download') as $module) {
$function = $module . '_file_download';
$result = $function($uri);
$headers = module_invoke_all('file_download', $uri);
foreach ($headers as $result) {
if ($result == -1) {
throw new AccessDeniedHttpException();
}
if (isset($result) && is_array($result)) {
$headers = array_merge($headers, $result);
}
}
if (count($headers)) {
return file_transfer($uri, $headers);
......
......@@ -6,6 +6,7 @@
*/
use Drupal\Component\Graph\Graph;
use Drupal\Component\Utility\NestedArray;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -921,7 +922,7 @@ function module_hook_info() {
if (function_exists($function)) {
$result = $function();
if (isset($result) && is_array($result)) {
$hook_info = array_merge_recursive($hook_info, $result);
$hook_info = NestedArray::mergeDeep($hook_info, $result);
}
}
}
......@@ -1002,7 +1003,7 @@ function module_invoke_all($hook) {
if (function_exists($function)) {
$result = call_user_func_array($function, $args);
if (isset($result) && is_array($result)) {
$return = array_merge_recursive($return, $result);
$return = NestedArray::mergeDeep($return, $result);
}
elseif (isset($result)) {
$return[] = $result;
......
......@@ -9,6 +9,7 @@
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Component\Utility\NestedArray;
/**
* JSON response object for AJAX requests.
......@@ -134,7 +135,7 @@ protected function ajaxRender(Request $request) {
$scripts = drupal_add_js();
if (!empty($scripts['settings'])) {
$settings = $scripts['settings'];
$this->addCommand(new SettingsCommand(call_user_func_array('array_merge_recursive', $settings['data']), TRUE), TRUE);
$this->addCommand(new SettingsCommand(NestedArray::mergeDeepArray($settings['data']), TRUE), TRUE);
}
$commands = $this->commands;
......
......@@ -11,6 +11,7 @@
use Drupal\Core\Entity\Query\QueryInterface;
use Exception;
use Drupal\Component\Uuid\Uuid;
use Drupal\Component\Utility\NestedArray;
/**
......@@ -678,9 +679,9 @@ public function getFieldDefinitions(array $constraints) {
// Invoke hooks.
$result = module_invoke_all($this->entityType . '_property_info');
$this->entityFieldInfo = array_merge_recursive($this->entityFieldInfo, $result);
$this->entityFieldInfo = NestedArray::mergeDeep($this->entityFieldInfo, $result);
$result = module_invoke_all('entity_field_info', $this->entityType);
$this->entityFieldInfo = array_merge_recursive($this->entityFieldInfo, $result);
$this->entityFieldInfo = NestedArray::mergeDeep($this->entityFieldInfo, $result);
$hooks = array('entity_field_info', $this->entityType . '_property_info');
drupal_alter($hooks, $this->entityFieldInfo, $this->entityType);
......
......@@ -13,6 +13,7 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\edit\Form\EditFieldForm;
use Drupal\Component\Utility\NestedArray;
/**
* Implements hook_custom_theme().
......@@ -65,7 +66,7 @@ function edit_toolbar() {
// Include the attachments and settings for all available editors.
$attachments = drupal_container()->get('edit.editor.selector')->getAllEditorAttachments();
$tab['edit']['tray']['#attached'] = array_merge_recursive($tab['edit']['tray']['#attached'], $attachments);
$tab['edit']['tray']['#attached'] = NestedArray::mergeDeep($tab['edit']['tray']['#attached'], $attachments);
return $tab;
}
......
......@@ -776,7 +776,7 @@ function file_ajax_upload() {
$output = theme('status_messages') . drupal_render($form);
$js = drupal_add_js();
$settings = call_user_func_array('array_merge_recursive', $js['settings']['data']);
$settings = NestedArray::mergeDeepArray($js['settings']['data']);
$response = new AjaxResponse();
return $response->addCommand(new ReplaceCommand(NULL, $output, $settings));
......
......@@ -7,6 +7,7 @@
namespace Drupal\node;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityFormController;
......@@ -91,7 +92,7 @@ public function form(array $form, array &$form_state, EntityInterface $node) {
// handlers to the form buttons below. Remove hook_form() entirely.
$function = node_hook($node->type, 'form');
if ($function && ($extra = $function($node, $form_state))) {
$form = array_merge_recursive($form, $extra);
$form = NestedArray::mergeDeep($form, $extra);
}
// If the node type has a title, and the node type form defined no special
// weight for it, we default to a weight of -5 for consistency.
......
......@@ -52,8 +52,8 @@ function testGetRdfNamespaces() {
$this->assertTrue(!empty($element), 'Two prefixes can be assigned the same namespace.');
$element = $this->xpath('//html[contains(@prefix, :prefix_binding)]', array(
':prefix_binding' => 'dc: ',
':prefix_binding' => 'dc: http://purl.org/dc/terms/',
));
$this->assertTrue(empty($element), 'A prefix with conflicting namespaces is discarded.');
$this->assertTrue(!empty($element), 'When a prefix has conflicting namespaces, the first declared one is used.');
}
}
......@@ -39,6 +39,6 @@ function testGetRdfNamespaces() {
$this->assertEqual($ns['rdfs'], 'http://www.w3.org/2000/01/rdf-schema#', 'A prefix declared once is included.');
$this->assertEqual($ns['foaf'], 'http://xmlns.com/foaf/0.1/', 'The same prefix declared in several implementations of hook_rdf_namespaces() is valid as long as all the namespaces are the same.');
$this->assertEqual($ns['foaf1'], 'http://xmlns.com/foaf/0.1/', 'Two prefixes can be assigned the same namespace.');
$this->assertTrue(!isset($ns['dc']), 'A prefix with conflicting namespaces is discarded.');
$this->assertEqual($ns['dc'], 'http://purl.org/dc/terms/', 'When a prefix has conflicting namespaces, the first declared one is used.');
}
}
......@@ -5,6 +5,7 @@
* Enables semantically enriched output for Drupal sites in the form of RDFa.
*/
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Template\Attribute;
/**
......@@ -99,27 +100,16 @@ function rdf_rdf_namespaces() {
* implement it.
*/
function rdf_get_namespaces() {
$rdf_namespaces = module_invoke_all('rdf_namespaces');
// module_invoke_all() uses array_merge_recursive() which might return nested
// arrays if several modules redefine the same prefix multiple times. We need
// to ensure the array of namespaces is flat and only contains strings as
// URIs.
foreach ($rdf_namespaces as $prefix => $uri) {
if (is_array($uri)) {
if (count(array_unique($uri)) == 1) {
// All namespaces declared for this prefix are the same, merge them all
// into a single namespace.
$rdf_namespaces[$prefix] = $uri[0];
}
else {
// There are conflicting namespaces for this prefix, do not include
// duplicates in order to avoid asserting any inaccurate RDF
// statements.
unset($rdf_namespaces[$prefix]);
}
$namespaces = array();
// In order to resolve duplicate namespaces by using the earliest defined
// namespace, do not use module_invoke_all().
foreach (module_implements('rdf_namespaces') as $module) {
$function = $module . '_rdf_namespaces';
if (function_exists($function)) {
$namespaces = NestedArray::mergeDeep($function(), $namespaces);
}
}
return $rdf_namespaces;
return $namespaces;
}
/**
......@@ -703,7 +693,7 @@ function rdf_preprocess_username(&$variables) {
// (see http://www.w3.org/TR/rdfa-syntax/#rdfa-attributes).
// Therefore, merge rather than override so as not to clobber values set by
// earlier preprocess functions.
$variables['attributes'] = array_merge_recursive($variables['attributes'], $attributes);
$variables['attributes'] = NestedArray::mergeDeep($variables['attributes'], $attributes);
}
/**
......
......@@ -158,6 +158,14 @@ function testAjaxCommands() {
);
$this->assertCommand($commands, $expected, "'settings' AJAX command issued with correct data");
// Test that the settings command merges settings properly.
$commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'settings' command with setting merging")));
$expected = array(
'command' => 'settings',
'settings' => array('ajax_forms_test' => array('foo' => 9001)),
);
$this->assertCommand($commands, $expected, "'settings' AJAX command with setting merging");
// Tests the 'add_css' command.
$commands = $this->drupalPostAJAX($form_path, $edit, array('op' => t("AJAX 'add_css' command")));
$expected = array(
......
......@@ -245,6 +245,18 @@ function ajax_forms_test_ajax_commands_form($form, &$form_state) {
),
);
// Tests the 'settings' command with a callback which sets the same
// setting multiple times. This is used to check that settings are
// merged properly (e.g., array_merge_recursive() merges settings
// incorrectly, #1356170).
$form['settings_command_with_merging_example'] = array(
'#type' => 'submit',
'#value' => t("AJAX 'settings' command with setting merging"),
'#ajax' => array(
'callback' => 'ajax_forms_test_advanced_commands_settings_with_merging_callback',
),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
......@@ -407,6 +419,16 @@ function ajax_forms_test_advanced_commands_add_css_callback($form, $form_state)
return array('#type' => 'ajax', '#commands' => $commands);
}
/**
* Ajax callback for 'settings' but with setting overrides.
*/
function ajax_forms_test_advanced_commands_settings_with_merging_callback($form, $form_state) {
drupal_add_js(array('ajax_forms_test' => array('foo' => 42)), 'setting');
drupal_add_js(array('ajax_forms_test' => array('foo' => 9001)), 'setting');
return array('#type' => 'ajax', '#commands' => array());
}
/**
* Form constructor for AJAX validation form.
*
......
......@@ -5,6 +5,7 @@
* User page callbacks for the Translation module.
*/
use Drupal\Component\Utility\NestedArray;
use Drupal\node\Plugin\Core\Entity\Node;
/**
......@@ -71,7 +72,7 @@ function translation_node_overview(Node $node) {
$options['add'] = array(
'title' => t('add translation'),
) + $links->links[$langcode];
$options['add'] = array_merge_recursive($options['add'], $query);
$options['add'] = NestedArray::mergeDeep($options['add'], $query);
}
}
$status = t('Not translated');
......
......@@ -763,6 +763,9 @@ function template_process_username(&$variables) {
// to use the former unless they want to add attributes on the link only.
// If a link is being rendered, these need to be merged. Some attributes are
// themselves arrays, so the merging needs to be recursive.
// This purposefully does not use
// \Drupal\Component\Utility\NestedArray::mergeDeep() for performance
// reasons, since it is potentially called very often.
$variables['link_options']['attributes'] = array_merge_recursive($variables['link_attributes'], $variables['attributes']);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment