Skip to content

[Form] Allow pass filter callback to delete_empty option. #20496

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

Merged
merged 1 commit into from
Jul 26, 2017

Conversation

Koc
Copy link
Contributor

@Koc Koc commented Nov 11, 2016

Q A
Branch? master
Bug fix? yes
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #13601, #13940, #22008, #22014
License MIT
Doc PR coming soon

Copy link
Contributor

@HeahDude HeahDude left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, thanks for your proposal!

$isNew = !isset($previousData[$name]);

// $isNew can only be true if allowAdd is true, so we don't
// need to check allowAdd again
if ($child->isEmpty() && ($isNew || $this->allowDelete)) {
if (($child->isEmpty() || (null !== $isEmptyCallback && $isEmptyCallback($child->getData()))) && ($isNew || $this->allowDelete)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add a variable above to ease readability:

/* @var $child FormInterface */
$isNew = !isset($previousData[$name]);
$isEmpty = $child->isEmpty() || (null !== $isEmptyCallback && $isEmptyCallback($child->getData());

// $isNew can only be true if allowAdd is true, so we don't
// need to check allowAdd again
if ($isEmpty && ($isNew || $this->allowDelete)) {

@@ -97,6 +98,7 @@ public function configureOptions(OptionsResolver $resolver)
'entry_type' => __NAMESPACE__.'\TextType',
'entry_options' => array(),
'delete_empty' => false,
'is_empty_callback' => null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add:

$resolver->setAllowedTypes('is_empty_callback', array('null', 'callable'));

@Koc Koc force-pushed the form-is-empty-callback branch 3 times, most recently from d542c63 to c3e6ff5 Compare November 12, 2016 10:50
@Koc
Copy link
Contributor Author

Koc commented Nov 12, 2016

@HeahDude done. Also I've changed the test for better description of this new feature.

@nicolas-grekas nicolas-grekas added this to the 3.x milestone Dec 6, 2016
@Koc
Copy link
Contributor Author

Koc commented Dec 26, 2016

can anybody review and merge?

@HeahDude
Copy link
Contributor

Some may have some concern about the naming of this option, for me it's a 👍

Status: Reviewed

@xabbuh
Copy link
Member

xabbuh commented Feb 8, 2017

I agree with the implementation, but the option name doesn't sound good. For example, we don't check if the whole collection is empty, but only check for each submitted entry if it should be ignored. Can we think of a better name?

@Koc
Copy link
Contributor Author

Koc commented Feb 8, 2017

give some examples of a better name, I'll rename it

@xabbuh
Copy link
Member

xabbuh commented Feb 8, 2017

What about something like filter_entry as we are basically filter our collection entries inside the callback?

@murilolobato
Copy link

If is_empty_callback is a option, I would rename it to just is_empty.

@fabpot
Copy link
Member

fabpot commented Mar 22, 2017

@Koc What about @xabbuh suggestion for the name?

@Koc Koc force-pushed the form-is-empty-callback branch 4 times, most recently from d9703d6 to cbd5707 Compare March 23, 2017 11:14
@Koc
Copy link
Contributor Author

Koc commented Mar 23, 2017

@fabpot done, except I prefer entry_filter to be consistent with other options like entry_type/entry_options. Callable should return true for leave entry in collection.

Test failure is unrelated.

@Koc Koc force-pushed the form-is-empty-callback branch from cbd5707 to 57a2aa5 Compare March 23, 2017 12:54
@Koc Koc changed the title [Form] Added is_empty_callback option to collection type. [Form] Added entry_filter option to collection type. Mar 23, 2017
@yceruto
Copy link
Member

yceruto commented Mar 23, 2017

IMHO, the option should be the same delete_empty, accepting bool or callable. Use true to delete empty (non-compound) entries, and use a callable function to delete empty (compound with or without data_class) entries like Author(null) or array('firstName' => '').

In case of compound entries with data_class:

'delete_empty' => function (Author $author = null) {
    return null === $author || empty($author->getFirstName());
},

In case of compound entries without data_class:

'delete_empty' => function ($author) {
    return empty($author['firstName']);
},

Thus, we avoid problems to use a new option entry_filter (learning curve!!) which will depend of delete_empty = true also.

@murilolobato
Copy link

When the property gets renamed, I can add the test I've made in #22014

$isNew = !isset($previousData[$name]);
$needRemove = $child->isEmpty() || (null !== $entryFilter && !$entryFilter($child->getData()));
Copy link
Member

@yceruto yceruto Mar 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is about whether the child form/data is empty or not, right?, so the previous name isEmpty sounds better IMO ;)

@Koc Koc force-pushed the form-is-empty-callback branch 3 times, most recently from 691cc34 to 4c0011e Compare March 24, 2017 12:31
$isNew = !isset($previousData[$name]);
$isEmpty = $child->isEmpty() || true === $entryFilter($child->getData());
Copy link
Member

@yceruto yceruto Mar 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The $entryFilter and the empty closure function looks a bit overkill, can be simplified?

$isEmpty = $child->isEmpty() || (is_callable($this->deleteEmpty) && true === $this->deleteEmpty($child->getData());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

));
$this->assertTrue($form->has('0'));
$this->assertFalse($form->has('1'));
$this->assertEquals(array('s_first', 's_last'), $form[0]->getData());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

foreach ($form as $name => $child) {
/* @var $child FormInterface */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change should not be done in master.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not? it improves autocomplete

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this should target 2.7 :)

@Koc Koc force-pushed the form-is-empty-callback branch from 4c0011e to 3b7f11a Compare April 9, 2017 21:18
@yceruto
Copy link
Member

yceruto commented Jun 4, 2017

Should be rebased to 3.4 branch?

@Koc Koc force-pushed the form-is-empty-callback branch from 3b7f11a to ff51ad8 Compare July 23, 2017 00:00
@Koc Koc changed the base branch from master to 3.4 July 23, 2017 00:00
@Koc Koc force-pushed the form-is-empty-callback branch from ff51ad8 to 8b49f00 Compare July 23, 2017 00:03
@Koc
Copy link
Contributor Author

Koc commented Jul 23, 2017

@yceruto done
@ogizanagi please review

foreach ($form as $name => $child) {
/* @var $child FormInterface */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this should go on a lower branch. Also, It'd rather be:

+            /** @var FormInterface $child */
             foreach ($form as $name => $child) {
-                 /* @var $child FormInterface */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, will open PR for that. Where can I find information about standards for inline @var phpdoc?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See PSR-5: https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md#3-definitions

About the foreach, though:

This Standard does not cover this specific instance as a foreach statement is not considered to be a "Structural Element" but a Control Flow statement.

but still:

It is RECOMMENDED to precede a "Structural Element" with a DocBlock where it is defined and not with each usage.

$isNew = !isset($previousData[$name]);
$isEmpty = $child->isEmpty() || (is_callable($entryFilter) && true === $entryFilter($child->getData()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the callback was set, shouldn't it prevail over (or actually replace entirely) the isEmpty implementation?

- $isEmpty = $child->isEmpty() || (is_callable($entryFilter) && true === $entryFilter($child->getData()));
+ $isEmpty = is_callable($entryFilter) ? $entryFilter($child->getData()) : $child->isEmpty();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imho not. It will force us to duplicate standard checks inside callables

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not convinced you need those standard checks to be run anyway. For instance, you'll already have to check for the data not being null inside your callable before further checks.

@Koc Koc force-pushed the form-is-empty-callback branch from 8b49f00 to e697559 Compare July 23, 2017 09:51
@Koc Koc force-pushed the form-is-empty-callback branch from e697559 to 8630abe Compare July 23, 2017 09:57
@Koc
Copy link
Contributor Author

Koc commented Jul 23, 2017

@ogizanagi updated again :), now all green

@@ -148,14 +148,15 @@ public function onSubmit(FormEvent $event)
throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)');
}

if ($this->deleteEmpty) {
$previousData = $event->getForm()->getData();
if ($entryFilter = $this->deleteEmpty) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess $entryFilter can be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? This variable uses some lines bottom

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, but why not use $this->deleteEmpty directly? IMHO $this->deleteEmpty($child->getData()) is quite easy to understand too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because $this->deleteEmpty() will call undefined method ResizeFormListener::deleteEmpty()

Copy link
Contributor

@ogizanagi ogizanagi Jul 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and ($this->deleteEmpty)($child->getData()) is only doable in PHP 7.0+

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, my bad ;)

@fabpot
Copy link
Member

fabpot commented Jul 26, 2017

Thank you @Koc.

@fabpot fabpot merged commit 8630abe into symfony:3.4 Jul 26, 2017
@fabpot
Copy link
Member

fabpot commented Jul 26, 2017

@Koc Can you submit a pull request to update the docs? Thank you

fabpot added a commit that referenced this pull request Jul 26, 2017
…on. (Koc)

This PR was merged into the 3.4 branch.

Discussion
----------

[Form] Allow pass filter callback to delete_empty option.

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | yes
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #13601, #13940, #22008, #22014
| License       | MIT
| Doc PR        | coming soon

Commits
-------

8630abe [Form] Allow pass filter callback to delete_empty option.
This was referenced Oct 18, 2017
@Koc Koc deleted the form-is-empty-callback branch July 22, 2019 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants