I open this as a "Bug report", even though I cannot currently present any symptoms.
Background
features_get_info() gets info about available modules from system_rebuild_module_data(), delivered as \stdClass objects.
In addition, features_get_info() does:
- Modify the objects slightly:
- unset $row->info['mtime']
- unset $row->info['php']
- modify $row->info['stylesheets']
- modify $row->info['scripts']
- modify $row->info['features']
- set $row->components
- Cache the objects (so that only on cache reset the core function is called).
- Provide a filtered list that only contains the modules with non-empty $row->info['features'].
Problem
In the reset/rebuild case, the modifications mentioned above are applied to the original objects from system_rebuild_module_data().
This can be reproduced in devel/php like so:
dpm(system_rebuild_module_data()['features_test']);
features_get_info('feature', NULL, TRUE);
dpm(system_rebuild_module_data()['features_test']);
Before the features_get_info(), the ->components is not present.
After the features_get_info(), the ->components is present.
Solution
Clone the objects.
Related issue
#1070912: features_get_info() hands back original objects, can get corrupted β
is about calling code that might poison the original objects from features_get_info().
A solution was committed, but only for the case of a single module returned.
If a list of modules is returned, they are the original objects.
This can still be a problem, but out of scope for this issue.
Normally I would say the API code should be responsible for preventing calling code from modifying data, e.g. by making objects immutable.
However, in Drupal 7, mutable \stdClass objects are the norm, and most API functions return not-cloned objects.
I would say in Drupal 7 the calling code is responsible for not poisoning the original objects.
This means features_get_info() should clone the original objects when fetching them from system_rebuild_module_data(), but it is not required to clone the objects again when returning them to calling code.