Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix submit filters #6877

Merged
merged 16 commits into from
Feb 22, 2021
Merged
18 changes: 17 additions & 1 deletion src/Admin/AbstractAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ public function getFilterParameters()
}
}

$parameters = array_merge($parameters, $filters);
$parameters = $this->mergeParameters($parameters, $filters);
VincentLanglet marked this conversation as resolved.
Show resolved Hide resolved

// always force the parent value
if ($this->isChild() && $this->getParentAssociationMapping()) {
Expand Down Expand Up @@ -3335,6 +3335,22 @@ private function buildRoutes(): void
$extension->configureRoutes($this, $this->routes);
}
}

/**
* Merge parameters but replace them when it's a subarray.
*/
private function mergeParameters(array $parameters, array $filters): array
{
foreach (array_intersect_key($parameters, $filters) as $key => $parameter) {
if (\is_array($parameter)) {
$parameters[$key] = array_replace($parameter, $filters[$key]);
} else {
$parameters[$key] = $filters[$key];
}
}

return array_merge($parameters, array_diff_key($filters, $parameters));
}
}

class_exists(\Sonata\Form\Validator\ErrorElement::class);
40 changes: 25 additions & 15 deletions src/Resources/public/Admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -334,22 +334,16 @@ var Admin = {
return;
}

var defaultValues = $.param({'filter': JSON.parse(this.dataset.defaultValues)}).split('&'),
submittedValues = $form.serialize().split('&');

// Compare default and submitted filter values in `keyValue` representation. (`keyValue` ex: "filter[publish][value][end]=2020-12-12")
// Only allow to submit non default and non empty values, because empty values means they are not present.
var changedValues = submittedValues.filter(function (keyValue) {
return defaultValues.indexOf(keyValue) === -1 && keyValue.split('=')[1] !== '';
var defaults = Admin.convert_query_string_to_object(
$.param({'filter': JSON.parse(this.dataset.defaultValues)})
VincentLanglet marked this conversation as resolved.
Show resolved Hide resolved
);

// Keep only changed values
$form.find('[name*=filter]').each(function (i, field) {
if ((defaults[field.name] || '') === field.value) {
field.removeAttribute('name');
}
});

// Disable all inputs and enable only the required ones
$form.find('[name*=filter]').attr('disabled', 'disabled');
changedValues
.map(function (keyValue) { return decodeURIComponent(keyValue.split('=')[0]); })
.forEach(function (key) {
$form.find('[name="' + key + '"]').removeAttr('disabled');
});
});

/* Advanced filters */
Expand Down Expand Up @@ -674,6 +668,7 @@ var Admin = {
Admin.handleScroll(footer, navbar, wrapper);
}
},

handleScroll: function(footer, navbar, wrapper) {
if (footer.length && jQuery(window).scrollTop() + jQuery(window).height() != jQuery(document).height()) {
jQuery(footer).addClass('stuck');
Expand Down Expand Up @@ -703,6 +698,7 @@ var Admin = {
}, 250)
);
},

handleResize: function(footer, navbar, wrapper) {
if (navbar.length && jQuery(navbar).hasClass('stuck')) {
jQuery(navbar).width(jQuery(wrapper).outerWidth());
Expand All @@ -712,6 +708,7 @@ var Admin = {
jQuery(footer).width(jQuery(wrapper).outerWidth());
}
},

refreshNavbarStuckClass: function(topNavbar) {
var stuck = jQuery('#navbar-stuck');

Expand All @@ -724,6 +721,7 @@ var Admin = {

stuck.html('body.fixed .content-header .navbar.stuck { top: ' + jQuery(topNavbar).outerHeight() + 'px; }');
},

// http://davidwalsh.name/javascript-debounce-function
debounce: function (func, wait, immediate) {
var timeout;
Expand All @@ -750,6 +748,7 @@ var Admin = {
}
};
},

setup_readmore_elements: function(subject) {
Admin.log('[core|setup_readmore_elements] setup readmore elements on', subject);

Expand All @@ -761,9 +760,11 @@ var Admin = {
});
});
},

handle_top_navbar_height: function() {
jQuery('body.fixed .content-wrapper').css('padding-top', jQuery('.navbar-static-top').outerHeight());
},

setup_form_submit: function(subject) {
Admin.log('[core|setup_form_submit] setup form submit on', subject);

Expand All @@ -782,6 +783,15 @@ var Admin = {
}
});
},

convert_query_string_to_object: function (str) {
return str.split('&').reduce(function (accumulator, keyValue) {
accumulator[decodeURIComponent(keyValue.split('=')[0])] = keyValue.split('=')[1];

return accumulator;
}, {});
},

/**
* Remember open tab after refreshing page.
*/
Expand Down
136 changes: 136 additions & 0 deletions tests/Admin/AdminTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2832,4 +2832,140 @@ public function getDeprecatedAbstractAdminConstructorArgs(): iterable
[1, 1, 1],
];
}

public function provideMergeParameters()
{
return [
[
[
'_sort_order' => 'DESC',
'_sort_by' => 'id',
'status' => [
'type' => '1',
'value' => 'foo',
],
],
[
'status' => [
'type' => '2',
'value' => 'foo',
],
],
[
'_sort_order' => 'DESC',
'_sort_by' => 'id',
'status' => [
'type' => '2',
'value' => 'foo',
],
],
],
[
[
'status' => [
'type' => '1',
],
],
[
'status' => [
'value' => 'foo',
],
],
[
'status' => [
'type' => '1',
'value' => 'foo',
],
],
],
[
[
'status' => [
'type' => '1',
'value' => 'foo',
],
],
[
'status' => [
'type' => '2',
],
'_page' => 2,
'_per_page' => 25,
],
[
'status' => [
'type' => '2',
'value' => 'foo',
],
'_page' => 2,
'_per_page' => 25,
],
],
[
[
'status' => [
'type' => '1',
'value' => [
'foo',
'bar',
],
],
],
[
'status' => [
'value' => [
'foo',
],
],
],
[
'status' => [
'type' => '1',
'value' => [
'foo',
],
],
],
],
[
[
'status' => [
'value' => [
'foo',
'bar',
],
],
],
[
'status' => [
'value' => [
'baz',
],
],
],
[
'status' => [
'value' => [
'baz',
],
],
],
],
];
}

/**
* @dataProvider provideMergeParameters
*/
public function testMergeParameters(array $parameters, array $filters, array $result): void
{
$admin = new FilteredAdmin('sonata.post.admin.model', 'Application\Sonata\FooBundle\Entity\Model', 'Sonata\FooBundle\Controller\ModelAdminController');

$reflectionClass = new \ReflectionClass($admin);

$method = $reflectionClass->getMethod('mergeParameters');
$method->setAccessible(true);

$this->assertSame($result, $method->invokeArgs($admin, [$parameters, $filters]));
}
}