Skip to content

Commit d8cd6b0

Browse files
add new feature: Make class like enum
1 parent 0185921 commit d8cd6b0

File tree

5 files changed

+254
-0
lines changed

5 files changed

+254
-0
lines changed
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
2+
3+
namespace App\Console\Commands\LaravelProjectAssist;
4+
5+
use Illuminate\Console\Command;
6+
use Illuminate\Support\Facades\File;
7+
use Illuminate\Support\Str;
8+
9+
class MakeClassLikeEnum extends Command
10+
{
11+
/**
12+
* The name and signature of the console command.
13+
*
14+
* @var string
15+
*/
16+
protected $signature = 'make:class-like-enum {name}';
17+
18+
/**
19+
* The console command description.
20+
*
21+
* @var string
22+
*/
23+
protected $description = 'Generates a data class file like enum but with int values to each field';
24+
25+
/**
26+
* Execute the console command.
27+
*
28+
* @return void
29+
*/
30+
public function handle(): void
31+
{
32+
$name = $this->argument('name');
33+
$className = Str::studly(class_basename($name));
34+
$subdirectory = rtrim(dirname($name), '/\\');
35+
36+
$onlyValues = $this->ask('Do you want the fields to have a label or you want them only by values? (y/n)', 'n') == "n";
37+
$prefix = $this->ask('Do you want to add a prefix to the fields? (e.g., "TYPE1 TYPE2" becomes "PREFIX_TYPE1 PREFIX_TYPE2") leave it blank if you dont', '');
38+
if ($onlyValues) {
39+
$fields = $this->collectFields($prefix);
40+
} else {
41+
$fields = $this->collectFieldsWithLabels($prefix);
42+
}
43+
44+
$defaultStartingNumber = 1;
45+
do {
46+
$defaultStartingNumber *= 10;
47+
} while (count($fields) >= $defaultStartingNumber);
48+
49+
50+
51+
52+
$startingNumber = $this->ask('What number do you want to start the values from?', $defaultStartingNumber);
53+
54+
while (!$this->checkStartingNumber($startingNumber, $fields)) {
55+
$this->error("The number you entered is too small, please enter a number greater like " . $defaultStartingNumber . " or more (add a zero)");
56+
$startingNumber = $this->ask('What number do you want to start the values from?', $defaultStartingNumber);
57+
}
58+
59+
$replaceFields = "";
60+
foreach ($fields as $key => $field) {
61+
$f = $onlyValues ? $field : $key;
62+
$replaceFields .= "\n const " . $f . " = " . ($startingNumber) . ";";
63+
$startingNumber++;
64+
}
65+
66+
67+
$replaceInAllMethod = "";
68+
if ($onlyValues) {
69+
for ($i = 0; $i < count($fields); $i++) {
70+
$replaceInAllMethod .= "\n self::" . $fields[$i] . ",";
71+
}
72+
} else {
73+
foreach ($fields as $key => $value) {
74+
$value = str_replace("'", "\\'", $value);
75+
$replaceInAllMethod .= "\n self::" . $key . " => '" . $value . "',";
76+
}
77+
}
78+
79+
$replacements = [
80+
'{{class}}' => $className,
81+
'\{{subdirectory}}' => ($subdirectory != "." ? "\\".$subdirectory : ""),
82+
'{{fields}}' => $replaceFields,
83+
'{{values}}' => $replaceInAllMethod,
84+
];
85+
86+
$extended = (!$onlyValues) ? "classLikeEnumKeyAndValue" : "classLikeEnumValueOnly";
87+
88+
$template = File::get(app_path('Console/Commands/LaravelProjectAssist/stubs/'.$extended.'.stub'));
89+
$generatedClass = str_replace(array_keys($replacements), array_values($replacements), $template);
90+
91+
$classPath = app_path('Enums/'.$subdirectory.'/'.$className . '.php');
92+
File::ensureDirectoryExists(dirname($classPath));
93+
File::put($classPath, $generatedClass);
94+
95+
$this->info("Class generated successfully!");
96+
}
97+
98+
function checkStartingNumber($startingNumber, $fields): bool
99+
{
100+
if ($startingNumber <= count($fields)) {
101+
return false;
102+
}
103+
$str = strval($startingNumber);
104+
$n = intval((intval($str[0])+1).str_repeat("0", strlen($str) - 1));
105+
return ($n - $startingNumber) > count($fields);
106+
}
107+
108+
protected function collectFields($prefix): array
109+
{
110+
$fields = $this->ask("Add fields separated by white space (e.g., TYPE1 TYPE2...)?");
111+
$fields = trim($fields);
112+
$fields = explode(" ", $fields);
113+
$fields = array_map(function ($field) use ($prefix) {
114+
$field = trim($field);
115+
if ($prefix != "") {
116+
$field = $prefix . "_" . $field;
117+
}
118+
$field = strtoupper($field);
119+
return preg_replace("/[^a-zA-Z0-9_\x7f-\xff]/", "", $field);
120+
}, $fields);
121+
$fields = array_filter($fields, function ($field) {
122+
return $field != "";
123+
});
124+
return array_values(array_unique($fields));
125+
}
126+
127+
protected function collectFieldsWithLabels($prefix): array
128+
{
129+
$fields = [];
130+
do {
131+
$field = $this->ask("Add field with label separated by ,,(e.g., first type,,TYPE1)?");
132+
$field = trim($field);
133+
$fields[] = $field;
134+
if (Str::startsWith($field, "/")) {
135+
$fields = $field;
136+
break;
137+
}
138+
} while ($field != "");
139+
if (is_array($fields)) {
140+
array_pop($fields);
141+
}
142+
else{
143+
$fields = substr($fields, 1);
144+
$fields = explode("//", $fields);
145+
$fields = array_map('trim', $fields);
146+
}
147+
$fields_ = array_filter($fields, function ($field) {
148+
return $field != "" AND Str::contains($field, ",,");
149+
});
150+
$fields_2 = [];
151+
for ($i = 0; $i < count($fields_); $i++) {
152+
$parts = explode(",,", $fields_[$i]);
153+
$fields_2[$parts[1]] = $parts[0];
154+
}
155+
156+
$keys = array_keys($fields_2);
157+
$keys = array_values(array_unique($keys));
158+
$fields = [];
159+
for ($i = 0; $i < count($keys); $i++) {
160+
$fields[$keys[$i]] = $fields_2[$keys[$i]];
161+
}
162+
163+
return array_combine(
164+
array_map(function ($key) use ($prefix) {
165+
$key = trim($key);
166+
if ($prefix != "") {
167+
$key = $prefix . "_" . $key;
168+
}
169+
$key = strtoupper($key);
170+
return preg_replace("/[^a-zA-Z0-9_\x7f-\xff]/", "", $key);
171+
}, array_keys($fields)),
172+
array_map('trim', array_values($fields))
173+
);
174+
}
175+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace App\Enums\{{subdirectory}};
4+
5+
use HichemtabTech\LaravelProjectAssist\DataClassLikeEnumKeyAndValue;
6+
7+
class {{class}} extends DataClassLikeEnumKeyAndValue
8+
{{{fields}}
9+
10+
public function ALL(): array
11+
{
12+
return [{{values}}
13+
];
14+
}
15+
16+
public function LABELS(): array
17+
{
18+
return array_keys($this->ALL());
19+
}
20+
21+
public function VALUES(): array
22+
{
23+
return array_values($this->ALL());
24+
}
25+
26+
public function getLabelByValue($value): ?string
27+
{
28+
return array_search($value, $this->ALL()) OR null;
29+
}
30+
31+
public function getValueByLabel($label): ?int
32+
{
33+
return $this->ALL()[$label]??null;
34+
}
35+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace App\Enums\{{subdirectory}};
4+
5+
use HichemtabTech\LaravelProjectAssist\DataClassLikeEnumValueOnly;
6+
7+
class {{class}} extends DataClassLikeEnumValueOnly
8+
{
9+
{{fields}}
10+
11+
public function ALL(): array
12+
{
13+
return [{{values}}
14+
];
15+
}
16+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace HichemtabTech\LaravelProjectAssist;
4+
5+
abstract class DataClassLikeEnumKeyAndValue
6+
{
7+
const __NONE__ = 0;
8+
9+
public abstract static function ALL(): array;
10+
11+
public abstract static function LABELS(): array;
12+
13+
public abstract static function VALUES(): array;
14+
15+
public abstract static function getLabelByValue(): ?string;
16+
17+
public abstract static function getValueByLabel(): ?int;
18+
}

src/DataClassLikeEnumValueOnly.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace HichemtabTech\LaravelProjectAssist;
4+
5+
abstract class DataClassLikeEnumValueOnly
6+
{
7+
const __NONE__ = 0;
8+
9+
public abstract static function ALL(): array;
10+
}

0 commit comments

Comments
 (0)