Issue #3266568 by mxr576, sourabhjain, quietone: Refactor array_merge() usage in loops as possible for performance

merge-requests/3490/head
catch 2023-02-17 12:16:21 +00:00
parent 74f7e5acc8
commit 8df6544ec1
26 changed files with 68 additions and 57 deletions

View File

@ -72,7 +72,7 @@ class AuthenticationCollector implements AuthenticationCollectorInterface {
krsort($this->providerOrders); krsort($this->providerOrders);
// Merge nested providers from $this->providers into $this->sortedProviders. // Merge nested providers from $this->providers into $this->sortedProviders.
$this->sortedProviders = array_merge([], ...$this->providerOrders); $this->sortedProviders = array_merge(...$this->providerOrders);
} }
return $this->sortedProviders; return $this->sortedProviders;

View File

@ -107,7 +107,7 @@ class BreadcrumbManager implements ChainBreadcrumbBuilderInterface {
// Sort the builders according to priority. // Sort the builders according to priority.
krsort($this->builders); krsort($this->builders);
// Merge nested builders from $this->builders into $this->sortedBuilders. // Merge nested builders from $this->builders into $this->sortedBuilders.
$this->sortedBuilders = array_merge([], ...$this->builders); $this->sortedBuilders = array_merge(...$this->builders);
} }
return $this->sortedBuilders; return $this->sortedBuilders;
} }

View File

@ -264,7 +264,7 @@ class ConfigManager implements ConfigManagerInterface {
foreach ($names as $name) { foreach ($names as $name) {
$dependencies[] = $dependency_manager->getDependentEntities($type, $name); $dependencies[] = $dependency_manager->getDependentEntities($type, $name);
} }
return array_merge([], ...$dependencies); return array_merge(...$dependencies);
} }
/** /**
@ -292,9 +292,9 @@ class ConfigManager implements ConfigManagerInterface {
$storage = $this->entityTypeManager->getStorage($entity_type_id); $storage = $this->entityTypeManager->getStorage($entity_type_id);
// Remove the keys since there are potential ID clashes from different // Remove the keys since there are potential ID clashes from different
// configuration entity types. // configuration entity types.
$entities_to_return = array_merge($entities_to_return, array_values($storage->loadMultiple($entities_to_load))); $entities_to_return[] = array_values($storage->loadMultiple($entities_to_load));
} }
return $entities_to_return; return array_merge(...$entities_to_return);
} }
/** /**
@ -487,13 +487,14 @@ class ConfigManager implements ConfigManagerInterface {
$missing_dependencies = []; $missing_dependencies = [];
foreach ($this->activeStorage->readMultiple($this->activeStorage->listAll()) as $config_data) { foreach ($this->activeStorage->readMultiple($this->activeStorage->listAll()) as $config_data) {
if (isset($config_data['dependencies']['content'])) { if (isset($config_data['dependencies']['content'])) {
$content_dependencies = array_merge($content_dependencies, $config_data['dependencies']['content']); $content_dependencies[] = $config_data['dependencies']['content'];
} }
if (isset($config_data['dependencies']['enforced']['content'])) { if (isset($config_data['dependencies']['enforced']['content'])) {
$content_dependencies = array_merge($content_dependencies, $config_data['dependencies']['enforced']['content']); $content_dependencies[] = $config_data['dependencies']['enforced']['content'];
} }
} }
foreach (array_unique($content_dependencies) as $content_dependency) { $unique_content_dependencies = array_unique(array_merge(...$content_dependencies));
foreach ($unique_content_dependencies as $content_dependency) {
// Format of the dependency is entity_type:bundle:uuid. // Format of the dependency is entity_type:bundle:uuid.
[$entity_type, $bundle, $uuid] = explode(':', $content_dependency, 3); [$entity_type, $bundle, $uuid] = explode(':', $content_dependency, 3);
if (!$this->entityRepository->loadEntityByUuid($entity_type, $uuid)) { if (!$this->entityRepository->loadEntityByUuid($entity_type, $uuid)) {

View File

@ -129,7 +129,8 @@ class Query extends QueryBase implements QueryInterface {
$prefix_length = strlen($prefix); $prefix_length = strlen($prefix);
// Search the conditions for restrictions on configuration object names. // Search the conditions for restrictions on configuration object names.
$names = FALSE; $filter_by_names = [];
$has_added_restrictions = FALSE;
$id_condition = NULL; $id_condition = NULL;
$id_key = $this->entityType->getKey('id'); $id_key = $this->entityType->getKey('id');
if ($this->condition->getConjunction() == 'AND') { if ($this->condition->getConjunction() == 'AND') {
@ -140,21 +141,22 @@ class Query extends QueryBase implements QueryInterface {
if (is_string($condition['field']) && ($operator == 'IN' || $operator == '=')) { if (is_string($condition['field']) && ($operator == 'IN' || $operator == '=')) {
// Special case ID lookups. // Special case ID lookups.
if ($condition['field'] == $id_key) { if ($condition['field'] == $id_key) {
$has_added_restrictions = TRUE;
$ids = (array) $condition['value']; $ids = (array) $condition['value'];
$names = array_map(function ($id) use ($prefix) { $filter_by_names[] = array_map(static function ($id) use ($prefix) {
return $prefix . $id; return $prefix . $id;
}, $ids); }, $ids);
} }
elseif (in_array($condition['field'], $lookup_keys)) { elseif (in_array($condition['field'], $lookup_keys)) {
$has_added_restrictions = TRUE;
// If we don't find anything then there are no matches. No point in // If we don't find anything then there are no matches. No point in
// listing anything. // listing anything.
$names = [];
$keys = (array) $condition['value']; $keys = (array) $condition['value'];
$keys = array_map(function ($value) use ($condition) { $keys = array_map(static function ($value) use ($condition) {
return $condition['field'] . ':' . $value; return $condition['field'] . ':' . $value;
}, $keys); }, $keys);
foreach ($this->getConfigKeyStore()->getMultiple($keys) as $list) { foreach ($this->getConfigKeyStore()->getMultiple($keys) as $list) {
$names = array_merge($names, $list); $filter_by_names[] = $list;
} }
} }
} }
@ -166,7 +168,7 @@ class Query extends QueryBase implements QueryInterface {
// We stop at the first restricting condition on name. In the case where // We stop at the first restricting condition on name. In the case where
// there are additional restricting conditions, results will be // there are additional restricting conditions, results will be
// eliminated when the conditions are checked on the loaded records. // eliminated when the conditions are checked on the loaded records.
if ($names !== FALSE) { if ($has_added_restrictions !== FALSE) {
// If the condition has been responsible for narrowing the list of // If the condition has been responsible for narrowing the list of
// configuration to check there is no point in checking it further. // configuration to check there is no point in checking it further.
unset($conditions[$condition_key]); unset($conditions[$condition_key]);
@ -174,52 +176,56 @@ class Query extends QueryBase implements QueryInterface {
} }
} }
} }
// If no restrictions on IDs were found, we need to parse all records. // If no restrictions on IDs were found, we need to parse all records.
if ($names === FALSE) { if ($has_added_restrictions === FALSE) {
$names = $this->configFactory->listAll($prefix); $filter_by_names = $this->configFactory->listAll($prefix);
}
else {
$filter_by_names = array_merge(...$filter_by_names);
} }
// In case we have an ID condition, try to narrow down the list of config // In case we have an ID condition, try to narrow down the list of config
// objects to load. // objects to load.
if ($id_condition && !empty($names)) { if ($id_condition && !empty($filter_by_names)) {
$value = $id_condition['value']; $value = $id_condition['value'];
$filter = NULL; $filter = NULL;
switch ($id_condition['operator']) { switch ($id_condition['operator']) {
case '<>': case '<>':
$filter = function ($name) use ($value, $prefix_length) { $filter = static function ($name) use ($value, $prefix_length) {
$id = substr($name, $prefix_length); $id = substr($name, $prefix_length);
return $id !== $value; return $id !== $value;
}; };
break; break;
case 'STARTS_WITH': case 'STARTS_WITH':
$filter = function ($name) use ($value, $prefix_length) { $filter = static function ($name) use ($value, $prefix_length) {
$id = substr($name, $prefix_length); $id = substr($name, $prefix_length);
return strpos($id, $value) === 0; return strpos($id, $value) === 0;
}; };
break; break;
case 'CONTAINS': case 'CONTAINS':
$filter = function ($name) use ($value, $prefix_length) { $filter = static function ($name) use ($value, $prefix_length) {
$id = substr($name, $prefix_length); $id = substr($name, $prefix_length);
return strpos($id, $value) !== FALSE; return strpos($id, $value) !== FALSE;
}; };
break; break;
case 'ENDS_WITH': case 'ENDS_WITH':
$filter = function ($name) use ($value, $prefix_length) { $filter = static function ($name) use ($value, $prefix_length) {
$id = substr($name, $prefix_length); $id = substr($name, $prefix_length);
return strrpos($id, $value) === strlen($id) - strlen($value); return strrpos($id, $value) === strlen($id) - strlen($value);
}; };
break; break;
} }
if ($filter) { if ($filter) {
$names = array_filter($names, $filter); $filter_by_names = array_filter($filter_by_names, $filter);
} }
} }
// Load the corresponding records. // Load the corresponding records.
$records = []; $records = [];
foreach ($this->configFactory->loadMultiple($names) as $config) { foreach ($this->configFactory->loadMultiple($filter_by_names) as $config) {
$records[substr($config->getName(), $prefix_length)] = $config->get(); $records[substr($config->getName(), $prefix_length)] = $config->get();
} }
return $records; return $records;

View File

@ -88,9 +88,9 @@ class PreExistingConfigException extends ConfigException {
} }
return $config_name; return $config_name;
}, $config_names); }, $config_names);
$flat_config_objects = array_merge($flat_config_objects, $config_names); $flat_config_objects[] = $config_names;
} }
return $flat_config_objects; return array_merge(...$flat_config_objects);
} }
} }

View File

@ -56,7 +56,7 @@ trait SchemaCheckTrait {
foreach ($config_data as $key => $value) { foreach ($config_data as $key => $value) {
$errors[] = $this->checkValue($key, $value); $errors[] = $this->checkValue($key, $value);
} }
$errors = array_merge([], ...$errors); $errors = array_merge(...$errors);
if (empty($errors)) { if (empty($errors)) {
return TRUE; return TRUE;
} }

View File

@ -560,8 +560,9 @@ class SqlContentEntityStorage extends ContentEntityStorageBase implements SqlEnt
// returns an array keyed by property names so remove the keys // returns an array keyed by property names so remove the keys
// before array_merge() to avoid losing data with fields having the // before array_merge() to avoid losing data with fields having the
// same columns i.e. value. // same columns i.e. value.
$column_names = array_merge($column_names, array_values($table_mapping->getColumnNames($data_field))); $column_names[] = array_values($table_mapping->getColumnNames($data_field));
} }
$column_names = array_merge(...$column_names);
$query->fields('data', $column_names); $query->fields('data', $column_names);
} }

View File

@ -499,7 +499,7 @@ class ModuleHandler implements ModuleHandlerInterface {
foreach ($extra_types as $extra_type) { foreach ($extra_types as $extra_type) {
$extra_modules[] = array_keys($this->getImplementationInfo($extra_type . '_alter')); $extra_modules[] = array_keys($this->getImplementationInfo($extra_type . '_alter'));
} }
$extra_modules = array_merge([], ...$extra_modules); $extra_modules = array_merge(...$extra_modules);
// If any modules implement one of the extra hooks that do not implement // If any modules implement one of the extra hooks that do not implement
// the primary hook, we need to add them to the $modules array in their // the primary hook, we need to add them to the $modules array in their
// appropriate order. $this->getImplementationInfo() can only return // appropriate order. $this->getImplementationInfo() can only return

View File

@ -700,7 +700,8 @@ class FileSystem implements FileSystemInterface {
* @see \Drupal\Core\File\FileSystemInterface::scanDirectory() * @see \Drupal\Core\File\FileSystemInterface::scanDirectory()
*/ */
protected function doScanDirectory($dir, $mask, array $options = [], $depth = 0) { protected function doScanDirectory($dir, $mask, array $options = [], $depth = 0) {
$files = []; $files_in_sub_dirs = [];
$files_in_this_directory = [];
// Avoid warnings when opendir does not have the permissions to open a // Avoid warnings when opendir does not have the permissions to open a
// directory. // directory.
if ($handle = @opendir($dir)) { if ($handle = @opendir($dir)) {
@ -714,19 +715,17 @@ class FileSystem implements FileSystemInterface {
$uri = "$dir/$filename"; $uri = "$dir/$filename";
} }
if ($options['recurse'] && is_dir($uri)) { if ($options['recurse'] && is_dir($uri)) {
// Give priority to files in this folder by merging them in after $files_in_sub_dirs[] = $this->doScanDirectory($uri, $mask, $options, $depth + 1);
// any subdirectory files.
$files = array_merge($this->doScanDirectory($uri, $mask, $options, $depth + 1), $files);
} }
elseif ($depth >= $options['min_depth'] && preg_match($mask, $filename)) { elseif ($depth >= $options['min_depth'] && preg_match($mask, $filename)) {
// Always use this match over anything already set in $files with // Always use this match over anything already set with the same
// the same $options['key']. // $options['key'].
$file = new \stdClass(); $file = new \stdClass();
$file->uri = $uri; $file->uri = $uri;
$file->filename = $filename; $file->filename = $filename;
$file->name = pathinfo($filename, PATHINFO_FILENAME); $file->name = pathinfo($filename, PATHINFO_FILENAME);
$key = $options['key']; $key = $options['key'];
$files[$file->$key] = $file; $files_in_this_directory[$file->$key] = $file;
if ($options['callback']) { if ($options['callback']) {
$options['callback']($uri); $options['callback']($uri);
} }
@ -739,7 +738,9 @@ class FileSystem implements FileSystemInterface {
$this->logger->error('@dir can not be opened', ['@dir' => $dir]); $this->logger->error('@dir can not be opened', ['@dir' => $dir]);
} }
return $files; // Give priority to files in this folder by merging them after
// any subdirectory files.
return array_merge(array_merge(...$files_in_sub_dirs), $files_in_this_directory);
} }
} }

View File

@ -108,7 +108,7 @@ class MimeTypeGuesser implements MimeTypeGuesserInterface {
*/ */
protected function sortGuessers() { protected function sortGuessers() {
krsort($this->guessers); krsort($this->guessers);
return array_merge([], ...$this->guessers); return array_merge(...$this->guessers);
} }
} }

View File

@ -166,7 +166,7 @@ class LoggerChannel implements LoggerChannelInterface {
*/ */
protected function sortLoggers() { protected function sortLoggers() {
krsort($this->loggers); krsort($this->loggers);
return array_merge([], ...$this->loggers); return array_merge(...$this->loggers);
} }
} }

View File

@ -132,7 +132,7 @@ class PathProcessorManager implements InboundPathProcessorInterface, OutboundPat
*/ */
protected function sortProcessors($type) { protected function sortProcessors($type) {
krsort($this->{$type}); krsort($this->{$type});
return array_merge([], ...$this->{$type}); return array_merge(...$this->{$type});
} }
} }

View File

@ -72,7 +72,7 @@ class RouteProcessorManager implements OutboundRouteProcessorInterface {
*/ */
protected function sortProcessors() { protected function sortProcessors() {
krsort($this->outboundProcessors); krsort($this->outboundProcessors);
return array_merge([], ...$this->outboundProcessors); return array_merge(...$this->outboundProcessors);
} }
} }

View File

@ -36,14 +36,14 @@ class MethodFilter implements FilterInterface {
} }
if (!in_array($method, $supported_methods, TRUE)) { if (!in_array($method, $supported_methods, TRUE)) {
$all_supported_methods = array_merge($supported_methods, $all_supported_methods); $all_supported_methods[] = $supported_methods;
$collection->remove($name); $collection->remove($name);
} }
} }
if (count($collection)) { if (count($collection)) {
return $collection; return $collection;
} }
throw new MethodNotAllowedException(array_unique($all_supported_methods)); throw new MethodNotAllowedException(array_unique(array_merge(...$all_supported_methods)));
} }
} }

View File

@ -78,7 +78,7 @@ class TranslationManager implements TranslationInterface, TranslatorInterface {
*/ */
protected function sortTranslators() { protected function sortTranslators() {
krsort($this->translators); krsort($this->translators);
return array_merge([], ...$this->translators); return array_merge(...$this->translators);
} }
/** /**

View File

@ -183,8 +183,9 @@ class Attribute implements \ArrayAccess, \IteratorAggregate, MarkupInterface {
// Merge the values passed in from the classes array. // Merge the values passed in from the classes array.
// The argument is cast to an array to support comma separated single // The argument is cast to an array to support comma separated single
// values or one or more array arguments. // values or one or more array arguments.
$classes = array_merge($classes, (array) $arg); $classes[] = (array) $arg;
} }
$classes = array_merge(...$classes);
// Merge if there are values, just add them otherwise. // Merge if there are values, just add them otherwise.
if (isset($this->storage['class']) && $this->storage['class'] instanceof AttributeArray) { if (isset($this->storage['class']) && $this->storage['class'] instanceof AttributeArray) {
@ -271,8 +272,9 @@ class Attribute implements \ArrayAccess, \IteratorAggregate, MarkupInterface {
// Merge the values passed in from the classes array. // Merge the values passed in from the classes array.
// The argument is cast to an array to support comma separated single // The argument is cast to an array to support comma separated single
// values or one or more array arguments. // values or one or more array arguments.
$classes = array_merge($classes, (array) $arg); $classes[] = (array) $arg;
} }
$classes = array_merge(...$classes);
// Remove the values passed in from the value array. Use array_values() to // Remove the values passed in from the value array. Use array_values() to
// ensure that the array index remains sequential. // ensure that the array index remains sequential.

View File

@ -90,9 +90,9 @@ class JUnitConverter {
if ($file && !$child->attributes()->file) { if ($file && !$child->attributes()->file) {
$child->addAttribute('file', $file); $child->addAttribute('file', $file);
} }
$test_cases = array_merge($test_cases, static::findTestCases($child, $element)); $test_cases[] = static::findTestCases($child, $element);
} }
return $test_cases; return array_merge(...$test_cases);
} }
/** /**

View File

@ -195,12 +195,12 @@ trait TestSetupTrait {
$exceptions = []; $exceptions = [];
while ($class) { while ($class) {
if (property_exists($class, 'configSchemaCheckerExclusions')) { if (property_exists($class, 'configSchemaCheckerExclusions')) {
$exceptions = array_merge($exceptions, $class::$configSchemaCheckerExclusions); $exceptions[] = $class::$configSchemaCheckerExclusions;
} }
$class = get_parent_class($class); $class = get_parent_class($class);
} }
// Filter out any duplicates. // Filter out any duplicates.
return array_unique($exceptions); return array_unique(array_merge(...$exceptions));
} }
} }

View File

@ -71,7 +71,7 @@ class ConfigTranslationMapperList extends ControllerBase {
$mappers[$weight] = $mapper; $mappers[$weight] = $mapper;
} }
$build['#rows'] = array_merge([], ...$mappers); $build['#rows'] = array_merge(...$mappers);
return $build; return $build;
} }

View File

@ -50,7 +50,7 @@ class ReadOnlyModeMethodFilter implements FilterInterface {
$all_supported_methods[] = $route->getMethods(); $all_supported_methods[] = $route->getMethods();
} }
$all_supported_methods = array_merge([], ...$all_supported_methods); $all_supported_methods = array_merge(...$all_supported_methods);
$collection = $this->inner->filter($collection, $request); $collection = $this->inner->filter($collection, $request);
if (!$this->readOnlyModeIsEnabled) { if (!$this->readOnlyModeIsEnabled) {

View File

@ -308,7 +308,7 @@ function locale_translate_batch_refresh(&$context) {
foreach ($context['results']['stats'] as $report) { foreach ($context['results']['stats'] as $report) {
$strings[] = $report['strings']; $strings[] = $report['strings'];
} }
$strings = array_merge([], ...$strings); $strings = array_merge(...$strings);
} }
if ($strings) { if ($strings) {
// Initialize multi-step string refresh. // Initialize multi-step string refresh.

View File

@ -49,7 +49,7 @@ class RegisterEntityResolversCompilerPass implements CompilerPassInterface {
*/ */
protected function sort($services) { protected function sort($services) {
krsort($services); krsort($services);
return array_merge([], ...$services); return array_merge(...$services);
} }
} }

View File

@ -75,7 +75,7 @@ class RegisterSerializationClassesCompilerPass implements CompilerPassInterface
*/ */
protected function sort($services) { protected function sort($services) {
krsort($services); krsort($services);
return array_merge([], ...$services); return array_merge(...$services);
} }
} }

View File

@ -163,7 +163,7 @@ class RenderedEntity extends FieldPluginBase implements CacheableDependencyInter
foreach ($view_displays as $view_display) { foreach ($view_displays as $view_display) {
$tags[] = $view_display->getCacheTags(); $tags[] = $view_display->getCacheTags();
} }
return array_merge([], ...$tags); return array_merge(...$tags);
} }
/** /**

View File

@ -1429,7 +1429,7 @@ class Sql extends QueryPluginBase {
* Get the arguments attached to the WHERE and HAVING clauses of this query. * Get the arguments attached to the WHERE and HAVING clauses of this query.
*/ */
public function getWhereArgs() { public function getWhereArgs() {
return array_merge([], ...array_column($this->where, 'args'), ...array_column($this->having, 'args')); return array_merge(...array_column($this->where, 'args'), ...array_column($this->having, 'args'));
} }
/** /**

View File

@ -43,7 +43,7 @@ class AuthenticationCollectorTest extends UnitTestCase {
krsort($providers); krsort($providers);
// Merge nested providers from $providers into $sorted_providers. // Merge nested providers from $providers into $sorted_providers.
$sorted_providers = array_merge([], ...$providers); $sorted_providers = array_merge(...$providers);
$this->assertEquals($sorted_providers, $authentication_collector->getSortedProviders()); $this->assertEquals($sorted_providers, $authentication_collector->getSortedProviders());
// Test AuthenticationCollector::getProvider() and // Test AuthenticationCollector::getProvider() and