Skip to content
Snippets Groups Projects
Unverified Commit d77f9a68 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #2979044 by BR0kEN, alexpott: Unable to change menu items weight when...

Issue #2979044 by BR0kEN, alexpott: Unable to change menu items weight when the "system.site.weight_select_max" exceeded and "#pre_render" for "number" element is modified

(cherry picked from commit d90d0ebb)
parent b2af74b6
No related branches found
No related tags found
No related merge requests found
......@@ -45,16 +45,16 @@ public function getInfo() {
}
/**
* Expands a weight element into a select element.
* Expands a weight element into a select/number element.
*/
public static function processWeight(&$element, FormStateInterface $form_state, &$complete_form) {
// If the number of options is small enough, use a select field. Otherwise,
// use a number field.
$type = $element['#delta'] <= \Drupal::config('system.site')->get('weight_select_max') ? 'select' : 'number';
$element = array_merge($element, \Drupal::service('element_info')->getInfo($type));
$element['#is_weight'] = TRUE;
$element_info_manager = \Drupal::service('element_info');
// If the number of options is small enough, use a select field.
$max_elements = \Drupal::config('system.site')->get('weight_select_max');
if ($element['#delta'] <= $max_elements) {
$element['#type'] = 'select';
if ($type === 'select') {
$weights = [];
for ($n = (-1 * $element['#delta']); $n <= $element['#delta']; $n++) {
$weights[$n] = $n;
......@@ -65,14 +65,10 @@ public static function processWeight(&$element, FormStateInterface $form_state,
ksort($weights);
}
$element['#options'] = $weights;
$element += $element_info_manager->getInfo('select');
}
// Otherwise, use a text field.
else {
$element['#type'] = 'number';
// Use a field big enough to fit most weights.
$element['#size'] = 10;
$element += $element_info_manager->getInfo('number');
}
return $element;
......
name: 'Element info test'
type: module
package: Testing
version: VERSION
core: 8.x
<?php
/**
* @file
* Element info test.
*/
/**
* Implements hook_element_info_alter().
*/
function element_info_test_element_info_alter(array &$info) {
$info['number'] += ['#pre_render' => []];
/* @see \Drupal\KernelTests\Core\Render\Element\WeightTest::testProcessWeightSelectMax() */
$info['number']['#pre_render'][] = 'element_info_test_element_pre_render';
}
/**
* {@inheritdoc}
*
* @see \Drupal\KernelTests\Core\Render\Element\WeightTest::testProcessWeightSelectMax()
*/
function element_info_test_element_pre_render(array $element) {
return $element;
}
......@@ -3,6 +3,8 @@
namespace Drupal\KernelTests\Core\Render\Element;
use Drupal\Core\Form\FormState;
use Drupal\Core\Render\Element\Number;
use Drupal\Core\Render\Element\Select;
use Drupal\Core\Render\Element\Weight;
use Drupal\KernelTests\KernelTestBase;
......@@ -15,7 +17,7 @@ class WeightTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['system'];
protected static $modules = ['system', 'element_info_test'];
/**
* {@inheritdoc}
......@@ -49,4 +51,76 @@ public function testProcessWeight() {
);
}
/**
* Test transformation from "select" to "number" for MAX_DELTA + 1.
*
* @throws \Exception
*
* @covers ::processWeight
*/
public function testProcessWeightSelectMax() {
$form_state = new FormState();
$definition = [
'#type' => 'weight',
'#delta' => $this->container
->get('config.factory')
->get('system.site')
->get('weight_select_max'),
// Expected by the "doBuildForm()" method of "form_builder" service.
'#parents' => [],
];
$assert = function ($type, array $element, array $expected) use ($form_state) {
// Pretend we have a form to trigger the "#process" callbacks.
$element = $this->container
->get('form_builder')
->doBuildForm(__FUNCTION__, $element, $form_state);
$expected['#type'] = $type;
foreach ($expected as $property => $value) {
static::assertSame($value, $element[$property]);
}
return $element;
};
// When the "#delta" is less or equal to maximum the "weight" must be
// rendered as a "select".
$select = $definition;
$assert('select', $select, [
'#process' => [
[Select::class, 'processSelect'],
[Select::class, 'processAjaxForm'],
],
'#pre_render' => [
[Select::class, 'preRenderSelect'],
],
]);
$number = $definition;
// Increase "#delta" in order to start rendering "number" elements
// instead of "select".
$number['#delta']++;
// The "number" element definition has the "#pre_render" declaration by
// default. The "hook_element_info_alter()" allows to modify the definition
// of an element. We must be sure the standard "#pre_render" callbacks
// are presented (unless explicitly removed) even in a case when the array
// is modified by the alter hook.
$assert('number', $number, [
'#process' => [
[Number::class, 'processAjaxForm'],
],
'#element_validate' => [
[Number::class, 'validateNumber'],
],
'#pre_render' => [
[Number::class, 'preRenderNumber'],
// The custom callback is appended.
/* @see element_info_test_element_info_alter() */
'element_info_test_element_pre_render',
],
]);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment