Failed Conditions
Pull Request — master (#15)
by Billie
02:47
created

src/SwaggerApiInstaller.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace PurpleBooth\JaneOpenApiAutogenerate;
4
5
use Composer\Composer;
6
use Composer\Installer\BinaryInstaller;
7
use Composer\Installer\LibraryInstaller;
8
use Composer\IO\IOInterface;
9
use Composer\Package\PackageInterface;
10
use Composer\Util\Filesystem;
11
use Joli\Jane\OpenApi\JaneOpenApi;
12
use RecursiveDirectoryIterator;
13
use RecursiveIteratorIterator;
14
use SplFileInfo;
15
16
class SwaggerApiInstaller extends LibraryInstaller
17
{
18
    const PACKAGE_TYPE = 'swagger-api';
19
20
    const EXTRA_KEY_NAMESPACE = 'namespace';
21
22
    const EXTRA_KEY_SCHEMA_FILE = 'schema-file';
23
24
    const EXTRA_KEY_ENVIRONMENT_VARIABLE  = 'environment-variable';
25
    const GENERATED_DIRECTORY             = "generated";
26
    const SCHEMA_PATH_IS_DOWNLOAD_PATTERN = "^https?:";
27
28
    /**
29
     * {@inheritdoc}
30
     */
31
    public function __construct(
32
        IOInterface $inputOutput,
33
        Composer $composer,
34
        $type = self::PACKAGE_TYPE,
35
        Filesystem $filesystem = null,
36
        BinaryInstaller $binaryInstaller = null
37
    ) {
38
        parent::__construct($inputOutput, $composer, $type, $filesystem, $binaryInstaller);
39
    }
40
41
42
    /**
43
     * { @inheritdoc }
44
     */
45
    protected function updateCode(PackageInterface $initial, PackageInterface $target)
46
    {
47
        $this->removeCode($initial);
48
        $this->installCode($target);
49
    }
50
51
    /**
52
     * { @inheritdoc }
53
     */
54
    protected function installCode(PackageInterface $package)
55
    {
56
        // Is this a schema we download from the internet or checkout locally
57
        if (!$this->isSchemaToDownload($package)) {
58
            parent::installCode($package);
59
        }
60
61
        $this->generateSwaggerClient(
62
            $package,
63
            $this->getInstallPath($package)
64
        );
65
    }
66
67
    /**
68
     * { @inheritdoc }
69
     */
70
    protected function removeCode(PackageInterface $package)
71
    {
72
        // Is this a schema we download from the internet or checkout locally
73
        if (!$this->isSchemaToDownload($package)) {
74
            parent::removeCode($package);
75
        } else {
76
            $downloadPath = $this->getInstallPath($package);
77
            $this->removeDirectory($downloadPath);
78
        }
79
    }
80
81
82
    /**
83
     * Generate the client for a package
84
     *
85
     * @param PackageInterface $package
86
     * @param string           $downloadPath
87
     */
88
    protected function generateSwaggerClient(PackageInterface $package, $downloadPath)
89
    {
90
        $janeOpenApi = JaneOpenApi::build();
91
92
        $extra             = $package->getExtra();
93
        $namespace         = $extra[ self::EXTRA_KEY_NAMESPACE ];
94
        $openApiSchemaFile = $this->getSchemaFile($downloadPath, $extra);
0 ignored issues
show
$downloadPath is of type string, but the function expects a object<Composer\Package\PackageInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
The call to SwaggerApiInstaller::getSchemaFile() has too many arguments starting with $extra.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
95
96
        $this->io->write(
97
            "Generating <info>$namespace</info> from <info>$openApiSchemaFile</info>",
98
            true,
99
            IOInterface::VERBOSE
100
        );
101
102
        $this->io->write(
103
            "Writing to <info>$downloadPath</info>",
104
            true,
105
            IOInterface::VERY_VERBOSE
106
        );
107
108
        $generatePath = implode(DIRECTORY_SEPARATOR, [$downloadPath, self::GENERATED_DIRECTORY]);
109
        $files        = $janeOpenApi->generate($openApiSchemaFile, $namespace, $generatePath);
110
        $janeOpenApi->printFiles($files, $downloadPath);
111
112
        foreach ($files as $file) {
113
            $this->io->write("Generated <info>{$file->getFilename()}</info>", true, IOInterface::DEBUG);
114
        }
115
116
        $this->io->write(
117
            "Generated <info>$namespace</info> from <info>$openApiSchemaFile</info>",
118
            true,
119
            IOInterface::VERBOSE
120
        );
121
    }
122
123
    /**
124
     * Get the schema file
125
     *
126
     * @param PackageInterface $package
127
     *
128
     * @return string
129
     */
130
    private function getSchemaFile(PackageInterface $package)
131
    {
132
        $downloadPath      = $this->getInstallPath($package);
133
        $extra             = $package->getExtra();
134
        $openApiSchemaFile = $extra[ self::EXTRA_KEY_SCHEMA_FILE ];
135
136
        if (isset($extra[ self::EXTRA_KEY_ENVIRONMENT_VARIABLE ])) {
137
            $envVariableName = $extra[ self::EXTRA_KEY_ENVIRONMENT_VARIABLE ];
138
            $envVariable     = getenv($envVariableName);
139
140
            if ($envVariable) {
141
                $openApiSchemaFile = $envVariable;
142
            }
143
        }
144
145
        $vendorSchemaPath = implode(DIRECTORY_SEPARATOR, [$downloadPath, $openApiSchemaFile]);
146
147
        if (file_exists($vendorSchemaPath)) {
148
            $openApiSchemaFile = $vendorSchemaPath;
149
150
            return $openApiSchemaFile;
151
        }
152
153
        return $openApiSchemaFile;
154
    }
155
156
    /**
157
     * Do we download or checkout this schema
158
     *
159
     * @param PackageInterface $package
160
     *
161
     * @return string
0 ignored issues
show
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
162
     */
163
    private function isSchemaToDownload(PackageInterface $package)
164
    {
165
        return preg_match(self::SCHEMA_PATH_IS_DOWNLOAD_PATTERN, $this->getInstallPath($package)) === 1;
166
    }
167
168
    /**
169
     * RM -rf in PHP
170
     *
171
     * @param string $downloadPath
172
     */
173
    private function removeDirectory($downloadPath)
174
    {
175
        if (!(new SplFileInfo($downloadPath))->isDir()) {
176
            return;
177
        }
178
179
180
        $directory = new RecursiveDirectoryIterator($downloadPath);
181
        $iterator  = new RecursiveIteratorIterator(
182
            -$directory,
183
            RecursiveIteratorIterator::CHILD_FIRST
184
        );
185
186
        /** @var SplFileInfo $item */
187
        foreach ($iterator as $item) {
188
            if ($item->isFile()) {
189
                unlink($item->getPathname());
190
            }
191
192
            if ($item->isDir()) {
193
                rmdir($item->getPathname());
194
            }
195
        }
196
197
        rmdir($downloadPath);
198
    }
199
200
}
201