WsdlToPhp / PackageGenerator

Generates a PHP SDK based on a WSDL, simple and powerful, WSDL to PHP
https://providr.io
MIT License
428 stars 73 forks source link

Composer Settings Are Incorrectly Created With A Numeric Index In The Composer JSON File #324

Open ajoh504 opened 4 days ago

ajoh504 commented 4 days ago

Describe the bug

When using the --composer-settings option in the PackageGenerator, the JSON keys are not correctly written to the composer.json file. They are written with a numeric key (as a string) when it should be the first key from the command line option. We're using the latest .phar file (v 4.1.13) on Windows.

Example:

--composer-settings="autoload.psr-4.Custom\SoapClient\:./Custom/SoapClient/"

In this example, the first key should be "autoload." However, the key is written to composer.json as a "0" or "1", depending on the number of times the --composer-settings option is used.

To Reproduce

Here is an example Windows batch file that our group uses to generate the package:

php ./wsdltophp.phar generate:package ^
  --urlorpath="https://url/to/wsdl" ^
  --destination="C:\path\to\package" ^
  --composer-name="author-name/package-name" ^
  --namespace="Test\Namespace" ^
  --composer-settings="config.disable-tls:true" ^
  --composer-settings="autoload.psr-4.Custom\SoapClient\:./Custom/SoapClient/" ^
  --validation=false ^
  --soapclient="Custom\SoapClient" ^
  --force

And here is the final output in composer.json:

{
    "name": "author-name/package-name",
    "description": "Package generated from https://url/to/wsdl using wsdltophp/packagegenerator",
    "require": {
        "php": ">=7.4",
        "ext-dom": "*",
        "ext-mbstring": "*",
        "ext-soap": "*",
        "wsdltophp/packagebase": "~5.0"
    },
    "autoload": {
        "psr-4": {
            "Test\\Namespace\\": "./src\\Test\\Namespace"
        }
    },
    "0": "config.disable-tls:true",
    "1": "autoload.psr-4.Custom\\SoapClient\\:./Custom/SoapClient/"
}

Expected behavior

The JSON is not formatted correctly.

Instead of this:

"0": "config.disable-tls:true",
"1": "autoload.psr-4.Custom\\SoapClient\\:./Custom/SoapClient/"

It should be this:


    "autoload": {
        "psr-4": {
            "Custom\\SoapClient\\": "./Custom/SoapClient/"
        }
    },
    "config": {
      "disable-tls": true
    }

Additional context

Looking at the source code, the GeneratorOptions class has a static method called dotNotationToArray. It appears this method is responsible for exploding the string via the . char, which is how the composer arguments are delimited on the command line.

I did some testing locally using the PHP interpreter. Unfortunately I am not able to fork the repo and install the dependencies due to limitations at my organization. However, when using the PHP interpreter, I called dotNotationToArray and the results are as expected (see below).

But one thing that caught my attention is that the dotNotationToArray method is marked as static in the source code. Yet it accesses the $array value by reference. That is one difference between the source code and the command line sample shown below. I don't know if this is an issue, but it caught my attention to see a static function access a value by reference when the containing class is not static, which is the case for GeneratorOptions. In other words, the GeneratorOptions class is instance, the $array is instance, but the dotNotationToArray function is static.

php > $value = "config.disable-tls:true";
php > $path = implode('', array_slice(explode(':', $value), 0, 1));
php > $val = implode(':', array_slice(explode(':', $value), 1));
php > $settings = [];
php >
php > function dotNotationToArray(string $string, $value, array &$array): void
php > {
php {     $keys = explode('.', $string);
php {     foreach ($keys as $key) {
php {         $array = &$array[$key];
php {     }
php {     $array = ('true' === $value || 'false' === $value) ? 'true' === $value : $value;
php { }
php >
php > dotNotationToArray($path, $val, $settings);
php >
php > var_dump($settings);
php shell code:1:
array(1) {
  'config' =>
  array(1) {
    'disable-tls' =>
    bool(true)
  }
}
php >

Extra Information

This is likely unrelated to the --composer-settings issue, but it's worth noting that the package source folder is not correctly written to composer.json, similar to issue #306. The value should have forward slashes but instead it has back slashes.

Instead of this:

    "autoload": {
        "psr-4": {
            "Test\\Namespace\\": "./src\\Test\\Namespace"
        }
    },

It should be this:

    "autoload": {
        "psr-4": {
            "Test\\Namespace\\": "./src/Test/Namespace/"
        }
    },