Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
GenerateClient
n/a
0 / 0
n/a
0 / 0
19
n/a
0 / 0
 handle
n/a
0 / 0
n/a
0 / 0
1
 copyApiConfigInfo
n/a
0 / 0
n/a
0 / 0
2
 copyRoutesList
n/a
0 / 0
n/a
0 / 0
4
 copyExceptions
n/a
0 / 0
n/a
0 / 0
2
 copyTraits
n/a
0 / 0
n/a
0 / 0
2
 copyEnums
n/a
0 / 0
n/a
0 / 0
2
 copyToFolder
n/a
0 / 0
n/a
0 / 0
3
 replaceInPhpFile
n/a
0 / 0
n/a
0 / 0
3
1<?php
2
3namespace App\Console\Commands;
4
5use App\Enums\ApiError;
6use App\Enums\ApiStatus;
7use App\Enums\ArcadiaOrderType;
8use App\Enums\Country;
9use App\Enums\QuestionType;
10use App\Exceptions\Api\V4\ApiErrorException;
11use App\Exceptions\Api\V4\CrmException;
12use App\Traits\Enums\BaseEnum;
13use Illuminate\Console\Command;
14use Illuminate\Support\Facades\File;
15use Illuminate\Support\Facades\Route;
16use Illuminate\Support\Str;
17
18/**
19 * @codeCoverageIgnore
20 */
21class GenerateClient extends Command
22{
23    private const TARGET          = 'client/src';
24    private const CLIENTNAMESPACE = 'LDC\\LDCCRM';
25
26    /**
27     * The name and signature of the console command.
28     *
29     * @var string
30     */
31    protected $signature = 'client:generate';
32
33    /**
34     * The console command description.
35     *
36     * @var string
37     */
38    protected $description = 'Generate the crm V4 client in client folder';
39
40    /**
41     * Execute the console command.
42     *
43     * @return integer
44     */
45    public function handle(): int
46    {
47        $this->copyTraits();
48        $this->copyEnums();
49        $this->copyExceptions();
50        $this->copyRoutesList();
51        $this->copyApiConfigInfo();
52        return 0;
53    }
54
55    /**
56     * Copy config files
57     *
58     * @return void
59     */
60    private function copyApiConfigInfo(): void
61    {
62        $this->info('Copy Api Config');
63        $rootTarget = app_path('../' . self::TARGET);
64        if (File::exists("$rootTarget/../apiConfig.readonly.json")) {
65            File::delete("$rootTarget/../apiConfig.readonly.json");
66        }
67        File::put(
68            "$rootTarget/../apiConfig.readonly.json",
69            \json_encode(config('api'), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
70        );
71    }
72
73    /**
74     * Copy routes into a json file
75     *
76     * @return void
77     */
78    private function copyRoutesList(): void
79    {
80        $this->info('Copy Routes');
81        $routes = [];
82        /** @var \Illuminate\Routing\Route */
83        foreach (Route::getRoutes() as $route) {
84            if (\strpos($route->getPrefix(), 'v4') !== false) {
85                $routes[$route->getName()] = [
86                    'uri' => $route->uri(),
87                    'methods' => $route->methods()
88                ];
89            }
90        }
91        $rootTarget = app_path('../' . self::TARGET);
92        if (File::exists("$rootTarget/routes.json")) {
93            File::delete("$rootTarget/routes.json");
94        }
95        File::put(
96            "$rootTarget/routes.json",
97            \json_encode($routes, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
98        );
99    }
100
101    /**
102     * Copy Exeption classes
103     *
104     * @return void
105     */
106    private function copyExceptions(): void
107    {
108        $this->info('Copy Exceptions');
109        $rootTarget = app_path('../' . self::TARGET);
110        $classes    = [
111            CrmException::class,
112            ApiErrorException::class
113        ];
114        $this->copyToFolder($classes, 'Exceptions');
115        foreach ($classes as $class) {
116            $classBasename = class_basename($class);
117            $dest          = "$rootTarget/Exceptions/$classBasename.php";
118            $this->replaceInPhpFile($dest, 'App\\', self::CLIENTNAMESPACE . '\\');
119        }
120    }
121
122    /**
123     * Copy base enums classes
124     *
125     * @return void
126     */
127    private function copyTraits(): void
128    {
129        $this->info('Copy Traits');
130        $rootTarget = app_path('../' . self::TARGET);
131        $classes    = [
132            BaseEnum::class
133        ];
134        $this->copyToFolder($classes, 'Traits');
135        foreach ($classes as $class) {
136            $classBasename = class_basename($class);
137            $dest          = "$rootTarget/Traits/$classBasename.php";
138            $this->replaceInPhpFile($dest, 'App\\', self::CLIENTNAMESPACE . '\\');
139        }
140    }
141
142    /**
143     * Copy enums classes
144     *
145     * @return void
146     */
147    private function copyEnums(): void
148    {
149        $this->info('Copy Enums');
150        $rootTarget = app_path('../' . self::TARGET);
151        $classes    = [
152            ApiError::class,
153            ApiStatus::class,
154            ArcadiaOrderType::class,
155            Country::class,
156            QuestionType::class
157        ];
158        $this->copyToFolder($classes, 'Enums');
159        foreach ($classes as $class) {
160            $classBasename = class_basename($class);
161            $dest          = "$rootTarget/Enums/$classBasename.php";
162            $this->replaceInPhpFile($dest, 'App\\', self::CLIENTNAMESPACE . '\\');
163        }
164    }
165
166    /**
167     * Copy Classes to specified folder
168     *
169     * @param array  $classes
170     * @param string $folder
171     * @return void
172     */
173    private function copyToFolder(array $classes, string $folder): void
174    {
175        $rootTarget      = app_path('../' . self::TARGET);
176        $folderNamespace = \str_replace('/', '\\', $folder);
177        foreach ($classes as $class) {
178            $classFileName = \str_replace("App\\$folderNamespace\\", '', sprintf('%s.php', $class));
179            $classFileName = \str_replace('\\', '/', $classFileName);
180            $classBasename = class_basename($class);
181            $source        = \app_path("$folder/$classFileName");
182            $dest          = "$rootTarget/$folder/$classBasename.php";
183            if (File::exists($dest)) {
184                File::delete($dest);
185            }
186            File::copy($source, $dest);
187            $this->replaceInPhpFile($dest, 'namespace App', 'namespace ' . self::CLIENTNAMESPACE);
188        }
189    }
190
191    /**
192     * Replaces a specific string with another on a file
193     *
194     * @param string $source
195     * @param string $search
196     * @param string $replace
197     * @return void
198     */
199    private function replaceInPhpFile(string $source, string $search, string $replace): void
200    {
201        $fContent = File::get($source);
202
203        // Remove trailing \Api\V4 .
204        if ($pos = strpos($fContent, '\Api\V4')) {
205            $fContent = substr_replace($fContent, '', $pos, strlen('\Api\V4'));
206        }
207
208        // Remove trailing \Api .
209        $fContent = Str::of($fContent)->replaceMatches("/\\\(Api)([\s;\\\])/", '$2');
210        $fContent = Str::of($fContent)->replaceMatches("/\\\Traits\\\Enums/", '\Traits');
211
212        // Replace namespace top level.
213        $pos = strpos($fContent, $search);
214        if ($pos !== false) {
215            File::put($source, \str_replace($search, $replace, $fContent));
216        }
217    }
218}