CopiesSkeleton   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 228
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 16
eloc 86
c 2
b 0
f 0
dl 0
loc 228
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getComposerKeywords() 0 11 1
A getVariables() 0 38 1
A getPathFromConfig() 0 17 3
A copyFileWithDirsCreating() 0 10 3
A copyStubs() 0 16 2
A copySkeleton() 0 32 2
A replaceTemplates() 0 25 4
1
<?php
2
3
namespace Blok\LaravelPackageGenerator\Commands\Traits;
4
5
use Blok\LaravelPackageGenerator\Exceptions\RuntimeException;
6
use Exception;
7
use Illuminate\Support\Facades\File;
8
use Illuminate\Support\Str;
9
use Illuminate\View\Engines\PhpEngine;
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
57
        $this->replaceTemplates($packagePath, $variables);
58
59
        $this->info('Skeleton was successfully copied.');
60
    }
61
62
    /**
63
     * Copy stubs.
64
     *
65
     * @param $packagePath
66
     * @param $package
67
     * @param $packageFolderName
68
     */
69
    protected function copyStubs($packagePath, $package, $packageFolderName)
70
    {
71
        $facadeFilePath = $this->packageBaseDir.'/stubs/Facade.php.tpl';
72
        $mainClassFilePath = $this->packageBaseDir.'/stubs/MainClass.php.tpl';
73
        $mainClassTestFilePath = $this->packageBaseDir.'/stubs/MainClassTest.php.tpl';
74
        $configFilePath = $this->packageBaseDir.'/stubs/config.php';
75
76
        $filePaths = [
77
            $facadeFilePath        => "$packagePath/src/Facades/$package.php.tpl",
78
            $mainClassFilePath     => "$packagePath/src/$package.php.tpl",
79
            $mainClassTestFilePath => "$packagePath/tests/{$package}Test.php.tpl",
80
            $configFilePath        => "$packagePath/config/$packageFolderName.php",
81
        ];
82
83
        foreach ($filePaths as $filePath => $destFilePath) {
84
            $this->copyFileWithDirsCreating($filePath, $destFilePath);
85
        }
86
    }
87
88
    /**
89
     * Substitute all variables in *.tpl files and remove tpl extension.
90
     *
91
     * @param string $packagePath
92
     * @param array  $variables
93
     */
94
    protected function replaceTemplates($packagePath, $variables)
95
    {
96
        $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

96
        $phpEngine = /** @scrutinizer ignore-call */ app()->make(PhpEngine::class);
Loading history...
97
98
        foreach (File::allFiles($packagePath, true) as $filePath) {
99
            $filePath = realpath($filePath);
100
101
            if (!Str::endsWith($filePath, '.tpl')) {
102
                continue;
103
            }
104
105
            try {
106
                $newFileContent = $phpEngine->get($filePath, $variables);
107
            } catch (Exception $e) {
108
                $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

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

204
        $path = /** @scrutinizer ignore-call */ config("laravel-package-generator.$configName");
Loading history...
205
206
        if (empty($path)) {
207
            $path = $default;
208
        } else {
209
            $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

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