Decode '0'-valued user options to integer 0
authorBrad Jorsch <bjorsch@wikimedia.org>
Tue, 21 Mar 2017 12:42:52 +0000 (08:42 -0400)
committerBrad Jorsch <bjorsch@wikimedia.org>
Thu, 23 Mar 2017 15:26:42 +0000 (11:26 -0400)
I13d0e402f fixed a MySQL strict-mode bug by having boolean false be
sent to the database as 0 rather than "", since so many of our
logically-boolean fields are typed as tinyints. That happened to also
cause logically-false user preferences to be stored in the
user_properties table as "0" rather than "", which works fine in PHP but
confuses JavaScript since it considers string-0 as truthy rather than
falsey.

To avoid this situation, convert "0" to 0 when loading the user
options. Completely solving T54542 is left for another time, since
identifying which type to normalize each option to seems nontrivial.

Change-Id: Ia3280b7ce923641eac077141b47cba10d3fb88db

includes/user/User.php

index a963388..ef4537f 100644 (file)
@@ -5266,6 +5266,13 @@ class User implements IDBAccessObject {
                                $this->mOptionOverrides = [];
                                $data = [];
                                foreach ( $res as $row ) {
+                                       // Convert '0' to 0. PHP's boolean conversion considers them both
+                                       // false, but e.g. JavaScript considers the former as true.
+                                       // @todo: T54542 Somehow determine the desired type (string/int/bool)
+                                       //  and convert all values here.
+                                       if ( $row->up_value === '0' ) {
+                                               $row->up_value = 0;
+                                       }
                                        $data[$row->up_property] = $row->up_value;
                                }
                        }