Problem/Motivation
Coming from #2602032: Not working anymore with multiple bundles. Existing configuration in other bundles not detected..
- A fresh checkout of Features, Config Update, Drupal Core
- A "Bundle One" with a feature containing the Article content type.
- A "Bundle Two" with a feature containing the Basic page content type.
Error:
The following module is missing from the file system: bundle_one_bundle_two_page
The error occurs in these lines in FeaturesManager::listExtensionConfig():
$extension = $bundle->getFullName($extension);
$pathname = drupal_get_filename('module', $extension);
In the case that the extension name in $extension is already prefixed but with a bundle other than the current bundle, the current bundle is prepended to the name. Thus bundle_two_page becomes bundle_one_bundle_two_page
While in itself small, this issue reflects an underlying problem in handling the distinction between packages and exported features.
- For packages that we're potentially generating, we use short names. This is so that we have a common format for existing packages (which may have a bundle prefix) and detected ones (which don't yet have a prefix).
- In some cases, however, we read information about existing features regardless of whether they are part of our packages array. In these cases, we need to use full names for operations like reading from a module's configuration.
- Currently in several places we're mixing these use cases, such that we're mixing long and short names.
The current handling is complicated by several factors:
- In multiple places we use mixed arguments for extensions: either a string (machine name) or Extension object. There is not consistent handling of whether the string is a long or short name.
- Packages don't have a consistent set of properties. Instead, the properties present differ depending on which method was called to initiate the package.
- Bundle information is not consistently associated with a package, with the result that the current bundle is assumed, in some cases incorrectly.
Proposed resolution
- Convert all methods that accept
Extensionarguments to use anExtensiontype declaration rather than supporting mixed arguments. - Rename
FeaturesManager::getProject()to::getPackageArray()and ensure that all properties are initialized. (This step should significantly facilitate our work in #2595263: Remodel packages as objects.) - Where feasible and appropriate, use the package's 'extension' and 'bundle' properties.
To further aid code clarity and consistency (and, admittedly, miscellaneous cleanup ;)):
- Add missing
useto features.drush.inc. - Rename
FeaturesManagerInterface::savePackage()to::setPackage()to be consistent with other get/set pairs. - Use
Drupal::CORE_COMPATIBILITYconstant in .info files rather than hard-coded string. - Remove protected method
FeaturesManager::getExtensionPath(). - Replace
FeaturesManagerInterface::getExistingPackages()withFeaturesManagerInterface::getFeaturesModules(). - Raname
FeaturesManagerInterface::initPackageFromInfo()toFeaturesManagerInterface::initPackageFromExtension(). - Remove protected method
FeaturesManager::setPackageNames(). - Remove
FeaturesManagerInterface::getModuleList(). - Tweak the handling of profile-provided configuration in
FeaturesAssignmentExclude::assignPackages()such that (a) we always use the installed profile and (b) If the configuration has been assigned to a feature that's present on the file system, we don't make an exception for it. This addresses what appears as a bug, where already-assigned configuration shows up for reassignment; see #2602032: Not working anymore with multiple bundles. Existing configuration in other bundles not detected..
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | features-existing-packages-2606926-6.patch | 47.19 KB | nedjo |
Comments
Comment #3
nedjoApplied the first approach under proposed resolution:
If this sort of problem recurs, we may need to refactor along the lines of the second approach:
Comment #4
nedjoI'm considering rolling back the previous commit in this issue.
The basic issue is this:
Much of the issue comes down to using the machine name rather than
Extensionobject when referencing an existing feature.Can we instead use
Extensionobjects consistently? This might include setting an 'extension' property on packges, so we always know if the package exists and can reference its extension directly.Comment #5
nedjoI'm digging into a fairly extensive refactoring to try to clean up the relationship of packages to generated features.
Comment #6
nedjoHere's a draft refactoring. I'll add notes tomorrow on what's included.
Comment #7
nedjoComment #9
nedjoI've applied these changes. This patch is admittedly a mixed bag, in that I've included some fixes and cleanup that's at best tangentially related. I've worked hard to ensure this patch doesn't set us back in terms of stability and in fact it appears to fix several unreported bugs left over from our incomplete handling of short and long names of packages vs. exported features. This cleanup should also help pave the way for further refactoring we're planning, particularly #2595263: Remodel packages as objects.
That said, this patch also reemphasizes the critical need for automated tests, #2383435: META: Features 3.x test coverage. I tried to run Features through its paces, but we have enough complexity that it's inevitable I will have missed many cases. Unfortunately, given the scope of this patch, it won't be surprising if I've introduced some short term instability.
Onwards!