Affects Version/s: 3.1.9, 3.1.10, 3.1.11, 3.1.12, 3.2.6, 3.2.7, 3.2.8, 3.3.3, 3.3.4, 3.3.5, 3.4, 3.4.1, 3.4.2
Fix Version/s: None
Component/s: User management
Affected Branches:MOODLE_31_STABLE, MOODLE_32_STABLE, MOODLE_33_STABLE, MOODLE_34_STABLE
This problem starts in Moodle 2.9 and above. And can't be detected unless you worked with it through web services since 2.8 version.
We created a custom registration form that can be hosted on different websites (Wordpress, static, . . . etc). The form sends its data to an API endpoint which handles data checks and sanitization then send them to central Moodle instance to `core_user_create_users` web services function to create and register a new user.
In this registration form, we have some custom fields, and most of them are of `Menu` type. In this type, data is a list of items put together and separated by a newline character (that's what Moodle imply). So when the user field render to a form (whether it was in edit profile form or register user) it will show as a dropdown list (a select input). Each input has the content formatted to the selected language and the value will be the key to that info when Moodle explode the field data with a `\n` character. Hence this code in Moodle 2.8
File link in GitHub here
1- It fetches the data from the database in the parent class `profile_field_base`.
2- It explodes the data of the menu field.
3- It constructs the list of options and put it in the data field `this->options`.
In this version, the construction of the options list happens in this line
After that, it retrieves the user data if it's provided, like in our case or the case of edit profile form. It will search for it using the following line:
This way Moodle won't be able to retrieve the data if he provides the key because the `array_search` function will lookup for the provided data in the options values and not in the keys.
In our case, I don't know if I can call it luck or someone else changed it. When we moved to 3.0 the options construction kept the 2.8 version (which I consider the correct one). But taking the data search changes of 3.0. So when we wrote our custom registration form and other tools as well. Sending the key of the data or option worked perfectly and it helped us in both backend and frontend.
Now we are moving registration instance to 3.2 (fresh installation) and while doing QA on the registration form we found that web service function `core_user_create_users` doesn't work and it returns invalid parameters exceptions. After debugging we found this messed up situation. In Moodle 2.9 and above this is what's wrong:
The options construction use $options value as the key for options data field of the profile field object. While it should be the $key as in 2.8. If you look at the user data retrieval code you can see that it checks the data against the key and if it doesn't return anything it searches in the values as follow:
I don't think that this is a major perhaps you won't even consider it a minor bug because no one reported it. So maybe no one used it this way as we did. But it certainly needs a fix in newer version to avoid conflicts.
We fixed this bug by changing the following lines in `moodle/user/profile/field/menu/field.class.php`
- Fix options construction using the $key => $options for options keys and options values:
In this solution, it doesn't matter which data we provide. If it's the value we will retrieve its key and use it to get the right data. If it's the key it works.