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
parent
0b95d68f71
commit
d90d0ebbda
|
@ -45,16 +45,16 @@ class Weight extends FormElement {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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 @@ class Weight extends FormElement {
|
|||
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;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
name: 'Element info test'
|
||||
type: module
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
|
@ -0,0 +1,24 @@
|
|||
<?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 @@ class WeightTest extends KernelTestBase {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue