CopiesSkeleton::getVariables()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 38
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 23
c 1
b 0
f 0
nc 1
nop 4
dl 0
loc 38
rs 9.552
1
<?php
2
3
namespace Cherrypulp\LaravelPackageGenerator\Commands\Traits;
4
5
use Exception;
6
use Illuminate\Support\Str;
7
use Illuminate\Support\Facades\File;
8
use Illuminate\View\Engines\PhpEngine;
9
use Cherrypulp\LaravelPackageGenerator\Exceptions\RuntimeException;
10
11
trait CopiesSkeleton
12
{
13
    use InteractsWithUser;
14
15
    protected $packageBaseDir = __DIR__.'/../../..';
16
17
    /**
18
     * Copy skeleton to package folder.
19
     *
20
     * @param string $packagePath
21
     * @param string $vendor
22
     * @param string $package
23
     * @param string $vendorFolderName
24
     * @param string $packageFolderName
25
     *
26
     * @throws RuntimeException
27
     */
28
    protected function copySkeleton(
29
        $packagePath,
30
        $vendor,
31
        $package,
32
        $vendorFolderName,
33
        $packageFolderName
34
    ) {
35
        $this->info('Copy skeleton.');
0 ignored issues
show
Bug introduced by
It seems like info() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

35
        $this->/** @scrutinizer ignore-call */ 
36
               info('Copy skeleton.');
Loading history...
36
37
        $skeletonDirPath = $this->getPathFromConfig(
38
            'skeleton_dir_path', $this->packageBaseDir.'/skeleton'
39
        );
40
41
        foreach (File::allFiles($skeletonDirPath, true) as $filePath) {
42
            $filePath = realpath($filePath);
43
44
            $destFilePath = Str::replaceFirst(
45
                $skeletonDirPath, $packagePath, $filePath
46
            );
47
48
            $this->copyFileWithDirsCreating($filePath, $destFilePath);
49
        }
50
51
        $this->copyStubs($packagePath, $package, $packageFolderName);
52
53
        $variables = $this->getVariables(
54
            $vendor, $package, $vendorFolderName, $packageFolderName
55
        );
56
        $this->replaceTemplates($packagePath, $variables);
57
58
        $this->info('Skeleton was successfully copied.');
59
    }
60
61
    /**
62
     * Copy stubs.
63
     *
64
     * @param $packagePath
65
     * @param $package
66
     * @param $packageFolderName
67
     */
68
    protected function copyStubs($packagePath, $package, $packageFolderName)
69
    {
70
        $facadeFilePath = $this->packageBaseDir.'/stubs/Facade.php.tpl';
71
        $mainClassFilePath = $this->packageBaseDir.'/stubs/MainClass.php.tpl';
72
        $mainClassTestFilePath = $this->packageBaseDir.'/stubs/MainClassTest.php.tpl';
73
        $configFilePath = $this->packageBaseDir.'/stubs/config.php';
74
75
        $filePaths = [
76
            $facadeFilePath => "$packagePath/src/Facades/$package.php.tpl",
77
            $mainClassFilePath => "$packagePath/src/$package.php.tpl",
78
            $mainClassTestFilePath => "$packagePath/tests/{$package}Test.php.tpl",
79
            $configFilePath => "$packagePath/config/$packageFolderName.php",
80
        ];
81
82
        foreach ($filePaths as $filePath => $destFilePath) {
83
            $this->copyFileWithDirsCreating($filePath, $destFilePath);
84
        }
85
    }
86
87
    /**
88
     * Substitute all variables in *.tpl files and remove tpl extension.
89
     *
90
     * @param string $packagePath
91
     * @param array $variables
92
     */
93
    protected function replaceTemplates($packagePath, $variables)
94
    {
95
        $phpEngine = app()->make(PhpEngine::class);
0 ignored issues
show
Bug introduced by
The function app was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
        $phpEngine = /** @scrutinizer ignore-call */ app()->make(PhpEngine::class);
Loading history...
96
97
        foreach (File::allFiles($packagePath, true) as $filePath) {
98
            $filePath = realpath($filePath);
99
100
            if (! Str::endsWith($filePath, '.tpl')) {
101
                continue;
102
            }
103
104
            try {
105
                $newFileContent = $phpEngine->get($filePath, $variables);
106
            } catch (Exception $e) {
107
                $this->error("Template [$filePath] contains syntax errors");
0 ignored issues
show
Bug introduced by
It seems like error() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

107
                $this->/** @scrutinizer ignore-call */ 
108
                       error("Template [$filePath] contains syntax errors");
Loading history...
108
                $this->error($e->getMessage());
109
                continue;
110
            }
111
112
            $filePathWithoutTplExt = Str::replaceLast(
113
                '.tpl', '', $filePath
114
            );
115
116
            File::put($filePathWithoutTplExt, $newFileContent);
117
            File::delete($filePath);
118
        }
119
    }
120
121
    /**
122
     * Copy source file to destination with needed directories creating.
123
     *
124
     * @param string $src
125
     * @param string $dest
126
     */
127
    protected function copyFileWithDirsCreating($src, $dest)
128
    {
129
        $dirPathOfDestFile = dirname($dest);
130
131
        if (! File::exists($dirPathOfDestFile)) {
132
            File::makeDirectory($dirPathOfDestFile, 0755, true);
133
        }
134
135
        if (! File::exists($dest)) {
136
            File::copy($src, $dest);
137
        }
138
    }
139
140
    /**
141
     * Get variables for substitution in templates.
142
     *
143
     * @param string $vendor
144
     * @param string $package
145
     * @param string $vendorFolderName
146
     * @param string $packageFolderName
147
     *
148
     * @return array
149
     */
150
    protected function getVariables(
151
        $vendor,
152
        $package,
153
        $vendorFolderName,
154
        $packageFolderName
155
    ) {
156
        $packageWords = str_replace('-', ' ', Str::snake($packageFolderName));
157
158
        $composerDescription = $this->askUser(
159
            'The composer description?', "A $packageWords"
160
        );
161
        $composerKeywords = $this->getComposerKeywords($packageWords);
162
163
        $packageHumanName = $this->askUser(
164
            'The package human name?', Str::title($packageWords)
165
        );
166
167
        return [
168
            'vendor' => $vendor,
169
            'package' => $package,
170
            'vendorFolderName' => $vendorFolderName,
171
            'packageFolderName' => $packageFolderName,
172
            'packageHumanName' => $packageHumanName,
173
174
            'composerName' => "$vendorFolderName/$packageFolderName",
175
            'composerDesc' => $composerDescription,
176
            'composerKeywords' => $composerKeywords,
177
            'license' => $this->askUser('The package licence?', 'MIT'),
178
            'phpVersion' => $this->askUser('Php version constraint?', '>=7.2'),
179
180
            'aliasName' => $packageFolderName,
181
            'configFileName' => $packageFolderName,
182
183
            'year' => date('Y'),
184
185
            'name' => $this->askUser('Your name?'),
186
            'email' => $this->askUser('Your email?'),
187
            'githubPackageUrl' => "https://github.com/$vendorFolderName/$packageFolderName",
188
        ];
189
    }
190
191
    /**
192
     * Get path from config.
193
     *
194
     * @param string $configName
195
     * @param string $default
196
     *
197
     * @return string
198
     *
199
     * @throws RuntimeException
200
     */
201
    protected function getPathFromConfig($configName, $default)
202
    {
203
        $path = config("laravel-package-generator.$configName");
0 ignored issues
show
Bug introduced by
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

203
        $path = /** @scrutinizer ignore-call */ config("laravel-package-generator.$configName");
Loading history...
204
205
        if (empty($path)) {
206
            $path = $default;
207
        } else {
208
            $path = base_path($path);
0 ignored issues
show
Bug introduced by
The function base_path was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

208
            $path = /** @scrutinizer ignore-call */ base_path($path);
Loading history...
209
        }
210
211
        $realPath = realpath($path);
212
213
        if ($realPath === false) {
214
            throw RuntimeException::noAccessTo($path);
215
        }
216
217
        return $realPath;
218
    }
219
220
    /**
221
     * Get composer keywords.
222
     *
223
     * @param $packageWords
224
     *
225
     * @return string
226
     */
227
    protected function getComposerKeywords($packageWords)
228
    {
229
        $keywords = $this->askUser(
230
            'The composer keywords? (comma delimited)', str_replace(' ', ',', $packageWords)
231
        );
232
        $keywords = explode(',', $keywords);
233
        $keywords = array_map(function ($keyword) {
234
            return "\"$keyword\"";
235
        }, $keywords);
236
237
        return implode(",\n".str_repeat(' ', 4), $keywords);
238
    }
239
}
240