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

src/SwaggerApiInstaller.php (1 issue)

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($package);
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