codefog/contao-haste

Boolean saveCallbacks in DcaAjaxOperationsListener with strict database

Closed this issue · 8 comments

This issue relates to #196 but I guess we need another solution.

I tried to support haste v5 in m-vo/facebook-import, which uses the haste_ajax_operation for toggling - e.g. see: https://github.com/m-vo/contao-facebook-import/blob/main/src/Resources/contao/dca/tl_mvo_facebook.php#L69

But there is also a save_callback (https://github.com/m-vo/contao-facebook-import/blob/main/src/Resources/contao/dca/tl_mvo_facebook.php#L181) which returns a boolean value

The boolean value cannot be set in the database here:

$value = $this->executeSaveCallback($dc, $value, $settings);
// Update the database
$this->connection->update($dc->table, [$settings['field'] => $value], ['id' => $id]);

You will get a database error

Incorrect integer value: '' for column

How can we solve this problem? Can we cast the value after executing the save_callback or do we need to refactor the save_callback of the extension?

EDIT: This problem already exists in v4 😭

see also: m-vo/contao-facebook-import#36

It's already a boolean. Why does it try to save an empty string?

I need to debug that again today - it was to late this night ;-)

@aschempp @Toflar should we type cast the value based on its SQL definition before it is even evaluated and stored in the database? The single checkbox value in Contao can return a lot of stuff:

  • true / false
  • '1' / '0'
  • '1' / ''
  • 1 / 0

Or shall we have an internal mapper that converts the values to boolean for evaluation, and sets the correct type right before updating the database?

Casting the value to a string for an empty check ('' === (string) $value) together with Widget::getEmptyValueByFieldType() should be your friend. See https://github.com/contao/contao/blob/5.x/core-bundle/contao/drivers/DC_Table.php#L3215-L3231.

Thanks @Toflar 🧡 that's what I also figured out while analysis.
I startet a PR. But I need to test it with my project in the next few days!

Unfortunately the getEmptyValueByFieldType is not enough or better say in my case it is already false because of the callback but the database update

$this->connection->update($dc->table, [$settings['field'] => $value], ['id' => $id]);

rejects false with Incorrect integer value: '' for column.

Do we need some special cast for doctrine call?

Why is your value an empty string if it expects a boolean?

Do we need some special cast for doctrine call?

You need to specify the field type otherwise Doctrine will cast everything to string (which is then an empty string for false).