Skip to content

Commit

Permalink
bug symfony#1467 [StimulusBundle] UxPackageReader class doesn't suppo…
Browse files Browse the repository at this point in the history
…rt projects with varied structures using Composer with custom directory structure (yobrx)

This PR was merged into the 2.x branch.

Discussion
----------

[StimulusBundle] UxPackageReader class doesn't support projects with varied structures using Composer with custom directory structure

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Issues        | no
| License       | MIT

Hello,

I've encountered an issue with the `UxPackageReader` class within the Symfony UX package, where it fails to accurately detect package existence in projects that have a structure differing from the standard Symfony application structure, despite these projects using Composer for package management.

## Description of the Issue
The `UxPackageReader` class appears to be designed with a certain project structure, which works well for typical Symfony applications. However, in projects that deviate from this structure (for instance, microservices or applications with a modular architecture), the class does not effectively locate and read the Composer-managed packages.

## Specific Scenario
To give a concrete example, my project consists of multiple directories at the root, each representing a sub-project within a larger ecosystem. These sub-projects are designed to have their own `vendor` directory for autoloading purposes. However, all Composer packages are installed in a shared `vendor` directory at the root of the project. This setup is beneficial for my project's architecture but unfortunately, `UxPackageReader` is unable to recognize the packages in this unique structure.

### Example :
```

app1
|- vendor
  |- composer
    |- autoload-*.php -> reference files to ../vendor/
    |- ... and other files of composer
app2
|- subapp1
  |- vendor
    |- composer
      |- autoload-*.php -> reference files to ../../vendor/
      |- ... and other files of composer
|- subapp2_legacy
  |- vendor
    |- composer
      |- autoload-*.php -> reference files to ../../vendor/
      |- ... and other files of composer
vendor
 |- symfony
   |- packages
     |- v6.3
       |- _files of package_
     |- v6.4
```

## Proposed Solution
To address this limitation, I have implemented a workaround by utilizing the `InstalledVersions` class from Composer, whenever it is available. This class offers a more robust and flexible way to check for the existence of packages, as it does not rely on the project's directory structure but instead directly reads from Composer's autoload mechanisms and installed packages metadata.

## Suggested Changes
I suggest that the Symfony UX team considers integrating a similar approach into the `UxPackageReader` class. By leveraging `InstalledVersions` or an equivalent method, Symfony UX can enhance its compatibility with a broader range of project structures that use Composer, thus increasing its versatility and usability.

This modification would not only resolve the issue for projects with unique structures but also align the package detection mechanism with Composer's native capabilities, ensuring a more consistent and reliable detection process.

My solution is not testable because it uses Composer class with static methods. Therefore, I was unable to write tests for it. However, I am open to any suggestions for improvement.

Commits
-------

0b17512 Used a Composer class to check for package existence in projects with varying structures
  • Loading branch information
weaverryan committed Feb 7, 2024
2 parents c1b369e + 0b17512 commit 9c6e3f7
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/StimulusBundle/src/Ux/UxPackageReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

namespace Symfony\UX\StimulusBundle\Ux;

use Composer\InstalledVersions;

/**
* @internal
*
Expand All @@ -28,7 +30,12 @@ public function readPackageMetadata(string $packageName): UxPackageMetadata
{
// remove the '@' from the name to get back to the PHP package name
$phpPackageName = substr($packageName, 1);
$phpPackagePath = $this->projectDir.'/vendor/'.$phpPackageName;
if (class_exists(InstalledVersions::class) && InstalledVersions::isInstalled($phpPackageName)) {
$phpPackagePath = InstalledVersions::getInstallPath($phpPackageName);
} else {
$phpPackagePath = $this->projectDir.'/vendor/'.$phpPackageName;
}

if (!is_dir($phpPackagePath)) {
throw new \RuntimeException(sprintf('Could not find package "%s" referred to from controllers.json.', $phpPackageName));
}
Expand Down

0 comments on commit 9c6e3f7

Please sign in to comment.