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) {
|
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['#is_weight'] = TRUE;
|
||||||
|
|
||||||
$element_info_manager = \Drupal::service('element_info');
|
if ($type === 'select') {
|
||||||
// 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';
|
|
||||||
$weights = [];
|
$weights = [];
|
||||||
for ($n = (-1 * $element['#delta']); $n <= $element['#delta']; $n++) {
|
for ($n = (-1 * $element['#delta']); $n <= $element['#delta']; $n++) {
|
||||||
$weights[$n] = $n;
|
$weights[$n] = $n;
|
||||||
|
@ -65,14 +65,10 @@ class Weight extends FormElement {
|
||||||
ksort($weights);
|
ksort($weights);
|
||||||
}
|
}
|
||||||
$element['#options'] = $weights;
|
$element['#options'] = $weights;
|
||||||
$element += $element_info_manager->getInfo('select');
|
|
||||||
}
|
}
|
||||||
// Otherwise, use a text field.
|
|
||||||
else {
|
else {
|
||||||
$element['#type'] = 'number';
|
|
||||||
// Use a field big enough to fit most weights.
|
// Use a field big enough to fit most weights.
|
||||||
$element['#size'] = 10;
|
$element['#size'] = 10;
|
||||||
$element += $element_info_manager->getInfo('number');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $element;
|
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;
|
namespace Drupal\KernelTests\Core\Render\Element;
|
||||||
|
|
||||||
use Drupal\Core\Form\FormState;
|
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\Core\Render\Element\Weight;
|
||||||
use Drupal\KernelTests\KernelTestBase;
|
use Drupal\KernelTests\KernelTestBase;
|
||||||
|
|
||||||
|
@ -15,7 +17,7 @@ class WeightTest extends KernelTestBase {
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
protected static $modules = ['system'];
|
protected static $modules = ['system', 'element_info_test'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@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