Problem/Motivation

As a carry over from Configuration Packager, currently we model packages as a structured array. A package has a complex set of properties and FeaturesManager includes several methods related to individual packages. It would be more consistent and appropriate to model packages as a custom object type.

Proposed resolution

Create a new FeaturesPackage object. TBD: is there any existing core object we should consider extending? E.g. an Extension?

Model existing array keys as properties.

#2631666: Move methods from FeaturesManager to \Drupal\features\Package

Remaining tasks

Comments

nedjo created an issue. See original summary.

mpotter’s picture

This is a good idea but would change the API so need to be a beta blocker.

Extending the Extension object seems like it would make some sense (Feature packages *are* modules). But I'm wondering about all of the side effects, and wonder how it would handle packages that aren't even exported into code yet. But I'd need to look more at the Extension object to decide.

dawehner’s picture

Ideally I think this object would not extend the extension object but rather wrap one, its just a bit better to deal with IMHO.
The extension object is a value object, so you could create one easily on runtime and fake something up, but yeah this is another reason why the package object
should be modelled as a wrapper or maybe you can create a package object from an extension object (Just an idea: $package = Package::fromExtension($extension)
which then fetches all the values and maybe pass it to the constructor.

dawehner’s picture

StatusFileSize
new67.49 KB

Here is just a rough start. As you will see, there aren't that many fixme/todos, but at least some start.

In an ideal world we would extract the tests first into its own issue. They are helping a bit.

nedjo’s picture

Title: Remodel packages as objects » Make config.installer service override conditional
Issue summary: View changes
Status: Active » Needs review

@dawehner: great start!

  1. +++ b/modules/features_ui/src/Form/FeaturesEditForm.php
    @@ -47,7 +48,7 @@ class FeaturesEditForm extends FormBase {
        * Current package array being edited.
    

    Could change to "Current package being edited."

    There are various other code comments were we could change "package array" to "package".

  2. +++ b/modules/features_ui/src/Form/FeaturesEditForm.php
    @@ -795,17 +794,18 @@ class FeaturesEditForm extends FormBase {
    -    $this->package['name'] = $form_state->getValue('name');
    -    $this->package['machine_name'] = $bundle->getFullName($form_state->getValue('machine_name'));
    -    $this->package['description'] = $form_state->getValue('description');
    -    $this->package['version'] = $form_state->getValue('version');
    -    $this->package['bundle'] = $bundle->getMachineName();
    +    $this->package = new Package($form_state->getValue('machine_name'), [
    +      'name' => $form_state->getValue('name'),
    +      'description' => $form_state->getValue('description'),
    +      'version' => $form_state->getValue('version'),
    +      'bundle' => $bundle->getMachineName(),
    +    ]);
    

    The revised code drops the call to $bundle->getFullName(). Is that to fix a bug?

  3. +++ b/src/Plugin/FeaturesAssignment/FeaturesAssignmentProfile.php
    @@ -148,6 +148,7 @@ class FeaturesAssignmentProfile extends FeaturesAssignmentMethodBase {
    +            // @fixme
    ...
               }
    

    The problem here is that the code we need to replace merges into the package array, which repeats these keys from the info array ('dependencies', 'themes').

    Maybe:

    $info  [
      'dependencies' => $profile_package->getDependencies(),
      'themes' => $profile_package->getThemes(),
    ];
    $info = $this->featuresManager->mergeInfoArray($info, $profile_info);
    $profile_package->setDependencies($info['dependencies']);
    $profile_package->setThemes($info['themes']);
    
  4. +++ b/src/Plugin/FeaturesGeneration/FeaturesGenerationArchive.php
    @@ -70,11 +73,13 @@ class FeaturesGenerationArchive extends FeaturesGenerationMethodBase {
    -          $package['files'][] = [
    +          $files = $package->getFiles();
    +          $files[] = [
                 'filename' => $file->filename,
                 'subdirectory' => $subdirectory,
                 'string' => file_get_contents($file->uri)
               ];
    +          $package->setFiles($files);
    

    Could maybe use $package->appendFile() here since we don't need to specify the file index (as we do with e.g. 'info', to enable later merging into that file)?

dawehner’s picture

Status: Active » Needs review
StatusFileSize
new68.42 KB
new4.07 KB

Thank you for the feedback!

The revised code drops the call to $bundle->getFullName(). Is that to fix a bug?

Nope, this is just a clear bug.

Could maybe use $package->appendFile() here since we don't need to specify the file index (as we do with e.g. 'info', to enable later merging into that file)?

Oh yeah we totally should. After doing this manually some times, it was too annoying so I introduced a proper helper method.

The problem here is that the code we need to replace merges into the package array, which repeats these keys from the info array ('dependencies', 'themes').

Thank you for that tip!

dawehner’s picture

Issue summary: View changes

Move the additional methods into its own issue.

dawehner’s picture

StatusFileSize
new2.25 KB
new69.41 KB

One bugfix with a test.

IMHO we should merge #2616408: Create SimpleTest for basic UI functionality in first, this is for sure.

dawehner’s picture

StatusFileSize
new87.39 KB
new21.14 KB

More fixes and tests.

dawehner’s picture

StatusFileSize
new98.54 KB
new14.2 KB

More fixes and more tests for the FeaturesManager

nedjo’s picture

This is looking great.

I did a string search for $package[ and there are a few places that probably still need fixing up, in modules/features_ui/src/Form/FeaturesDiffForm.php, src/FeaturesGenerator.php, src/FeaturesManager.php, and tests/src/Kernel/FeaturesGenerateTest.php.

nedjo’s picture

  1. +++ b/modules/features_ui/src/Form/FeaturesEditForm.php
    @@ -603,7 +602,6 @@ class FeaturesEditForm extends FormBase {
    -    $export = $this->package;
    

    From the subsequent code in this method, which works with $export['package'], it looks like instead of removing this line we should do something like:

    $export = [
      'package' => $this->package,
    ];
    
  2. +++ b/modules/features_ui/src/Form/FeaturesExportForm.php
    @@ -282,36 +283,36 @@ class FeaturesExportForm extends FormBase {
    +   * @param \Drupal\features\Package $package
        *   The package name.
    

    Comment should be "The package." rather than "The package name."

  3. +++ b/src/FeaturesManager.php
    @@ -317,7 +317,7 @@ class FeaturesManager implements FeaturesManagerInterface {
    -    return \Drupal::service('info_parser')->parse($extension->getPathname());
    +    return \Drupal::service('info_parser')->parse(\Drupal::root() . '/' . $extension->getPathname());
    

    This looks like an unrelated bugfix? Worth catching and no prob to add here.

dawehner’s picture

StatusFileSize
new101.07 KB
new3.76 KB

From the subsequent code in this method, which works with $export['package'], it looks like instead of removing this line we should do something like:

Good catch! I was quite confused about these lines in general, now this seems to be good and make sense. There is data which is part of the package + additional metadata in this $export array.

Comment should be "The package." rather than "The package name."

Fixed!

This looks like an unrelated bugfix? Worth catching and no prob to add here.

Using this allows you to mock the filesystem using VFS

Some intermediate work.

dawehner’s picture

StatusFileSize
new104.71 KB
new4.31 KB

Fixed the other instances ...

nedjo’s picture

All the fixes look good.

I'm getting some failures for Drupal\features\Tests\FeaturesCreateUITest, haven't looked into them.

  1. +++ b/src/FeaturesManager.php
    @@ -676,13 +680,13 @@ class FeaturesManager implements FeaturesManagerInterface {
    +      $package->setStatus($this->moduleHandler->moduleExists($extension->getName()))
             ? FeaturesManagerInterface::STATUS_ENABLED
             : FeaturesManagerInterface::STATUS_DISABLED;
    

    Should be:

          $package->setStatus($this->moduleHandler->moduleExists($extension->getName())
            ? FeaturesManagerInterface::STATUS_ENABLED
            : FeaturesManagerInterface::STATUS_DISABLED
          );
    
  2. +++ b/src/Plugin/FeaturesGeneration/FeaturesGenerationArchive.php
    @@ -12,6 +12,7 @@ use Drupal\features\FeaturesGenerationMethodBase;
    +use Drupal\features\Package;
    

    Needs rerolling after a recent change.

dawehner’s picture

StatusFileSize
new106.23 KB
new3.08 KB

Should be:

Good catch! Added a unit test for that.

Needs rerolling after a recent change.

Fixed that

nedjo’s picture

I'm getting some failures for Drupal\features\Tests\FeaturesCreateUITest

First error includes:

Fatal error: Call to a member function getFeaturesInfo() on a non-object in /path/to/site/modules/features/src/Plugin/FeaturesAssignment/FeaturesAssignmentPackages.php on line 37

dawehner’s picture

StatusFileSize
new107.07 KB
new1.96 KB

Thanks for that.

Here is one fix for the FeaturesManager, interesting that this was not there before.
Now though the remaining failure seems to be that there is just one component added to the feature.

I fear that \Drupal\features_ui\Form\FeaturesEditForm::getComponentList might be involved in that, which scares me a bit, to be honest. Help would be more than welcomed.

dawehner’s picture

StatusFileSize
new109.02 KB
new3.36 KB

Found the problem.

  • nedjo committed 0ab0c78 on 8.x-3.x authored by dawehner
    Issue #2595263 by dawehner: Remodel packages as objects
    
nedjo’s picture

Status: Needs review » Fixed

@dawehner

Given the scope of the change it will be surprising if we got absolutely everything, but my basic manual testing plus the new tests introduced here didn't show any issues.

Thanks for your amazing work and perseverance here. It's great to have this refactoring complete.

The last submitted patch, 4: 2595263-4.patch, failed testing.

The last submitted patch, 6: 2595263-6.patch, failed testing.

The last submitted patch, 8: 2595263-8.patch, failed testing.

The last submitted patch, 9: 2595263-9.patch, failed testing.

The last submitted patch, 10: 2595263-10.patch, failed testing.

The last submitted patch, 13: 2595263-13.patch, failed testing.

The last submitted patch, 14: 2595263-14.patch, failed testing.

The last submitted patch, 16: 2595263-16.patch, failed testing.

The last submitted patch, 18: 2595263-18.patch, failed testing.

Status: Fixed » Needs work

The last submitted patch, 19: 2595263-19.patch, failed testing.

nedjo’s picture

Status: Needs work » Fixed
dawehner’s picture

Given the scope of the change it will be surprising if we got absolutely everything, but my basic manual testing plus the new tests introduced here didn't show any issues.

yeah, we are in alpha state and sometimes iterating quickly is just more sane than perfectionism everywhere.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.